@smythos/sre 1.7.42 → 1.8.1
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/CHANGELOG +448 -66
- package/dist/index.js +65 -50
- package/dist/index.js.map +1 -1
- package/dist/types/Components/Async.class.d.ts +11 -5
- package/dist/types/index.d.ts +2 -0
- package/dist/types/subsystems/AgentManager/AgentData.service/connectors/SQLiteAgentDataConnector.class.d.ts +45 -0
- package/dist/types/subsystems/LLMManager/LLM.helper.d.ts +32 -1
- package/dist/types/subsystems/LLMManager/LLM.inference.d.ts +25 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.d.ts +22 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.d.ts +2 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +27 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Groq.class.d.ts +22 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Ollama.class.d.ts +22 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.d.ts +3 -3
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.d.ts +23 -3
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.d.ts +2 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/OpenAIApiInterface.d.ts +2 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.d.ts +2 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/xAI.class.d.ts +3 -3
- package/dist/types/subsystems/MemoryManager/LLMContext.d.ts +10 -3
- package/dist/types/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.d.ts +24 -0
- package/dist/types/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.redaction.helper.d.ts +49 -0
- package/dist/types/types/LLM.types.d.ts +30 -1
- package/package.json +4 -3
- package/src/Components/APICall/OAuth.helper.ts +16 -1
- package/src/Components/APIEndpoint.class.ts +11 -4
- package/src/Components/Async.class.ts +38 -5
- package/src/Components/GenAILLM.class.ts +13 -7
- package/src/Components/ImageGenerator.class.ts +32 -13
- package/src/Components/LLMAssistant.class.ts +3 -1
- package/src/Components/LogicAND.class.ts +13 -0
- package/src/Components/LogicAtLeast.class.ts +18 -0
- package/src/Components/LogicAtMost.class.ts +19 -0
- package/src/Components/LogicOR.class.ts +12 -2
- package/src/Components/LogicXOR.class.ts +11 -0
- package/src/constants.ts +1 -1
- package/src/helpers/Conversation.helper.ts +10 -8
- package/src/index.ts +2 -0
- package/src/index.ts.bak +2 -0
- package/src/subsystems/AgentManager/AgentData.service/connectors/SQLiteAgentDataConnector.class.ts +190 -0
- package/src/subsystems/AgentManager/AgentData.service/index.ts +2 -0
- package/src/subsystems/LLMManager/LLM.helper.ts +117 -1
- package/src/subsystems/LLMManager/LLM.inference.ts +136 -67
- package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +22 -6
- package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +157 -33
- package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +9 -8
- package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +124 -90
- package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +125 -62
- package/src/subsystems/LLMManager/LLM.service/connectors/Ollama.class.ts +168 -76
- package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +18 -8
- package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +8 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.ts +50 -8
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.ts +30 -16
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/OpenAIApiInterface.ts +2 -2
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.ts +29 -15
- package/src/subsystems/LLMManager/LLM.service/connectors/xAI.class.ts +10 -8
- package/src/subsystems/MemoryManager/LLMContext.ts +27 -8
- package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +313 -85
- package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.redaction.helper.ts +203 -0
- package/src/types/LLM.types.ts +31 -1
- package/src/types/node-sqlite.d.ts +45 -0
|
@@ -4,6 +4,7 @@ import { ACL } from '@sre/Security/AccessControl/ACL.class';
|
|
|
4
4
|
import { IAccessCandidate } from '@sre/types/ACL.types';
|
|
5
5
|
import { TelemetryConnector } from '../../TelemetryConnector';
|
|
6
6
|
import { AgentCallLog } from '@sre/types/AgentLogger.types';
|
|
7
|
+
import { redactSensitiveString, redactData, redactHeaders } from './OTel.redaction.helper';
|
|
7
8
|
|
|
8
9
|
import { trace, context, SpanStatusCode, Tracer, propagation } from '@opentelemetry/api';
|
|
9
10
|
import { Logger as OTelLogger, logs, SeverityNumber } from '@opentelemetry/api-logs';
|
|
@@ -50,6 +51,14 @@ export type OTelLogConfig = {
|
|
|
50
51
|
* These will be replaced with '[REDACTED]' in logs
|
|
51
52
|
*/
|
|
52
53
|
redactFields?: string[];
|
|
54
|
+
/**
|
|
55
|
+
* Enable automatic redaction of sensitive data in logs and traces.
|
|
56
|
+
* When true (or omitted), sensitive data such as passwords, tokens,
|
|
57
|
+
* API keys, and JWT tokens are automatically replaced with '[REDACTED]'.
|
|
58
|
+
* Set to false to disable all automatic redaction.
|
|
59
|
+
* Default: true
|
|
60
|
+
*/
|
|
61
|
+
enableRedaction?: boolean;
|
|
53
62
|
};
|
|
54
63
|
const OTEL_DEBUG_LOGS = true;
|
|
55
64
|
export class OTel extends TelemetryConnector {
|
|
@@ -62,6 +71,9 @@ export class OTel extends TelemetryConnector {
|
|
|
62
71
|
|
|
63
72
|
constructor(protected _settings: OTelLogConfig) {
|
|
64
73
|
super();
|
|
74
|
+
// Default enableRedaction to true when not explicitly provided
|
|
75
|
+
_settings.enableRedaction = _settings.enableRedaction ?? true;
|
|
76
|
+
|
|
65
77
|
if (!_settings.endpoint) {
|
|
66
78
|
outputLogger.warn('OTel initialization skipped, endpoint is not set');
|
|
67
79
|
return;
|
|
@@ -141,6 +153,7 @@ export class OTel extends TelemetryConnector {
|
|
|
141
153
|
* Redact sensitive fields from an object
|
|
142
154
|
*/
|
|
143
155
|
private redactSensitiveData(data: any, redactFields?: string[]): any {
|
|
156
|
+
if (!this._settings.enableRedaction) return data;
|
|
144
157
|
if (!redactFields || redactFields.length === 0) return data;
|
|
145
158
|
if (typeof data !== 'object' || data === null) return data;
|
|
146
159
|
|
|
@@ -157,6 +170,35 @@ export class OTel extends TelemetryConnector {
|
|
|
157
170
|
return redacted;
|
|
158
171
|
}
|
|
159
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Redact sensitive patterns from a string value.
|
|
175
|
+
* Skips redaction when enableRedaction is explicitly set to false.
|
|
176
|
+
*/
|
|
177
|
+
private redactString(value: string): string {
|
|
178
|
+
if (!this._settings.enableRedaction) return value;
|
|
179
|
+
return redactSensitiveString(value);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Redact sensitive data from any data type (objects, arrays, strings).
|
|
184
|
+
* Skips redaction when enableRedaction is explicitly set to false.
|
|
185
|
+
*/
|
|
186
|
+
private redactObject<T>(data: T): T {
|
|
187
|
+
if (!this._settings.enableRedaction) return data;
|
|
188
|
+
return redactData(data);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Redact sensitive HTTP headers.
|
|
193
|
+
* Skips redaction when enableRedaction is explicitly set to false.
|
|
194
|
+
*/
|
|
195
|
+
private redactRequestHeaders(
|
|
196
|
+
headers: Record<string, unknown> | string | undefined | null,
|
|
197
|
+
): Record<string, unknown> | string | undefined | null {
|
|
198
|
+
if (!this._settings.enableRedaction) return headers;
|
|
199
|
+
return redactHeaders(headers);
|
|
200
|
+
}
|
|
201
|
+
|
|
160
202
|
/**
|
|
161
203
|
* Safely format output for logging with size limits and redaction
|
|
162
204
|
*/
|
|
@@ -170,11 +212,17 @@ export class OTel extends TelemetryConnector {
|
|
|
170
212
|
return undefined;
|
|
171
213
|
}
|
|
172
214
|
|
|
173
|
-
// Redact sensitive fields
|
|
174
|
-
|
|
215
|
+
// Redact sensitive fields (config-based)
|
|
216
|
+
let redacted = this.redactSensitiveData(output, config.redactFields);
|
|
217
|
+
|
|
218
|
+
// Apply SENSITIVE_WORDS-based redaction on the object (automatic key-based redaction)
|
|
219
|
+
redacted = this.redactObject(redacted);
|
|
175
220
|
|
|
176
221
|
// Stringify
|
|
177
|
-
|
|
222
|
+
let outputStr = JSON.stringify(redacted);
|
|
223
|
+
|
|
224
|
+
// Apply string-based redaction on the stringified output to catch embedded JSON
|
|
225
|
+
outputStr = this.redactString(outputStr);
|
|
178
226
|
|
|
179
227
|
// Check size limit
|
|
180
228
|
if (outputStr && outputStr.length > maxSize) {
|
|
@@ -200,12 +248,38 @@ export class OTel extends TelemetryConnector {
|
|
|
200
248
|
for (let key in data) {
|
|
201
249
|
result[prefix ? `${prefix}.${key}` : key] = (typeof data[key] === 'object' ? JSON.stringify(data[key]) : data[key].toString()).substring(
|
|
202
250
|
0,
|
|
203
|
-
maxEntryLength
|
|
251
|
+
maxEntryLength,
|
|
204
252
|
);
|
|
205
253
|
}
|
|
206
254
|
|
|
207
255
|
return result;
|
|
208
256
|
}
|
|
257
|
+
|
|
258
|
+
private prepareContext(contextWindow: Array<{ role: string; content: string; [key: string]: unknown }>): string {
|
|
259
|
+
if (!contextWindow || !Array.isArray(contextWindow)) return '[]';
|
|
260
|
+
|
|
261
|
+
const filtered = contextWindow.filter((msg) => {
|
|
262
|
+
if (typeof msg !== 'object' || msg === null) return false;
|
|
263
|
+
const keys = Object.keys(msg);
|
|
264
|
+
return !keys.some((k) => k.includes('___smyth_metadata___'));
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
const lastAssistant = [...filtered].reverse().find((msg) => msg.role === 'assistant' && msg.content);
|
|
268
|
+
const lastUser = [...filtered].reverse().find((msg) => msg.role === 'user' && msg.content);
|
|
269
|
+
|
|
270
|
+
const messages: Array<{ role: string; content: string }> = [];
|
|
271
|
+
if (lastAssistant) {
|
|
272
|
+
const raw = typeof lastAssistant.content === 'string' ? lastAssistant.content : JSON.stringify(lastAssistant.content);
|
|
273
|
+
messages.push({ role: 'assistant', content: raw.substring(0, 2000) });
|
|
274
|
+
}
|
|
275
|
+
if (lastUser) {
|
|
276
|
+
const raw = typeof lastUser.content === 'string' ? lastUser.content : JSON.stringify(lastUser.content);
|
|
277
|
+
messages.push({ role: 'user', content: raw.substring(0, 2000) });
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return JSON.stringify(messages);
|
|
281
|
+
}
|
|
282
|
+
|
|
209
283
|
protected setupHooks(): Promise<void> {
|
|
210
284
|
const tracer = this.tracer;
|
|
211
285
|
const logger = this.logger;
|
|
@@ -219,15 +293,18 @@ export class OTel extends TelemetryConnector {
|
|
|
219
293
|
|
|
220
294
|
const modelId = toolInfo.model;
|
|
221
295
|
const contextWindow = toolInfo.contextWindow;
|
|
222
|
-
const lastContext = contextWindow.filter((context) => context.role === 'user').slice(-2);
|
|
223
296
|
|
|
224
|
-
const toolNames = toolInfo.map((tool) =>
|
|
297
|
+
const toolNames = toolInfo.map((tool) => {
|
|
298
|
+
const args = typeof tool.arguments === 'string' ? tool.arguments : JSON.stringify(tool.arguments);
|
|
299
|
+
return `${tool.name}(${args})`;
|
|
300
|
+
});
|
|
225
301
|
hookContext.curLLMGenSpan.addEvent('llm.gen.tool.calls', {
|
|
226
|
-
'tool.calls': toolNames.join(', '),
|
|
227
|
-
'llm.model': modelId || '
|
|
228
|
-
'context.preview':
|
|
302
|
+
'tool.calls': oTelInstance.redactString(toolNames.join(', ')),
|
|
303
|
+
'llm.model': modelId || '',
|
|
304
|
+
'context.preview': oTelInstance.redactString(oTelInstance.prepareContext(contextWindow).substring(0, 200)),
|
|
229
305
|
});
|
|
230
306
|
|
|
307
|
+
const llmSpanCtx = hookContext.curLLMGenSpan.spanContext();
|
|
231
308
|
const spanContext = trace.setSpan(context.active(), hookContext.curLLMGenSpan);
|
|
232
309
|
context.with(spanContext, () => {
|
|
233
310
|
logger.emit({
|
|
@@ -235,10 +312,15 @@ export class OTel extends TelemetryConnector {
|
|
|
235
312
|
severityText: 'INFO',
|
|
236
313
|
body: `LLM tool calls: ${toolNames.join(', ')}`,
|
|
237
314
|
attributes: {
|
|
315
|
+
// Explicit trace correlation (some backends need these)
|
|
316
|
+
trace_id: llmSpanCtx.traceId,
|
|
317
|
+
span_id: llmSpanCtx.spanId,
|
|
318
|
+
trace_flags: llmSpanCtx.traceFlags,
|
|
319
|
+
|
|
238
320
|
'agent.id': hookContext.agentId,
|
|
239
321
|
'conv.id': hookContext.processId,
|
|
240
|
-
'llm.model': modelId || '
|
|
241
|
-
'context.preview':
|
|
322
|
+
'llm.model': modelId || '',
|
|
323
|
+
'context.preview': oTelInstance.redactString(oTelInstance.prepareContext(contextWindow)),
|
|
242
324
|
},
|
|
243
325
|
});
|
|
244
326
|
});
|
|
@@ -259,7 +341,6 @@ export class OTel extends TelemetryConnector {
|
|
|
259
341
|
const modelId = reqInfo.model;
|
|
260
342
|
const contextWindow = reqInfo.contextWindow;
|
|
261
343
|
|
|
262
|
-
const lastContext = contextWindow.filter((context) => context.role === 'user').slice(-2);
|
|
263
344
|
// End TTFB span when first data arrives
|
|
264
345
|
if (hookContext?.latencySpans?.[reqInfo.requestId]) {
|
|
265
346
|
const ttfbSpan = hookContext.latencySpans[reqInfo.requestId];
|
|
@@ -268,7 +349,7 @@ export class OTel extends TelemetryConnector {
|
|
|
268
349
|
ttfbSpan.addEvent('llm.first.byte.received', {
|
|
269
350
|
'request.id': reqInfo.requestId,
|
|
270
351
|
'data.size': JSON.stringify(data || {}).length,
|
|
271
|
-
'llm.model': modelId || '
|
|
352
|
+
'llm.model': modelId || '',
|
|
272
353
|
});
|
|
273
354
|
|
|
274
355
|
ttfbSpan.setStatus({ code: SpanStatusCode.OK });
|
|
@@ -284,22 +365,98 @@ export class OTel extends TelemetryConnector {
|
|
|
284
365
|
'agent.id': hookContext.agentId,
|
|
285
366
|
'conv.id': hookContext.processId,
|
|
286
367
|
'team.id': hookContext.teamId,
|
|
287
|
-
'llm.model': modelId || '
|
|
368
|
+
'llm.model': modelId || '',
|
|
288
369
|
},
|
|
289
370
|
},
|
|
290
|
-
trace.setSpan(context.active(), hookContext.convSpan)
|
|
371
|
+
trace.setSpan(context.active(), hookContext.convSpan),
|
|
291
372
|
);
|
|
292
373
|
llmGenSpan.addEvent('llm.gen.started', {
|
|
293
374
|
'request.id': reqInfo.requestId,
|
|
294
375
|
timestamp: Date.now(),
|
|
295
|
-
'llm.model': modelId || '
|
|
296
|
-
'context.preview':
|
|
376
|
+
'llm.model': modelId || '',
|
|
377
|
+
'context.preview': oTelInstance.redactString(oTelInstance.prepareContext(contextWindow).substring(0, 200)),
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
const llmGenSpanCtx = llmGenSpan.spanContext();
|
|
381
|
+
const llmGenSpanContext = trace.setSpan(context.active(), llmGenSpan);
|
|
382
|
+
context.with(llmGenSpanContext, () => {
|
|
383
|
+
logger.emit({
|
|
384
|
+
severityNumber: SeverityNumber.INFO,
|
|
385
|
+
severityText: 'INFO',
|
|
386
|
+
body: `LLM generation started: ${hookContext.processId}`,
|
|
387
|
+
attributes: {
|
|
388
|
+
// Explicit trace correlation (some backends need these)
|
|
389
|
+
trace_id: llmGenSpanCtx.traceId,
|
|
390
|
+
span_id: llmGenSpanCtx.spanId,
|
|
391
|
+
trace_flags: llmGenSpanCtx.traceFlags,
|
|
392
|
+
|
|
393
|
+
'agent.id': hookContext.agentId,
|
|
394
|
+
'conv.id': hookContext.processId,
|
|
395
|
+
'team.id': hookContext.teamId,
|
|
396
|
+
'llm.model': modelId || '',
|
|
397
|
+
'request.id': reqInfo.requestId,
|
|
398
|
+
'context.preview': oTelInstance.redactString(oTelInstance.prepareContext(contextWindow)),
|
|
399
|
+
},
|
|
400
|
+
});
|
|
297
401
|
});
|
|
402
|
+
|
|
298
403
|
hookContext.curLLMGenSpan = llmGenSpan;
|
|
299
404
|
if (OTEL_DEBUG_LOGS) outputLogger.debug('createDataHandler completed', reqInfo?.requestId, accessCandidate);
|
|
300
405
|
};
|
|
301
406
|
};
|
|
302
407
|
|
|
408
|
+
const createErrorHandler = function (hookContext: any) {
|
|
409
|
+
return function (error: Error, metadata?: { requestId?: string }) {
|
|
410
|
+
if (!hookContext.convSpan) return;
|
|
411
|
+
const accessCandidate = AccessCandidate.agent(hookContext?.agentId);
|
|
412
|
+
if (OTEL_DEBUG_LOGS)
|
|
413
|
+
outputLogger.debug('Error event received', { error: error?.message, requestId: metadata?.requestId }, accessCandidate);
|
|
414
|
+
|
|
415
|
+
// Mark that an error occurred so after hook knows not to log success
|
|
416
|
+
hookContext.hasError = true;
|
|
417
|
+
hookContext.errorDetails = error;
|
|
418
|
+
|
|
419
|
+
const convSpan = hookContext.convSpan;
|
|
420
|
+
const spanCtx = convSpan.spanContext();
|
|
421
|
+
const spanContext = trace.setSpan(context.active(), convSpan);
|
|
422
|
+
|
|
423
|
+
// Record exception on span
|
|
424
|
+
convSpan.recordException(error);
|
|
425
|
+
convSpan.setStatus({ code: SpanStatusCode.ERROR, message: error?.message || 'Unknown error' });
|
|
426
|
+
convSpan.addEvent('conv.error', {
|
|
427
|
+
'error.message': error?.message || 'Unknown error',
|
|
428
|
+
'request.id': metadata?.requestId || 'unknown',
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
context.with(spanContext, () => {
|
|
432
|
+
logger.emit({
|
|
433
|
+
severityNumber: SeverityNumber.ERROR,
|
|
434
|
+
severityText: 'ERROR',
|
|
435
|
+
body: `Conversation error: ${hookContext.processId}`,
|
|
436
|
+
attributes: {
|
|
437
|
+
// Explicit trace correlation (some backends need these)
|
|
438
|
+
trace_id: spanCtx.traceId,
|
|
439
|
+
span_id: spanCtx.spanId,
|
|
440
|
+
trace_flags: spanCtx.traceFlags,
|
|
441
|
+
|
|
442
|
+
'agent.id': hookContext.agentId,
|
|
443
|
+
'agent.name': hookContext.agentName,
|
|
444
|
+
'conv.id': hookContext.processId,
|
|
445
|
+
'error.message': error?.message || 'Unknown error',
|
|
446
|
+
'error.stack': error?.stack,
|
|
447
|
+
'team.id': hookContext.teamId,
|
|
448
|
+
'org.slot': hookContext.orgSlot,
|
|
449
|
+
'agent.debug': hookContext.isDebugSession,
|
|
450
|
+
'agent.isTest': hookContext.isTestDomain,
|
|
451
|
+
'request.id': metadata?.requestId || 'unknown',
|
|
452
|
+
},
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('Error event handled', { error: error?.message }, accessCandidate);
|
|
457
|
+
};
|
|
458
|
+
};
|
|
459
|
+
|
|
303
460
|
const createRequestedHandler = function (hookContext) {
|
|
304
461
|
return function (reqInfo: any) {
|
|
305
462
|
if (!hookContext.convSpan) return;
|
|
@@ -308,8 +465,6 @@ export class OTel extends TelemetryConnector {
|
|
|
308
465
|
if (!hookContext.latencySpans) hookContext.latencySpans = {};
|
|
309
466
|
const contextWindow = reqInfo.contextWindow;
|
|
310
467
|
|
|
311
|
-
const lastContext = contextWindow.filter((context) => context.role === 'user').slice(-2);
|
|
312
|
-
|
|
313
468
|
const modelId = reqInfo.model;
|
|
314
469
|
const llmGenLatencySpan = tracer.startSpan(
|
|
315
470
|
'Conv.GenAI.TTFB',
|
|
@@ -319,16 +474,16 @@ export class OTel extends TelemetryConnector {
|
|
|
319
474
|
'conv.id': hookContext.processId,
|
|
320
475
|
'team.id': hookContext.teamId,
|
|
321
476
|
'request.id': reqInfo.requestId,
|
|
322
|
-
'llm.model': modelId || '
|
|
477
|
+
'llm.model': modelId || '',
|
|
323
478
|
'metric.type': 'ttfb',
|
|
324
479
|
},
|
|
325
480
|
},
|
|
326
|
-
trace.setSpan(context.active(), hookContext.convSpan)
|
|
481
|
+
trace.setSpan(context.active(), hookContext.convSpan),
|
|
327
482
|
);
|
|
328
483
|
llmGenLatencySpan.addEvent('llm.requested', {
|
|
329
484
|
'request.id': reqInfo.requestId,
|
|
330
485
|
timestamp: Date.now(),
|
|
331
|
-
'context.preview':
|
|
486
|
+
'context.preview': oTelInstance.redactString(oTelInstance.prepareContext(contextWindow).substring(0, 200)),
|
|
332
487
|
});
|
|
333
488
|
hookContext.latencySpans[reqInfo.requestId] = llmGenLatencySpan;
|
|
334
489
|
if (OTEL_DEBUG_LOGS) outputLogger.debug('createRequestedHandler completed', reqInfo?.requestId, accessCandidate);
|
|
@@ -351,6 +506,7 @@ export class OTel extends TelemetryConnector {
|
|
|
351
506
|
const sessionId = processId;
|
|
352
507
|
const workflowId = agentData?.workflowReqId || agentData?.workflowID || agentData?.workflowId || undefined;
|
|
353
508
|
const logTags = agentData?.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
509
|
+
const agentName = agentData?.name || undefined;
|
|
354
510
|
|
|
355
511
|
if (message == null) {
|
|
356
512
|
//this is a conversation step, will be handled by createRequestedHandler
|
|
@@ -366,16 +522,17 @@ export class OTel extends TelemetryConnector {
|
|
|
366
522
|
attributes: {
|
|
367
523
|
// OTel standard attributes
|
|
368
524
|
'gen_ai.operation.name': 'chat',
|
|
369
|
-
'gen_ai.provider.name': conversation?.llmInference?.llmProviderName || '
|
|
525
|
+
'gen_ai.provider.name': conversation?.llmInference?.llmProviderName || '',
|
|
370
526
|
'gen_ai.conversation.id': processId,
|
|
371
|
-
'gen_ai.request.model': modelId || '
|
|
527
|
+
'gen_ai.request.model': modelId || '',
|
|
372
528
|
////////////////////////////////
|
|
373
529
|
'team.id': teamId,
|
|
374
530
|
'org.tier': orgTier,
|
|
375
531
|
'org.slot': orgSlot,
|
|
376
532
|
'agent.id': agentId,
|
|
533
|
+
'agent.name': agentName,
|
|
377
534
|
'conv.id': processId,
|
|
378
|
-
'llm.model': modelId || '
|
|
535
|
+
'llm.model': modelId || '',
|
|
379
536
|
'agent.debug': isDebugSession,
|
|
380
537
|
'agent.isTest': isTestDomain,
|
|
381
538
|
'session.id': sessionId,
|
|
@@ -384,6 +541,7 @@ export class OTel extends TelemetryConnector {
|
|
|
384
541
|
});
|
|
385
542
|
hookContext.convSpan = convSpan;
|
|
386
543
|
hookContext.agentId = agentId;
|
|
544
|
+
hookContext.agentName = agentData?.name || undefined;
|
|
387
545
|
hookContext.processId = processId;
|
|
388
546
|
hookContext.teamId = teamId;
|
|
389
547
|
hookContext.orgSlot = orgSlot;
|
|
@@ -410,12 +568,15 @@ export class OTel extends TelemetryConnector {
|
|
|
410
568
|
hookContext.toolInfoHandler = createToolInfoHandler(hookContext);
|
|
411
569
|
conversation.on(TLLMEvent.ToolInfo, hookContext.toolInfoHandler);
|
|
412
570
|
|
|
571
|
+
hookContext.errorHandler = createErrorHandler(hookContext);
|
|
572
|
+
conversation.on(TLLMEvent.Error, hookContext.errorHandler);
|
|
573
|
+
|
|
413
574
|
// Add start event
|
|
414
575
|
|
|
415
576
|
convSpan.addEvent('skill.process.started', {
|
|
416
577
|
'input.size': JSON.stringify(message || {}).length,
|
|
417
|
-
'input.preview': message.substring(0, 200),
|
|
418
|
-
'llm.model': modelId || '
|
|
578
|
+
'input.preview': oTelInstance.redactString(message.substring(0, 200)),
|
|
579
|
+
'llm.model': modelId || '',
|
|
419
580
|
});
|
|
420
581
|
|
|
421
582
|
OTelContextRegistry.startProcess(agentId, processId, convSpan);
|
|
@@ -438,9 +599,10 @@ export class OTel extends TelemetryConnector {
|
|
|
438
599
|
'org.slot': orgSlot,
|
|
439
600
|
|
|
440
601
|
'agent.id': agentId,
|
|
602
|
+
'agent.name': agentName,
|
|
441
603
|
'conv.id': processId,
|
|
442
604
|
'input.size': JSON.stringify(message || {}).length,
|
|
443
|
-
'input.preview': message.substring(0,
|
|
605
|
+
'input.preview': oTelInstance.redactString(message.substring(0, 4000)),
|
|
444
606
|
'agent.debug': isDebugSession,
|
|
445
607
|
'agent.isTest': isTestDomain,
|
|
446
608
|
'session.id': sessionId,
|
|
@@ -450,7 +612,7 @@ export class OTel extends TelemetryConnector {
|
|
|
450
612
|
});
|
|
451
613
|
});
|
|
452
614
|
},
|
|
453
|
-
THook.NonBlocking
|
|
615
|
+
THook.NonBlocking,
|
|
454
616
|
);
|
|
455
617
|
|
|
456
618
|
HookService.registerAfter(
|
|
@@ -471,6 +633,7 @@ export class OTel extends TelemetryConnector {
|
|
|
471
633
|
const sessionId = processId;
|
|
472
634
|
const workflowId = agentData?.workflowReqId || agentData?.workflowID || agentData?.workflowId || undefined;
|
|
473
635
|
const logTags = agentData?.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
636
|
+
const agentName = agentData?.name || undefined;
|
|
474
637
|
|
|
475
638
|
if (message == null) {
|
|
476
639
|
return;
|
|
@@ -489,7 +652,9 @@ export class OTel extends TelemetryConnector {
|
|
|
489
652
|
}
|
|
490
653
|
hookContext.curLLMGenSpan.addEvent('llm.gen.content', {
|
|
491
654
|
'content.size': JSON.stringify(result || {}).length,
|
|
492
|
-
'content.preview':
|
|
655
|
+
'content.preview': oTelInstance.redactString(
|
|
656
|
+
typeof result === 'string' ? result.substring(0, 200) : JSON.stringify(result || {}).substring(0, 200),
|
|
657
|
+
),
|
|
493
658
|
});
|
|
494
659
|
hookContext.curLLMGenSpan.end();
|
|
495
660
|
|
|
@@ -498,46 +663,52 @@ export class OTel extends TelemetryConnector {
|
|
|
498
663
|
if (hookContext.requestedHandler) conversation.off(TLLMEvent.Requested, hookContext.requestedHandler);
|
|
499
664
|
}
|
|
500
665
|
|
|
666
|
+
if (hookContext.errorHandler) conversation.off(TLLMEvent.Error, hookContext.errorHandler);
|
|
667
|
+
|
|
501
668
|
const { rootSpan: convSpan } = ctx;
|
|
502
669
|
|
|
503
670
|
const spanCtx = convSpan.spanContext();
|
|
504
671
|
const spanContext = trace.setSpan(context.active(), convSpan);
|
|
505
672
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
convSpan.recordException(error);
|
|
509
|
-
convSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
510
|
-
convSpan.addEvent('conv.error', {
|
|
511
|
-
'error.message': error.message,
|
|
512
|
-
});
|
|
673
|
+
// Check for errors - either thrown (error param) or emitted via event (hookContext.hasError)
|
|
674
|
+
const hasError = error || hookContext.hasError;
|
|
513
675
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
// Explicit trace correlation
|
|
522
|
-
trace_id: spanCtx.traceId,
|
|
523
|
-
span_id: spanCtx.spanId,
|
|
524
|
-
trace_flags: spanCtx.traceFlags,
|
|
676
|
+
if (hasError) {
|
|
677
|
+
if (error && !hookContext.hasError) {
|
|
678
|
+
convSpan.recordException(error);
|
|
679
|
+
convSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message || 'Unknown error' });
|
|
680
|
+
convSpan.addEvent('conv.error', {
|
|
681
|
+
'error.message': error.message || 'Unknown error',
|
|
682
|
+
});
|
|
525
683
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
'
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
684
|
+
context.with(spanContext, () => {
|
|
685
|
+
logger.emit({
|
|
686
|
+
severityNumber: SeverityNumber.ERROR,
|
|
687
|
+
severityText: 'ERROR',
|
|
688
|
+
body: `Conversation.streamPrompt failed: ${processId}`,
|
|
689
|
+
attributes: {
|
|
690
|
+
// Explicit trace correlation (some backends need these)
|
|
691
|
+
trace_id: spanCtx.traceId,
|
|
692
|
+
span_id: spanCtx.spanId,
|
|
693
|
+
trace_flags: spanCtx.traceFlags,
|
|
694
|
+
|
|
695
|
+
'agent.id': agentId,
|
|
696
|
+
'agent.name': agentName,
|
|
697
|
+
'conv.id': processId,
|
|
698
|
+
'error.message': error.message || 'Unknown error',
|
|
699
|
+
'error.stack': error.stack,
|
|
700
|
+
'team.id': teamId,
|
|
701
|
+
'org.tier': orgTier,
|
|
702
|
+
'org.slot': orgSlot,
|
|
703
|
+
'agent.debug': isDebugSession,
|
|
704
|
+
'agent.isTest': isTestDomain,
|
|
705
|
+
'session.id': sessionId,
|
|
706
|
+
'workflow.id': workflowId,
|
|
707
|
+
'log.tags': logTags,
|
|
708
|
+
},
|
|
709
|
+
});
|
|
539
710
|
});
|
|
540
|
-
}
|
|
711
|
+
}
|
|
541
712
|
} else {
|
|
542
713
|
// Success handling
|
|
543
714
|
convSpan.setStatus({ code: SpanStatusCode.OK });
|
|
@@ -548,11 +719,18 @@ export class OTel extends TelemetryConnector {
|
|
|
548
719
|
severityText: 'INFO',
|
|
549
720
|
body: `Conversation.streamPrompt completed: ${processId}`,
|
|
550
721
|
attributes: {
|
|
722
|
+
// Explicit trace correlation (some backends need these)
|
|
723
|
+
trace_id: spanCtx.traceId,
|
|
724
|
+
span_id: spanCtx.spanId,
|
|
725
|
+
trace_flags: spanCtx.traceFlags,
|
|
726
|
+
|
|
551
727
|
'agent.id': agentId,
|
|
728
|
+
'agent.name': agentName,
|
|
552
729
|
'conv.id': processId,
|
|
553
730
|
'output.size': JSON.stringify(result || {}).length,
|
|
554
|
-
'output.preview':
|
|
555
|
-
typeof result === 'string' ? result
|
|
731
|
+
'output.preview': oTelInstance.redactString(
|
|
732
|
+
(typeof result === 'string' ? result : JSON.stringify(result || {})).substring(0, 4000),
|
|
733
|
+
),
|
|
556
734
|
'team.id': teamId,
|
|
557
735
|
'org.tier': orgTier,
|
|
558
736
|
'org.slot': orgSlot,
|
|
@@ -570,7 +748,7 @@ export class OTel extends TelemetryConnector {
|
|
|
570
748
|
|
|
571
749
|
OTelContextRegistry.endProcess(agentId, processId);
|
|
572
750
|
},
|
|
573
|
-
THook.NonBlocking
|
|
751
|
+
THook.NonBlocking,
|
|
574
752
|
);
|
|
575
753
|
|
|
576
754
|
HookService.register(
|
|
@@ -597,6 +775,7 @@ export class OTel extends TelemetryConnector {
|
|
|
597
775
|
const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
598
776
|
const isTestDomain = agent.usingTestDomain || false;
|
|
599
777
|
const domain = agent.domain || undefined;
|
|
778
|
+
const agentName = agent.name || undefined;
|
|
600
779
|
|
|
601
780
|
const accessCandidate = AccessCandidate.agent(agentId);
|
|
602
781
|
if (OTEL_DEBUG_LOGS) outputLogger.debug('SREAgent.process started', { processId, agentProcessId, endpointPath }, accessCandidate);
|
|
@@ -608,6 +787,11 @@ export class OTel extends TelemetryConnector {
|
|
|
608
787
|
|
|
609
788
|
const input = { body, query, headers, processInput: agentInput };
|
|
610
789
|
|
|
790
|
+
const logBody = oTelInstance.prepareComponentData(agentRequest.body || {}, undefined, 4000);
|
|
791
|
+
const logQuery = oTelInstance.prepareComponentData(agentRequest.query || {}, undefined, 4000);
|
|
792
|
+
const logHeaders = oTelInstance.prepareComponentData(agentRequest.headers || {}, undefined, 4000);
|
|
793
|
+
const logAgentInput = oTelInstance.prepareComponentData(inputData || {}, undefined, 4000);
|
|
794
|
+
|
|
611
795
|
let convSpan;
|
|
612
796
|
let parentContext = context.active();
|
|
613
797
|
|
|
@@ -640,6 +824,7 @@ export class OTel extends TelemetryConnector {
|
|
|
640
824
|
{
|
|
641
825
|
attributes: {
|
|
642
826
|
'agent.id': agentId,
|
|
827
|
+
'agent.name': agentName,
|
|
643
828
|
'team.id': teamId,
|
|
644
829
|
'conv.id': conversationId,
|
|
645
830
|
'process.id': agentProcessId,
|
|
@@ -652,11 +837,11 @@ export class OTel extends TelemetryConnector {
|
|
|
652
837
|
'agent.domain': domain,
|
|
653
838
|
},
|
|
654
839
|
},
|
|
655
|
-
parentContext
|
|
840
|
+
parentContext,
|
|
656
841
|
);
|
|
657
842
|
|
|
658
843
|
// Add start event
|
|
659
|
-
const inputPreview = JSON.stringify(input || {}).substring(0, 200);
|
|
844
|
+
const inputPreview = oTelInstance.redactString(JSON.stringify(input || {}).substring(0, 200));
|
|
660
845
|
agentSpan.addEvent('skill.process.started', {
|
|
661
846
|
endpoint: endpointPath,
|
|
662
847
|
'input.size': JSON.stringify(input || {}).length,
|
|
@@ -678,12 +863,14 @@ export class OTel extends TelemetryConnector {
|
|
|
678
863
|
trace_id: spanCtx.traceId,
|
|
679
864
|
span_id: spanCtx.spanId,
|
|
680
865
|
trace_flags: spanCtx.traceFlags,
|
|
866
|
+
|
|
681
867
|
'agent.id': agentId,
|
|
868
|
+
'agent.name': agentName,
|
|
682
869
|
'process.id': agentProcessId,
|
|
683
|
-
input:
|
|
684
|
-
body,
|
|
685
|
-
query,
|
|
686
|
-
headers,
|
|
870
|
+
input: oTelInstance.redactObject(logAgentInput),
|
|
871
|
+
body: oTelInstance.redactObject(logBody),
|
|
872
|
+
query: oTelInstance.redactObject(logQuery),
|
|
873
|
+
headers: oTelInstance.redactRequestHeaders(logHeaders),
|
|
687
874
|
'team.id': teamId,
|
|
688
875
|
'org.slot': orgSlot,
|
|
689
876
|
'org.tier': orgTier,
|
|
@@ -698,7 +885,7 @@ export class OTel extends TelemetryConnector {
|
|
|
698
885
|
} as any);
|
|
699
886
|
});
|
|
700
887
|
},
|
|
701
|
-
THook.NonBlocking
|
|
888
|
+
THook.NonBlocking,
|
|
702
889
|
);
|
|
703
890
|
|
|
704
891
|
HookService.registerAfter(
|
|
@@ -720,6 +907,7 @@ export class OTel extends TelemetryConnector {
|
|
|
720
907
|
const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
721
908
|
const isTestDomain = agent.usingTestDomain || false;
|
|
722
909
|
const domain = agent.domain || undefined;
|
|
910
|
+
const agentName = agent.name || undefined;
|
|
723
911
|
|
|
724
912
|
const ctx = OTelContextRegistry.get(agentId, agentProcessId);
|
|
725
913
|
if (!ctx) return;
|
|
@@ -774,7 +962,9 @@ export class OTel extends TelemetryConnector {
|
|
|
774
962
|
trace_id: spanCtx.traceId,
|
|
775
963
|
span_id: spanCtx.spanId,
|
|
776
964
|
trace_flags: spanCtx.traceFlags,
|
|
965
|
+
|
|
777
966
|
'agent.id': agentId,
|
|
967
|
+
'agent.name': agentName,
|
|
778
968
|
'process.id': agentProcessId,
|
|
779
969
|
hasError: isError,
|
|
780
970
|
'error.message': isError ? errorMessage : undefined,
|
|
@@ -813,7 +1003,7 @@ export class OTel extends TelemetryConnector {
|
|
|
813
1003
|
|
|
814
1004
|
OTelContextRegistry.endProcess(agentId, agentProcessId);
|
|
815
1005
|
},
|
|
816
|
-
THook.NonBlocking
|
|
1006
|
+
THook.NonBlocking,
|
|
817
1007
|
);
|
|
818
1008
|
|
|
819
1009
|
// In setupHooks() - Enhanced Component.process hook
|
|
@@ -844,6 +1034,7 @@ export class OTel extends TelemetryConnector {
|
|
|
844
1034
|
const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
|
|
845
1035
|
const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
846
1036
|
const isTestDomain = agent.usingTestDomain || false;
|
|
1037
|
+
const agentName = agent.name || undefined;
|
|
847
1038
|
|
|
848
1039
|
const inputAction = input?.__action || undefined;
|
|
849
1040
|
const inputStatus = input?.__status || undefined;
|
|
@@ -860,6 +1051,7 @@ export class OTel extends TelemetryConnector {
|
|
|
860
1051
|
{
|
|
861
1052
|
attributes: {
|
|
862
1053
|
'agent.id': agentId,
|
|
1054
|
+
'agent.name': agentName,
|
|
863
1055
|
'process.id': processId,
|
|
864
1056
|
'event.id': eventId,
|
|
865
1057
|
'cmp.id': componentId,
|
|
@@ -878,22 +1070,30 @@ export class OTel extends TelemetryConnector {
|
|
|
878
1070
|
...compSettingsData,
|
|
879
1071
|
},
|
|
880
1072
|
},
|
|
881
|
-
parentSpan ? trace.setSpan(context.active(), parentSpan) : undefined
|
|
1073
|
+
parentSpan ? trace.setSpan(context.active(), parentSpan) : undefined,
|
|
882
1074
|
);
|
|
883
1075
|
|
|
884
1076
|
// Add event: Component started - includes input.action and input.status for workflow tracking
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
const
|
|
1077
|
+
// Use component-specific input (from predecessor nodes), not the merged object with agent variables
|
|
1078
|
+
// For APIEndpoint, use HTTP request body/query as the actual user input
|
|
1079
|
+
const componentInput =
|
|
1080
|
+
componentType === 'APIEndpoint'
|
|
1081
|
+
? agent.agentRequest?.method === 'GET'
|
|
1082
|
+
? agent.agentRequest?.query
|
|
1083
|
+
: agent.agentRequest?.body
|
|
1084
|
+
: componentData?.runtimeData?.input || {};
|
|
1085
|
+
|
|
1086
|
+
const compInputData = oTelInstance.prepareComponentData(componentInput || {});
|
|
888
1087
|
span.addEvent('cmp.call', {
|
|
889
1088
|
'event.id': eventId,
|
|
890
|
-
'cmp.input.size': JSON.stringify(
|
|
891
|
-
'cmp.input': JSON.stringify(compInputData),
|
|
1089
|
+
'cmp.input.size': JSON.stringify(componentInput || {}).length,
|
|
1090
|
+
'cmp.input': oTelInstance.redactString(JSON.stringify(compInputData)),
|
|
892
1091
|
'input.action': inputAction,
|
|
893
1092
|
'input.status': inputStatus,
|
|
894
1093
|
});
|
|
895
1094
|
|
|
896
1095
|
// Emit structured log with full details
|
|
1096
|
+
const cmpSpanCtx = span.spanContext();
|
|
897
1097
|
const spanContext = trace.setSpan(context.active(), span);
|
|
898
1098
|
context.with(spanContext, () => {
|
|
899
1099
|
logger.emit({
|
|
@@ -901,13 +1101,19 @@ export class OTel extends TelemetryConnector {
|
|
|
901
1101
|
severityText: 'INFO',
|
|
902
1102
|
body: `Component ${componentType} started`,
|
|
903
1103
|
attributes: {
|
|
1104
|
+
// Explicit trace correlation (some backends need these)
|
|
1105
|
+
trace_id: cmpSpanCtx.traceId,
|
|
1106
|
+
span_id: cmpSpanCtx.spanId,
|
|
1107
|
+
trace_flags: cmpSpanCtx.traceFlags,
|
|
1108
|
+
|
|
904
1109
|
'agent.id': agentId,
|
|
1110
|
+
'agent.name': agentName,
|
|
905
1111
|
'process.id': processId,
|
|
906
1112
|
'event.id': eventId,
|
|
907
1113
|
'cmp.id': componentId,
|
|
908
1114
|
'cmp.type': componentType,
|
|
909
1115
|
'cmp.name': componentName,
|
|
910
|
-
'cmp.input':
|
|
1116
|
+
'cmp.input': oTelInstance.redactObject(componentInput),
|
|
911
1117
|
'team.id': teamId,
|
|
912
1118
|
'org.slot': orgSlot,
|
|
913
1119
|
'org.tier': orgTier,
|
|
@@ -926,7 +1132,7 @@ export class OTel extends TelemetryConnector {
|
|
|
926
1132
|
// Store span in hook context (isolated per component execution, concurrency-safe)
|
|
927
1133
|
this.context.otelSpan = span;
|
|
928
1134
|
},
|
|
929
|
-
THook.NonBlocking
|
|
1135
|
+
THook.NonBlocking,
|
|
930
1136
|
);
|
|
931
1137
|
|
|
932
1138
|
HookService.registerAfter(
|
|
@@ -961,6 +1167,7 @@ export class OTel extends TelemetryConnector {
|
|
|
961
1167
|
const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
|
|
962
1168
|
const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
963
1169
|
const isTestDomain = agent.usingTestDomain || false;
|
|
1170
|
+
const agentName = agent.name || undefined;
|
|
964
1171
|
|
|
965
1172
|
const accessCandidate = AccessCandidate.agent(agentId);
|
|
966
1173
|
if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process completed', { componentId }, accessCandidate);
|
|
@@ -982,6 +1189,7 @@ export class OTel extends TelemetryConnector {
|
|
|
982
1189
|
});
|
|
983
1190
|
|
|
984
1191
|
// Emit error log
|
|
1192
|
+
const cmpErrorSpanCtx = span.spanContext();
|
|
985
1193
|
const spanContext = trace.setSpan(context.active(), span);
|
|
986
1194
|
context.with(spanContext, () => {
|
|
987
1195
|
logger.emit({
|
|
@@ -989,7 +1197,13 @@ export class OTel extends TelemetryConnector {
|
|
|
989
1197
|
severityText: 'ERROR',
|
|
990
1198
|
body: `Component ${componentType} (${componentId}) failed: ${error.message}`,
|
|
991
1199
|
attributes: {
|
|
1200
|
+
// Explicit trace correlation (some backends need these)
|
|
1201
|
+
trace_id: cmpErrorSpanCtx.traceId,
|
|
1202
|
+
span_id: cmpErrorSpanCtx.spanId,
|
|
1203
|
+
trace_flags: cmpErrorSpanCtx.traceFlags,
|
|
1204
|
+
|
|
992
1205
|
'agent.id': agentId,
|
|
1206
|
+
'agent.name': agentName,
|
|
993
1207
|
'process.id': processId,
|
|
994
1208
|
'event.id': eventId,
|
|
995
1209
|
'cmp.id': componentId,
|
|
@@ -1039,6 +1253,7 @@ export class OTel extends TelemetryConnector {
|
|
|
1039
1253
|
});
|
|
1040
1254
|
|
|
1041
1255
|
// Emit ERROR log for result error
|
|
1256
|
+
const cmpResultErrorSpanCtx = span.spanContext();
|
|
1042
1257
|
const spanContext = trace.setSpan(context.active(), span);
|
|
1043
1258
|
context.with(spanContext, () => {
|
|
1044
1259
|
logger.emit({
|
|
@@ -1046,7 +1261,13 @@ export class OTel extends TelemetryConnector {
|
|
|
1046
1261
|
severityText: 'ERROR',
|
|
1047
1262
|
body: `Component ${componentType} (${componentId}) failed: ${errorMessage}`,
|
|
1048
1263
|
attributes: {
|
|
1264
|
+
// Explicit trace correlation (some backends need these)
|
|
1265
|
+
trace_id: cmpResultErrorSpanCtx.traceId,
|
|
1266
|
+
span_id: cmpResultErrorSpanCtx.spanId,
|
|
1267
|
+
trace_flags: cmpResultErrorSpanCtx.traceFlags,
|
|
1268
|
+
|
|
1049
1269
|
'agent.id': agentId,
|
|
1270
|
+
'agent.name': agentName,
|
|
1050
1271
|
'process.id': processId,
|
|
1051
1272
|
'event.id': eventId,
|
|
1052
1273
|
'cmp.id': componentId,
|
|
@@ -1054,7 +1275,7 @@ export class OTel extends TelemetryConnector {
|
|
|
1054
1275
|
'cmp.type': componentType,
|
|
1055
1276
|
'error.type': 'result_error',
|
|
1056
1277
|
'error.message': errorMessage,
|
|
1057
|
-
'cmp.output': result,
|
|
1278
|
+
'cmp.output': oTelInstance.redactObject(result),
|
|
1058
1279
|
'team.id': teamId,
|
|
1059
1280
|
'org.slot': orgSlot,
|
|
1060
1281
|
'org.tier': orgTier,
|
|
@@ -1076,7 +1297,7 @@ export class OTel extends TelemetryConnector {
|
|
|
1076
1297
|
// Add success event with output summary
|
|
1077
1298
|
span.addEvent('cmp.call.result', {
|
|
1078
1299
|
'output.size': resultStr.length,
|
|
1079
|
-
'output.preview': resultStr.substring(0, 200),
|
|
1300
|
+
'output.preview': oTelInstance.redactString(resultStr.substring(0, 200)),
|
|
1080
1301
|
});
|
|
1081
1302
|
|
|
1082
1303
|
// Add output attributes to span
|
|
@@ -1086,14 +1307,21 @@ export class OTel extends TelemetryConnector {
|
|
|
1086
1307
|
});
|
|
1087
1308
|
|
|
1088
1309
|
// Emit success log with output (formatted safely)
|
|
1310
|
+
const cmpSuccessSpanCtx = span.spanContext();
|
|
1089
1311
|
const logAttributes: Record<string, any> = {
|
|
1312
|
+
// Explicit trace correlation (some backends need these)
|
|
1313
|
+
trace_id: cmpSuccessSpanCtx.traceId,
|
|
1314
|
+
span_id: cmpSuccessSpanCtx.spanId,
|
|
1315
|
+
trace_flags: cmpSuccessSpanCtx.traceFlags,
|
|
1316
|
+
|
|
1090
1317
|
'agent.id': agentId,
|
|
1318
|
+
'agent.name': agentName,
|
|
1091
1319
|
'cmp.id': componentId,
|
|
1092
1320
|
'cmp.type': componentType,
|
|
1093
1321
|
'cmp.name': componentName,
|
|
1094
1322
|
'process.id': processId,
|
|
1095
1323
|
'event.id': eventId,
|
|
1096
|
-
'cmp.output': result,
|
|
1324
|
+
'cmp.output': oTelInstance.redactObject(result),
|
|
1097
1325
|
'team.id': teamId,
|
|
1098
1326
|
'org.slot': orgSlot,
|
|
1099
1327
|
'org.tier': orgTier,
|
|
@@ -1121,7 +1349,7 @@ export class OTel extends TelemetryConnector {
|
|
|
1121
1349
|
|
|
1122
1350
|
span.end();
|
|
1123
1351
|
},
|
|
1124
|
-
THook.NonBlocking
|
|
1352
|
+
THook.NonBlocking,
|
|
1125
1353
|
);
|
|
1126
1354
|
return Promise.resolve();
|
|
1127
1355
|
}
|