@smythos/sre 1.7.40 → 1.7.42
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.js +49 -42
- package/dist/index.js.map +1 -1
- package/dist/types/Components/AgentPlugin.class.d.ts +1 -1
- package/dist/types/Components/RAG/DataSourceCleaner.class.d.ts +4 -4
- package/dist/types/Components/RAG/DataSourceComponent.class.d.ts +5 -1
- package/dist/types/config.d.ts +1 -0
- package/dist/types/helpers/Conversation.helper.d.ts +10 -13
- package/dist/types/helpers/TemplateString.helper.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/subsystems/IO/VectorDB.service/VectorDBConnector.d.ts +1 -0
- package/dist/types/subsystems/LLMManager/LLM.helper.d.ts +19 -0
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +15 -10
- package/dist/types/types/LLM.types.d.ts +23 -0
- package/package.json +1 -1
- package/src/Components/AgentPlugin.class.ts +20 -3
- package/src/Components/Classifier.class.ts +79 -16
- package/src/Components/ForEach.class.ts +34 -6
- package/src/Components/GenAILLM.class.ts +54 -23
- package/src/Components/LLMAssistant.class.ts +56 -21
- package/src/Components/RAG/DataSourceCleaner.class.ts +13 -11
- package/src/Components/RAG/DataSourceComponent.class.ts +39 -13
- package/src/Components/RAG/DataSourceIndexer.class.ts +18 -12
- package/src/Components/RAG/DataSourceLookup.class.ts +14 -10
- package/src/Components/ScrapflyWebScrape.class.ts +7 -0
- package/src/config.ts +1 -0
- package/src/helpers/Conversation.helper.ts +112 -26
- package/src/helpers/TemplateString.helper.ts +6 -5
- package/src/index.ts +213 -212
- package/src/index.ts.bak +213 -212
- package/src/subsystems/IO/VectorDB.service/VectorDBConnector.ts +1 -0
- package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +11 -0
- package/src/subsystems/IO/VectorDB.service/embed/index.ts +9 -11
- package/src/subsystems/LLMManager/LLM.helper.ts +25 -0
- package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +1 -1
- package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +190 -146
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/utils.ts +1 -1
- package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +402 -66
- package/src/types/LLM.types.ts +24 -0
- package/src/utils/data.utils.ts +6 -4
- package/src/Components/DataSourceIndexer.class.ts +0 -295
|
@@ -5,7 +5,7 @@ import { IAccessCandidate } from '@sre/types/ACL.types';
|
|
|
5
5
|
import { TelemetryConnector } from '../../TelemetryConnector';
|
|
6
6
|
import { AgentCallLog } from '@sre/types/AgentLogger.types';
|
|
7
7
|
|
|
8
|
-
import { trace, context, SpanStatusCode, Tracer } from '@opentelemetry/api';
|
|
8
|
+
import { trace, context, SpanStatusCode, Tracer, propagation } from '@opentelemetry/api';
|
|
9
9
|
import { Logger as OTelLogger, logs, SeverityNumber } from '@opentelemetry/api-logs';
|
|
10
10
|
import { OTelContextRegistry } from './OTelContextRegistry';
|
|
11
11
|
import { HookService, THook } from '@sre/Core/HookService';
|
|
@@ -62,6 +62,10 @@ export class OTel extends TelemetryConnector {
|
|
|
62
62
|
|
|
63
63
|
constructor(protected _settings: OTelLogConfig) {
|
|
64
64
|
super();
|
|
65
|
+
if (!_settings.endpoint) {
|
|
66
|
+
outputLogger.warn('OTel initialization skipped, endpoint is not set');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
65
69
|
|
|
66
70
|
outputLogger.log(`Initializing Tracer ...`);
|
|
67
71
|
|
|
@@ -279,6 +283,7 @@ export class OTel extends TelemetryConnector {
|
|
|
279
283
|
attributes: {
|
|
280
284
|
'agent.id': hookContext.agentId,
|
|
281
285
|
'conv.id': hookContext.processId,
|
|
286
|
+
'team.id': hookContext.teamId,
|
|
282
287
|
'llm.model': modelId || 'unknown',
|
|
283
288
|
},
|
|
284
289
|
},
|
|
@@ -312,6 +317,7 @@ export class OTel extends TelemetryConnector {
|
|
|
312
317
|
attributes: {
|
|
313
318
|
'agent.id': hookContext.agentId,
|
|
314
319
|
'conv.id': hookContext.processId,
|
|
320
|
+
'team.id': hookContext.teamId,
|
|
315
321
|
'request.id': reqInfo.requestId,
|
|
316
322
|
'llm.model': modelId || 'unknown',
|
|
317
323
|
'metric.type': 'ttfb',
|
|
@@ -331,11 +337,21 @@ export class OTel extends TelemetryConnector {
|
|
|
331
337
|
HookService.register(
|
|
332
338
|
'Conversation.streamPrompt',
|
|
333
339
|
async function (additionalContext, args) {
|
|
334
|
-
const conversation: Conversation = this.instance;
|
|
335
|
-
const processId = conversation.id;
|
|
340
|
+
const conversation: Conversation = this.instance; //this.instance.agentData.teamId // this.instance.agentData.parenparentTeamId //this.instance.agentData.planInfo.properties this.instance.agentData.planInfo.flags
|
|
341
|
+
const processId = conversation.storeId || conversation.id;
|
|
336
342
|
const agentId = conversation.agentId;
|
|
337
343
|
const message = typeof args === 'object' ? args?.message : args || null;
|
|
338
344
|
const hookContext: any = this.context;
|
|
345
|
+
const teamId = conversation.agentData.teamId;
|
|
346
|
+
const orgTier = 'standard';
|
|
347
|
+
const orgSlot = this.instance.agentData?.planInfo?.flags ? `standard/${teamId}` : undefined;
|
|
348
|
+
const agentData = conversation.agentData || {};
|
|
349
|
+
const isDebugSession = agentData.debugSessionEnabled || false;
|
|
350
|
+
const isTestDomain = agentData.usingTestDomain || false;
|
|
351
|
+
const sessionId = processId;
|
|
352
|
+
const workflowId = agentData?.workflowReqId || agentData?.workflowID || agentData?.workflowId || undefined;
|
|
353
|
+
const logTags = agentData?.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
354
|
+
|
|
339
355
|
if (message == null) {
|
|
340
356
|
//this is a conversation step, will be handled by createRequestedHandler
|
|
341
357
|
|
|
@@ -354,14 +370,36 @@ export class OTel extends TelemetryConnector {
|
|
|
354
370
|
'gen_ai.conversation.id': processId,
|
|
355
371
|
'gen_ai.request.model': modelId || 'unknown',
|
|
356
372
|
////////////////////////////////
|
|
373
|
+
'team.id': teamId,
|
|
374
|
+
'org.tier': orgTier,
|
|
375
|
+
'org.slot': orgSlot,
|
|
357
376
|
'agent.id': agentId,
|
|
358
377
|
'conv.id': processId,
|
|
359
378
|
'llm.model': modelId || 'unknown',
|
|
379
|
+
'agent.debug': isDebugSession,
|
|
380
|
+
'agent.isTest': isTestDomain,
|
|
381
|
+
'session.id': sessionId,
|
|
382
|
+
'workflow.id': workflowId,
|
|
360
383
|
},
|
|
361
384
|
});
|
|
362
385
|
hookContext.convSpan = convSpan;
|
|
363
386
|
hookContext.agentId = agentId;
|
|
364
387
|
hookContext.processId = processId;
|
|
388
|
+
hookContext.teamId = teamId;
|
|
389
|
+
hookContext.orgSlot = orgSlot;
|
|
390
|
+
hookContext.isDebugSession = isDebugSession;
|
|
391
|
+
hookContext.isTestDomain = isTestDomain;
|
|
392
|
+
|
|
393
|
+
// Inject trace context into conversation headers for distributed tracing
|
|
394
|
+
let headers = {};
|
|
395
|
+
const traceContext = trace.setSpan(context.active(), convSpan);
|
|
396
|
+
propagation.inject(traceContext, headers);
|
|
397
|
+
for (let [key, value] of Object.entries(headers)) {
|
|
398
|
+
conversation.headers[key] = value as string;
|
|
399
|
+
}
|
|
400
|
+
if (OTEL_DEBUG_LOGS) {
|
|
401
|
+
outputLogger.debug('Injected trace headers into conversation', { processId, headers });
|
|
402
|
+
}
|
|
365
403
|
|
|
366
404
|
hookContext.dataHandler = createDataHandler(hookContext);
|
|
367
405
|
conversation.on(TLLMEvent.Data, hookContext.dataHandler);
|
|
@@ -395,10 +433,19 @@ export class OTel extends TelemetryConnector {
|
|
|
395
433
|
span_id: spanCtx.spanId,
|
|
396
434
|
trace_flags: spanCtx.traceFlags,
|
|
397
435
|
|
|
436
|
+
/////
|
|
437
|
+
'team.id': teamId,
|
|
438
|
+
'org.slot': orgSlot,
|
|
439
|
+
|
|
398
440
|
'agent.id': agentId,
|
|
399
441
|
'conv.id': processId,
|
|
400
442
|
'input.size': JSON.stringify(message || {}).length,
|
|
401
443
|
'input.preview': message.substring(0, 2000),
|
|
444
|
+
'agent.debug': isDebugSession,
|
|
445
|
+
'agent.isTest': isTestDomain,
|
|
446
|
+
'session.id': sessionId,
|
|
447
|
+
'workflow.id': workflowId,
|
|
448
|
+
'log.tags': logTags,
|
|
402
449
|
},
|
|
403
450
|
});
|
|
404
451
|
});
|
|
@@ -410,10 +457,21 @@ export class OTel extends TelemetryConnector {
|
|
|
410
457
|
'Conversation.streamPrompt',
|
|
411
458
|
async function ({ result, args, error }) {
|
|
412
459
|
const conversation: Conversation = this.instance;
|
|
413
|
-
const processId = conversation.id;
|
|
460
|
+
const processId = conversation.storeId || conversation.id;
|
|
414
461
|
const agentId = conversation.agentId;
|
|
415
462
|
const message = typeof args?.[0] === 'object' ? args?.[0]?.message : args?.[0] || null;
|
|
416
463
|
const hookContext: any = this.context;
|
|
464
|
+
const teamId = conversation.agentData.teamId;
|
|
465
|
+
const orgTier = 'standard';
|
|
466
|
+
const orgSlot = this.instance.agentData?.planInfo?.flags ? `standard/${teamId}` : undefined;
|
|
467
|
+
|
|
468
|
+
const isDebugSession = hookContext.isDebugSession || conversation.agentData?.debugSessionEnabled || false;
|
|
469
|
+
const isTestDomain = hookContext.isTestDomain || conversation.agentData?.usingTestDomain || false;
|
|
470
|
+
const agentData = conversation.agentData || {};
|
|
471
|
+
const sessionId = processId;
|
|
472
|
+
const workflowId = agentData?.workflowReqId || agentData?.workflowID || agentData?.workflowId || undefined;
|
|
473
|
+
const logTags = agentData?.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
474
|
+
|
|
417
475
|
if (message == null) {
|
|
418
476
|
return;
|
|
419
477
|
}
|
|
@@ -424,10 +482,14 @@ export class OTel extends TelemetryConnector {
|
|
|
424
482
|
const accessCandidate = AccessCandidate.agent(agentId);
|
|
425
483
|
if (OTEL_DEBUG_LOGS) outputLogger.debug('Conversation.streamPrompt completed', { processId }, accessCandidate);
|
|
426
484
|
|
|
485
|
+
// Handle curLLMGenSpan with error awareness
|
|
427
486
|
if (hookContext.curLLMGenSpan) {
|
|
487
|
+
if (error) {
|
|
488
|
+
hookContext.curLLMGenSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
489
|
+
}
|
|
428
490
|
hookContext.curLLMGenSpan.addEvent('llm.gen.content', {
|
|
429
491
|
'content.size': JSON.stringify(result || {}).length,
|
|
430
|
-
'content.preview': result.substring(0, 200),
|
|
492
|
+
'content.preview': typeof result === 'string' ? result.substring(0, 200) : JSON.stringify(result || {}).substring(0, 200),
|
|
431
493
|
});
|
|
432
494
|
hookContext.curLLMGenSpan.end();
|
|
433
495
|
|
|
@@ -440,19 +502,69 @@ export class OTel extends TelemetryConnector {
|
|
|
440
502
|
|
|
441
503
|
const spanCtx = convSpan.spanContext();
|
|
442
504
|
const spanContext = trace.setSpan(context.active(), convSpan);
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
'conv.id': processId,
|
|
451
|
-
'output.size': JSON.stringify(result || {}).length,
|
|
452
|
-
'output.preview': result.substring(0, 2000),
|
|
453
|
-
},
|
|
505
|
+
|
|
506
|
+
if (error) {
|
|
507
|
+
// Error handling for conversation span
|
|
508
|
+
convSpan.recordException(error);
|
|
509
|
+
convSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
510
|
+
convSpan.addEvent('conv.error', {
|
|
511
|
+
'error.message': error.message,
|
|
454
512
|
});
|
|
455
|
-
|
|
513
|
+
|
|
514
|
+
// Emit ERROR log
|
|
515
|
+
context.with(spanContext, () => {
|
|
516
|
+
logger.emit({
|
|
517
|
+
severityNumber: SeverityNumber.ERROR,
|
|
518
|
+
severityText: 'ERROR',
|
|
519
|
+
body: `Conversation.streamPrompt failed: ${processId}`,
|
|
520
|
+
attributes: {
|
|
521
|
+
// Explicit trace correlation
|
|
522
|
+
trace_id: spanCtx.traceId,
|
|
523
|
+
span_id: spanCtx.spanId,
|
|
524
|
+
trace_flags: spanCtx.traceFlags,
|
|
525
|
+
|
|
526
|
+
'agent.id': agentId,
|
|
527
|
+
'conv.id': processId,
|
|
528
|
+
'error.message': error.message,
|
|
529
|
+
'error.stack': error.stack,
|
|
530
|
+
'team.id': teamId,
|
|
531
|
+
'org.tier': orgTier,
|
|
532
|
+
'org.slot': orgSlot,
|
|
533
|
+
'agent.debug': isDebugSession,
|
|
534
|
+
'agent.isTest': isTestDomain,
|
|
535
|
+
'session.id': sessionId,
|
|
536
|
+
'workflow.id': workflowId,
|
|
537
|
+
'log.tags': logTags,
|
|
538
|
+
},
|
|
539
|
+
});
|
|
540
|
+
});
|
|
541
|
+
} else {
|
|
542
|
+
// Success handling
|
|
543
|
+
convSpan.setStatus({ code: SpanStatusCode.OK });
|
|
544
|
+
|
|
545
|
+
context.with(spanContext, () => {
|
|
546
|
+
logger.emit({
|
|
547
|
+
severityNumber: SeverityNumber.INFO,
|
|
548
|
+
severityText: 'INFO',
|
|
549
|
+
body: `Conversation.streamPrompt completed: ${processId}`,
|
|
550
|
+
attributes: {
|
|
551
|
+
'agent.id': agentId,
|
|
552
|
+
'conv.id': processId,
|
|
553
|
+
'output.size': JSON.stringify(result || {}).length,
|
|
554
|
+
'output.preview':
|
|
555
|
+
typeof result === 'string' ? result.substring(0, 2000) : JSON.stringify(result || {}).substring(0, 2000),
|
|
556
|
+
'team.id': teamId,
|
|
557
|
+
'org.tier': orgTier,
|
|
558
|
+
'org.slot': orgSlot,
|
|
559
|
+
'agent.debug': isDebugSession,
|
|
560
|
+
'agent.isTest': isTestDomain,
|
|
561
|
+
'session.id': sessionId,
|
|
562
|
+
'workflow.id': workflowId,
|
|
563
|
+
'log.tags': logTags,
|
|
564
|
+
},
|
|
565
|
+
});
|
|
566
|
+
});
|
|
567
|
+
}
|
|
456
568
|
|
|
457
569
|
convSpan.end();
|
|
458
570
|
|
|
@@ -471,11 +583,21 @@ export class OTel extends TelemetryConnector {
|
|
|
471
583
|
const conversationId = agent.conversationId || agent.agentRequest?.header('X-CONVERSATION-ID');
|
|
472
584
|
const processId = agentProcessId.split(':').shift();
|
|
473
585
|
|
|
586
|
+
const orgTier = 'standard';
|
|
587
|
+
const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
|
|
474
588
|
const agentId = agent.id;
|
|
475
589
|
const agentRequest = agent.agentRequest;
|
|
476
590
|
const teamId = agent.teamId;
|
|
477
591
|
const _hookContext: any = this.context;
|
|
478
592
|
|
|
593
|
+
const sessionId = agent.callerSessionId || undefined;
|
|
594
|
+
const workflowId = agent.agentRuntime?.workflowReqId || undefined;
|
|
595
|
+
|
|
596
|
+
const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
|
|
597
|
+
const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
598
|
+
const isTestDomain = agent.usingTestDomain || false;
|
|
599
|
+
const domain = agent.domain || undefined;
|
|
600
|
+
|
|
479
601
|
const accessCandidate = AccessCandidate.agent(agentId);
|
|
480
602
|
if (OTEL_DEBUG_LOGS) outputLogger.debug('SREAgent.process started', { processId, agentProcessId, endpointPath }, accessCandidate);
|
|
481
603
|
|
|
@@ -487,22 +609,50 @@ export class OTel extends TelemetryConnector {
|
|
|
487
609
|
const input = { body, query, headers, processInput: agentInput };
|
|
488
610
|
|
|
489
611
|
let convSpan;
|
|
490
|
-
|
|
612
|
+
let parentContext = context.active();
|
|
613
|
+
|
|
614
|
+
//try reading ctx from local registry (local execution)
|
|
615
|
+
let ctx = OTelContextRegistry.get(agentId, processId) || OTelContextRegistry.get(agentId, conversationId);
|
|
491
616
|
|
|
492
617
|
if (ctx) {
|
|
493
618
|
convSpan = ctx.rootSpan;
|
|
494
619
|
_hookContext.otelSpan = convSpan;
|
|
620
|
+
parentContext = trace.setSpan(context.active(), convSpan);
|
|
621
|
+
} else {
|
|
622
|
+
// No local context found - try extracting from headers (remote execution)
|
|
623
|
+
const extractedContext = propagation.extract(context.active(), agentRequest.headers);
|
|
624
|
+
const extractedSpan = trace.getSpan(extractedContext);
|
|
625
|
+
|
|
626
|
+
if (extractedSpan) {
|
|
627
|
+
// Successfully extracted parent span from headers
|
|
628
|
+
parentContext = extractedContext;
|
|
629
|
+
if (OTEL_DEBUG_LOGS) {
|
|
630
|
+
outputLogger.debug('SREAgent.process extracted remote parent context from headers', {
|
|
631
|
+
processId,
|
|
632
|
+
traceId: extractedSpan.spanContext().traceId,
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
}
|
|
495
636
|
}
|
|
637
|
+
|
|
496
638
|
const agentSpan = tracer.startSpan(
|
|
497
639
|
'Agent.Skill',
|
|
498
640
|
{
|
|
499
641
|
attributes: {
|
|
500
642
|
'agent.id': agentId,
|
|
501
643
|
'team.id': teamId,
|
|
644
|
+
'conv.id': conversationId,
|
|
502
645
|
'process.id': agentProcessId,
|
|
646
|
+
'org.slot': orgSlot,
|
|
647
|
+
'org.tier': orgTier,
|
|
648
|
+
'session.id': sessionId,
|
|
649
|
+
'workflow.id': workflowId,
|
|
650
|
+
'agent.debug': isDebugSession,
|
|
651
|
+
'agent.isTest': isTestDomain,
|
|
652
|
+
'agent.domain': domain,
|
|
503
653
|
},
|
|
504
654
|
},
|
|
505
|
-
|
|
655
|
+
parentContext
|
|
506
656
|
);
|
|
507
657
|
|
|
508
658
|
// Add start event
|
|
@@ -528,12 +678,22 @@ export class OTel extends TelemetryConnector {
|
|
|
528
678
|
trace_id: spanCtx.traceId,
|
|
529
679
|
span_id: spanCtx.spanId,
|
|
530
680
|
trace_flags: spanCtx.traceFlags,
|
|
531
|
-
agentId,
|
|
532
|
-
|
|
681
|
+
'agent.id': agentId,
|
|
682
|
+
'process.id': agentProcessId,
|
|
533
683
|
input: agentInput,
|
|
534
684
|
body,
|
|
535
685
|
query,
|
|
536
686
|
headers,
|
|
687
|
+
'team.id': teamId,
|
|
688
|
+
'org.slot': orgSlot,
|
|
689
|
+
'org.tier': orgTier,
|
|
690
|
+
'conv.id': conversationId,
|
|
691
|
+
'session.id': sessionId,
|
|
692
|
+
'workflow.id': workflowId,
|
|
693
|
+
'log.tags': logTags,
|
|
694
|
+
'agent.debug': isDebugSession,
|
|
695
|
+
'agent.isTest': isTestDomain,
|
|
696
|
+
'agent.domain': domain,
|
|
537
697
|
},
|
|
538
698
|
} as any);
|
|
539
699
|
});
|
|
@@ -546,8 +706,20 @@ export class OTel extends TelemetryConnector {
|
|
|
546
706
|
async function ({ result, error }) {
|
|
547
707
|
const agent = this.instance;
|
|
548
708
|
const agentProcessId = agent.agentRuntime.processID; // nested process has a subID that needs to be removed
|
|
709
|
+
const conversationId = agent.conversationId || agent.agentRequest?.header('X-CONVERSATION-ID');
|
|
549
710
|
const agentId = agent.id;
|
|
550
711
|
const _hookContext: any = this.context;
|
|
712
|
+
const teamId = agent.teamId;
|
|
713
|
+
const orgTier = 'standard';
|
|
714
|
+
const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
|
|
715
|
+
|
|
716
|
+
const sessionId = agent.callerSessionId || undefined;
|
|
717
|
+
const workflowId = agent.agentRuntime?.workflowReqId || undefined;
|
|
718
|
+
|
|
719
|
+
const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
|
|
720
|
+
const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
721
|
+
const isTestDomain = agent.usingTestDomain || false;
|
|
722
|
+
const domain = agent.domain || undefined;
|
|
551
723
|
|
|
552
724
|
const ctx = OTelContextRegistry.get(agentId, agentProcessId);
|
|
553
725
|
if (!ctx) return;
|
|
@@ -558,12 +730,32 @@ export class OTel extends TelemetryConnector {
|
|
|
558
730
|
const accessCandidate = AccessCandidate.agent(agentId);
|
|
559
731
|
if (OTEL_DEBUG_LOGS) outputLogger.debug('SREAgent.process completed', { agentProcessId }, accessCandidate);
|
|
560
732
|
|
|
733
|
+
// Check for error indicators in result (process returned error without throwing)
|
|
734
|
+
const hasResultError = !error && (!!result?._error || !!result?.error);
|
|
735
|
+
const resultError = hasResultError ? result._error || result.error : null;
|
|
736
|
+
const resultErrorMessage = resultError?.message || (typeof resultError === 'string' ? resultError : null);
|
|
737
|
+
|
|
738
|
+
// Determine if this is an error case (either thrown error or result error)
|
|
739
|
+
const isError = !!error || hasResultError;
|
|
740
|
+
const errorMessage = error?.message || resultErrorMessage || 'Process returned error';
|
|
741
|
+
|
|
561
742
|
if (error) {
|
|
562
743
|
agentSpan.recordException(error);
|
|
563
744
|
agentSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
564
745
|
agentSpan.addEvent('skill.process.error', {
|
|
565
746
|
'error.message': error.message,
|
|
566
747
|
});
|
|
748
|
+
} else if (hasResultError) {
|
|
749
|
+
// Handle error in result (no exception thrown)
|
|
750
|
+
agentSpan.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
|
|
751
|
+
agentSpan.addEvent('skill.process.error', {
|
|
752
|
+
'error.message': errorMessage,
|
|
753
|
+
'error.type': 'result_error',
|
|
754
|
+
});
|
|
755
|
+
agentSpan.setAttributes({
|
|
756
|
+
'output.size': JSON.stringify(result || {}).length,
|
|
757
|
+
'output.has_error': true,
|
|
758
|
+
});
|
|
567
759
|
} else {
|
|
568
760
|
agentSpan.setStatus({ code: SpanStatusCode.OK });
|
|
569
761
|
agentSpan.addEvent('skill.process.completed', {
|
|
@@ -575,18 +767,29 @@ export class OTel extends TelemetryConnector {
|
|
|
575
767
|
}
|
|
576
768
|
|
|
577
769
|
// Emit log BEFORE ending span to ensure context is active
|
|
578
|
-
const outputForLog = oTelInstance.formatOutputForLog(result,
|
|
770
|
+
const outputForLog = oTelInstance.formatOutputForLog(result, isError);
|
|
579
771
|
const spanCtx = agentSpan.spanContext();
|
|
580
772
|
const logAttributes: Record<string, any> = {
|
|
581
773
|
// Explicit trace correlation (some backends need these)
|
|
582
774
|
trace_id: spanCtx.traceId,
|
|
583
775
|
span_id: spanCtx.spanId,
|
|
584
776
|
trace_flags: spanCtx.traceFlags,
|
|
585
|
-
agentId,
|
|
586
|
-
|
|
587
|
-
hasError:
|
|
588
|
-
'error.message':
|
|
777
|
+
'agent.id': agentId,
|
|
778
|
+
'process.id': agentProcessId,
|
|
779
|
+
hasError: isError,
|
|
780
|
+
'error.message': isError ? errorMessage : undefined,
|
|
589
781
|
'error.stack': error?.stack,
|
|
782
|
+
'error.type': hasResultError ? 'result_error' : undefined,
|
|
783
|
+
'team.id': teamId,
|
|
784
|
+
'org.slot': orgSlot,
|
|
785
|
+
'org.tier': orgTier,
|
|
786
|
+
'conv.id': conversationId,
|
|
787
|
+
'session.id': sessionId,
|
|
788
|
+
'workflow.id': workflowId,
|
|
789
|
+
'log.tags': logTags,
|
|
790
|
+
'agent.debug': isDebugSession,
|
|
791
|
+
'agent.isTest': isTestDomain,
|
|
792
|
+
'agent.domain': domain,
|
|
590
793
|
};
|
|
591
794
|
|
|
592
795
|
// Only include output if formatOutputForLog returns a value
|
|
@@ -598,9 +801,9 @@ export class OTel extends TelemetryConnector {
|
|
|
598
801
|
const spanContext = trace.setSpan(context.active(), agentSpan);
|
|
599
802
|
context.with(spanContext, () => {
|
|
600
803
|
logger.emit({
|
|
601
|
-
severityNumber:
|
|
602
|
-
severityText:
|
|
603
|
-
body: `Agent process ${
|
|
804
|
+
severityNumber: isError ? SeverityNumber.ERROR : SeverityNumber.INFO,
|
|
805
|
+
severityText: isError ? 'ERROR' : 'INFO',
|
|
806
|
+
body: `Agent process ${isError ? 'failed' : 'completed'}: ${agentProcessId}`,
|
|
604
807
|
attributes: logAttributes,
|
|
605
808
|
} as any);
|
|
606
809
|
});
|
|
@@ -625,7 +828,27 @@ export class OTel extends TelemetryConnector {
|
|
|
625
828
|
const componentName = settings.displayName || settings.name;
|
|
626
829
|
const eventId = settings.eventId; // specific event id attached to this component execution
|
|
627
830
|
const accessCandidate = AccessCandidate.agent(agentId);
|
|
628
|
-
|
|
831
|
+
const teamId = agent.teamId;
|
|
832
|
+
const orgTier = 'standard';
|
|
833
|
+
const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
|
|
834
|
+
|
|
835
|
+
const componentData = agent.agentRuntime?.getComponentData?.(componentId);
|
|
836
|
+
const sourceId = componentData?.sourceId || 'AGENT';
|
|
837
|
+
const sourceComponentData = sourceId !== 'AGENT' ? agent.components?.[sourceId] : null;
|
|
838
|
+
const sourceName = sourceComponentData?.displayName || sourceComponentData?.name || sourceId;
|
|
839
|
+
|
|
840
|
+
const sessionId = agent.callerSessionId || undefined;
|
|
841
|
+
const workflowId = agent.agentRuntime?.workflowReqId || undefined;
|
|
842
|
+
const workflowStep = agent.agentRuntime?.curStep || undefined;
|
|
843
|
+
|
|
844
|
+
const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
|
|
845
|
+
const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
846
|
+
const isTestDomain = agent.usingTestDomain || false;
|
|
847
|
+
|
|
848
|
+
const inputAction = input?.__action || undefined;
|
|
849
|
+
const inputStatus = input?.__status || undefined;
|
|
850
|
+
|
|
851
|
+
if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process started', { componentId, sourceId }, accessCandidate);
|
|
629
852
|
|
|
630
853
|
const ctx = OTelContextRegistry.get(agentId, processId);
|
|
631
854
|
const parentSpan = ctx?.rootSpan;
|
|
@@ -642,13 +865,23 @@ export class OTel extends TelemetryConnector {
|
|
|
642
865
|
'cmp.id': componentId,
|
|
643
866
|
'cmp.type': componentType,
|
|
644
867
|
'cmp.name': componentName,
|
|
868
|
+
'team.id': teamId,
|
|
869
|
+
'org.tier': orgTier,
|
|
870
|
+
'org.slot': orgSlot,
|
|
871
|
+
'source.id': sourceId,
|
|
872
|
+
'source.name': sourceName,
|
|
873
|
+
'session.id': sessionId,
|
|
874
|
+
'workflow.id': workflowId,
|
|
875
|
+
'workflow.step': workflowStep,
|
|
876
|
+
'agent.debug': isDebugSession,
|
|
877
|
+
'agent.isTest': isTestDomain,
|
|
645
878
|
...compSettingsData,
|
|
646
879
|
},
|
|
647
880
|
},
|
|
648
881
|
parentSpan ? trace.setSpan(context.active(), parentSpan) : undefined
|
|
649
882
|
);
|
|
650
883
|
|
|
651
|
-
// Add event: Component started
|
|
884
|
+
// Add event: Component started - includes input.action and input.status for workflow tracking
|
|
652
885
|
const inputStr = JSON.stringify(input || {});
|
|
653
886
|
|
|
654
887
|
const compInputData = oTelInstance.prepareComponentData(input || {});
|
|
@@ -656,6 +889,8 @@ export class OTel extends TelemetryConnector {
|
|
|
656
889
|
'event.id': eventId,
|
|
657
890
|
'cmp.input.size': JSON.stringify(input || {}).length,
|
|
658
891
|
'cmp.input': JSON.stringify(compInputData),
|
|
892
|
+
'input.action': inputAction,
|
|
893
|
+
'input.status': inputStatus,
|
|
659
894
|
});
|
|
660
895
|
|
|
661
896
|
// Emit structured log with full details
|
|
@@ -673,6 +908,17 @@ export class OTel extends TelemetryConnector {
|
|
|
673
908
|
'cmp.type': componentType,
|
|
674
909
|
'cmp.name': componentName,
|
|
675
910
|
'cmp.input': input,
|
|
911
|
+
'team.id': teamId,
|
|
912
|
+
'org.slot': orgSlot,
|
|
913
|
+
'org.tier': orgTier,
|
|
914
|
+
'source.id': sourceId,
|
|
915
|
+
'source.name': sourceName,
|
|
916
|
+
'session.id': sessionId,
|
|
917
|
+
'workflow.id': workflowId,
|
|
918
|
+
'workflow.step': workflowStep,
|
|
919
|
+
'log.tags': logTags,
|
|
920
|
+
'agent.debug': isDebugSession,
|
|
921
|
+
'agent.isTest': isTestDomain,
|
|
676
922
|
},
|
|
677
923
|
});
|
|
678
924
|
});
|
|
@@ -699,6 +945,22 @@ export class OTel extends TelemetryConnector {
|
|
|
699
945
|
const componentId = settings.id || 'unknown';
|
|
700
946
|
const componentType = settings.name;
|
|
701
947
|
const componentName = settings.displayName || settings.name;
|
|
948
|
+
const teamId = agent.teamId;
|
|
949
|
+
const orgTier = 'standard';
|
|
950
|
+
const orgSlot = agent.data.planInfo?.flags ? `standard/${agent.data.teamId}` : undefined;
|
|
951
|
+
|
|
952
|
+
const componentData = agent.agentRuntime?.getComponentData?.(componentId);
|
|
953
|
+
const sourceId = componentData?.sourceId || 'AGENT';
|
|
954
|
+
const sourceComponentData = sourceId !== 'AGENT' ? agent.components?.[sourceId] : null;
|
|
955
|
+
const sourceName = sourceComponentData?.displayName || sourceComponentData?.name || sourceId;
|
|
956
|
+
|
|
957
|
+
const sessionId = agent.callerSessionId || undefined;
|
|
958
|
+
const workflowId = agent.agentRuntime?.workflowReqId || undefined;
|
|
959
|
+
const workflowStep = agent.agentRuntime?.curStep || undefined;
|
|
960
|
+
|
|
961
|
+
const isDebugSession = agent.debugSessionEnabled || agent.agentRuntime?.debug || false;
|
|
962
|
+
const logTags = agent.sessionTag || (isDebugSession ? 'DEBUG' : undefined);
|
|
963
|
+
const isTestDomain = agent.usingTestDomain || false;
|
|
702
964
|
|
|
703
965
|
const accessCandidate = AccessCandidate.agent(agentId);
|
|
704
966
|
if (OTEL_DEBUG_LOGS) outputLogger.debug('Component.process completed', { componentId }, accessCandidate);
|
|
@@ -736,51 +998,125 @@ export class OTel extends TelemetryConnector {
|
|
|
736
998
|
'error.type': error.name,
|
|
737
999
|
'error.message': error.message,
|
|
738
1000
|
'error.stack': error.stack, // ← Full stack in logs
|
|
1001
|
+
'team.id': teamId,
|
|
1002
|
+
'org.slot': orgSlot,
|
|
1003
|
+
'org.tier': orgTier,
|
|
1004
|
+
'source.id': sourceId,
|
|
1005
|
+
'source.name': sourceName,
|
|
1006
|
+
'session.id': sessionId,
|
|
1007
|
+
'workflow.id': workflowId,
|
|
1008
|
+
'workflow.step': workflowStep,
|
|
1009
|
+
'log.tags': logTags,
|
|
1010
|
+
'agent.debug': isDebugSession,
|
|
1011
|
+
'agent.isTest': isTestDomain,
|
|
739
1012
|
},
|
|
740
1013
|
});
|
|
741
1014
|
});
|
|
742
1015
|
} else {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
// Add success event with output summary
|
|
1016
|
+
// Check if result contains an error indicator (component returned error without throwing)
|
|
1017
|
+
const hasResultError = !!result?._error || !!result?.error;
|
|
746
1018
|
const resultStr = JSON.stringify(result || {});
|
|
747
|
-
span.addEvent('cmp.call.result', {
|
|
748
|
-
'output.size': resultStr.length,
|
|
749
|
-
'output.preview': resultStr.substring(0, 200),
|
|
750
|
-
});
|
|
751
1019
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
'
|
|
756
|
-
});
|
|
1020
|
+
if (hasResultError) {
|
|
1021
|
+
// Treat as error even though no exception was thrown
|
|
1022
|
+
const resultError = result._error || result.error;
|
|
1023
|
+
const errorMessage = resultError?.message || (typeof resultError === 'string' ? resultError : 'Component returned error');
|
|
757
1024
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
'cmp.output': result,
|
|
768
|
-
};
|
|
1025
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: errorMessage });
|
|
1026
|
+
span.addEvent('cmp.call.error', {
|
|
1027
|
+
'event.id': eventId,
|
|
1028
|
+
'cmp.id': componentId,
|
|
1029
|
+
'cmp.type': componentType,
|
|
1030
|
+
'cmp.name': componentName,
|
|
1031
|
+
'error.type': 'result_error',
|
|
1032
|
+
'error.message': errorMessage,
|
|
1033
|
+
});
|
|
769
1034
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
1035
|
+
// Add output attributes to span
|
|
1036
|
+
span.setAttributes({
|
|
1037
|
+
'output.size': resultStr.length,
|
|
1038
|
+
'output.has_error': true,
|
|
1039
|
+
});
|
|
774
1040
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
1041
|
+
// Emit ERROR log for result error
|
|
1042
|
+
const spanContext = trace.setSpan(context.active(), span);
|
|
1043
|
+
context.with(spanContext, () => {
|
|
1044
|
+
logger.emit({
|
|
1045
|
+
severityNumber: SeverityNumber.ERROR,
|
|
1046
|
+
severityText: 'ERROR',
|
|
1047
|
+
body: `Component ${componentType} (${componentId}) failed: ${errorMessage}`,
|
|
1048
|
+
attributes: {
|
|
1049
|
+
'agent.id': agentId,
|
|
1050
|
+
'process.id': processId,
|
|
1051
|
+
'event.id': eventId,
|
|
1052
|
+
'cmp.id': componentId,
|
|
1053
|
+
'cmp.name': componentName,
|
|
1054
|
+
'cmp.type': componentType,
|
|
1055
|
+
'error.type': 'result_error',
|
|
1056
|
+
'error.message': errorMessage,
|
|
1057
|
+
'cmp.output': result,
|
|
1058
|
+
'team.id': teamId,
|
|
1059
|
+
'org.slot': orgSlot,
|
|
1060
|
+
'org.tier': orgTier,
|
|
1061
|
+
'source.id': sourceId,
|
|
1062
|
+
'source.name': sourceName,
|
|
1063
|
+
'session.id': sessionId,
|
|
1064
|
+
'workflow.id': workflowId,
|
|
1065
|
+
'workflow.step': workflowStep,
|
|
1066
|
+
'log.tags': logTags,
|
|
1067
|
+
'agent.debug': isDebugSession,
|
|
1068
|
+
'agent.isTest': isTestDomain,
|
|
1069
|
+
},
|
|
1070
|
+
});
|
|
782
1071
|
});
|
|
783
|
-
}
|
|
1072
|
+
} else {
|
|
1073
|
+
// True success case
|
|
1074
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
1075
|
+
|
|
1076
|
+
// Add success event with output summary
|
|
1077
|
+
span.addEvent('cmp.call.result', {
|
|
1078
|
+
'output.size': resultStr.length,
|
|
1079
|
+
'output.preview': resultStr.substring(0, 200),
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
// Add output attributes to span
|
|
1083
|
+
span.setAttributes({
|
|
1084
|
+
'output.size': resultStr.length,
|
|
1085
|
+
'output.has_error': false,
|
|
1086
|
+
});
|
|
1087
|
+
|
|
1088
|
+
// Emit success log with output (formatted safely)
|
|
1089
|
+
const logAttributes: Record<string, any> = {
|
|
1090
|
+
'agent.id': agentId,
|
|
1091
|
+
'cmp.id': componentId,
|
|
1092
|
+
'cmp.type': componentType,
|
|
1093
|
+
'cmp.name': componentName,
|
|
1094
|
+
'process.id': processId,
|
|
1095
|
+
'event.id': eventId,
|
|
1096
|
+
'cmp.output': result,
|
|
1097
|
+
'team.id': teamId,
|
|
1098
|
+
'org.slot': orgSlot,
|
|
1099
|
+
'org.tier': orgTier,
|
|
1100
|
+
'source.id': sourceId,
|
|
1101
|
+
'source.name': sourceName,
|
|
1102
|
+
'session.id': sessionId,
|
|
1103
|
+
'workflow.id': workflowId,
|
|
1104
|
+
'workflow.step': workflowStep,
|
|
1105
|
+
'log.tags': logTags,
|
|
1106
|
+
'agent.debug': isDebugSession,
|
|
1107
|
+
'agent.isTest': isTestDomain,
|
|
1108
|
+
};
|
|
1109
|
+
|
|
1110
|
+
const spanContext = trace.setSpan(context.active(), span);
|
|
1111
|
+
context.with(spanContext, () => {
|
|
1112
|
+
logger.emit({
|
|
1113
|
+
severityNumber: SeverityNumber.INFO,
|
|
1114
|
+
severityText: 'INFO',
|
|
1115
|
+
body: `Component ${componentType} (${componentId}) completed successfully`,
|
|
1116
|
+
attributes: logAttributes,
|
|
1117
|
+
});
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
784
1120
|
}
|
|
785
1121
|
|
|
786
1122
|
span.end();
|