mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
refactor(server): standarderlize metrics and trace with OTEL (#5054)
you can now export span to Zipkin and metrics to Prometheus when developing locally follow the docs of OTEL: https://opentelemetry.io/docs/instrumentation/js/exporters/ <img width="2357" alt="image" src="https://github.com/toeverything/AFFiNE/assets/8281226/ec615e1f-3e91-43f7-9111-d7d2629e9679">
This commit is contained in:
@@ -5,7 +5,6 @@ import test from 'ava';
|
||||
|
||||
import { ConfigModule } from '../src/config';
|
||||
import { GqlModule } from '../src/graphql.module';
|
||||
import { MetricsModule } from '../src/metrics';
|
||||
import { AuthModule } from '../src/modules/auth';
|
||||
import { AuthResolver } from '../src/modules/auth/resolver';
|
||||
import { AuthService } from '../src/modules/auth/service';
|
||||
@@ -40,7 +39,6 @@ test.beforeEach(async () => {
|
||||
PrismaModule,
|
||||
GqlModule,
|
||||
AuthModule,
|
||||
MetricsModule,
|
||||
RateLimiterModule,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
@@ -10,7 +10,6 @@ import { Doc as YDoc, encodeStateAsUpdate } from 'yjs';
|
||||
|
||||
import { CacheModule } from '../src/cache';
|
||||
import { Config, ConfigModule } from '../src/config';
|
||||
import { MetricsModule } from '../src/metrics';
|
||||
import { DocManager, DocModule } from '../src/modules/doc';
|
||||
import { PrismaModule, PrismaService } from '../src/prisma';
|
||||
import { flushDB } from './utils';
|
||||
@@ -19,7 +18,6 @@ const createModule = () => {
|
||||
return Test.createTestingModule({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
MetricsModule,
|
||||
CacheModule,
|
||||
EventEmitterModule.forRoot(),
|
||||
ConfigModule.forRoot(),
|
||||
|
||||
@@ -6,7 +6,6 @@ import test from 'ava';
|
||||
import * as Sinon from 'sinon';
|
||||
|
||||
import { ConfigModule } from '../src/config';
|
||||
import { MetricsModule } from '../src/metrics';
|
||||
import { DocHistoryManager } from '../src/modules/doc';
|
||||
import { PrismaModule, PrismaService } from '../src/prisma';
|
||||
import { flushDB } from './utils';
|
||||
@@ -20,12 +19,7 @@ let db: PrismaService;
|
||||
test.beforeEach(async () => {
|
||||
await flushDB();
|
||||
m = await Test.createTestingModule({
|
||||
imports: [
|
||||
PrismaModule,
|
||||
MetricsModule,
|
||||
ScheduleModule.forRoot(),
|
||||
ConfigModule.forRoot(),
|
||||
],
|
||||
imports: [PrismaModule, ScheduleModule.forRoot(), ConfigModule.forRoot()],
|
||||
providers: [DocHistoryManager],
|
||||
}).compile();
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import ava, { type TestFn } from 'ava';
|
||||
|
||||
import { ConfigModule } from '../src/config';
|
||||
import { GqlModule } from '../src/graphql.module';
|
||||
import { MetricsModule } from '../src/metrics';
|
||||
import { AuthModule } from '../src/modules/auth';
|
||||
import { AuthService } from '../src/modules/auth/service';
|
||||
import { PrismaModule } from '../src/prisma';
|
||||
@@ -44,7 +43,6 @@ test.beforeEach(async t => {
|
||||
PrismaModule,
|
||||
GqlModule,
|
||||
AuthModule,
|
||||
MetricsModule,
|
||||
RateLimiterModule,
|
||||
],
|
||||
}).compile();
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import test from 'ava';
|
||||
import { register } from 'prom-client';
|
||||
|
||||
import { MetricsModule } from '../src/metrics';
|
||||
import { Metrics } from '../src/metrics/metrics';
|
||||
import { PrismaModule } from '../src/prisma';
|
||||
|
||||
let metrics: Metrics;
|
||||
let module: TestingModule;
|
||||
|
||||
test.beforeEach(async () => {
|
||||
module = await Test.createTestingModule({
|
||||
imports: [MetricsModule, PrismaModule],
|
||||
}).compile();
|
||||
|
||||
metrics = module.get(Metrics);
|
||||
});
|
||||
|
||||
test.afterEach.always(async () => {
|
||||
await module.close();
|
||||
});
|
||||
|
||||
test('should be able to increment counter', async t => {
|
||||
metrics.socketIOEventCounter(1, { event: 'client-handshake' });
|
||||
const socketIOCounterMetric = register.getSingleMetric('socket_io_counter');
|
||||
t.truthy(socketIOCounterMetric);
|
||||
|
||||
t.truthy(
|
||||
JSON.stringify((await socketIOCounterMetric!.get()).values) ===
|
||||
'[{"value":1,"labels":{"event":"client-handshake"}}]'
|
||||
);
|
||||
t.pass();
|
||||
});
|
||||
|
||||
test('should be able to timer', async t => {
|
||||
let minimum: number;
|
||||
{
|
||||
const endTimer = metrics.socketIOEventTimer({ event: 'client-handshake' });
|
||||
const a = performance.now();
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
const b = performance.now();
|
||||
minimum = b - a;
|
||||
endTimer();
|
||||
}
|
||||
|
||||
let maximum: number;
|
||||
{
|
||||
const a = performance.now();
|
||||
const endTimer = metrics.socketIOEventTimer({ event: 'client-handshake' });
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
endTimer();
|
||||
const b = performance.now();
|
||||
maximum = b - a;
|
||||
}
|
||||
|
||||
const socketIOTimerMetric = register.getSingleMetric('socket_io_timer');
|
||||
t.truthy(socketIOTimerMetric);
|
||||
|
||||
const observations = (await socketIOTimerMetric!.get()).values;
|
||||
|
||||
for (const observation of observations) {
|
||||
if (
|
||||
observation.labels.event === 'client-handshake' &&
|
||||
'quantile' in observation.labels
|
||||
) {
|
||||
t.truthy(
|
||||
observation.value >= minimum / 1000,
|
||||
'observation.value should be greater than minimum'
|
||||
);
|
||||
t.truthy(
|
||||
observation.value <= maximum / 1000,
|
||||
'observation.value should be less than maximum'
|
||||
);
|
||||
}
|
||||
}
|
||||
t.pass();
|
||||
});
|
||||
Reference in New Issue
Block a user