@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.
- package/dist/telemetry.d.ts +3 -1
- package/dist/telemetry.js +84 -17
- package/package.json +2 -2
package/dist/telemetry.d.ts
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
241
|
-
|
|
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.
|
|
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.
|
|
74
|
+
"@blaxel/core": "0.2.17-dev.120"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@eslint/js": "^9.26.0",
|