mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-16 13:57:02 +08:00
fix(server): duplicate registered otel providers (#11513)
This commit is contained in:
@@ -2,14 +2,18 @@ import './config';
|
|||||||
|
|
||||||
import { Global, Module } from '@nestjs/common';
|
import { Global, Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { OpentelemetryFactory } from './opentelemetry';
|
import {
|
||||||
|
OpentelemetryOptionsFactory,
|
||||||
|
OpentelemetryProvider,
|
||||||
|
} from './opentelemetry';
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
@Module({
|
@Module({
|
||||||
providers: [OpentelemetryFactory],
|
providers: [OpentelemetryOptionsFactory, OpentelemetryProvider],
|
||||||
|
exports: [OpentelemetryOptionsFactory],
|
||||||
})
|
})
|
||||||
export class MetricsModule {}
|
export class MetricsModule {}
|
||||||
|
|
||||||
export * from './metrics';
|
export * from './metrics';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
export { OpentelemetryFactory };
|
export { OpentelemetryOptionsFactory };
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Injectable, Logger, OnModuleDestroy } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { ModuleRef } from '@nestjs/core';
|
||||||
import {
|
import {
|
||||||
CompositePropagator,
|
CompositePropagator,
|
||||||
W3CBaggagePropagator,
|
W3CBaggagePropagator,
|
||||||
@@ -14,7 +15,7 @@ import { NestInstrumentation } from '@opentelemetry/instrumentation-nestjs-core'
|
|||||||
import { SocketIoInstrumentation } from '@opentelemetry/instrumentation-socket.io';
|
import { SocketIoInstrumentation } from '@opentelemetry/instrumentation-socket.io';
|
||||||
import { Resource } from '@opentelemetry/resources';
|
import { Resource } from '@opentelemetry/resources';
|
||||||
import { MetricProducer, MetricReader } from '@opentelemetry/sdk-metrics';
|
import { MetricProducer, MetricReader } from '@opentelemetry/sdk-metrics';
|
||||||
import { NodeSDK } from '@opentelemetry/sdk-node';
|
import { NodeSDK, NodeSDKConfiguration } from '@opentelemetry/sdk-node';
|
||||||
import {
|
import {
|
||||||
BatchSpanProcessor,
|
BatchSpanProcessor,
|
||||||
SpanExporter,
|
SpanExporter,
|
||||||
@@ -34,7 +35,7 @@ import { PrismaMetricProducer } from './prisma';
|
|||||||
|
|
||||||
const { PrismaInstrumentation } = prismaInstrument;
|
const { PrismaInstrumentation } = prismaInstrument;
|
||||||
|
|
||||||
export abstract class BaseOpentelemetryFactory {
|
export abstract class BaseOpentelemetryOptionsFactory {
|
||||||
abstract getMetricReader(): MetricReader;
|
abstract getMetricReader(): MetricReader;
|
||||||
abstract getSpanExporter(): SpanExporter;
|
abstract getSpanExporter(): SpanExporter;
|
||||||
|
|
||||||
@@ -61,9 +62,9 @@ export abstract class BaseOpentelemetryFactory {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
create() {
|
create(): Partial<NodeSDKConfiguration> {
|
||||||
const traceExporter = this.getSpanExporter();
|
const traceExporter = this.getSpanExporter();
|
||||||
return new NodeSDK({
|
return {
|
||||||
resource: this.getResource(),
|
resource: this.getResource(),
|
||||||
sampler: new TraceIdRatioBasedSampler(0.1),
|
sampler: new TraceIdRatioBasedSampler(0.1),
|
||||||
traceExporter,
|
traceExporter,
|
||||||
@@ -77,21 +78,32 @@ export abstract class BaseOpentelemetryFactory {
|
|||||||
}),
|
}),
|
||||||
instrumentations: this.getInstractions(),
|
instrumentations: this.getInstractions(),
|
||||||
serviceName: 'affine-cloud',
|
serviceName: 'affine-cloud',
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OpentelemetryFactory
|
export class OpentelemetryOptionsFactory extends BaseOpentelemetryOptionsFactory {
|
||||||
extends BaseOpentelemetryFactory
|
override getMetricReader(): MetricReader {
|
||||||
implements OnModuleDestroy
|
return new PrometheusExporter({
|
||||||
{
|
metricProducers: this.getMetricsProducers(),
|
||||||
private readonly logger = new Logger(OpentelemetryFactory.name);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
override getSpanExporter(): SpanExporter {
|
||||||
|
return new ZipkinExporter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class OpentelemetryProvider {
|
||||||
|
readonly #logger = new Logger(OpentelemetryProvider.name);
|
||||||
#sdk: NodeSDK | null = null;
|
#sdk: NodeSDK | null = null;
|
||||||
|
|
||||||
constructor(private readonly config: Config) {
|
constructor(
|
||||||
super();
|
private readonly config: Config,
|
||||||
}
|
private readonly ref: ModuleRef
|
||||||
|
) {}
|
||||||
|
|
||||||
@OnEvent('config.init')
|
@OnEvent('config.init')
|
||||||
async init(event: Events['config.init']) {
|
async init(event: Events['config.init']) {
|
||||||
@@ -112,27 +124,21 @@ export class OpentelemetryFactory
|
|||||||
await this.#sdk?.shutdown();
|
await this.#sdk?.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
override getMetricReader(): MetricReader {
|
|
||||||
return new PrometheusExporter({
|
|
||||||
metricProducers: this.getMetricsProducers(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
override getSpanExporter(): SpanExporter {
|
|
||||||
return new ZipkinExporter();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async setup() {
|
private async setup() {
|
||||||
if (this.config.metrics.enabled) {
|
if (this.config.metrics.enabled) {
|
||||||
if (!this.#sdk) {
|
if (!this.#sdk) {
|
||||||
this.#sdk = this.create();
|
const factory = this.ref.get(OpentelemetryOptionsFactory, {
|
||||||
|
strict: false,
|
||||||
|
});
|
||||||
|
this.#sdk = new NodeSDK(factory.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#sdk.start();
|
this.#sdk.start();
|
||||||
this.logger.log('OpenTelemetry SDK started');
|
this.#logger.log('OpenTelemetry SDK started');
|
||||||
} else {
|
} else {
|
||||||
await this.#sdk?.shutdown();
|
await this.#sdk?.shutdown();
|
||||||
this.#sdk = null;
|
this.#sdk = null;
|
||||||
this.logger.log('OpenTelemetry SDK stopped');
|
this.#logger.log('OpenTelemetry SDK stopped');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import {
|
|||||||
SEMRESATTRS_K8S_POD_NAME,
|
SEMRESATTRS_K8S_POD_NAME,
|
||||||
} from '@opentelemetry/semantic-conventions';
|
} from '@opentelemetry/semantic-conventions';
|
||||||
|
|
||||||
import { OpentelemetryFactory } from '../../base/metrics';
|
import { OpentelemetryOptionsFactory } from '../../base/metrics';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class GCloudOpentelemetryFactory extends OpentelemetryFactory {
|
export class GCloudOpentelemetryOptionsFactory extends OpentelemetryOptionsFactory {
|
||||||
override getResource(): Resource {
|
override getResource(): Resource {
|
||||||
const env = getEnv();
|
const env = getEnv();
|
||||||
return super
|
return super
|
||||||
@@ -48,8 +48,8 @@ export class GCloudOpentelemetryFactory extends OpentelemetryFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const FactorProvider: Provider = {
|
const FactorProvider: Provider = {
|
||||||
provide: OpentelemetryFactory,
|
provide: OpentelemetryOptionsFactory,
|
||||||
useClass: GCloudOpentelemetryFactory,
|
useClass: GCloudOpentelemetryOptionsFactory,
|
||||||
};
|
};
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
|
|||||||
Reference in New Issue
Block a user