@@ -19,10 +19,11 @@ import { version } from '../package.json';
19
19
import PodUidDetector from './detectors/node/opentelemetry-resource-detector-kubernetes-pod' ;
20
20
import ServiceNameFallbackDetector from './detectors/node/opentelemetry-resource-detector-service-name-fallback' ;
21
21
import { FileSpanExporter } from './util/FileSpanExporter' ;
22
+ import { hasOptedIn , hasOptedOut , parseNumericEnvironmentVariableWithDefault } from './util/environment' ;
22
23
23
- if ( process . env . DASH0_DEBUG ) {
24
- console . log ( 'Dash0 OpenTelemetry distribution for Node.js: Starting NodeSDK.' ) ;
25
- }
24
+ const debugOutput = hasOptedIn ( ' DASH0_DEBUG' ) ;
25
+
26
+ printDebugOutput ( 'Dash0 OpenTelemetry distribution for Node.js: Starting NodeSDK.' ) ;
26
27
27
28
let sdkShutdownHasBeenCalled = false ;
28
29
@@ -31,98 +32,121 @@ if (process.env.DASH0_OTEL_COLLECTOR_BASE_URL) {
31
32
baseUrl = process . env . DASH0_OTEL_COLLECTOR_BASE_URL ;
32
33
}
33
34
34
- const instrumentationConfig : any = { } ;
35
- if (
36
- ! process . env . DASH0_ENABLE_FS_INSTRUMENTATION ||
37
- process . env . DASH0_ENABLE_FS_INSTRUMENTATION . trim ( ) . toLowerCase ( ) !== 'true'
38
- ) {
39
- instrumentationConfig [ '@opentelemetry/instrumentation-fs' ] = {
40
- enabled : false ,
41
- } ;
42
- }
35
+ const configuration : Partial < NodeSDKConfiguration > = {
36
+ spanProcessors : spanProcessors ( ) ,
37
+ metricReader : metricsReader ( ) ,
38
+ logRecordProcessor : logRecordProcessor ( ) ,
39
+ instrumentations : [ getNodeAutoInstrumentations ( createInstrumentationConfig ( ) ) ] ,
40
+ resource : resource ( ) ,
41
+ resourceDetectors : resourceDetectors ( ) ,
42
+ } ;
43
43
44
- const spanProcessors : SpanProcessor [ ] = [
45
- new BatchSpanProcessor (
46
- new OTLPTraceExporter ( {
47
- url : `${ baseUrl } /v1/traces` ,
48
- } ) ,
49
- ) ,
50
- ] ;
51
-
52
- const logRecordProcessor = new BatchLogRecordProcessor (
53
- new OTLPLogExporter ( {
54
- url : `${ baseUrl } /v1/logs` ,
55
- } ) ,
56
- ) ;
57
-
58
- if ( process . env . DASH0_DEBUG_PRINT_SPANS != null ) {
59
- if ( process . env . DASH0_DEBUG_PRINT_SPANS . toLocaleLowerCase ( ) === 'true' ) {
60
- spanProcessors . push ( new BatchSpanProcessor ( new ConsoleSpanExporter ( ) ) ) ;
61
- } else {
62
- spanProcessors . push ( new BatchSpanProcessor ( new FileSpanExporter ( process . env . DASH0_DEBUG_PRINT_SPANS ) ) ) ;
44
+ const sdk = new NodeSDK ( configuration ) ;
45
+
46
+ sdk . start ( ) ;
47
+
48
+ createBootstrapSpanIfRequested ( ) ;
49
+ installProcessExitHandlers ( ) ;
50
+
51
+ printDebugOutput ( 'Dash0 OpenTelemetry distribution for Node.js: NodeSDK started.' ) ;
52
+
53
+ function spanProcessors ( ) : SpanProcessor [ ] {
54
+ const spanProcessors : SpanProcessor [ ] = [
55
+ new BatchSpanProcessor (
56
+ new OTLPTraceExporter ( {
57
+ url : `${ baseUrl } /v1/traces` ,
58
+ } ) ,
59
+ ) ,
60
+ ] ;
61
+
62
+ if ( process . env . DASH0_DEBUG_PRINT_SPANS != null ) {
63
+ if ( process . env . DASH0_DEBUG_PRINT_SPANS . toLowerCase ( ) === 'true' ) {
64
+ spanProcessors . push ( new BatchSpanProcessor ( new ConsoleSpanExporter ( ) ) ) ;
65
+ } else {
66
+ spanProcessors . push ( new BatchSpanProcessor ( new FileSpanExporter ( process . env . DASH0_DEBUG_PRINT_SPANS ) ) ) ;
67
+ }
63
68
}
69
+ return spanProcessors ;
64
70
}
65
71
66
- const configuration : Partial < NodeSDKConfiguration > = {
67
- spanProcessors : spanProcessors ,
72
+ function metricsReader ( ) : PeriodicExportingMetricReader {
73
+ // Implement support for config of metric export timeout/interval via environment variables here in the distribution
74
+ // until https://github.com/open-telemetry/opentelemetry-js/issues/4655 has been implemented.
75
+ // The default values are taken from
76
+ // https://github.com/open-telemetry/opentelemetry-js/blob/812c774998fb60a0c666404ae71b1d508e0568f4/packages/sdk-metrics/src/export/PeriodicExportingMetricReader.ts#L97-L98
77
+ const exportIntervalMillis = parseNumericEnvironmentVariableWithDefault ( 'OTEL_METRIC_EXPORT_INTERVAL' , 60000 ) ;
78
+ const exportTimeoutMillis = parseNumericEnvironmentVariableWithDefault ( 'OTEL_METRIC_EXPORT_TIMEOUT' , 30000 ) ;
68
79
69
- metricReader : new PeriodicExportingMetricReader ( {
80
+ return new PeriodicExportingMetricReader ( {
70
81
exporter : new OTLPMetricExporter ( {
71
82
url : `${ baseUrl } /v1/metrics` ,
72
83
} ) ,
73
- } ) ,
84
+ exportIntervalMillis,
85
+ exportTimeoutMillis,
86
+ } ) ;
87
+ }
74
88
75
- logRecordProcessor,
89
+ function logRecordProcessor ( ) {
90
+ return new BatchLogRecordProcessor (
91
+ new OTLPLogExporter ( {
92
+ url : `${ baseUrl } /v1/logs` ,
93
+ } ) ,
94
+ ) ;
95
+ }
76
96
77
- instrumentations : [ getNodeAutoInstrumentations ( instrumentationConfig ) ] ,
97
+ function createInstrumentationConfig ( ) : any {
98
+ const instrumentationConfig : any = { } ;
99
+ if ( ! hasOptedIn ( 'DASH0_ENABLE_FS_INSTRUMENTATION' ) ) {
100
+ instrumentationConfig [ '@opentelemetry/instrumentation-fs' ] = {
101
+ enabled : false ,
102
+ } ;
103
+ }
104
+ return instrumentationConfig ;
105
+ }
78
106
79
- resource : new Resource ( {
107
+ function resource ( ) {
108
+ return new Resource ( {
80
109
'telemetry.distro.name' : 'dash0-nodejs' ,
81
110
'telemetry.distro.version' : version ,
82
- } ) ,
83
- } ;
84
-
85
- // Copy the behavior of the NodeSDK constructor with regard to resource detectors, but add the pod uid detector.
86
- // https://github.com/open-telemetry/opentelemetry-js/blob/73fddf9b5e7a93bd4cf21c2dbf444cee31d26c88/experimental/packages/opentelemetry-sdk-node/src/sdk.ts#L126-L132
87
- let detectors : ( Detector | DetectorSync ) [ ] ;
88
- if ( process . env . OTEL_NODE_RESOURCE_DETECTORS != null ) {
89
- detectors = getResourceDetectors ( ) ;
90
- } else {
91
- detectors = [ envDetector , processDetector , containerDetector , hostDetector ] ;
111
+ } ) ;
92
112
}
93
- detectors . push ( new PodUidDetector ( ) ) ;
94
- detectors . push ( new ServiceNameFallbackDetector ( ) ) ;
95
- configuration . resourceDetectors = detectors ;
96
-
97
- const sdk = new NodeSDK ( configuration ) ;
98
113
99
- sdk . start ( ) ;
100
-
101
- if ( process . env . DASH0_BOOTSTRAP_SPAN != null ) {
102
- const tracer = trace . getTracer ( 'dash0-nodejs-distribution' ) ;
103
- tracer //
104
- . startSpan ( process . env . DASH0_BOOTSTRAP_SPAN , {
105
- root : true ,
106
- kind : SpanKind . INTERNAL ,
107
- } )
108
- . end ( ) ;
114
+ function resourceDetectors ( ) : ( Detector | DetectorSync ) [ ] {
115
+ // Copy the behavior of the NodeSDK constructor with regard to resource detectors, but add the pod uid detector.
116
+ // https://github.com/open-telemetry/opentelemetry-js/blob/73fddf9b5e7a93bd4cf21c2dbf444cee31d26c88/experimental/packages/opentelemetry-sdk-node/src/sdk.ts#L126-L132
117
+ let detectors : ( Detector | DetectorSync ) [ ] ;
118
+ if ( process . env . OTEL_NODE_RESOURCE_DETECTORS != null ) {
119
+ detectors = getResourceDetectors ( ) ;
120
+ } else {
121
+ detectors = [ envDetector , processDetector , containerDetector , hostDetector ] ;
122
+ }
123
+ detectors . push ( new PodUidDetector ( ) ) ;
124
+ detectors . push ( new ServiceNameFallbackDetector ( ) ) ;
125
+ return detectors ;
109
126
}
110
127
111
- if ( process . env . DASH0_FLUSH_ON_SIGTERM_SIGINT && process . env . DASH0_FLUSH_ON_SIGTERM_SIGINT . toLowerCase ( ) === 'true' ) {
112
- [ 'SIGTERM' , 'SIGINT' ] . forEach ( signal => {
113
- process . once ( signal , onProcessExit . bind ( null , true ) ) ;
114
- } ) ;
128
+ function createBootstrapSpanIfRequested ( ) {
129
+ if ( process . env . DASH0_BOOTSTRAP_SPAN != null ) {
130
+ const tracer = trace . getTracer ( 'dash0-nodejs-distribution' ) ;
131
+ tracer //
132
+ . startSpan ( process . env . DASH0_BOOTSTRAP_SPAN , {
133
+ root : true ,
134
+ kind : SpanKind . INTERNAL ,
135
+ } )
136
+ . end ( ) ;
137
+ }
115
138
}
116
139
117
- if (
118
- ! process . env . DASH0_FLUSH_ON_EMPTY_EVENT_LOOP ||
119
- process . env . DASH0_FLUSH_ON_EMPTY_EVENT_LOOP . toLowerCase ( ) !== 'false'
120
- ) {
121
- process . once ( 'beforeExit' , onProcessExit . bind ( null , false ) ) ;
122
- }
140
+ function installProcessExitHandlers ( ) {
141
+ if ( hasOptedIn ( 'DASH0_FLUSH_ON_SIGTERM_SIGINT' ) ) {
142
+ [ 'SIGTERM' , 'SIGINT' ] . forEach ( signal => {
143
+ process . once ( signal , onProcessExit . bind ( null , true ) ) ;
144
+ } ) ;
145
+ }
123
146
124
- if ( process . env . DASH0_DEBUG ) {
125
- console . log ( 'Dash0 OpenTelemetry distribution for Node.js: NodeSDK started.' ) ;
147
+ if ( ! hasOptedOut ( 'DASH0_FLUSH_ON_EMPTY_EVENT_LOOP' ) ) {
148
+ process . once ( 'beforeExit' , onProcessExit . bind ( null , false ) ) ;
149
+ }
126
150
}
127
151
128
152
async function onProcessExit ( callProcessExit : boolean ) {
@@ -141,9 +165,9 @@ async function gracefulSdkShutdown(callProcessExit: boolean) {
141
165
sdkShutdownHasBeenCalled = true ;
142
166
await sdk . shutdown ( ) ;
143
167
144
- if ( process . env . DASH0_DEBUG ) {
145
- console . log ( 'Dash0 OpenTelemetry distribution for Node.js: OpenTelemetry SDK has been shut down successfully.' ) ;
146
- }
168
+ printDebugOutput (
169
+ 'Dash0 OpenTelemetry distribution for Node.js: OpenTelemetry SDK has been shut down successfully.' ,
170
+ ) ;
147
171
} catch ( err ) {
148
172
console . error ( 'Dash0 OpenTelemetry distribution for Node.js: Error shutting down the OpenTelemetry SDK:' , err ) ;
149
173
} finally {
@@ -174,3 +198,9 @@ function executePromiseWithTimeout(promise: Promise<any>, timeoutMillis: number,
174
198
}
175
199
} ) ;
176
200
}
201
+
202
+ function printDebugOutput ( message : string ) {
203
+ if ( debugOutput ) {
204
+ console . log ( message ) ;
205
+ }
206
+ }
0 commit comments