1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-22 01:16:07 +02:00

feat: now instances are only shown for last 24 hours (#9372)

This commit is contained in:
Jaanus Sellin 2025-02-27 09:19:48 +02:00 committed by GitHub
parent e0f0108c19
commit 9ae9221960
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 60 additions and 11 deletions

View File

@ -129,7 +129,7 @@ export const Application = () => {
name: 'overview', name: 'overview',
}, },
{ {
title: 'Connected instances', title: 'Last Seen Instances (24h)',
path: `${basePath}/instances`, path: `${basePath}/instances`,
name: 'instances', name: 'instances',
}, },

View File

@ -287,7 +287,7 @@ export const ApplicationChart = ({ data }: IApplicationChartProps) => {
theme.fontSizes theme.fontSizes
.smallBody .smallBody
} }
tooltip='Active instances in the last 2 days' tooltip='Active instances in the last 24 hours'
/> />
</StyledCell> </StyledCell>
<StyledCell> <StyledCell>

View File

@ -331,6 +331,7 @@ export default class ClientApplicationsStore
]) ])
.from('client_instances as ci') .from('client_instances as ci')
.where('ci.app_name', appName) .where('ci.app_name', appName)
.whereRaw("ci.last_seen >= NOW() - INTERVAL '24 hours'")
.groupBy('ci.app_name', 'ci.environment'); .groupBy('ci.app_name', 'ci.environment');
}) })
.select([ .select([
@ -378,7 +379,7 @@ export default class ClientApplicationsStore
if (!environment) return acc; if (!environment) return acc;
strategies.forEach((strategy) => { strategies?.forEach((strategy) => {
if ( if (
!DEPRECATED_STRATEGIES.includes(strategy) && !DEPRECATED_STRATEGIES.includes(strategy) &&
!existingStrategies.includes(strategy) !existingStrategies.includes(strategy)

View File

@ -180,7 +180,7 @@ export default class ClientInstanceStore implements IClientInstanceStore {
return rows.map(mapRow); return rows.map(mapRow);
} }
async getByAppNameAndEnvironment( async getRecentByAppNameAndEnvironment(
appName: string, appName: string,
environment: string, environment: string,
): Promise<IClientInstance[]> { ): Promise<IClientInstance[]> {
@ -189,6 +189,7 @@ export default class ClientInstanceStore implements IClientInstanceStore {
.from(TABLE) .from(TABLE)
.where('app_name', appName) .where('app_name', appName)
.where('environment', environment) .where('environment', environment)
.whereRaw("last_seen >= NOW() - INTERVAL '24 hours'")
.orderBy('last_seen', 'desc') .orderBy('last_seen', 'desc')
.limit(1000); .limit(1000);

View File

@ -262,12 +262,12 @@ export default class ClientInstanceService {
return result; return result;
} }
async getApplicationEnvironmentInstances( async getRecentApplicationEnvironmentInstances(
appName: string, appName: string,
environment: string, environment: string,
) { ) {
const instances = const instances =
await this.clientInstanceStore.getByAppNameAndEnvironment( await this.clientInstanceStore.getRecentByAppNameAndEnvironment(
appName, appName,
environment, environment,
); );

View File

@ -168,9 +168,9 @@ class MetricsController extends Controller {
openApiService.validPath({ openApiService.validPath({
tags: ['Metrics'], tags: ['Metrics'],
operationId: 'getApplicationEnvironmentInstances', operationId: 'getApplicationEnvironmentInstances',
summary: 'Get application environment instances', summary: 'Get application environment instances (Last 24h)',
description: description:
'Returns an overview of the instances for the given `appName` and `environment` that receive traffic.', 'Returns an overview of the instances for the given `appName` and `environment` that have received traffic in the last 24 hours.',
responses: { responses: {
200: createResponseSchema( 200: createResponseSchema(
'applicationEnvironmentInstancesSchema', 'applicationEnvironmentInstancesSchema',
@ -315,7 +315,7 @@ class MetricsController extends Controller {
): Promise<void> { ): Promise<void> {
const { appName, environment } = req.params; const { appName, environment } = req.params;
const instances = const instances =
await this.clientInstanceService.getApplicationEnvironmentInstances( await this.clientInstanceService.getRecentApplicationEnvironmentInstances(
appName, appName,
environment, environment,
); );

View File

@ -21,7 +21,7 @@ export interface IClientInstanceStore
setLastSeen(INewClientInstance): Promise<void>; setLastSeen(INewClientInstance): Promise<void>;
insert(details: INewClientInstance): Promise<void>; insert(details: INewClientInstance): Promise<void>;
getByAppName(appName: string): Promise<IClientInstance[]>; getByAppName(appName: string): Promise<IClientInstance[]>;
getByAppNameAndEnvironment( getRecentByAppNameAndEnvironment(
appName: string, appName: string,
environment: string, environment: string,
): Promise<IClientInstance[]>; ): Promise<IClientInstance[]>;

View File

@ -221,3 +221,50 @@ test('should show missing features and strategies', async () => {
expect(body).toMatchObject(expected); expect(body).toMatchObject(expected);
}); });
test('should not return instances older than 24h', async () => {
await app.request
.post('/api/client/metrics')
.set('Authorization', defaultToken.secret)
.send(metrics)
.expect(202);
await app.services.clientMetricsServiceV2.bulkAdd();
await db.stores.clientApplicationsStore.upsert({
appName: metrics.appName,
});
await db.stores.clientInstanceStore.insert({
appName: metrics.appName,
clientIp: '127.0.0.1',
instanceId: 'old-instance',
lastSeen: new Date(Date.now() - 26 * 60 * 60 * 1000), // 26 hours ago
});
const { body } = await app.request
.get(`/api/admin/metrics/applications/${metrics.appName}/overview`)
.expect(200);
const expected = {
environments: [
{
instanceCount: 1,
},
],
};
expect(body).toMatchObject(expected);
const { body: instancesBody } = await app.request
.get(
`/api/admin/metrics/instances/${metrics.appName}/environment/default`,
)
.expect(200);
expect(instancesBody.instances).toHaveLength(1);
expect(instancesBody.instances).toMatchObject([
{
instanceId: metrics.instanceId,
},
]);
});

View File

@ -93,7 +93,7 @@ export default class FakeClientInstanceStore implements IClientInstanceStore {
return this.instances.filter((i) => i.appName === appName); return this.instances.filter((i) => i.appName === appName);
} }
async getByAppNameAndEnvironment( async getRecentByAppNameAndEnvironment(
appName: string, appName: string,
environment: string, environment: string,
): Promise<IClientInstance[]> { ): Promise<IClientInstance[]> {