@probelabs/probe 0.6.0-rc147 → 0.6.0-rc148
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/bin/binaries/probe-v0.6.0-rc148-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc148-aarch64-unknown-linux-gnu.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc148-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc148-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc148-x86_64-unknown-linux-gnu.tar.gz +0 -0
- package/bin/probe +12 -3
- package/build/agent/index.js +18 -404
- package/build/index.js +1 -7
- package/cjs/agent/ProbeAgent.cjs +659 -697
- package/cjs/index.cjs +610 -1274
- package/package.json +1 -12
- package/src/index.js +1 -7
- package/bin/binaries/probe-v0.6.0-rc147-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc147-aarch64-unknown-linux-gnu.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc147-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc147-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc147-x86_64-unknown-linux-gnu.tar.gz +0 -0
- package/build/agent/appTracer.js +0 -360
- package/build/agent/fileSpanExporter.js +0 -167
- package/build/agent/telemetry.js +0 -219
- package/cjs/agent/telemetry.cjs +0 -358
- package/src/agent/appTracer.js +0 -360
- package/src/agent/fileSpanExporter.js +0 -167
- package/src/agent/telemetry.js +0 -219
package/build/agent/telemetry.js
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
2
|
-
import { resourceFromAttributes } from '@opentelemetry/resources';
|
|
3
|
-
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
|
|
4
|
-
import { trace, context, SpanStatusCode } from '@opentelemetry/api';
|
|
5
|
-
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
6
|
-
import { BatchSpanProcessor, ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
7
|
-
|
|
8
|
-
import { existsSync, mkdirSync } from 'fs';
|
|
9
|
-
import { dirname } from 'path';
|
|
10
|
-
import { FileSpanExporter } from './fileSpanExporter.js';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Custom OpenTelemetry configuration for probe-agent
|
|
14
|
-
*/
|
|
15
|
-
export class TelemetryConfig {
|
|
16
|
-
constructor(options = {}) {
|
|
17
|
-
this.serviceName = options.serviceName || 'probe-agent';
|
|
18
|
-
this.serviceVersion = options.serviceVersion || '1.0.0';
|
|
19
|
-
this.enableFile = options.enableFile || false;
|
|
20
|
-
this.enableRemote = options.enableRemote || false;
|
|
21
|
-
this.enableConsole = options.enableConsole || false;
|
|
22
|
-
this.filePath = options.filePath || './traces.jsonl';
|
|
23
|
-
this.remoteEndpoint = options.remoteEndpoint || 'http://localhost:4318/v1/traces';
|
|
24
|
-
this.sdk = null;
|
|
25
|
-
this.tracer = null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Initialize OpenTelemetry SDK
|
|
30
|
-
*/
|
|
31
|
-
initialize() {
|
|
32
|
-
if (this.sdk) {
|
|
33
|
-
console.warn('Telemetry already initialized');
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const resource = resourceFromAttributes({
|
|
38
|
-
[ATTR_SERVICE_NAME]: this.serviceName,
|
|
39
|
-
[ATTR_SERVICE_VERSION]: this.serviceVersion,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const spanProcessors = [];
|
|
43
|
-
|
|
44
|
-
// Add file exporter if enabled
|
|
45
|
-
if (this.enableFile) {
|
|
46
|
-
try {
|
|
47
|
-
// Ensure the directory exists
|
|
48
|
-
const dir = dirname(this.filePath);
|
|
49
|
-
if (!existsSync(dir)) {
|
|
50
|
-
mkdirSync(dir, { recursive: true });
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const fileExporter = new FileSpanExporter(this.filePath);
|
|
54
|
-
spanProcessors.push(new BatchSpanProcessor(fileExporter, {
|
|
55
|
-
maxQueueSize: 2048,
|
|
56
|
-
maxExportBatchSize: 512,
|
|
57
|
-
scheduledDelayMillis: 500,
|
|
58
|
-
exportTimeoutMillis: 30000,
|
|
59
|
-
}));
|
|
60
|
-
console.log(`[Telemetry] File exporter enabled, writing to: ${this.filePath}`);
|
|
61
|
-
} catch (error) {
|
|
62
|
-
console.error(`[Telemetry] Failed to initialize file exporter: ${error.message}`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Add remote exporter if enabled
|
|
67
|
-
if (this.enableRemote) {
|
|
68
|
-
try {
|
|
69
|
-
const remoteExporter = new OTLPTraceExporter({
|
|
70
|
-
url: this.remoteEndpoint,
|
|
71
|
-
});
|
|
72
|
-
spanProcessors.push(new BatchSpanProcessor(remoteExporter, {
|
|
73
|
-
maxQueueSize: 2048,
|
|
74
|
-
maxExportBatchSize: 512,
|
|
75
|
-
scheduledDelayMillis: 500,
|
|
76
|
-
exportTimeoutMillis: 30000,
|
|
77
|
-
}));
|
|
78
|
-
console.log(`[Telemetry] Remote exporter enabled, endpoint: ${this.remoteEndpoint}`);
|
|
79
|
-
} catch (error) {
|
|
80
|
-
console.error(`[Telemetry] Failed to initialize remote exporter: ${error.message}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Add console exporter if enabled (useful for debugging)
|
|
85
|
-
if (this.enableConsole) {
|
|
86
|
-
const consoleExporter = new ConsoleSpanExporter();
|
|
87
|
-
spanProcessors.push(new BatchSpanProcessor(consoleExporter, {
|
|
88
|
-
maxQueueSize: 2048,
|
|
89
|
-
maxExportBatchSize: 512,
|
|
90
|
-
scheduledDelayMillis: 500,
|
|
91
|
-
exportTimeoutMillis: 30000,
|
|
92
|
-
}));
|
|
93
|
-
console.log(`[Telemetry] Console exporter enabled`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (spanProcessors.length === 0) {
|
|
97
|
-
console.log('[Telemetry] No exporters configured, telemetry will not be collected');
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
this.sdk = new NodeSDK({
|
|
102
|
-
resource,
|
|
103
|
-
spanProcessors,
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
this.sdk.start();
|
|
108
|
-
this.tracer = trace.getTracer(this.serviceName, this.serviceVersion);
|
|
109
|
-
console.log(`[Telemetry] OpenTelemetry SDK initialized successfully`);
|
|
110
|
-
} catch (error) {
|
|
111
|
-
console.error(`[Telemetry] Failed to start OpenTelemetry SDK: ${error.message}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Get the tracer instance
|
|
117
|
-
*/
|
|
118
|
-
getTracer() {
|
|
119
|
-
return this.tracer;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Create a span with the given name and attributes
|
|
124
|
-
*/
|
|
125
|
-
createSpan(name, attributes = {}) {
|
|
126
|
-
if (!this.tracer) {
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return this.tracer.startSpan(name, {
|
|
131
|
-
attributes,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Wrap a function to automatically create spans
|
|
137
|
-
*/
|
|
138
|
-
wrapFunction(name, fn, attributes = {}) {
|
|
139
|
-
if (!this.tracer) {
|
|
140
|
-
return fn;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return async (...args) => {
|
|
144
|
-
const span = this.createSpan(name, attributes);
|
|
145
|
-
if (!span) {
|
|
146
|
-
return fn(...args);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
const result = await context.with(trace.setSpan(context.active(), span), () => fn(...args));
|
|
151
|
-
span.setStatus({ code: SpanStatusCode.OK });
|
|
152
|
-
return result;
|
|
153
|
-
} catch (error) {
|
|
154
|
-
span.setStatus({
|
|
155
|
-
code: SpanStatusCode.ERROR,
|
|
156
|
-
message: error.message,
|
|
157
|
-
});
|
|
158
|
-
span.recordException(error);
|
|
159
|
-
throw error;
|
|
160
|
-
} finally {
|
|
161
|
-
span.end();
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Force flush all pending spans
|
|
168
|
-
*/
|
|
169
|
-
async forceFlush() {
|
|
170
|
-
if (this.sdk) {
|
|
171
|
-
try {
|
|
172
|
-
const tracerProvider = trace.getTracerProvider();
|
|
173
|
-
|
|
174
|
-
if (tracerProvider && typeof tracerProvider.forceFlush === 'function') {
|
|
175
|
-
await tracerProvider.forceFlush();
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Add a small delay to ensure file writes complete
|
|
179
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
180
|
-
|
|
181
|
-
console.log('[Telemetry] OpenTelemetry spans flushed successfully');
|
|
182
|
-
} catch (error) {
|
|
183
|
-
console.error(`[Telemetry] Failed to flush OpenTelemetry spans: ${error.message}`);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Shutdown telemetry
|
|
190
|
-
*/
|
|
191
|
-
async shutdown() {
|
|
192
|
-
if (this.sdk) {
|
|
193
|
-
try {
|
|
194
|
-
await this.sdk.shutdown();
|
|
195
|
-
console.log('[Telemetry] OpenTelemetry SDK shutdown successfully');
|
|
196
|
-
} catch (error) {
|
|
197
|
-
console.error(`[Telemetry] Failed to shutdown OpenTelemetry SDK: ${error.message}`);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Initialize telemetry from CLI options
|
|
205
|
-
*/
|
|
206
|
-
export function initializeTelemetryFromOptions(options) {
|
|
207
|
-
const config = new TelemetryConfig({
|
|
208
|
-
serviceName: 'probe-agent',
|
|
209
|
-
serviceVersion: '1.0.0',
|
|
210
|
-
enableFile: options.traceFile !== undefined,
|
|
211
|
-
enableRemote: options.traceRemote !== undefined,
|
|
212
|
-
enableConsole: options.traceConsole,
|
|
213
|
-
filePath: options.traceFile || './traces.jsonl',
|
|
214
|
-
remoteEndpoint: options.traceRemote || 'http://localhost:4318/v1/traces',
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
config.initialize();
|
|
218
|
-
return config;
|
|
219
|
-
}
|
package/cjs/agent/telemetry.cjs
DELETED
|
@@ -1,358 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/agent/telemetry.js
|
|
21
|
-
var telemetry_exports = {};
|
|
22
|
-
__export(telemetry_exports, {
|
|
23
|
-
TelemetryConfig: () => TelemetryConfig,
|
|
24
|
-
initializeTelemetryFromOptions: () => initializeTelemetryFromOptions
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(telemetry_exports);
|
|
27
|
-
var import_sdk_node = require("@opentelemetry/sdk-node");
|
|
28
|
-
var import_resources = require("@opentelemetry/resources");
|
|
29
|
-
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
30
|
-
var import_api = require("@opentelemetry/api");
|
|
31
|
-
var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
|
|
32
|
-
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
33
|
-
var import_fs2 = require("fs");
|
|
34
|
-
var import_path = require("path");
|
|
35
|
-
|
|
36
|
-
// src/agent/fileSpanExporter.js
|
|
37
|
-
var import_fs = require("fs");
|
|
38
|
-
var import_core = require("@opentelemetry/core");
|
|
39
|
-
var FileSpanExporter = class {
|
|
40
|
-
constructor(filePath = "./traces.jsonl") {
|
|
41
|
-
this.filePath = filePath;
|
|
42
|
-
this.stream = (0, import_fs.createWriteStream)(filePath, { flags: "a" });
|
|
43
|
-
this.stream.on("error", (error) => {
|
|
44
|
-
console.error(`[FileSpanExporter] Stream error: ${error.message}`);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Export spans to file
|
|
49
|
-
* @param {ReadableSpan[]} spans - Array of spans to export
|
|
50
|
-
* @param {function} resultCallback - Callback to call with the export result
|
|
51
|
-
*/
|
|
52
|
-
export(spans, resultCallback) {
|
|
53
|
-
if (!spans || spans.length === 0) {
|
|
54
|
-
resultCallback({ code: import_core.ExportResultCode.SUCCESS });
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
try {
|
|
58
|
-
const timestamp = Date.now();
|
|
59
|
-
spans.forEach((span, index) => {
|
|
60
|
-
let parentSpanId = void 0;
|
|
61
|
-
if (span.parentSpanContext) {
|
|
62
|
-
parentSpanId = span.parentSpanContext.spanId;
|
|
63
|
-
} else if (span._parentSpanContext) {
|
|
64
|
-
parentSpanId = span._parentSpanContext.spanId;
|
|
65
|
-
} else if (span.parent) {
|
|
66
|
-
parentSpanId = span.parent.spanId;
|
|
67
|
-
} else if (span._parent) {
|
|
68
|
-
parentSpanId = span._parent.spanId;
|
|
69
|
-
} else if (span._parentId) {
|
|
70
|
-
parentSpanId = span._parentId;
|
|
71
|
-
} else if (span.parentSpanId) {
|
|
72
|
-
parentSpanId = span.parentSpanId;
|
|
73
|
-
}
|
|
74
|
-
const spanData = {
|
|
75
|
-
traceId: span.spanContext().traceId,
|
|
76
|
-
spanId: span.spanContext().spanId,
|
|
77
|
-
parentSpanId,
|
|
78
|
-
name: span.name,
|
|
79
|
-
kind: span.kind,
|
|
80
|
-
startTimeUnixNano: span.startTime[0] * 1e9 + span.startTime[1],
|
|
81
|
-
endTimeUnixNano: span.endTime[0] * 1e9 + span.endTime[1],
|
|
82
|
-
attributes: this.convertAttributes(span.attributes),
|
|
83
|
-
status: span.status,
|
|
84
|
-
events: span.events?.map((event) => ({
|
|
85
|
-
timeUnixNano: event.time[0] * 1e9 + event.time[1],
|
|
86
|
-
name: event.name,
|
|
87
|
-
attributes: this.convertAttributes(event.attributes)
|
|
88
|
-
})) || [],
|
|
89
|
-
links: span.links?.map((link) => ({
|
|
90
|
-
traceId: link.context.traceId,
|
|
91
|
-
spanId: link.context.spanId,
|
|
92
|
-
attributes: this.convertAttributes(link.attributes)
|
|
93
|
-
})) || [],
|
|
94
|
-
resource: {
|
|
95
|
-
attributes: this.convertAttributes(span.resource?.attributes || {})
|
|
96
|
-
},
|
|
97
|
-
instrumentationLibrary: {
|
|
98
|
-
name: span.instrumentationLibrary?.name || "unknown",
|
|
99
|
-
version: span.instrumentationLibrary?.version || "unknown"
|
|
100
|
-
},
|
|
101
|
-
timestamp
|
|
102
|
-
};
|
|
103
|
-
this.stream.write(JSON.stringify(spanData) + "\n");
|
|
104
|
-
});
|
|
105
|
-
resultCallback({ code: import_core.ExportResultCode.SUCCESS });
|
|
106
|
-
} catch (error) {
|
|
107
|
-
console.error(`[FileSpanExporter] Export error: ${error.message}`);
|
|
108
|
-
resultCallback({
|
|
109
|
-
code: import_core.ExportResultCode.FAILED,
|
|
110
|
-
error
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Convert OpenTelemetry attributes to plain object
|
|
116
|
-
* @param {Object} attributes - OpenTelemetry attributes
|
|
117
|
-
* @returns {Object} Plain object with string values
|
|
118
|
-
*/
|
|
119
|
-
convertAttributes(attributes) {
|
|
120
|
-
if (!attributes) return {};
|
|
121
|
-
const result = {};
|
|
122
|
-
for (const [key, value] of Object.entries(attributes)) {
|
|
123
|
-
if (typeof value === "object" && value !== null) {
|
|
124
|
-
result[key] = JSON.stringify(value);
|
|
125
|
-
} else {
|
|
126
|
-
result[key] = String(value);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return result;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Shutdown the exporter
|
|
133
|
-
* @returns {Promise<void>}
|
|
134
|
-
*/
|
|
135
|
-
async shutdown() {
|
|
136
|
-
return new Promise((resolve) => {
|
|
137
|
-
if (this.stream) {
|
|
138
|
-
this.stream.end(() => {
|
|
139
|
-
console.log(`[FileSpanExporter] File stream closed: ${this.filePath}`);
|
|
140
|
-
resolve();
|
|
141
|
-
});
|
|
142
|
-
} else {
|
|
143
|
-
resolve();
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Force flush any pending spans
|
|
149
|
-
* @returns {Promise<void>}
|
|
150
|
-
*/
|
|
151
|
-
async forceFlush() {
|
|
152
|
-
return new Promise((resolve, reject) => {
|
|
153
|
-
if (this.stream) {
|
|
154
|
-
const flushTimeout = setTimeout(() => {
|
|
155
|
-
console.warn("[FileSpanExporter] Flush timeout after 5 seconds");
|
|
156
|
-
resolve();
|
|
157
|
-
}, 5e3);
|
|
158
|
-
if (this.stream.writableCorked) {
|
|
159
|
-
this.stream.uncork();
|
|
160
|
-
}
|
|
161
|
-
if (this.stream.writableNeedDrain) {
|
|
162
|
-
this.stream.once("drain", () => {
|
|
163
|
-
clearTimeout(flushTimeout);
|
|
164
|
-
resolve();
|
|
165
|
-
});
|
|
166
|
-
} else {
|
|
167
|
-
setImmediate(() => {
|
|
168
|
-
clearTimeout(flushTimeout);
|
|
169
|
-
resolve();
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
resolve();
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
// src/agent/telemetry.js
|
|
180
|
-
var TelemetryConfig = class {
|
|
181
|
-
constructor(options = {}) {
|
|
182
|
-
this.serviceName = options.serviceName || "probe-agent";
|
|
183
|
-
this.serviceVersion = options.serviceVersion || "1.0.0";
|
|
184
|
-
this.enableFile = options.enableFile || false;
|
|
185
|
-
this.enableRemote = options.enableRemote || false;
|
|
186
|
-
this.enableConsole = options.enableConsole || false;
|
|
187
|
-
this.filePath = options.filePath || "./traces.jsonl";
|
|
188
|
-
this.remoteEndpoint = options.remoteEndpoint || "http://localhost:4318/v1/traces";
|
|
189
|
-
this.sdk = null;
|
|
190
|
-
this.tracer = null;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Initialize OpenTelemetry SDK
|
|
194
|
-
*/
|
|
195
|
-
initialize() {
|
|
196
|
-
if (this.sdk) {
|
|
197
|
-
console.warn("Telemetry already initialized");
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
const resource = (0, import_resources.resourceFromAttributes)({
|
|
201
|
-
[import_semantic_conventions.ATTR_SERVICE_NAME]: this.serviceName,
|
|
202
|
-
[import_semantic_conventions.ATTR_SERVICE_VERSION]: this.serviceVersion
|
|
203
|
-
});
|
|
204
|
-
const spanProcessors = [];
|
|
205
|
-
if (this.enableFile) {
|
|
206
|
-
try {
|
|
207
|
-
const dir = (0, import_path.dirname)(this.filePath);
|
|
208
|
-
if (!(0, import_fs2.existsSync)(dir)) {
|
|
209
|
-
(0, import_fs2.mkdirSync)(dir, { recursive: true });
|
|
210
|
-
}
|
|
211
|
-
const fileExporter = new FileSpanExporter(this.filePath);
|
|
212
|
-
spanProcessors.push(new import_sdk_trace_base.BatchSpanProcessor(fileExporter, {
|
|
213
|
-
maxQueueSize: 2048,
|
|
214
|
-
maxExportBatchSize: 512,
|
|
215
|
-
scheduledDelayMillis: 500,
|
|
216
|
-
exportTimeoutMillis: 3e4
|
|
217
|
-
}));
|
|
218
|
-
console.log(`[Telemetry] File exporter enabled, writing to: ${this.filePath}`);
|
|
219
|
-
} catch (error) {
|
|
220
|
-
console.error(`[Telemetry] Failed to initialize file exporter: ${error.message}`);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
if (this.enableRemote) {
|
|
224
|
-
try {
|
|
225
|
-
const remoteExporter = new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
|
226
|
-
url: this.remoteEndpoint
|
|
227
|
-
});
|
|
228
|
-
spanProcessors.push(new import_sdk_trace_base.BatchSpanProcessor(remoteExporter, {
|
|
229
|
-
maxQueueSize: 2048,
|
|
230
|
-
maxExportBatchSize: 512,
|
|
231
|
-
scheduledDelayMillis: 500,
|
|
232
|
-
exportTimeoutMillis: 3e4
|
|
233
|
-
}));
|
|
234
|
-
console.log(`[Telemetry] Remote exporter enabled, endpoint: ${this.remoteEndpoint}`);
|
|
235
|
-
} catch (error) {
|
|
236
|
-
console.error(`[Telemetry] Failed to initialize remote exporter: ${error.message}`);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
if (this.enableConsole) {
|
|
240
|
-
const consoleExporter = new import_sdk_trace_base.ConsoleSpanExporter();
|
|
241
|
-
spanProcessors.push(new import_sdk_trace_base.BatchSpanProcessor(consoleExporter, {
|
|
242
|
-
maxQueueSize: 2048,
|
|
243
|
-
maxExportBatchSize: 512,
|
|
244
|
-
scheduledDelayMillis: 500,
|
|
245
|
-
exportTimeoutMillis: 3e4
|
|
246
|
-
}));
|
|
247
|
-
console.log(`[Telemetry] Console exporter enabled`);
|
|
248
|
-
}
|
|
249
|
-
if (spanProcessors.length === 0) {
|
|
250
|
-
console.log("[Telemetry] No exporters configured, telemetry will not be collected");
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
this.sdk = new import_sdk_node.NodeSDK({
|
|
254
|
-
resource,
|
|
255
|
-
spanProcessors
|
|
256
|
-
});
|
|
257
|
-
try {
|
|
258
|
-
this.sdk.start();
|
|
259
|
-
this.tracer = import_api.trace.getTracer(this.serviceName, this.serviceVersion);
|
|
260
|
-
console.log(`[Telemetry] OpenTelemetry SDK initialized successfully`);
|
|
261
|
-
} catch (error) {
|
|
262
|
-
console.error(`[Telemetry] Failed to start OpenTelemetry SDK: ${error.message}`);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Get the tracer instance
|
|
267
|
-
*/
|
|
268
|
-
getTracer() {
|
|
269
|
-
return this.tracer;
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Create a span with the given name and attributes
|
|
273
|
-
*/
|
|
274
|
-
createSpan(name, attributes = {}) {
|
|
275
|
-
if (!this.tracer) {
|
|
276
|
-
return null;
|
|
277
|
-
}
|
|
278
|
-
return this.tracer.startSpan(name, {
|
|
279
|
-
attributes
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Wrap a function to automatically create spans
|
|
284
|
-
*/
|
|
285
|
-
wrapFunction(name, fn, attributes = {}) {
|
|
286
|
-
if (!this.tracer) {
|
|
287
|
-
return fn;
|
|
288
|
-
}
|
|
289
|
-
return async (...args) => {
|
|
290
|
-
const span = this.createSpan(name, attributes);
|
|
291
|
-
if (!span) {
|
|
292
|
-
return fn(...args);
|
|
293
|
-
}
|
|
294
|
-
try {
|
|
295
|
-
const result = await import_api.context.with(import_api.trace.setSpan(import_api.context.active(), span), () => fn(...args));
|
|
296
|
-
span.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
297
|
-
return result;
|
|
298
|
-
} catch (error) {
|
|
299
|
-
span.setStatus({
|
|
300
|
-
code: import_api.SpanStatusCode.ERROR,
|
|
301
|
-
message: error.message
|
|
302
|
-
});
|
|
303
|
-
span.recordException(error);
|
|
304
|
-
throw error;
|
|
305
|
-
} finally {
|
|
306
|
-
span.end();
|
|
307
|
-
}
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Force flush all pending spans
|
|
312
|
-
*/
|
|
313
|
-
async forceFlush() {
|
|
314
|
-
if (this.sdk) {
|
|
315
|
-
try {
|
|
316
|
-
const tracerProvider = import_api.trace.getTracerProvider();
|
|
317
|
-
if (tracerProvider && typeof tracerProvider.forceFlush === "function") {
|
|
318
|
-
await tracerProvider.forceFlush();
|
|
319
|
-
}
|
|
320
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
321
|
-
console.log("[Telemetry] OpenTelemetry spans flushed successfully");
|
|
322
|
-
} catch (error) {
|
|
323
|
-
console.error(`[Telemetry] Failed to flush OpenTelemetry spans: ${error.message}`);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Shutdown telemetry
|
|
329
|
-
*/
|
|
330
|
-
async shutdown() {
|
|
331
|
-
if (this.sdk) {
|
|
332
|
-
try {
|
|
333
|
-
await this.sdk.shutdown();
|
|
334
|
-
console.log("[Telemetry] OpenTelemetry SDK shutdown successfully");
|
|
335
|
-
} catch (error) {
|
|
336
|
-
console.error(`[Telemetry] Failed to shutdown OpenTelemetry SDK: ${error.message}`);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
function initializeTelemetryFromOptions(options) {
|
|
342
|
-
const config = new TelemetryConfig({
|
|
343
|
-
serviceName: "probe-agent",
|
|
344
|
-
serviceVersion: "1.0.0",
|
|
345
|
-
enableFile: options.traceFile !== void 0,
|
|
346
|
-
enableRemote: options.traceRemote !== void 0,
|
|
347
|
-
enableConsole: options.traceConsole,
|
|
348
|
-
filePath: options.traceFile || "./traces.jsonl",
|
|
349
|
-
remoteEndpoint: options.traceRemote || "http://localhost:4318/v1/traces"
|
|
350
|
-
});
|
|
351
|
-
config.initialize();
|
|
352
|
-
return config;
|
|
353
|
-
}
|
|
354
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
355
|
-
0 && (module.exports = {
|
|
356
|
-
TelemetryConfig,
|
|
357
|
-
initializeTelemetryFromOptions
|
|
358
|
-
});
|