-
Notifications
You must be signed in to change notification settings - Fork 42
/
Copy pathOpenTelemetryModule.ts
142 lines (132 loc) · 4.27 KB
/
OpenTelemetryModule.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { DynamicModule } from '@nestjs/common';
import { NodeSDK } from '@opentelemetry/sdk-node';
import { TraceService } from './Trace/TraceService';
import { Constants } from './Constants';
import {
OpenTelemetryModuleConfig,
OpenTelemetryModuleDefaultConfig,
} from './OpenTelemetryModuleConfig';
import { FactoryProvider } from '@nestjs/common/interfaces/modules/provider.interface';
import { OpenTelemetryService } from './OpenTelemetryService';
import { OpenTelemetryModuleAsyncOption } from './OpenTelemetryModuleAsyncOption';
import { DecoratorInjector } from './Trace/Injectors/DecoratorInjector';
import { ModuleRef } from '@nestjs/core';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { Tracer } from '@opentelemetry/sdk-trace-base';
export class OpenTelemetryModule {
static async forRoot(
configuration: Partial<OpenTelemetryModuleConfig> = {},
): Promise<DynamicModule> {
configuration = { ...OpenTelemetryModuleDefaultConfig, ...configuration };
const injectors = configuration?.traceAutoInjectors ?? [];
return {
global: true,
module: OpenTelemetryModule,
imports: [EventEmitterModule.forRoot()],
providers: [
...injectors,
TraceService,
OpenTelemetryService,
DecoratorInjector,
this.buildProvider(configuration),
this.buildInjectors(configuration),
this.buildTracer(),
{
provide: Constants.SDK_CONFIG,
useValue: configuration,
},
],
exports: [TraceService, Tracer],
};
}
private static buildProvider(
configuration?: Partial<OpenTelemetryModuleConfig>,
): FactoryProvider {
return {
provide: Constants.SDK,
useFactory: async () => {
const sdk = new NodeSDK(configuration);
await sdk.start();
return sdk;
},
};
}
private static buildInjectors(
configuration?: Partial<OpenTelemetryModuleConfig>,
): FactoryProvider {
const injectors = configuration?.traceAutoInjectors ?? [];
return {
provide: Constants.SDK_INJECTORS,
useFactory: async (...injectors) => {
for await (const injector of injectors) {
if (injector['inject']) await injector.inject();
}
},
inject: [
DecoratorInjector,
// eslint-disable-next-line @typescript-eslint/ban-types
...(injectors as Function[]),
],
};
}
static async forRootAsync(
configuration: OpenTelemetryModuleAsyncOption = {},
): Promise<DynamicModule> {
return {
global: true,
module: OpenTelemetryModule,
imports: [...configuration?.imports, EventEmitterModule.forRoot()],
providers: [
TraceService,
OpenTelemetryService,
this.buildAsyncProvider(),
this.buildAsyncInjectors(),
this.buildTracer(),
{
provide: Constants.SDK_CONFIG,
useFactory: configuration.useFactory,
inject: configuration.inject,
},
],
exports: [TraceService, Tracer],
};
}
private static buildAsyncProvider(): FactoryProvider {
return {
provide: Constants.SDK,
useFactory: async (config) => {
config = { ...OpenTelemetryModuleDefaultConfig, ...config };
const sdk = new NodeSDK(config);
await sdk.start();
return sdk;
},
inject: [Constants.SDK_CONFIG],
};
}
private static buildAsyncInjectors(): FactoryProvider {
return {
provide: Constants.SDK_INJECTORS,
useFactory: async (config, moduleRef: ModuleRef) => {
config = { ...OpenTelemetryModuleDefaultConfig, ...config };
const injectors =
config.traceAutoInjectors ??
OpenTelemetryModuleDefaultConfig.traceAutoInjectors;
const decoratorInjector = await moduleRef.create(DecoratorInjector);
await decoratorInjector.inject();
for await (const injector of injectors) {
const created = await moduleRef.create(injector);
if (created['inject']) await created.inject();
}
return {};
},
inject: [Constants.SDK_CONFIG, ModuleRef],
};
}
private static buildTracer() {
return {
provide: Tracer,
useFactory: (traceService: TraceService) => traceService.getTracer(),
inject: [TraceService],
};
}
}