@observantic/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,159 @@
1
+ import { NodeSDK } from '@opentelemetry/sdk-node';
2
+ import { Tracer, Meter } from '@opentelemetry/api';
3
+ export { SpanKind, SpanStatusCode, context, metrics, trace } from '@opentelemetry/api';
4
+ import { Logger } from '@opentelemetry/api-logs';
5
+ export { logs } from '@opentelemetry/api-logs';
6
+
7
+ interface ObservanticOptions {
8
+ /**
9
+ * Ingestion API key for your Observantic workspace.
10
+ * Defaults to process.env.OBSERVANTIC_API_KEY.
11
+ */
12
+ apiKey?: string;
13
+ /**
14
+ * Observantic ingestion base endpoint URL.
15
+ * Defaults to process.env.OBSERVANTIC_ENDPOINT or "https://api.observantic.com".
16
+ */
17
+ endpoint?: string;
18
+ /**
19
+ * Name of your application service.
20
+ * Defaults to process.env.OBSERVANTIC_SERVICE_NAME, process.env.OTEL_SERVICE_NAME,
21
+ * process.env.npm_package_name, or "node-service".
22
+ */
23
+ serviceName?: string;
24
+ /**
25
+ * Deployment environment (e.g., "production", "staging", "development").
26
+ * Defaults to process.env.OBSERVANTIC_ENVIRONMENT, process.env.NODE_ENV, or "development".
27
+ */
28
+ environment?: string;
29
+ /**
30
+ * Version of your application.
31
+ * Defaults to process.env.OBSERVANTIC_SERVICE_VERSION, process.env.npm_package_version, or "1.0.0".
32
+ */
33
+ serviceVersion?: string;
34
+ /**
35
+ * Custom resource attributes to attach to all telemetry (traces, metrics, logs).
36
+ */
37
+ resourceAttributes?: Record<string, string | number | boolean>;
38
+ /**
39
+ * Additional HTTP headers to attach to OTLP export requests.
40
+ */
41
+ headers?: Record<string, string>;
42
+ /**
43
+ * Disable telemetry collection entirely (useful in test or CI environments).
44
+ * Defaults to process.env.OBSERVANTIC_DISABLED === "true".
45
+ */
46
+ disabled?: boolean;
47
+ /**
48
+ * Enable verbose OpenTelemetry internal diagnostic logging.
49
+ * Defaults to process.env.OBSERVANTIC_DEBUG === "true".
50
+ */
51
+ debug?: boolean;
52
+ /**
53
+ * Automatically install graceful shutdown hooks for SIGINT and SIGTERM.
54
+ * Defaults to true.
55
+ */
56
+ autoShutdown?: boolean;
57
+ /**
58
+ * Sampling ratio for traces from 0.0 (0%) to 1.0 (100%).
59
+ * Defaults to 1.0.
60
+ */
61
+ traceSampleRate?: number;
62
+ /**
63
+ * Batch span export timeout in milliseconds.
64
+ * Defaults to 5000ms.
65
+ */
66
+ batchTimeoutMillis?: number;
67
+ /**
68
+ * Maximum queue size for spans and logs waiting to be exported.
69
+ * Defaults to 2048.
70
+ */
71
+ maxQueueSize?: number;
72
+ /**
73
+ * Maximum batch size per export request.
74
+ * Defaults to 512.
75
+ */
76
+ maxExportBatchSize?: number;
77
+ /**
78
+ * Metrics periodic export interval in milliseconds.
79
+ * Defaults to 60000ms (60s).
80
+ */
81
+ metricExportIntervalMillis?: number;
82
+ /**
83
+ * Enable or disable individual telemetry signals.
84
+ */
85
+ signals?: {
86
+ traces?: boolean;
87
+ metrics?: boolean;
88
+ logs?: boolean;
89
+ };
90
+ }
91
+ interface ResolvedObservanticConfig {
92
+ apiKey: string;
93
+ endpoint: string;
94
+ tracesEndpoint: string;
95
+ metricsEndpoint: string;
96
+ logsEndpoint: string;
97
+ serviceName: string;
98
+ environment: string;
99
+ serviceVersion: string;
100
+ resourceAttributes: Record<string, string | number | boolean>;
101
+ headers: Record<string, string>;
102
+ disabled: boolean;
103
+ debug: boolean;
104
+ autoShutdown: boolean;
105
+ traceSampleRate: number;
106
+ batchTimeoutMillis: number;
107
+ maxQueueSize: number;
108
+ maxExportBatchSize: number;
109
+ metricExportIntervalMillis: number;
110
+ signals: {
111
+ traces: boolean;
112
+ metrics: boolean;
113
+ logs: boolean;
114
+ };
115
+ }
116
+ /**
117
+ * Normalizes an endpoint URL and constructs signal-specific paths.
118
+ */
119
+ declare function normalizeEndpoints(baseEndpoint: string): {
120
+ endpoint: string;
121
+ tracesEndpoint: string;
122
+ metricsEndpoint: string;
123
+ logsEndpoint: string;
124
+ };
125
+ /**
126
+ * Resolves user options with environment variables and sensible defaults.
127
+ */
128
+ declare function resolveConfig(options?: ObservanticOptions): ResolvedObservanticConfig;
129
+
130
+ /**
131
+ * Gracefully shuts down the Observantic OpenTelemetry SDK and flushes pending telemetry.
132
+ */
133
+ declare function shutdownObservantic(): Promise<void>;
134
+
135
+ interface ObservanticClient {
136
+ sdk: NodeSDK | null;
137
+ config: ResolvedObservanticConfig;
138
+ shutdown: () => Promise<void>;
139
+ getTracer: (name?: string, version?: string) => Tracer;
140
+ getMeter: (name?: string, version?: string) => Meter;
141
+ getLogger: (name?: string, version?: string) => Logger;
142
+ }
143
+ /**
144
+ * Initializes Observantic OpenTelemetry instrumentation for Node.js and Express.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * import { initObservantic } from "@observantic/node";
149
+ *
150
+ * initObservantic({
151
+ * apiKey: "cw_live_sec_xxxxx",
152
+ * endpoint: "https://api.observantic.com",
153
+ * serviceName: "my-express-app"
154
+ * });
155
+ * ```
156
+ */
157
+ declare function initObservantic(options?: ObservanticOptions): ObservanticClient;
158
+
159
+ export { type ObservanticClient, type ObservanticOptions, type ResolvedObservanticConfig, initObservantic, normalizeEndpoints, resolveConfig, shutdownObservantic };
@@ -0,0 +1,159 @@
1
+ import { NodeSDK } from '@opentelemetry/sdk-node';
2
+ import { Tracer, Meter } from '@opentelemetry/api';
3
+ export { SpanKind, SpanStatusCode, context, metrics, trace } from '@opentelemetry/api';
4
+ import { Logger } from '@opentelemetry/api-logs';
5
+ export { logs } from '@opentelemetry/api-logs';
6
+
7
+ interface ObservanticOptions {
8
+ /**
9
+ * Ingestion API key for your Observantic workspace.
10
+ * Defaults to process.env.OBSERVANTIC_API_KEY.
11
+ */
12
+ apiKey?: string;
13
+ /**
14
+ * Observantic ingestion base endpoint URL.
15
+ * Defaults to process.env.OBSERVANTIC_ENDPOINT or "https://api.observantic.com".
16
+ */
17
+ endpoint?: string;
18
+ /**
19
+ * Name of your application service.
20
+ * Defaults to process.env.OBSERVANTIC_SERVICE_NAME, process.env.OTEL_SERVICE_NAME,
21
+ * process.env.npm_package_name, or "node-service".
22
+ */
23
+ serviceName?: string;
24
+ /**
25
+ * Deployment environment (e.g., "production", "staging", "development").
26
+ * Defaults to process.env.OBSERVANTIC_ENVIRONMENT, process.env.NODE_ENV, or "development".
27
+ */
28
+ environment?: string;
29
+ /**
30
+ * Version of your application.
31
+ * Defaults to process.env.OBSERVANTIC_SERVICE_VERSION, process.env.npm_package_version, or "1.0.0".
32
+ */
33
+ serviceVersion?: string;
34
+ /**
35
+ * Custom resource attributes to attach to all telemetry (traces, metrics, logs).
36
+ */
37
+ resourceAttributes?: Record<string, string | number | boolean>;
38
+ /**
39
+ * Additional HTTP headers to attach to OTLP export requests.
40
+ */
41
+ headers?: Record<string, string>;
42
+ /**
43
+ * Disable telemetry collection entirely (useful in test or CI environments).
44
+ * Defaults to process.env.OBSERVANTIC_DISABLED === "true".
45
+ */
46
+ disabled?: boolean;
47
+ /**
48
+ * Enable verbose OpenTelemetry internal diagnostic logging.
49
+ * Defaults to process.env.OBSERVANTIC_DEBUG === "true".
50
+ */
51
+ debug?: boolean;
52
+ /**
53
+ * Automatically install graceful shutdown hooks for SIGINT and SIGTERM.
54
+ * Defaults to true.
55
+ */
56
+ autoShutdown?: boolean;
57
+ /**
58
+ * Sampling ratio for traces from 0.0 (0%) to 1.0 (100%).
59
+ * Defaults to 1.0.
60
+ */
61
+ traceSampleRate?: number;
62
+ /**
63
+ * Batch span export timeout in milliseconds.
64
+ * Defaults to 5000ms.
65
+ */
66
+ batchTimeoutMillis?: number;
67
+ /**
68
+ * Maximum queue size for spans and logs waiting to be exported.
69
+ * Defaults to 2048.
70
+ */
71
+ maxQueueSize?: number;
72
+ /**
73
+ * Maximum batch size per export request.
74
+ * Defaults to 512.
75
+ */
76
+ maxExportBatchSize?: number;
77
+ /**
78
+ * Metrics periodic export interval in milliseconds.
79
+ * Defaults to 60000ms (60s).
80
+ */
81
+ metricExportIntervalMillis?: number;
82
+ /**
83
+ * Enable or disable individual telemetry signals.
84
+ */
85
+ signals?: {
86
+ traces?: boolean;
87
+ metrics?: boolean;
88
+ logs?: boolean;
89
+ };
90
+ }
91
+ interface ResolvedObservanticConfig {
92
+ apiKey: string;
93
+ endpoint: string;
94
+ tracesEndpoint: string;
95
+ metricsEndpoint: string;
96
+ logsEndpoint: string;
97
+ serviceName: string;
98
+ environment: string;
99
+ serviceVersion: string;
100
+ resourceAttributes: Record<string, string | number | boolean>;
101
+ headers: Record<string, string>;
102
+ disabled: boolean;
103
+ debug: boolean;
104
+ autoShutdown: boolean;
105
+ traceSampleRate: number;
106
+ batchTimeoutMillis: number;
107
+ maxQueueSize: number;
108
+ maxExportBatchSize: number;
109
+ metricExportIntervalMillis: number;
110
+ signals: {
111
+ traces: boolean;
112
+ metrics: boolean;
113
+ logs: boolean;
114
+ };
115
+ }
116
+ /**
117
+ * Normalizes an endpoint URL and constructs signal-specific paths.
118
+ */
119
+ declare function normalizeEndpoints(baseEndpoint: string): {
120
+ endpoint: string;
121
+ tracesEndpoint: string;
122
+ metricsEndpoint: string;
123
+ logsEndpoint: string;
124
+ };
125
+ /**
126
+ * Resolves user options with environment variables and sensible defaults.
127
+ */
128
+ declare function resolveConfig(options?: ObservanticOptions): ResolvedObservanticConfig;
129
+
130
+ /**
131
+ * Gracefully shuts down the Observantic OpenTelemetry SDK and flushes pending telemetry.
132
+ */
133
+ declare function shutdownObservantic(): Promise<void>;
134
+
135
+ interface ObservanticClient {
136
+ sdk: NodeSDK | null;
137
+ config: ResolvedObservanticConfig;
138
+ shutdown: () => Promise<void>;
139
+ getTracer: (name?: string, version?: string) => Tracer;
140
+ getMeter: (name?: string, version?: string) => Meter;
141
+ getLogger: (name?: string, version?: string) => Logger;
142
+ }
143
+ /**
144
+ * Initializes Observantic OpenTelemetry instrumentation for Node.js and Express.
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * import { initObservantic } from "@observantic/node";
149
+ *
150
+ * initObservantic({
151
+ * apiKey: "cw_live_sec_xxxxx",
152
+ * endpoint: "https://api.observantic.com",
153
+ * serviceName: "my-express-app"
154
+ * });
155
+ * ```
156
+ */
157
+ declare function initObservantic(options?: ObservanticOptions): ObservanticClient;
158
+
159
+ export { type ObservanticClient, type ObservanticOptions, type ResolvedObservanticConfig, initObservantic, normalizeEndpoints, resolveConfig, shutdownObservantic };
package/dist/index.js ADDED
@@ -0,0 +1,369 @@
1
+ // src/index.ts
2
+ import { NodeSDK } from "@opentelemetry/sdk-node";
3
+ import {
4
+ diag as diag2,
5
+ DiagConsoleLogger,
6
+ DiagLogLevel,
7
+ trace,
8
+ context,
9
+ metrics,
10
+ SpanStatusCode,
11
+ SpanKind
12
+ } from "@opentelemetry/api";
13
+ import { logs } from "@opentelemetry/api-logs";
14
+
15
+ // src/config.ts
16
+ function normalizeEndpoints(baseEndpoint) {
17
+ let cleaned = (baseEndpoint || "https://api.observantic.com").trim();
18
+ cleaned = cleaned.replace(/\/+$/, "");
19
+ if (cleaned.endsWith("/v1/traces")) {
20
+ const root = cleaned.slice(0, -"/v1/traces".length);
21
+ return {
22
+ endpoint: root,
23
+ tracesEndpoint: cleaned,
24
+ metricsEndpoint: `${root}/v1/metrics`,
25
+ logsEndpoint: `${root}/v1/logs`
26
+ };
27
+ }
28
+ if (cleaned.endsWith("/v1")) {
29
+ return {
30
+ endpoint: cleaned,
31
+ tracesEndpoint: `${cleaned}/traces`,
32
+ metricsEndpoint: `${cleaned}/metrics`,
33
+ logsEndpoint: `${cleaned}/logs`
34
+ };
35
+ }
36
+ return {
37
+ endpoint: cleaned,
38
+ tracesEndpoint: `${cleaned}/v1/traces`,
39
+ metricsEndpoint: `${cleaned}/v1/metrics`,
40
+ logsEndpoint: `${cleaned}/v1/logs`
41
+ };
42
+ }
43
+ function parseOtelHeaders(headerStr) {
44
+ if (!headerStr) return {};
45
+ const headers = {};
46
+ const pairs = headerStr.split(",");
47
+ for (const pair of pairs) {
48
+ const idx = pair.indexOf("=");
49
+ if (idx > 0) {
50
+ const key = pair.substring(0, idx).trim();
51
+ const val = pair.substring(idx + 1).trim();
52
+ if (key) headers[key] = val;
53
+ }
54
+ }
55
+ return headers;
56
+ }
57
+ function resolveConfig(options = {}) {
58
+ const env = process.env;
59
+ const apiKey = options.apiKey || env.OBSERVANTIC_API_KEY || "";
60
+ const rawEndpoint = options.endpoint || env.OBSERVANTIC_ENDPOINT || env.OTEL_EXPORTER_OTLP_ENDPOINT || "https://api.observantic.com";
61
+ const { endpoint, tracesEndpoint, metricsEndpoint, logsEndpoint } = normalizeEndpoints(rawEndpoint);
62
+ const serviceName = options.serviceName || env.OBSERVANTIC_SERVICE_NAME || env.OTEL_SERVICE_NAME || env.npm_package_name || process.title || "node-service";
63
+ const environment = options.environment || env.OBSERVANTIC_ENVIRONMENT || env.NODE_ENV || "development";
64
+ const serviceVersion = options.serviceVersion || env.OBSERVANTIC_SERVICE_VERSION || env.npm_package_version || "1.0.0";
65
+ const disabled = options.disabled !== void 0 ? options.disabled : env.OBSERVANTIC_DISABLED === "true" || env.OTEL_SDK_DISABLED === "true";
66
+ const debug = options.debug !== void 0 ? options.debug : env.OBSERVANTIC_DEBUG === "true" || env.OTEL_LOG_LEVEL === "debug";
67
+ const autoShutdown = options.autoShutdown !== void 0 ? options.autoShutdown : true;
68
+ const traceSampleRate = options.traceSampleRate !== void 0 ? Math.max(0, Math.min(1, options.traceSampleRate)) : env.OBSERVANTIC_TRACE_SAMPLE_RATE ? parseFloat(env.OBSERVANTIC_TRACE_SAMPLE_RATE) : 1;
69
+ const envHeaders = parseOtelHeaders(env.OTEL_EXPORTER_OTLP_HEADERS);
70
+ const headers = {
71
+ ...envHeaders,
72
+ ...options.headers || {}
73
+ };
74
+ if (apiKey) {
75
+ headers["Authorization"] = `Bearer ${apiKey}`;
76
+ headers["x-cw-token"] = apiKey;
77
+ }
78
+ return {
79
+ apiKey,
80
+ endpoint,
81
+ tracesEndpoint,
82
+ metricsEndpoint,
83
+ logsEndpoint,
84
+ serviceName,
85
+ environment,
86
+ serviceVersion,
87
+ resourceAttributes: options.resourceAttributes || {},
88
+ headers,
89
+ disabled,
90
+ debug,
91
+ autoShutdown,
92
+ traceSampleRate,
93
+ batchTimeoutMillis: options.batchTimeoutMillis || 5e3,
94
+ maxQueueSize: options.maxQueueSize || 2048,
95
+ maxExportBatchSize: options.maxExportBatchSize || 512,
96
+ metricExportIntervalMillis: options.metricExportIntervalMillis || 6e4,
97
+ signals: {
98
+ traces: options.signals?.traces !== false,
99
+ metrics: options.signals?.metrics !== false,
100
+ logs: options.signals?.logs !== false
101
+ }
102
+ };
103
+ }
104
+
105
+ // src/resource.ts
106
+ import { Resource } from "@opentelemetry/resources";
107
+ import {
108
+ SEMRESATTRS_SERVICE_NAME,
109
+ SEMRESATTRS_SERVICE_VERSION,
110
+ SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
111
+ SEMRESATTRS_TELEMETRY_SDK_NAME,
112
+ SEMRESATTRS_TELEMETRY_SDK_LANGUAGE,
113
+ SEMRESATTRS_TELEMETRY_SDK_VERSION,
114
+ SEMRESATTRS_PROCESS_PID,
115
+ SEMRESATTRS_PROCESS_RUNTIME_NAME,
116
+ SEMRESATTRS_PROCESS_RUNTIME_VERSION
117
+ } from "@opentelemetry/semantic-conventions";
118
+ function createResource(config) {
119
+ const customAttributes = {
120
+ [SEMRESATTRS_SERVICE_NAME]: config.serviceName,
121
+ [SEMRESATTRS_SERVICE_VERSION]: config.serviceVersion,
122
+ [SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: config.environment,
123
+ [SEMRESATTRS_TELEMETRY_SDK_NAME]: "@observantic/sdk",
124
+ [SEMRESATTRS_TELEMETRY_SDK_LANGUAGE]: "nodejs",
125
+ [SEMRESATTRS_TELEMETRY_SDK_VERSION]: "1.0.0",
126
+ [SEMRESATTRS_PROCESS_PID]: process.pid,
127
+ [SEMRESATTRS_PROCESS_RUNTIME_NAME]: "nodejs",
128
+ [SEMRESATTRS_PROCESS_RUNTIME_VERSION]: process.version,
129
+ ...config.resourceAttributes
130
+ };
131
+ return new Resource(customAttributes);
132
+ }
133
+
134
+ // src/tracing.ts
135
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
136
+ import {
137
+ BatchSpanProcessor,
138
+ ParentBasedSampler,
139
+ TraceIdRatioBasedSampler,
140
+ AlwaysOnSampler,
141
+ AlwaysOffSampler
142
+ } from "@opentelemetry/sdk-trace-base";
143
+ function createTraceExporter(config) {
144
+ return new OTLPTraceExporter({
145
+ url: config.tracesEndpoint,
146
+ headers: config.headers,
147
+ timeoutMillis: 1e4
148
+ });
149
+ }
150
+ function createSampler(sampleRate) {
151
+ if (sampleRate >= 1) {
152
+ return new ParentBasedSampler({ root: new AlwaysOnSampler() });
153
+ }
154
+ if (sampleRate <= 0) {
155
+ return new ParentBasedSampler({ root: new AlwaysOffSampler() });
156
+ }
157
+ return new ParentBasedSampler({
158
+ root: new TraceIdRatioBasedSampler(sampleRate)
159
+ });
160
+ }
161
+ function createSpanProcessor(exporter, config) {
162
+ return new BatchSpanProcessor(exporter, {
163
+ maxQueueSize: config.maxQueueSize,
164
+ maxExportBatchSize: config.maxExportBatchSize,
165
+ scheduledDelayMillis: config.batchTimeoutMillis,
166
+ exportTimeoutMillis: 1e4
167
+ });
168
+ }
169
+
170
+ // src/metrics.ts
171
+ import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
172
+ import {
173
+ PeriodicExportingMetricReader,
174
+ AggregationTemporality
175
+ } from "@opentelemetry/sdk-metrics";
176
+ function createMetricExporter(config) {
177
+ return new OTLPMetricExporter({
178
+ url: config.metricsEndpoint,
179
+ headers: config.headers,
180
+ timeoutMillis: 1e4,
181
+ temporalityPreference: AggregationTemporality.DELTA
182
+ });
183
+ }
184
+ function createMetricReader(exporter, config) {
185
+ return new PeriodicExportingMetricReader({
186
+ exporter,
187
+ exportIntervalMillis: config.metricExportIntervalMillis,
188
+ exportTimeoutMillis: 1e4
189
+ });
190
+ }
191
+
192
+ // src/logging.ts
193
+ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
194
+ import { BatchLogRecordProcessor } from "@opentelemetry/sdk-logs";
195
+ function createLogExporter(config) {
196
+ return new OTLPLogExporter({
197
+ url: config.logsEndpoint,
198
+ headers: config.headers,
199
+ timeoutMillis: 1e4
200
+ });
201
+ }
202
+ function createLogRecordProcessor(exporter, config) {
203
+ return new BatchLogRecordProcessor(exporter, {
204
+ maxQueueSize: config.maxQueueSize,
205
+ maxExportBatchSize: config.maxExportBatchSize,
206
+ scheduledDelayMillis: config.batchTimeoutMillis,
207
+ exportTimeoutMillis: 1e4
208
+ });
209
+ }
210
+
211
+ // src/instrumentation.ts
212
+ import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
213
+ function createInstrumentations(_config) {
214
+ return [
215
+ getNodeAutoInstrumentations({
216
+ "@opentelemetry/instrumentation-fs": {
217
+ // Disable noisy fs hooks by default to prevent span flooding
218
+ enabled: false
219
+ },
220
+ "@opentelemetry/instrumentation-http": {
221
+ enabled: true
222
+ },
223
+ "@opentelemetry/instrumentation-express": {
224
+ enabled: true
225
+ }
226
+ })
227
+ ];
228
+ }
229
+
230
+ // src/shutdown.ts
231
+ import { diag } from "@opentelemetry/api";
232
+ var activeSdk = null;
233
+ var isShuttingDown = false;
234
+ var isSignalHandlerRegistered = false;
235
+ function registerSdk(sdk) {
236
+ activeSdk = sdk;
237
+ }
238
+ async function shutdownObservantic() {
239
+ if (!activeSdk) {
240
+ return;
241
+ }
242
+ if (isShuttingDown) {
243
+ return;
244
+ }
245
+ isShuttingDown = true;
246
+ diag.info("Shutting down Observantic OpenTelemetry SDK...");
247
+ try {
248
+ await activeSdk.shutdown();
249
+ diag.info("Observantic OpenTelemetry SDK terminated successfully.");
250
+ } catch (err) {
251
+ diag.error("Error shutting down Observantic OpenTelemetry SDK", err);
252
+ throw err;
253
+ } finally {
254
+ activeSdk = null;
255
+ isShuttingDown = false;
256
+ }
257
+ }
258
+ function installShutdownHooks(sdk) {
259
+ registerSdk(sdk);
260
+ if (isSignalHandlerRegistered) {
261
+ return;
262
+ }
263
+ const handleSignal = async (signal) => {
264
+ diag.info(`Received ${signal}, gracefully shutting down Observantic telemetry...`);
265
+ try {
266
+ await shutdownObservantic();
267
+ } catch (err) {
268
+ diag.error(`Failed to flush telemetry on ${signal}:`, err);
269
+ }
270
+ };
271
+ process.once("SIGTERM", () => void handleSignal("SIGTERM"));
272
+ process.once("SIGINT", () => void handleSignal("SIGINT"));
273
+ isSignalHandlerRegistered = true;
274
+ }
275
+
276
+ // src/index.ts
277
+ import { logs as logs2 } from "@opentelemetry/api-logs";
278
+ var isInitialized = false;
279
+ function initObservantic(options = {}) {
280
+ const config = resolveConfig(options);
281
+ if (config.debug) {
282
+ diag2.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);
283
+ }
284
+ if (config.disabled) {
285
+ diag2.info("[@observantic/node] Telemetry is disabled via configuration.");
286
+ return {
287
+ sdk: null,
288
+ config,
289
+ shutdown: async () => {
290
+ },
291
+ getTracer: (name = "observantic", version = "1.0.0") => trace.getTracer(name, version),
292
+ getMeter: (name = "observantic", version = "1.0.0") => metrics.getMeter(name, version),
293
+ getLogger: (name = "observantic", version = "1.0.0") => logs.getLogger(name, version)
294
+ };
295
+ }
296
+ if (!config.apiKey) {
297
+ console.warn(
298
+ "[@observantic/node] Warning: No apiKey provided. Please provide an apiKey in initObservantic({ apiKey }) or set the OBSERVANTIC_API_KEY environment variable."
299
+ );
300
+ }
301
+ if (isInitialized) {
302
+ diag2.warn("[@observantic/node] initObservantic was called multiple times. Returning existing client.");
303
+ return {
304
+ sdk: null,
305
+ config,
306
+ shutdown: shutdownObservantic,
307
+ getTracer: (name = "observantic", version = "1.0.0") => trace.getTracer(name, version),
308
+ getMeter: (name = "observantic", version = "1.0.0") => metrics.getMeter(name, version),
309
+ getLogger: (name = "observantic", version = "1.0.0") => logs.getLogger(name, version)
310
+ };
311
+ }
312
+ const resource = createResource(config);
313
+ const sdkConfig = {
314
+ resource,
315
+ instrumentations: createInstrumentations(config)
316
+ };
317
+ if (config.signals.traces) {
318
+ const traceExporter = createTraceExporter(config);
319
+ const spanProcessor = createSpanProcessor(traceExporter, config);
320
+ const sampler = createSampler(config.traceSampleRate);
321
+ sdkConfig.spanProcessor = spanProcessor;
322
+ sdkConfig.sampler = sampler;
323
+ }
324
+ if (config.signals.metrics) {
325
+ const metricExporter = createMetricExporter(config);
326
+ const metricReader = createMetricReader(metricExporter, config);
327
+ sdkConfig.metricReader = metricReader;
328
+ }
329
+ if (config.signals.logs) {
330
+ const logExporter = createLogExporter(config);
331
+ const logRecordProcessor = createLogRecordProcessor(logExporter, config);
332
+ sdkConfig.logRecordProcessor = logRecordProcessor;
333
+ }
334
+ const sdk = new NodeSDK(sdkConfig);
335
+ try {
336
+ sdk.start();
337
+ isInitialized = true;
338
+ diag2.info(`[@observantic/node] Initialized successfully for service: "${config.serviceName}" [${config.environment}]`);
339
+ if (config.autoShutdown) {
340
+ installShutdownHooks(sdk);
341
+ } else {
342
+ registerSdk(sdk);
343
+ }
344
+ } catch (err) {
345
+ diag2.error("[@observantic/node] Failed to start OpenTelemetry NodeSDK:", err);
346
+ throw err;
347
+ }
348
+ return {
349
+ sdk,
350
+ config,
351
+ shutdown: shutdownObservantic,
352
+ getTracer: (name = config.serviceName, version = config.serviceVersion) => trace.getTracer(name, version),
353
+ getMeter: (name = config.serviceName, version = config.serviceVersion) => metrics.getMeter(name, version),
354
+ getLogger: (name = config.serviceName, version = config.serviceVersion) => logs.getLogger(name, version)
355
+ };
356
+ }
357
+ export {
358
+ SpanKind,
359
+ SpanStatusCode,
360
+ context,
361
+ initObservantic,
362
+ logs2 as logs,
363
+ metrics,
364
+ normalizeEndpoints,
365
+ resolveConfig,
366
+ shutdownObservantic,
367
+ trace
368
+ };
369
+ //# sourceMappingURL=index.js.map