@blaxel/telemetry 0.2.23-dev.173 → 0.2.23-preview.53
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/index.d.ts +0 -1
- package/dist/index.js +6 -4
- package/dist/json_logger.js +6 -90
- package/dist/legacy_logger.d.ts +8 -0
- package/dist/legacy_logger.js +58 -0
- package/dist/telemetry.d.ts +9 -0
- package/dist/telemetry.js +40 -13
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.blaxelTelemetry =
|
|
3
|
+
exports.blaxelTelemetry = void 0;
|
|
4
4
|
const core_1 = require("@blaxel/core");
|
|
5
5
|
const json_logger_1 = require("./json_logger");
|
|
6
|
+
const legacy_logger_1 = require("./legacy_logger");
|
|
6
7
|
const telemetry_1 = require("./telemetry");
|
|
7
8
|
Object.defineProperty(exports, "blaxelTelemetry", { enumerable: true, get: function () { return telemetry_1.blaxelTelemetry; } });
|
|
8
9
|
telemetry_1.blaxelTelemetry.initialize();
|
|
9
|
-
if (core_1.settings.loggerType === "
|
|
10
|
+
if (core_1.settings.loggerType === "http") {
|
|
11
|
+
(0, legacy_logger_1.setLegacyLogger)();
|
|
12
|
+
}
|
|
13
|
+
else if (core_1.settings.loggerType === "json") {
|
|
10
14
|
(0, json_logger_1.setJsonLogger)();
|
|
11
15
|
}
|
|
12
|
-
var json_logger_2 = require("./json_logger");
|
|
13
|
-
Object.defineProperty(exports, "setJsonLogger", { enumerable: true, get: function () { return json_logger_2.setJsonLogger; } });
|
package/dist/json_logger.js
CHANGED
|
@@ -43,83 +43,16 @@ const taskIndex = core_1.env.BL_TASK_KEY || 'TASK_INDEX';
|
|
|
43
43
|
const taskPrefix = core_1.env.BL_TASK_PREFIX || '';
|
|
44
44
|
const executionKey = core_1.env.BL_EXECUTION_KEY || 'BL_EXECUTION_ID';
|
|
45
45
|
const executionPrefix = core_1.env.BL_EXECUTION_PREFIX || '';
|
|
46
|
-
// Validate environment variables to prevent issues
|
|
47
|
-
function validateEnvVar(value, defaultValue, varName) {
|
|
48
|
-
if (!value || value.trim() === '') {
|
|
49
|
-
exports.originalLogger.warn(`Warning: ${varName} environment variable is empty, using default: ${defaultValue}`);
|
|
50
|
-
return defaultValue;
|
|
51
|
-
}
|
|
52
|
-
return value;
|
|
53
|
-
}
|
|
54
|
-
const validatedLabelsName = validateEnvVar(labelsName, 'labels', 'BL_LOGGER_LABELS');
|
|
55
|
-
// Enhanced error serialization to capture all properties
|
|
56
|
-
function serializeError(error) {
|
|
57
|
-
const serialized = {
|
|
58
|
-
message: error.message,
|
|
59
|
-
name: error.name,
|
|
60
|
-
stack: error.stack
|
|
61
|
-
};
|
|
62
|
-
// Capture any additional properties on the error object
|
|
63
|
-
for (const key of Object.keys(error)) {
|
|
64
|
-
if (!(key in serialized)) {
|
|
65
|
-
try {
|
|
66
|
-
const value = error[key];
|
|
67
|
-
// Avoid circular references by limiting depth
|
|
68
|
-
serialized[key] = typeof value === 'object' ? (0, core_1.stringify)(value, 2) : value;
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
serialized[key] = '[Unserializable]';
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return serialized;
|
|
76
|
-
}
|
|
77
|
-
// Enhanced stringify function with better error handling
|
|
78
|
-
function enhancedStringify(obj, maxDepth = 2) {
|
|
79
|
-
if (obj instanceof Error) {
|
|
80
|
-
return JSON.stringify(serializeError(obj));
|
|
81
|
-
}
|
|
82
|
-
// Handle circular references by using a simple set to track seen objects
|
|
83
|
-
const seen = new WeakSet();
|
|
84
|
-
const stringifyWithCircularCheck = (value, depth = 0) => {
|
|
85
|
-
if (value === null || value === undefined)
|
|
86
|
-
return value;
|
|
87
|
-
if (typeof value !== 'object')
|
|
88
|
-
return value;
|
|
89
|
-
if (seen.has(value)) {
|
|
90
|
-
return '[Circular Reference]';
|
|
91
|
-
}
|
|
92
|
-
if (depth >= maxDepth) {
|
|
93
|
-
return Array.isArray(value) ? '[Array]' : '[Object]';
|
|
94
|
-
}
|
|
95
|
-
seen.add(value);
|
|
96
|
-
if (Array.isArray(value)) {
|
|
97
|
-
return value.map(item => stringifyWithCircularCheck(item, depth + 1));
|
|
98
|
-
}
|
|
99
|
-
const result = {};
|
|
100
|
-
for (const [key, val] of Object.entries(value)) {
|
|
101
|
-
result[key] = stringifyWithCircularCheck(val, depth + 1);
|
|
102
|
-
}
|
|
103
|
-
return result;
|
|
104
|
-
};
|
|
105
|
-
try {
|
|
106
|
-
const processed = stringifyWithCircularCheck(obj);
|
|
107
|
-
return JSON.stringify(processed);
|
|
108
|
-
}
|
|
109
|
-
catch {
|
|
110
|
-
return (0, core_1.stringify)(obj, maxDepth);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
46
|
// Format a log message with appropriate color and prefix
|
|
114
47
|
function formatLogMessage(severity, message, args) {
|
|
115
|
-
const messageStr = typeof message === "string" ? message :
|
|
116
|
-
const argsStr = args.map(arg => typeof arg === "string" ? arg :
|
|
48
|
+
const messageStr = typeof message === "string" ? message : (0, core_1.stringify)(message, 2);
|
|
49
|
+
const argsStr = args.map(arg => typeof arg === "string" ? arg : (0, core_1.stringify)(arg, 2)).join(" ");
|
|
117
50
|
const msg = `${messageStr}${argsStr ? " " + argsStr : ""}`;
|
|
118
51
|
const logEntry = {
|
|
119
52
|
message: msg,
|
|
120
53
|
severity
|
|
121
54
|
};
|
|
122
|
-
logEntry[
|
|
55
|
+
logEntry[labelsName] = {};
|
|
123
56
|
const currentSpan = api_1.trace.getActiveSpan();
|
|
124
57
|
if (currentSpan) {
|
|
125
58
|
const { traceId, spanId } = currentSpan.spanContext();
|
|
@@ -128,28 +61,11 @@ function formatLogMessage(severity, message, args) {
|
|
|
128
61
|
}
|
|
129
62
|
const taskId = core_1.env[taskIndex] || null;
|
|
130
63
|
if (taskId) {
|
|
131
|
-
logEntry[
|
|
64
|
+
logEntry[labelsName]['blaxel-task'] = `${taskPrefix}${taskId}`;
|
|
132
65
|
}
|
|
133
66
|
const executionId = core_1.env[executionKey] || null;
|
|
134
67
|
if (executionId) {
|
|
135
|
-
logEntry[
|
|
136
|
-
}
|
|
137
|
-
try {
|
|
138
|
-
return JSON.stringify(logEntry);
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
// Fallback for serialization errors
|
|
142
|
-
const fallbackEntry = {
|
|
143
|
-
message: `JSON serialization failed: ${msg}`,
|
|
144
|
-
severity,
|
|
145
|
-
error: error instanceof Error ? error.message : String(error)
|
|
146
|
-
};
|
|
147
|
-
try {
|
|
148
|
-
return JSON.stringify(fallbackEntry);
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
// Last resort fallback
|
|
152
|
-
return `{"message":"${severity}: ${msg.replace(/"/g, '\\"')}","severity":"${severity}","error":"Failed to serialize log entry"}`;
|
|
153
|
-
}
|
|
68
|
+
logEntry[labelsName]['blaxel-execution'] = `${executionPrefix}${executionId.split('-').pop()}`;
|
|
154
69
|
}
|
|
70
|
+
return JSON.stringify(logEntry);
|
|
155
71
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function setLegacyLogger(): void;
|
|
2
|
+
export declare const originalLogger: {
|
|
3
|
+
info: (message?: any, ...optionalParams: any[]) => void;
|
|
4
|
+
error: (message?: any, ...optionalParams: any[]) => void;
|
|
5
|
+
warn: (message?: any, ...optionalParams: any[]) => void;
|
|
6
|
+
debug: (message?: any, ...optionalParams: any[]) => void;
|
|
7
|
+
log: (message?: any, ...optionalParams: any[]) => void;
|
|
8
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.originalLogger = void 0;
|
|
4
|
+
exports.setLegacyLogger = setLegacyLogger;
|
|
5
|
+
/* eslint-disable no-console */
|
|
6
|
+
const core_1 = require("@blaxel/core");
|
|
7
|
+
const api_logs_1 = require("@opentelemetry/api-logs");
|
|
8
|
+
const telemetry_1 = require("./telemetry");
|
|
9
|
+
function setLegacyLogger() {
|
|
10
|
+
console.debug = (message, ...args) => {
|
|
11
|
+
const msg = formatLogMessage(message, args);
|
|
12
|
+
exports.originalLogger.log(msg);
|
|
13
|
+
emitLogSync(api_logs_1.SeverityNumber.DEBUG, msg);
|
|
14
|
+
};
|
|
15
|
+
console.log = (message, ...args) => {
|
|
16
|
+
const msg = formatLogMessage(message, args);
|
|
17
|
+
exports.originalLogger.log(msg);
|
|
18
|
+
emitLogSync(api_logs_1.SeverityNumber.INFO, msg);
|
|
19
|
+
};
|
|
20
|
+
console.info = (message, ...args) => {
|
|
21
|
+
const msg = formatLogMessage(message, args);
|
|
22
|
+
exports.originalLogger.log(msg);
|
|
23
|
+
emitLogSync(api_logs_1.SeverityNumber.INFO, msg);
|
|
24
|
+
};
|
|
25
|
+
console.error = (message, ...args) => {
|
|
26
|
+
const msg = formatLogMessage(message, args);
|
|
27
|
+
exports.originalLogger.log(msg);
|
|
28
|
+
emitLogSync(api_logs_1.SeverityNumber.ERROR, msg);
|
|
29
|
+
};
|
|
30
|
+
console.warn = (message, ...args) => {
|
|
31
|
+
const msg = formatLogMessage(message, args);
|
|
32
|
+
exports.originalLogger.log(msg);
|
|
33
|
+
emitLogSync(api_logs_1.SeverityNumber.WARN, msg);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
exports.originalLogger = {
|
|
37
|
+
info: console.info,
|
|
38
|
+
error: console.error,
|
|
39
|
+
warn: console.warn,
|
|
40
|
+
debug: console.debug,
|
|
41
|
+
log: console.log,
|
|
42
|
+
};
|
|
43
|
+
// Format a log message with appropriate color and prefix
|
|
44
|
+
function formatLogMessage(message, args) {
|
|
45
|
+
const messageStr = typeof message === "string" ? message : (0, core_1.stringify)(message, 2);
|
|
46
|
+
const argsStr = args.map(arg => typeof arg === "string" ? arg : (0, core_1.stringify)(arg, 2)).join(" ");
|
|
47
|
+
return `${messageStr}${argsStr ? " " + argsStr : ""}`;
|
|
48
|
+
}
|
|
49
|
+
async function emitLog(severityNumber, message) {
|
|
50
|
+
const loggerInstance = await telemetry_1.blaxelTelemetry.getLogger();
|
|
51
|
+
loggerInstance.emit({
|
|
52
|
+
severityNumber: severityNumber,
|
|
53
|
+
body: message,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function emitLogSync(severityNumber, message) {
|
|
57
|
+
emitLog(severityNumber, message).catch(() => { });
|
|
58
|
+
}
|
package/dist/telemetry.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Span } from "@opentelemetry/api";
|
|
2
|
+
import { Logger } from "@opentelemetry/api-logs";
|
|
3
|
+
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
2
4
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
3
5
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
4
6
|
import { RawResourceAttribute, Resource } from "@opentelemetry/resources";
|
|
@@ -26,6 +28,8 @@ export type TelemetryOptions = {
|
|
|
26
28
|
declare class TelemetryManager {
|
|
27
29
|
private nodeTracerProvider;
|
|
28
30
|
private meterProvider;
|
|
31
|
+
private loggerProvider;
|
|
32
|
+
private otelLogger;
|
|
29
33
|
private initialized;
|
|
30
34
|
private configured;
|
|
31
35
|
constructor();
|
|
@@ -36,6 +40,7 @@ declare class TelemetryManager {
|
|
|
36
40
|
get authHeaders(): Record<string, string>;
|
|
37
41
|
sleep(ms: number): Promise<unknown>;
|
|
38
42
|
flush(): Promise<void>;
|
|
43
|
+
getLogger(): Promise<Logger>;
|
|
39
44
|
setupSignalHandler(): void;
|
|
40
45
|
/**
|
|
41
46
|
* Get resource attributes for OpenTelemetry.
|
|
@@ -49,6 +54,10 @@ declare class TelemetryManager {
|
|
|
49
54
|
* Initialize and return the OTLP Trace Exporter.
|
|
50
55
|
*/
|
|
51
56
|
getTraceExporter(): OTLPTraceExporter;
|
|
57
|
+
/**
|
|
58
|
+
* Initialize and return the OTLP Log Exporter.
|
|
59
|
+
*/
|
|
60
|
+
getLogExporter(): OTLPLogExporter;
|
|
52
61
|
instrumentApp(): void;
|
|
53
62
|
setExporters(): void;
|
|
54
63
|
shutdownApp(): Promise<void>;
|
package/dist/telemetry.js
CHANGED
|
@@ -3,11 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.blaxelTelemetry = exports.DefaultAttributesSpanProcessor = exports.BlaxelResource = void 0;
|
|
4
4
|
const core_1 = require("@blaxel/core");
|
|
5
5
|
const api_1 = require("@opentelemetry/api");
|
|
6
|
+
const api_logs_1 = require("@opentelemetry/api-logs");
|
|
7
|
+
const exporter_logs_otlp_http_1 = require("@opentelemetry/exporter-logs-otlp-http");
|
|
6
8
|
const exporter_metrics_otlp_http_1 = require("@opentelemetry/exporter-metrics-otlp-http");
|
|
7
9
|
const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
|
|
8
10
|
const instrumentation_1 = require("@opentelemetry/instrumentation");
|
|
9
11
|
const instrumentation_http_1 = require("@opentelemetry/instrumentation-http");
|
|
10
12
|
const resources_1 = require("@opentelemetry/resources");
|
|
13
|
+
const sdk_logs_1 = require("@opentelemetry/sdk-logs");
|
|
11
14
|
const sdk_metrics_1 = require("@opentelemetry/sdk-metrics");
|
|
12
15
|
const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
|
|
13
16
|
const telemetry_provider_1 = require("./telemetry_provider");
|
|
@@ -51,9 +54,6 @@ class DefaultAttributesSpanProcessor {
|
|
|
51
54
|
}
|
|
52
55
|
exports.DefaultAttributesSpanProcessor = DefaultAttributesSpanProcessor;
|
|
53
56
|
class HasBeenProcessedSpanProcessor extends sdk_trace_node_1.BatchSpanProcessor {
|
|
54
|
-
constructor(exporter, config) {
|
|
55
|
-
super(exporter, config);
|
|
56
|
-
}
|
|
57
57
|
onEnd(span) {
|
|
58
58
|
super.onEnd(span);
|
|
59
59
|
}
|
|
@@ -61,11 +61,15 @@ class HasBeenProcessedSpanProcessor extends sdk_trace_node_1.BatchSpanProcessor
|
|
|
61
61
|
class TelemetryManager {
|
|
62
62
|
nodeTracerProvider;
|
|
63
63
|
meterProvider;
|
|
64
|
+
loggerProvider;
|
|
65
|
+
otelLogger;
|
|
64
66
|
initialized;
|
|
65
67
|
configured;
|
|
66
68
|
constructor() {
|
|
67
69
|
this.nodeTracerProvider = null;
|
|
68
70
|
this.meterProvider = null;
|
|
71
|
+
this.loggerProvider = null;
|
|
72
|
+
this.otelLogger = null;
|
|
69
73
|
this.initialized = false;
|
|
70
74
|
this.configured = false;
|
|
71
75
|
}
|
|
@@ -87,6 +91,7 @@ class TelemetryManager {
|
|
|
87
91
|
}
|
|
88
92
|
await (0, core_1.authenticate)();
|
|
89
93
|
this.setExporters();
|
|
94
|
+
this.otelLogger = api_logs_1.logs.getLogger("blaxel");
|
|
90
95
|
core_1.logger.debug("Telemetry ready");
|
|
91
96
|
this.configured = true;
|
|
92
97
|
}
|
|
@@ -116,6 +121,16 @@ class TelemetryManager {
|
|
|
116
121
|
if (this.meterProvider) {
|
|
117
122
|
await this.meterProvider.shutdown();
|
|
118
123
|
}
|
|
124
|
+
if (this.loggerProvider) {
|
|
125
|
+
await this.loggerProvider.shutdown();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async getLogger() {
|
|
129
|
+
if (!this.otelLogger) {
|
|
130
|
+
await this.sleep(100);
|
|
131
|
+
return this.getLogger();
|
|
132
|
+
}
|
|
133
|
+
return this.otelLogger;
|
|
119
134
|
}
|
|
120
135
|
setupSignalHandler() {
|
|
121
136
|
const signals = ["SIGINT", "SIGTERM", "uncaughtException", "exit"];
|
|
@@ -168,6 +183,14 @@ class TelemetryManager {
|
|
|
168
183
|
headers: this.authHeaders,
|
|
169
184
|
});
|
|
170
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Initialize and return the OTLP Log Exporter.
|
|
188
|
+
*/
|
|
189
|
+
getLogExporter() {
|
|
190
|
+
return new exporter_logs_otlp_http_1.OTLPLogExporter({
|
|
191
|
+
headers: this.authHeaders,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
171
194
|
instrumentApp() {
|
|
172
195
|
core_1.telemetryRegistry.registerProvider(new telemetry_provider_1.OtelTelemetryProvider());
|
|
173
196
|
const httpInstrumentation = new instrumentation_http_1.HttpInstrumentation({
|
|
@@ -179,13 +202,12 @@ class TelemetryManager {
|
|
|
179
202
|
}
|
|
180
203
|
setExporters() {
|
|
181
204
|
const resource = new BlaxelResource(this.resourceAttributes);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
};
|
|
205
|
+
const logExporter = this.getLogExporter();
|
|
206
|
+
this.loggerProvider = new sdk_logs_1.LoggerProvider({
|
|
207
|
+
resource,
|
|
208
|
+
});
|
|
209
|
+
this.loggerProvider.addLogRecordProcessor(new sdk_logs_1.BatchLogRecordProcessor(logExporter));
|
|
210
|
+
api_logs_1.logs.setGlobalLoggerProvider(this.loggerProvider);
|
|
189
211
|
const traceExporter = this.getTraceExporter();
|
|
190
212
|
this.nodeTracerProvider = new sdk_trace_node_1.NodeTracerProvider({
|
|
191
213
|
resource,
|
|
@@ -196,8 +218,8 @@ class TelemetryManager {
|
|
|
196
218
|
"workload.type": core_1.settings.type ? core_1.settings.type + "s" : "",
|
|
197
219
|
workspace: core_1.settings.workspace || "",
|
|
198
220
|
}),
|
|
199
|
-
new sdk_trace_node_1.BatchSpanProcessor(traceExporter
|
|
200
|
-
new HasBeenProcessedSpanProcessor(traceExporter
|
|
221
|
+
new sdk_trace_node_1.BatchSpanProcessor(traceExporter),
|
|
222
|
+
new HasBeenProcessedSpanProcessor(traceExporter),
|
|
201
223
|
],
|
|
202
224
|
});
|
|
203
225
|
this.nodeTracerProvider.register();
|
|
@@ -207,7 +229,7 @@ class TelemetryManager {
|
|
|
207
229
|
readers: [
|
|
208
230
|
new sdk_metrics_1.PeriodicExportingMetricReader({
|
|
209
231
|
exporter: metricExporter,
|
|
210
|
-
exportIntervalMillis:
|
|
232
|
+
exportIntervalMillis: 60000,
|
|
211
233
|
}),
|
|
212
234
|
],
|
|
213
235
|
});
|
|
@@ -231,6 +253,11 @@ class TelemetryManager {
|
|
|
231
253
|
.shutdown()
|
|
232
254
|
.catch((error) => core_1.logger.debug("Error shutting down meter provider:", error)));
|
|
233
255
|
}
|
|
256
|
+
if (this.loggerProvider) {
|
|
257
|
+
shutdownPromises.push(this.loggerProvider
|
|
258
|
+
.shutdown()
|
|
259
|
+
.catch((error) => core_1.logger.debug("Error shutting down logger provider:", error)));
|
|
260
|
+
}
|
|
234
261
|
// Wait for all providers to shutdown with a timeout
|
|
235
262
|
await Promise.race([
|
|
236
263
|
Promise.all(shutdownPromises),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blaxel/telemetry",
|
|
3
|
-
"version": "0.2.23-
|
|
3
|
+
"version": "0.2.23-preview.53",
|
|
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.23-
|
|
74
|
+
"@blaxel/core": "0.2.23-preview.53"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@eslint/js": "^9.26.0",
|