@blaxel/telemetry 0.2.17-dev.118 → 0.2.17-dev.120

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.
@@ -37,8 +37,10 @@ declare class TelemetryManager {
37
37
  setConfiguration(): Promise<void>;
38
38
  get tracer(): import("@opentelemetry/api").Tracer;
39
39
  get enabled(): boolean;
40
+ get isLambdaEnvironment(): boolean;
40
41
  get authHeaders(): Record<string, string>;
41
42
  sleep(ms: number): Promise<unknown>;
43
+ retryContextExtraction(headers: Record<string, string | string[]>, span: Span, traceparentParts: string[]): Promise<void>;
42
44
  flush(): Promise<void>;
43
45
  getLogger(): Promise<Logger>;
44
46
  setupSignalHandler(): void;
@@ -58,7 +60,7 @@ declare class TelemetryManager {
58
60
  * Initialize and return the OTLP Log Exporter.
59
61
  */
60
62
  getLogExporter(): OTLPLogExporter;
61
- instrumentApp(): void;
63
+ instrumentAppAsync(): Promise<void>;
62
64
  setExporters(): void;
63
65
  shutdownApp(): Promise<void>;
64
66
  }
package/dist/telemetry.js CHANGED
@@ -78,7 +78,9 @@ class TelemetryManager {
78
78
  if (!this.enabled || this.initialized) {
79
79
  return;
80
80
  }
81
- this.instrumentApp();
81
+ this.instrumentAppAsync().catch((error) => {
82
+ core_1.logger.error("Error during async instrumentation setup:", error);
83
+ });
82
84
  this.setupSignalHandler();
83
85
  this.initialized = true;
84
86
  this.setConfiguration().catch((error) => {
@@ -101,6 +103,9 @@ class TelemetryManager {
101
103
  get enabled() {
102
104
  return core_1.env.BL_ENABLE_OPENTELEMETRY === "true";
103
105
  }
106
+ get isLambdaEnvironment() {
107
+ return !!(process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.LAMBDA_TASK_ROOT);
108
+ }
104
109
  get authHeaders() {
105
110
  const headers = {};
106
111
  if (core_1.settings.authorization) {
@@ -114,6 +119,64 @@ class TelemetryManager {
114
119
  async sleep(ms) {
115
120
  return new Promise((resolve) => setTimeout(resolve, ms));
116
121
  }
122
+ async retryContextExtraction(headers, span, traceparentParts) {
123
+ // More aggressive retries in Lambda environment
124
+ const maxRetries = this.isLambdaEnvironment ? 5 : 3;
125
+ const retryDelay = this.isLambdaEnvironment ? 100 : 50; // Longer delays for Lambda cold starts
126
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
127
+ try {
128
+ core_1.logger.debug(`Context extraction attempt ${attempt}/${maxRetries}`);
129
+ // Check if propagation is ready
130
+ const propagationFields = api_1.propagation.fields();
131
+ core_1.logger.debug("Current propagation fields:", propagationFields);
132
+ if (propagationFields.length === 0 && attempt < maxRetries) {
133
+ core_1.logger.debug(`Propagation not ready on attempt ${attempt}, waiting ${retryDelay * attempt}ms...`);
134
+ await this.sleep(retryDelay * attempt);
135
+ continue;
136
+ }
137
+ // Try to extract trace context
138
+ const extractedContext = api_1.propagation.extract(api_1.context.active(), headers);
139
+ const extractedSpan = api_1.trace.getSpan(extractedContext);
140
+ if (extractedSpan) {
141
+ const extractedSpanContext = extractedSpan.spanContext();
142
+ core_1.logger.debug("Manual context extraction succeeded on attempt " + attempt + ":", JSON.stringify({
143
+ traceId: extractedSpanContext.traceId,
144
+ spanId: extractedSpanContext.spanId,
145
+ traceFlags: extractedSpanContext.traceFlags,
146
+ }));
147
+ return; // Success!
148
+ }
149
+ if (attempt < maxRetries) {
150
+ core_1.logger.debug(`Context extraction failed on attempt ${attempt}, retrying...`);
151
+ await this.sleep(retryDelay * attempt);
152
+ }
153
+ }
154
+ catch (error) {
155
+ core_1.logger.debug(`Error on context extraction attempt ${attempt}:`, error);
156
+ if (attempt < maxRetries) {
157
+ await this.sleep(retryDelay * attempt);
158
+ }
159
+ }
160
+ }
161
+ // All retries failed - add fallback attributes
162
+ core_1.logger.debug("All context extraction attempts failed, adding fallback attributes");
163
+ if (traceparentParts.length === 4 &&
164
+ traceparentParts[1] !== "00000000000000000000000000000000") {
165
+ try {
166
+ span.setAttributes({
167
+ "trace.parent.trace_id": traceparentParts[1],
168
+ "trace.parent.span_id": traceparentParts[2],
169
+ "trace.parent.trace_flags": traceparentParts[3],
170
+ "trace.extraction.failed": "true",
171
+ "trace.extraction.reason": "lambda_cold_start",
172
+ });
173
+ core_1.logger.debug("Added fallback parent trace info as span attributes");
174
+ }
175
+ catch (error) {
176
+ core_1.logger.debug("Error setting fallback trace attributes:", error);
177
+ }
178
+ }
179
+ }
117
180
  async flush() {
118
181
  if (this.nodeTracerProvider) {
119
182
  await this.nodeTracerProvider.shutdown();
@@ -191,9 +254,24 @@ class TelemetryManager {
191
254
  headers: this.authHeaders,
192
255
  });
193
256
  }
194
- instrumentApp() {
257
+ async instrumentAppAsync() {
195
258
  core_1.logger.debug("Available propagation fields before setup:", api_1.propagation.fields());
259
+ if (this.isLambdaEnvironment) {
260
+ core_1.logger.debug("Lambda environment detected - using enhanced cold start handling");
261
+ }
262
+ // Note: W3C propagator should be auto-registered by NodeTracerProvider
263
+ core_1.logger.debug("Will check propagation after tracer registration...");
196
264
  core_1.telemetryRegistry.registerProvider(new telemetry_provider_1.OtelTelemetryProvider());
265
+ // Set up a basic tracer provider early to enable propagation
266
+ const earlyResource = new BlaxelResource(this.resourceAttributes);
267
+ const earlyTracerProvider = new sdk_trace_node_1.NodeTracerProvider({
268
+ resource: earlyResource,
269
+ sampler: new sdk_trace_node_1.AlwaysOnSampler(),
270
+ });
271
+ earlyTracerProvider.register();
272
+ // Small delay to ensure propagation is ready (especially important for Lambda cold starts)
273
+ await this.sleep(10);
274
+ core_1.logger.debug("Early tracer provider registered, checking propagation:", api_1.propagation.fields());
197
275
  const httpInstrumentation = new instrumentation_http_1.HttpInstrumentation({
198
276
  requireParentforOutgoingSpans: true,
199
277
  requireParentforIncomingSpans: false, // Allow root spans for incoming requests
@@ -237,21 +315,8 @@ class TelemetryManager {
237
315
  core_1.logger.debug("Traceparent contains invalid IDs");
238
316
  }
239
317
  }
240
- // Extract trace context manually to see what should be extracted
241
- const extractedContext = api_1.propagation.extract(api_1.context.active(), headers);
242
- const extractedSpan = api_1.trace.getSpan(extractedContext);
243
- if (extractedSpan) {
244
- const extractedSpanContext = extractedSpan.spanContext();
245
- core_1.logger.debug("Manual context extraction result:", JSON.stringify({
246
- traceId: extractedSpanContext.traceId,
247
- spanId: extractedSpanContext.spanId,
248
- traceFlags: extractedSpanContext.traceFlags,
249
- }));
250
- }
251
- else {
252
- core_1.logger.debug("Manual context extraction failed - no span found");
253
- core_1.logger.debug("Available propagation fields:", api_1.propagation.fields());
254
- }
318
+ // Extract trace context with retry for Lambda cold starts
319
+ void this.retryContextExtraction(headers, span, parts);
255
320
  }
256
321
  catch (error) {
257
322
  core_1.logger.debug("Manual context extraction error:", error);
@@ -290,6 +355,7 @@ class TelemetryManager {
290
355
  this.loggerProvider.addLogRecordProcessor(new sdk_logs_1.BatchLogRecordProcessor(logExporter));
291
356
  api_logs_1.logs.setGlobalLoggerProvider(this.loggerProvider);
292
357
  const traceExporter = this.getTraceExporter();
358
+ // Create a new tracer provider with full configuration
293
359
  this.nodeTracerProvider = new sdk_trace_node_1.NodeTracerProvider({
294
360
  resource,
295
361
  sampler: new sdk_trace_node_1.AlwaysOnSampler(),
@@ -303,6 +369,7 @@ class TelemetryManager {
303
369
  new HasBeenProcessedSpanProcessor(traceExporter),
304
370
  ],
305
371
  });
372
+ // Replace the early tracer provider with the fully configured one
306
373
  this.nodeTracerProvider.register();
307
374
  // Ensure W3C trace context propagation is working
308
375
  core_1.logger.debug("Propagation fields after tracer registration:", api_1.propagation.fields());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blaxel/telemetry",
3
- "version": "0.2.17-dev.118",
3
+ "version": "0.2.17-dev.120",
4
4
  "description": "Blaxel SDK for TypeScript",
5
5
  "license": "MIT",
6
6
  "author": "Blaxel, INC (https://blaxel.ai)",
@@ -71,7 +71,7 @@
71
71
  "@opentelemetry/sdk-trace-base": "^2.0.0",
72
72
  "@opentelemetry/sdk-trace-node": "^2.0.0",
73
73
  "ai": "^4.3.13",
74
- "@blaxel/core": "0.2.17-dev.118"
74
+ "@blaxel/core": "0.2.17-dev.120"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@eslint/js": "^9.26.0",