1+ /**
2+ * @license
3+ * Copyright 2025 Google LLC
4+ * SPDX-License-Identifier: Apache-2.0
5+ */
6+
7+ import { trace , metrics } from '@opentelemetry/api' ;
8+ import { logs } from '@opentelemetry/api-logs' ;
9+ import { LoggerProvider , LogRecordProcessor , BatchLogRecordProcessor } from '@opentelemetry/sdk-logs' ;
10+ import { MetricReader , MeterProvider , PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics' ;
11+ import { detectResources , Resource } from '@opentelemetry/resources' ;
12+ import { SpanProcessor , BatchSpanProcessor } from '@opentelemetry/sdk-trace-base' ;
13+ import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node' ;
14+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http' ;
15+ import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http' ;
16+ import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http' ;
17+
18+ export interface OtelExportersConfig {
19+ enableTracing ?: boolean ;
20+ enableMetrics ?: boolean ;
21+ enableLogging ?: boolean ;
22+ }
23+
24+ /**
25+ * Configuration hooks for OpenTelemetry setup.
26+ *
27+ * This interface defines the structure for configuring OpenTelemetry
28+ * components including span processors, metric readers, and log record processors.
29+ */
30+ export interface OTelHooks {
31+ spanProcessors ?: SpanProcessor [ ] ;
32+ metricReaders ?: MetricReader [ ] ;
33+ logRecordProcessors ?: LogRecordProcessor [ ] ;
34+ }
35+
36+ /**
37+ * Sets up OTel providers if hooks for a given telemetry type were passed.
38+ *
39+ * Additionally adds generic OTLP exporters based on following env variables:
40+ * OTEL_EXPORTER_OTLP_ENDPOINT
41+ * OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
42+ * OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
43+ * OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
44+ * See https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/
45+ * for how they are used.
46+ *
47+ * If a provider for a specific telemetry type was already globally set -
48+ * this function will not override it or register more exporters.
49+ *
50+ * @experimental (Experimental, subject to change)
51+ *
52+ * @param otelHooksToSetup per-telemetry-type processors and readers to be added
53+ * to OTel providers. If no hooks for a specific telemetry type are passed -
54+ * provider will not be set.
55+ * @param otelResource OTel resource to use in providers.
56+ * If empty - default OTel resource detection will be used.
57+ */
58+ export function maybeSetOtelProviders (
59+ otelHooksToSetup : OTelHooks [ ] = [ ] ,
60+ otelResource ?: Resource
61+ ) : void {
62+ const resource = otelResource || getOtelResource ( ) ;
63+ const allHooks = [ ...otelHooksToSetup , getOtelExporters ( ) ] ;
64+ const spanProcessors = allHooks . flatMap ( hooks => hooks . spanProcessors || [ ] ) ;
65+ const metricReaders = allHooks . flatMap ( hooks => hooks . metricReaders || [ ] ) ;
66+ const logRecordProcessors = allHooks . flatMap ( hooks => hooks . logRecordProcessors || [ ] ) ;
67+
68+ if ( spanProcessors . length > 0 ) {
69+ const tracerProvider = new NodeTracerProvider ( {
70+ resource,
71+ spanProcessors
72+ } ) ;
73+ tracerProvider . register ( ) ;
74+ trace . setGlobalTracerProvider ( tracerProvider ) ;
75+ }
76+
77+ if ( metricReaders . length > 0 ) {
78+ const meterProvider = new MeterProvider ( {
79+ readers : metricReaders ,
80+ resource,
81+ } ) ;
82+ metrics . setGlobalMeterProvider ( meterProvider ) ;
83+ }
84+
85+ if ( logRecordProcessors . length > 0 ) {
86+ const loggerProvider = new LoggerProvider ( {
87+ resource,
88+ processors : logRecordProcessors ,
89+ } ) ;
90+ // logs is experimental, reference to https://open-telemetry.github.io/opentelemetry-js/modules/_opentelemetry_api-logs.html#alpha-software---use-at-your-own-risk
91+ logs . setGlobalLoggerProvider ( loggerProvider ) ;
92+ }
93+ }
94+
95+ /**
96+ * Gets the OTel resource with environment variable detection.
97+ *
98+ * The resource detection populates resource labels from
99+ * environment variables like OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES.
100+ *
101+ * @returns A Resource object with detected attributes
102+ */
103+ function getOtelResource ( ) : Resource {
104+ return detectResources ( {
105+ detectors : [ ] ,
106+ } ) ;
107+ }
108+
109+ /**
110+ * Gets OTel exporters configuration based on environment variables.
111+ *
112+ * @returns OtelExportersConfig with flags based on environment variables
113+ */
114+ function getOtelExportersConfig ( ) : OtelExportersConfig {
115+ return {
116+ enableTracing : ! ! ( process . env . OTEL_EXPORTER_OTLP_ENDPOINT || process . env . OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ) ,
117+ enableMetrics : ! ! ( process . env . OTEL_EXPORTER_OTLP_ENDPOINT || process . env . OTEL_EXPORTER_OTLP_METRICS_ENDPOINT ) ,
118+ enableLogging : ! ! ( process . env . OTEL_EXPORTER_OTLP_ENDPOINT || process . env . OTEL_EXPORTER_OTLP_LOGS_ENDPOINT ) ,
119+ } ;
120+ }
121+
122+ /**
123+ * Gets OTel exporters based on configuration.
124+ *
125+ * @param config Configuration for which exporters to enable
126+ * @returns OTelHooks containing configured exporters
127+ */
128+ function getOtelExporters ( config = getOtelExportersConfig ( ) ) : OTelHooks {
129+ const { enableTracing, enableMetrics, enableLogging } = config ;
130+ return {
131+ spanProcessors : enableTracing ? [ new BatchSpanProcessor ( new OTLPTraceExporter ( ) ) ] : [ ] ,
132+ metricReaders : enableMetrics ? [ new PeriodicExportingMetricReader ( { exporter : new OTLPMetricExporter ( ) } ) ] : [ ] ,
133+ logRecordProcessors : enableLogging ? [ new BatchLogRecordProcessor ( new OTLPLogExporter ( ) ) ] : [ ] ,
134+ } ;
135+ }
0 commit comments