@moduna/otel 1.1.1 → 1.1.2

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.
@@ -15,6 +15,10 @@ interface ModunaOTELBaseConfig {
15
15
  * Additional OTLP headers sent with telemetry exports.
16
16
  */
17
17
  headers?: Record<string, string>;
18
+ /**
19
+ * Automatically flushes and shuts down telemetry when the Node.js process exits.
20
+ */
21
+ autoShutdown?: boolean;
18
22
  }
19
23
  /**
20
24
  * Configuration options for a ModunaOTEL instance.
@@ -43,6 +43,10 @@ export declare class ModunaOTEL {
43
43
  * Shuts down the singleton OpenTelemetry SDK.
44
44
  */
45
45
  shutdown(): Promise<void>;
46
+ /**
47
+ * Shuts down the singleton OpenTelemetry SDK and suppresses telemetry failures.
48
+ */
49
+ private shutdownSafely;
46
50
  /**
47
51
  * Creates telemetry settings for one Vercel AI SDK generateText or streamText call.
48
52
  *
@@ -82,6 +86,7 @@ export declare class ModunaOTEL {
82
86
  */
83
87
  instrument<T>(spanName: string, context: ModunaTraceContext, callback: TraceCallback<T>): Promise<T>;
84
88
  private normalizeConfig;
89
+ private registerLifecycleHooks;
85
90
  private createSDK;
86
91
  private startSafely;
87
92
  private createTraceMetadata;
@@ -51,6 +51,7 @@ class SilentOTLPTraceExporter extends OTLPTraceExporter {
51
51
  */
52
52
  export class ModunaOTEL {
53
53
  static shared = {
54
+ lifecycleHooksRegistered: false,
54
55
  started: false,
55
56
  warned: false,
56
57
  };
@@ -64,6 +65,7 @@ export class ModunaOTEL {
64
65
  const normalizedConfig = this.normalizeConfig(config);
65
66
  this.framework = normalizedConfig.framework;
66
67
  ModunaOTEL.shared.sdk ??= this.createSDK(normalizedConfig);
68
+ this.registerLifecycleHooks(normalizedConfig);
67
69
  void this.start();
68
70
  }
69
71
  /**
@@ -91,6 +93,15 @@ export class ModunaOTEL {
91
93
  * Shuts down the singleton OpenTelemetry SDK.
92
94
  */
93
95
  async shutdown() {
96
+ ModunaOTEL.shared.shutdownPromise ??= this.shutdownSafely().finally(() => {
97
+ ModunaOTEL.shared.shutdownPromise = undefined;
98
+ });
99
+ await ModunaOTEL.shared.shutdownPromise;
100
+ }
101
+ /**
102
+ * Shuts down the singleton OpenTelemetry SDK and suppresses telemetry failures.
103
+ */
104
+ async shutdownSafely() {
94
105
  const sdk = ModunaOTEL.shared.sdk;
95
106
  if (!ModunaOTEL.shared.started || !sdk) {
96
107
  return;
@@ -165,11 +176,32 @@ export class ModunaOTEL {
165
176
  normalizeConfig(config) {
166
177
  return {
167
178
  agentName: config.agentName,
179
+ autoShutdown: config.autoShutdown ?? true,
168
180
  apiKey: config.apiKey ?? process.env.MODUNA_API_KEY,
169
181
  framework: config.framework ?? config.sdkIntegration,
170
182
  headers: config.headers,
171
183
  };
172
184
  }
185
+ registerLifecycleHooks(config) {
186
+ if (!config.autoShutdown ||
187
+ ModunaOTEL.shared.lifecycleHooksRegistered) {
188
+ return;
189
+ }
190
+ process.once("beforeExit", () => {
191
+ void this.shutdown();
192
+ });
193
+ process.once("SIGINT", () => {
194
+ void this.shutdown().finally(() => {
195
+ process.exit(130);
196
+ });
197
+ });
198
+ process.once("SIGTERM", () => {
199
+ void this.shutdown().finally(() => {
200
+ process.exit(143);
201
+ });
202
+ });
203
+ ModunaOTEL.shared.lifecycleHooksRegistered = true;
204
+ }
173
205
  createSDK(config) {
174
206
  return new NodeSDK({
175
207
  resource: resourceFromAttributes({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moduna/otel",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "private": false,
5
5
  "description": "One-line OpenTelemetry setup for Moduna AI traces.",
6
6
  "license": "MIT",