@blaxel/telemetry 0.2.18-dev.142 → 0.2.18-dev.146
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 +0 -1
- package/dist/telemetry.js +1 -49
- package/dist/telemetry_provider.d.ts +5 -0
- package/dist/telemetry_provider.js +113 -26
- package/package.json +2 -2
package/dist/telemetry.d.ts
CHANGED
package/dist/telemetry.js
CHANGED
|
@@ -192,67 +192,22 @@ class TelemetryManager {
|
|
|
192
192
|
});
|
|
193
193
|
}
|
|
194
194
|
instrumentApp() {
|
|
195
|
-
// Setup telemetry provider first
|
|
196
195
|
core_1.telemetryRegistry.registerProvider(new telemetry_provider_1.OtelTelemetryProvider());
|
|
197
|
-
// Setup TracerProvider and other providers BEFORE instrumentation
|
|
198
|
-
this.setupProviders();
|
|
199
196
|
const httpInstrumentation = new instrumentation_http_1.HttpInstrumentation({
|
|
200
|
-
requireParentforOutgoingSpans:
|
|
201
|
-
requestHook: (span) => {
|
|
202
|
-
// Debug incoming trace headers
|
|
203
|
-
console.log("=== HTTP INSTRUMENTATION REQUEST HOOK ===");
|
|
204
|
-
// Check current span context after HTTP instrumentation processes headers
|
|
205
|
-
const activeSpan = api_1.trace.getActiveSpan();
|
|
206
|
-
if (activeSpan) {
|
|
207
|
-
console.log("Active span in request hook:", {
|
|
208
|
-
traceId: activeSpan.spanContext().traceId,
|
|
209
|
-
spanId: activeSpan.spanContext().spanId,
|
|
210
|
-
traceFlags: activeSpan.spanContext().traceFlags,
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
console.log("No active span found in request hook");
|
|
215
|
-
}
|
|
216
|
-
console.log("Current span from hook parameter:", {
|
|
217
|
-
traceId: span.spanContext().traceId,
|
|
218
|
-
spanId: span.spanContext().spanId,
|
|
219
|
-
traceFlags: span.spanContext().traceFlags,
|
|
220
|
-
});
|
|
221
|
-
console.log("=== END HTTP INSTRUMENTATION REQUEST HOOK ===");
|
|
222
|
-
},
|
|
197
|
+
requireParentforOutgoingSpans: true,
|
|
223
198
|
});
|
|
224
199
|
(0, instrumentation_1.registerInstrumentations)({
|
|
225
200
|
instrumentations: [httpInstrumentation],
|
|
226
201
|
});
|
|
227
202
|
}
|
|
228
|
-
setupProviders() {
|
|
229
|
-
const resource = new BlaxelResource(this.resourceAttributes);
|
|
230
|
-
// Setup TracerProvider first - this is critical for context propagation
|
|
231
|
-
this.nodeTracerProvider = new sdk_trace_node_1.NodeTracerProvider({
|
|
232
|
-
resource,
|
|
233
|
-
sampler: new sdk_trace_node_1.AlwaysOnSampler(),
|
|
234
|
-
spanProcessors: [
|
|
235
|
-
new DefaultAttributesSpanProcessor({
|
|
236
|
-
"workload.id": core_1.settings.name || "",
|
|
237
|
-
"workload.type": core_1.settings.type ? core_1.settings.type + "s" : "",
|
|
238
|
-
workspace: core_1.settings.workspace || "",
|
|
239
|
-
}),
|
|
240
|
-
],
|
|
241
|
-
});
|
|
242
|
-
// Register the tracer provider BEFORE any instrumentation
|
|
243
|
-
this.nodeTracerProvider.register();
|
|
244
|
-
console.log("TracerProvider registered - ready for context propagation");
|
|
245
|
-
}
|
|
246
203
|
setExporters() {
|
|
247
204
|
const resource = new BlaxelResource(this.resourceAttributes);
|
|
248
|
-
// Setup logging
|
|
249
205
|
const logExporter = this.getLogExporter();
|
|
250
206
|
this.loggerProvider = new sdk_logs_1.LoggerProvider({
|
|
251
207
|
resource,
|
|
252
208
|
});
|
|
253
209
|
this.loggerProvider.addLogRecordProcessor(new sdk_logs_1.BatchLogRecordProcessor(logExporter));
|
|
254
210
|
api_logs_1.logs.setGlobalLoggerProvider(this.loggerProvider);
|
|
255
|
-
// Recreate TracerProvider with exporters - this ensures proper initialization
|
|
256
211
|
const traceExporter = this.getTraceExporter();
|
|
257
212
|
this.nodeTracerProvider = new sdk_trace_node_1.NodeTracerProvider({
|
|
258
213
|
resource,
|
|
@@ -267,10 +222,7 @@ class TelemetryManager {
|
|
|
267
222
|
new HasBeenProcessedSpanProcessor(traceExporter),
|
|
268
223
|
],
|
|
269
224
|
});
|
|
270
|
-
// Re-register the tracer provider with exporters
|
|
271
225
|
this.nodeTracerProvider.register();
|
|
272
|
-
console.log("TracerProvider re-registered with exporters");
|
|
273
|
-
// Setup metrics
|
|
274
226
|
const metricExporter = this.getMetricExporter();
|
|
275
227
|
this.meterProvider = new sdk_metrics_1.MeterProvider({
|
|
276
228
|
resource,
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { BlaxelSpan, BlaxelSpanOptions, BlaxelTelemetryProvider } from "@blaxel/core";
|
|
2
2
|
export declare class OtelTelemetryProvider implements BlaxelTelemetryProvider {
|
|
3
3
|
startSpan(name: string, options?: BlaxelSpanOptions): BlaxelSpan;
|
|
4
|
+
/**
|
|
5
|
+
* Extract context from headers manually
|
|
6
|
+
* This can be used when automatic context propagation isn't working
|
|
7
|
+
*/
|
|
8
|
+
extractContextFromHeaders(headers: Record<string, string | string[]>): unknown;
|
|
4
9
|
flush(): Promise<void>;
|
|
5
10
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OtelTelemetryProvider = void 0;
|
|
4
|
+
const core_1 = require("@blaxel/core");
|
|
4
5
|
const api_1 = require("@opentelemetry/api");
|
|
5
6
|
const telemetry_1 = require("./telemetry");
|
|
6
7
|
class OtelSpan {
|
|
7
8
|
span;
|
|
8
|
-
closed = false;
|
|
9
9
|
constructor(span) {
|
|
10
10
|
this.span = span;
|
|
11
11
|
}
|
|
@@ -26,7 +26,6 @@ class OtelSpan {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
end() {
|
|
29
|
-
this.closed = true;
|
|
30
29
|
this.span.end();
|
|
31
30
|
}
|
|
32
31
|
getContext() {
|
|
@@ -35,39 +34,127 @@ class OtelSpan {
|
|
|
35
34
|
}
|
|
36
35
|
class OtelTelemetryProvider {
|
|
37
36
|
startSpan(name, options) {
|
|
37
|
+
// Use the tracer from the registered NodeTracerProvider
|
|
38
38
|
const tracer = api_1.trace.getTracer("blaxel");
|
|
39
|
-
// Get the current active context
|
|
40
|
-
|
|
39
|
+
// Get the current active context
|
|
40
|
+
let ctx = api_1.context.active();
|
|
41
41
|
const activeSpan = api_1.trace.getActiveSpan();
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
42
|
+
// Log context information for debugging
|
|
43
|
+
if (activeSpan) {
|
|
44
|
+
const spanContext = activeSpan.spanContext();
|
|
45
|
+
core_1.logger.debug("Creating span with active parent context", {
|
|
46
|
+
spanName: name,
|
|
47
|
+
parentTraceId: spanContext.traceId,
|
|
48
|
+
parentSpanId: spanContext.spanId,
|
|
49
|
+
isRoot: options?.isRoot,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
core_1.logger.debug("Creating span without active parent context", {
|
|
54
|
+
spanName: name,
|
|
55
|
+
isRoot: options?.isRoot,
|
|
56
|
+
contextProvided: !!options?.parentContext,
|
|
57
|
+
});
|
|
58
|
+
// Try to extract context from headers if available in the environment
|
|
59
|
+
// This is a fallback when HttpInstrumentation doesn't set the context properly
|
|
60
|
+
if (typeof globalThis !== "undefined" && globalThis.process?.env) {
|
|
61
|
+
const headers = {};
|
|
62
|
+
// Check if there are any trace headers in the environment
|
|
63
|
+
if (process.env.TRACEPARENT) {
|
|
64
|
+
headers["traceparent"] = process.env.TRACEPARENT;
|
|
65
|
+
}
|
|
66
|
+
if (process.env.TRACESTATE) {
|
|
67
|
+
headers["tracestate"] = process.env.TRACESTATE;
|
|
68
|
+
}
|
|
69
|
+
if (headers.traceparent) {
|
|
70
|
+
core_1.logger.debug("Found traceparent in environment, attempting to extract context", {
|
|
71
|
+
traceparent: headers.traceparent,
|
|
72
|
+
tracestate: headers.tracestate,
|
|
73
|
+
});
|
|
74
|
+
try {
|
|
75
|
+
const extractedContext = api_1.propagation.extract(api_1.context.active(), headers);
|
|
76
|
+
const extractedSpan = api_1.trace.getSpan(extractedContext);
|
|
77
|
+
if (extractedSpan) {
|
|
78
|
+
ctx = extractedContext;
|
|
79
|
+
core_1.logger.debug("Successfully extracted context from traceparent", {
|
|
80
|
+
extractedTraceId: extractedSpan.spanContext().traceId,
|
|
81
|
+
extractedSpanId: extractedSpan.spanContext().spanId,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
core_1.logger.debug("Failed to extract context from traceparent", {
|
|
87
|
+
error: error instanceof Error ? error.message : String(error),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
50
91
|
}
|
|
51
|
-
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
spanId: spanContext.spanId,
|
|
58
|
-
traceFlags: spanContext.traceFlags,
|
|
92
|
+
}
|
|
93
|
+
// Handle parent context if provided
|
|
94
|
+
if (options?.parentContext) {
|
|
95
|
+
ctx = options.parentContext;
|
|
96
|
+
core_1.logger.debug("Using provided parent context for span", {
|
|
97
|
+
spanName: name,
|
|
59
98
|
});
|
|
60
99
|
}
|
|
100
|
+
// Prepare OpenTelemetry span options
|
|
61
101
|
const otelOptions = {
|
|
62
102
|
attributes: options?.attributes,
|
|
63
103
|
root: options?.isRoot,
|
|
64
104
|
};
|
|
65
|
-
//
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
105
|
+
// Start the span
|
|
106
|
+
const span = tracer.startSpan(name, otelOptions, ctx);
|
|
107
|
+
const spanContext = span.spanContext();
|
|
108
|
+
core_1.logger.debug("Span created successfully", {
|
|
109
|
+
spanName: name,
|
|
110
|
+
traceId: spanContext.traceId,
|
|
111
|
+
spanId: spanContext.spanId,
|
|
112
|
+
isRoot: options?.isRoot,
|
|
113
|
+
});
|
|
114
|
+
return new OtelSpan(span);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Extract context from headers manually
|
|
118
|
+
* This can be used when automatic context propagation isn't working
|
|
119
|
+
*/
|
|
120
|
+
extractContextFromHeaders(headers) {
|
|
121
|
+
try {
|
|
122
|
+
// Normalize headers to string values
|
|
123
|
+
const normalizedHeaders = {};
|
|
124
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
125
|
+
if (Array.isArray(value)) {
|
|
126
|
+
normalizedHeaders[key.toLowerCase()] = value[0] || "";
|
|
127
|
+
}
|
|
128
|
+
else if (typeof value === "string") {
|
|
129
|
+
normalizedHeaders[key.toLowerCase()] = value;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
core_1.logger.debug("Attempting to extract context from headers", {
|
|
133
|
+
headers: Object.keys(normalizedHeaders),
|
|
134
|
+
traceparent: normalizedHeaders.traceparent,
|
|
135
|
+
tracestate: normalizedHeaders.tracestate,
|
|
136
|
+
});
|
|
137
|
+
const extractedContext = api_1.propagation.extract(api_1.context.active(), normalizedHeaders);
|
|
138
|
+
const extractedSpan = api_1.trace.getSpan(extractedContext);
|
|
139
|
+
if (extractedSpan) {
|
|
140
|
+
const spanContext = extractedSpan.spanContext();
|
|
141
|
+
core_1.logger.debug("Successfully extracted context from headers", {
|
|
142
|
+
traceId: spanContext.traceId,
|
|
143
|
+
spanId: spanContext.spanId,
|
|
144
|
+
});
|
|
145
|
+
return extractedContext;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
core_1.logger.debug("No span found in extracted context");
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
core_1.logger.debug("Failed to extract context from headers", {
|
|
154
|
+
error: error instanceof Error ? error.message : String(error),
|
|
155
|
+
});
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
71
158
|
}
|
|
72
159
|
async flush() {
|
|
73
160
|
await telemetry_1.blaxelTelemetry.flush();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blaxel/telemetry",
|
|
3
|
-
"version": "0.2.18-dev.
|
|
3
|
+
"version": "0.2.18-dev.146",
|
|
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.18-dev.
|
|
74
|
+
"@blaxel/core": "0.2.18-dev.146"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@eslint/js": "^9.26.0",
|