@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.
- package/dist/telemetry.d.ts +3 -2
- package/dist/telemetry.js +97 -50
- 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,8 +60,7 @@ declare class TelemetryManager {
|
|
|
58
60
|
* Initialize and return the OTLP Log Exporter.
|
|
59
61
|
*/
|
|
60
62
|
getLogExporter(): OTLPLogExporter;
|
|
61
|
-
|
|
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.
|
|
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
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
|
258
|
-
|
|
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
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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.
|
|
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",
|