@blaxel/telemetry 0.2.17-dev.119 → 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,8 +60,7 @@ declare class TelemetryManager {
58
60
  * Initialize and return the OTLP Log Exporter.
59
61
  */
60
62
  getLogExporter(): OTLPLogExporter;
61
- setupTracerProvider(): void;
62
- instrumentApp(): void;
63
+ instrumentAppAsync(): Promise<void>;
63
64
  setExporters(): void;
64
65
  shutdownApp(): Promise<void>;
65
66
  }
package/dist/telemetry.js CHANGED
@@ -13,9 +13,6 @@ const resources_1 = require("@opentelemetry/resources");
13
13
  const sdk_logs_1 = require("@opentelemetry/sdk-logs");
14
14
  const sdk_metrics_1 = require("@opentelemetry/sdk-metrics");
15
15
  const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
16
- // W3CTraceContextPropagator import - trying different paths
17
- // import { W3CTraceContextPropagator } from "@opentelemetry/core";
18
- // import { W3CTraceContextPropagator } from "@opentelemetry/sdk-trace-base";
19
16
  const telemetry_provider_1 = require("./telemetry_provider");
20
17
  class BlaxelResource {
21
18
  attributes;
@@ -81,7 +78,9 @@ class TelemetryManager {
81
78
  if (!this.enabled || this.initialized) {
82
79
  return;
83
80
  }
84
- this.instrumentApp();
81
+ this.instrumentAppAsync().catch((error) => {
82
+ core_1.logger.error("Error during async instrumentation setup:", error);
83
+ });
85
84
  this.setupSignalHandler();
86
85
  this.initialized = true;
87
86
  this.setConfiguration().catch((error) => {
@@ -104,6 +103,9 @@ class TelemetryManager {
104
103
  get enabled() {
105
104
  return core_1.env.BL_ENABLE_OPENTELEMETRY === "true";
106
105
  }
106
+ get isLambdaEnvironment() {
107
+ return !!(process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.LAMBDA_TASK_ROOT);
108
+ }
107
109
  get authHeaders() {
108
110
  const headers = {};
109
111
  if (core_1.settings.authorization) {
@@ -117,6 +119,64 @@ class TelemetryManager {
117
119
  async sleep(ms) {
118
120
  return new Promise((resolve) => setTimeout(resolve, ms));
119
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
+ }
120
180
  async flush() {
121
181
  if (this.nodeTracerProvider) {
122
182
  await this.nodeTracerProvider.shutdown();
@@ -194,23 +254,24 @@ class TelemetryManager {
194
254
  headers: this.authHeaders,
195
255
  });
196
256
  }
197
- setupTracerProvider() {
198
- if (this.nodeTracerProvider) {
199
- return; // Already set up
257
+ async instrumentAppAsync() {
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");
200
261
  }
201
- const resource = new BlaxelResource(this.resourceAttributes);
202
- this.nodeTracerProvider = new sdk_trace_node_1.NodeTracerProvider({
203
- resource,
262
+ // Note: W3C propagator should be auto-registered by NodeTracerProvider
263
+ core_1.logger.debug("Will check propagation after tracer registration...");
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,
204
269
  sampler: new sdk_trace_node_1.AlwaysOnSampler(),
205
270
  });
206
- this.nodeTracerProvider.register();
207
- core_1.logger.debug("NodeTracerProvider registered early - propagation fields:", api_1.propagation.fields());
208
- }
209
- instrumentApp() {
210
- core_1.logger.debug("Available propagation fields before setup:", api_1.propagation.fields());
211
- // Set up tracer provider FIRST before instrumentation
212
- this.setupTracerProvider();
213
- core_1.telemetryRegistry.registerProvider(new telemetry_provider_1.OtelTelemetryProvider());
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());
214
275
  const httpInstrumentation = new instrumentation_http_1.HttpInstrumentation({
215
276
  requireParentforOutgoingSpans: true,
216
277
  requireParentforIncomingSpans: false, // Allow root spans for incoming requests
@@ -254,21 +315,8 @@ class TelemetryManager {
254
315
  core_1.logger.debug("Traceparent contains invalid IDs");
255
316
  }
256
317
  }
257
- // Extract trace context manually to see what should be extracted
258
- const extractedContext = api_1.propagation.extract(api_1.context.active(), headers);
259
- const extractedSpan = api_1.trace.getSpan(extractedContext);
260
- if (extractedSpan) {
261
- const extractedSpanContext = extractedSpan.spanContext();
262
- core_1.logger.debug("Manual context extraction result:", JSON.stringify({
263
- traceId: extractedSpanContext.traceId,
264
- spanId: extractedSpanContext.spanId,
265
- traceFlags: extractedSpanContext.traceFlags,
266
- }));
267
- }
268
- else {
269
- core_1.logger.debug("Manual context extraction failed - no span found");
270
- core_1.logger.debug("Available propagation fields:", api_1.propagation.fields());
271
- }
318
+ // Extract trace context with retry for Lambda cold starts
319
+ void this.retryContextExtraction(headers, span, parts);
272
320
  }
273
321
  catch (error) {
274
322
  core_1.logger.debug("Manual context extraction error:", error);
@@ -307,23 +355,22 @@ class TelemetryManager {
307
355
  this.loggerProvider.addLogRecordProcessor(new sdk_logs_1.BatchLogRecordProcessor(logExporter));
308
356
  api_logs_1.logs.setGlobalLoggerProvider(this.loggerProvider);
309
357
  const traceExporter = this.getTraceExporter();
310
- if (!this.nodeTracerProvider) {
311
- // Create tracer provider if not already created
312
- this.nodeTracerProvider = new sdk_trace_node_1.NodeTracerProvider({
313
- resource,
314
- sampler: new sdk_trace_node_1.AlwaysOnSampler(),
315
- spanProcessors: [
316
- new DefaultAttributesSpanProcessor({
317
- "workload.id": core_1.settings.name || "",
318
- "workload.type": core_1.settings.type ? core_1.settings.type + "s" : "",
319
- workspace: core_1.settings.workspace || "",
320
- }),
321
- new sdk_trace_node_1.BatchSpanProcessor(traceExporter),
322
- new HasBeenProcessedSpanProcessor(traceExporter),
323
- ],
324
- });
325
- this.nodeTracerProvider.register();
326
- }
358
+ // Create a new tracer provider with full configuration
359
+ this.nodeTracerProvider = new sdk_trace_node_1.NodeTracerProvider({
360
+ resource,
361
+ sampler: new sdk_trace_node_1.AlwaysOnSampler(),
362
+ spanProcessors: [
363
+ new DefaultAttributesSpanProcessor({
364
+ "workload.id": core_1.settings.name || "",
365
+ "workload.type": core_1.settings.type ? core_1.settings.type + "s" : "",
366
+ workspace: core_1.settings.workspace || "",
367
+ }),
368
+ new sdk_trace_node_1.BatchSpanProcessor(traceExporter),
369
+ new HasBeenProcessedSpanProcessor(traceExporter),
370
+ ],
371
+ });
372
+ // Replace the early tracer provider with the fully configured one
373
+ this.nodeTracerProvider.register();
327
374
  // Ensure W3C trace context propagation is working
328
375
  core_1.logger.debug("Propagation fields after tracer registration:", api_1.propagation.fields());
329
376
  const metricExporter = this.getMetricExporter();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blaxel/telemetry",
3
- "version": "0.2.17-dev.119",
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.119"
74
+ "@blaxel/core": "0.2.17-dev.120"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@eslint/js": "^9.26.0",