Skip to content

Commit 40e93da

Browse files
committed
feat(nodejs): load metric and log providers dynamic
1 parent 984d275 commit 40e93da

File tree

1 file changed

+98
-39
lines changed

1 file changed

+98
-39
lines changed

nodejs/packages/layer/src/wrapper.ts

+98-39
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ import {
33
diag,
44
DiagConsoleLogger,
55
DiagLogLevel,
6-
metrics,
76
propagation,
87
TextMapPropagator,
98
trace,
9+
TracerProvider,
1010
} from '@opentelemetry/api';
11-
import { logs } from '@opentelemetry/api-logs';
1211
import {
1312
CompositePropagator,
1413
getEnv,
@@ -23,26 +22,14 @@ import {
2322
SimpleSpanProcessor,
2423
TracerConfig,
2524
} from '@opentelemetry/sdk-trace-base';
26-
import {
27-
MeterProvider,
28-
MeterProviderOptions,
29-
PeriodicExportingMetricReader,
30-
} from '@opentelemetry/sdk-metrics';
31-
import {
32-
LoggerProvider,
33-
SimpleLogRecordProcessor,
34-
ConsoleLogRecordExporter,
35-
LoggerProviderConfig,
36-
} from '@opentelemetry/sdk-logs';
3725
import {
3826
detectResourcesSync,
3927
envDetector,
28+
IResource,
4029
processDetector,
4130
} from '@opentelemetry/resources';
4231
import { awsLambdaDetector } from '@opentelemetry/resource-detector-aws';
4332
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
44-
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
45-
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
4633
import {
4734
Instrumentation,
4835
registerInstrumentations,
@@ -85,24 +72,27 @@ const propagatorMap = new Map<string, () => TextMapPropagator>([
8572

8673
declare global {
8774
// In case of downstream configuring span processors etc
75+
function configureLambdaInstrumentation(
76+
config: AwsLambdaInstrumentationConfig,
77+
): AwsLambdaInstrumentationConfig;
8878
function configureAwsInstrumentation(
8979
defaultConfig: AwsSdkInstrumentationConfig,
9080
): AwsSdkInstrumentationConfig;
91-
function configureTracerProvider(tracerProvider: BasicTracerProvider): void;
92-
function configureTracer(defaultConfig: TracerConfig): TracerConfig;
81+
function configureInstrumentations(): Instrumentation[];
9382
function configureSdkRegistration(
9483
defaultSdkRegistration: SDKRegistrationConfig,
9584
): SDKRegistrationConfig;
96-
function configureInstrumentations(): Instrumentation[];
97-
function configureLoggerProvider(loggerProvider: LoggerProvider): void;
98-
function configureMeter(
99-
defaultConfig: MeterProviderOptions,
100-
): MeterProviderOptions;
101-
function configureMeterProvider(meterProvider: MeterProvider): void;
102-
function configureLambdaInstrumentation(
103-
config: AwsLambdaInstrumentationConfig,
104-
): AwsLambdaInstrumentationConfig;
105-
function configureInstrumentations(): Instrumentation[];
85+
function configureTracer(defaultConfig: TracerConfig): TracerConfig;
86+
function configureTracerProvider(tracerProvider: BasicTracerProvider): void;
87+
88+
// No explicit metric type here, but "unknown" type.
89+
// Because metric packages are important dynamically.
90+
function configureMeter(defaultConfig: unknown): unknown;
91+
function configureMeterProvider(meterProvider: unknown): void;
92+
93+
// No explicit log type here, but "unknown" type.
94+
// Because log packages are important dynamically.
95+
function configureLoggerProvider(loggerProvider: unknown): void;
10696
}
10797

10898
function getActiveInstumentations(): Set<string> {
@@ -264,11 +254,9 @@ function getPropagator(): TextMapPropagator {
264254
return new CompositePropagator({ propagators });
265255
}
266256

267-
async function initializeProvider() {
268-
const resource = detectResourcesSync({
269-
detectors: [awsLambdaDetector, envDetector, processDetector],
270-
});
271-
257+
async function initializeTracerProvider(
258+
resource: IResource,
259+
): Promise<TracerProvider> {
272260
let config: TracerConfig = {
273261
resource,
274262
};
@@ -302,9 +290,27 @@ async function initializeProvider() {
302290
}
303291
tracerProvider.register(sdkRegistrationConfig);
304292

293+
return tracerProvider;
294+
}
295+
296+
async function initializeMeterProvider(
297+
resource: IResource,
298+
): Promise<unknown | undefined> {
299+
if (process.env.OTEL_METRICS_EXPORTER === 'none') {
300+
return;
301+
}
302+
303+
const { metrics } = await import('@opentelemetry/api');
304+
const { MeterProvider, PeriodicExportingMetricReader } = await import(
305+
'@opentelemetry/sdk-metrics'
306+
);
307+
const { OTLPMetricExporter } = await import(
308+
'@opentelemetry/exporter-metrics-otlp-http'
309+
);
310+
305311
// Configure default meter provider (doesn't export metrics)
306312
const metricExporter = new OTLPMetricExporter();
307-
let meterConfig: MeterProviderOptions = {
313+
let meterConfig: unknown = {
308314
resource,
309315
readers: [
310316
new PeriodicExportingMetricReader({
@@ -316,15 +322,36 @@ async function initializeProvider() {
316322
meterConfig = configureMeter(meterConfig);
317323
}
318324

319-
const meterProvider = new MeterProvider(meterConfig);
325+
const meterProvider = new MeterProvider(meterConfig as object);
320326
if (typeof configureMeterProvider === 'function') {
321327
configureMeterProvider(meterProvider);
322328
} else {
323329
metrics.setGlobalMeterProvider(meterProvider);
324330
}
325331

332+
metricsDisableFunction = () => {
333+
metrics.disable();
334+
};
335+
336+
return meterProvider;
337+
}
338+
339+
async function initializeLoggerProvider(
340+
resource: IResource,
341+
): Promise<unknown | undefined> {
342+
if (process.env.OTEL_LOGS_EXPORTER === 'none') {
343+
return;
344+
}
345+
346+
const { logs } = await import('@opentelemetry/api-logs');
347+
const { LoggerProvider, SimpleLogRecordProcessor, ConsoleLogRecordExporter } =
348+
await import('@opentelemetry/sdk-logs');
349+
const { OTLPLogExporter } = await import(
350+
'@opentelemetry/exporter-logs-otlp-http'
351+
);
352+
326353
const logExporter = new OTLPLogExporter();
327-
const loggerConfig: LoggerProviderConfig = {
354+
const loggerConfig = {
328355
resource,
329356
};
330357
const loggerProvider = new LoggerProvider(loggerConfig);
@@ -344,6 +371,25 @@ async function initializeProvider() {
344371
);
345372
}
346373

374+
logsDisableFunction = () => {
375+
logs.disable();
376+
};
377+
378+
return loggerProvider;
379+
}
380+
381+
async function initializeProvider() {
382+
const resource = detectResourcesSync({
383+
detectors: [awsLambdaDetector, envDetector, processDetector],
384+
});
385+
386+
const tracerProvider: TracerProvider =
387+
await initializeTracerProvider(resource);
388+
const meterProvider: unknown | undefined =
389+
await initializeMeterProvider(resource);
390+
const loggerProvider: unknown | undefined =
391+
await initializeLoggerProvider(resource);
392+
347393
// Create instrumentations if they have not been created before
348394
// to prevent additional coldstart overhead
349395
// caused by creations and initializations of instrumentations.
@@ -352,11 +398,14 @@ async function initializeProvider() {
352398
}
353399

354400
// Re-register instrumentation with initialized provider. Patched code will see the update.
401+
355402
disableInstrumentations = registerInstrumentations({
356403
instrumentations,
357404
tracerProvider,
358-
meterProvider,
359-
loggerProvider,
405+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
406+
meterProvider: meterProvider as any,
407+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
408+
loggerProvider: loggerProvider as any,
360409
});
361410
}
362411

@@ -382,8 +431,16 @@ export async function unwrap() {
382431
context.disable();
383432
propagation.disable();
384433
trace.disable();
385-
metrics.disable();
386-
logs.disable();
434+
435+
if (metricsDisableFunction) {
436+
metricsDisableFunction();
437+
metricsDisableFunction = () => {};
438+
}
439+
440+
if (logsDisableFunction) {
441+
logsDisableFunction();
442+
logsDisableFunction = () => {};
443+
}
387444
}
388445

389446
export async function init() {
@@ -406,6 +463,8 @@ console.log('Registering OpenTelemetry');
406463
let initialized = false;
407464
let instrumentations: Instrumentation[];
408465
let disableInstrumentations: () => void;
466+
let metricsDisableFunction: () => void;
467+
let logsDisableFunction: () => void;
409468

410469
// Configure lambda logging
411470
const logLevel = getEnv().OTEL_LOG_LEVEL;

0 commit comments

Comments
 (0)