From 7564849e8168a0dab3fd19d259e73a3e9e31d386 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Wed, 18 Feb 2026 17:02:15 -0800 Subject: [PATCH 01/19] Support new telemetry schema attribute names gated by A365_USE_NEW_TELEMETRY_SCHEMA env var Co-Authored-By: Claude Opus 4.6 --- .../src/utils/TurnContextUtils.ts | 1 - .../src/tracing/constants.ts | 57 +++++++++------ .../src/tracing/contracts.ts | 3 + .../src/tracing/middleware/BaggageBuilder.ts | 8 +- .../src/tracing/processors/SpanProcessor.ts | 14 +++- .../src/tracing/processors/util.ts | 11 +-- .../src/tracing/scopes/ExecuteToolScope.ts | 14 ++-- .../src/tracing/scopes/InferenceScope.ts | 18 +++-- .../src/tracing/scopes/InvokeAgentScope.ts | 21 +++--- .../src/tracing/scopes/OpenTelemetryScope.ts | 20 ++++- .../observability/core/SpanProcessor.test.ts | 8 +- tests/observability/core/scopes.test.ts | 58 ++++++++++++++- .../hosting/BaggageBuilderUtils.test.ts | 1 - .../extension/hosting/scope-utils.test.ts | 73 ++++++++++--------- .../tracing/exporter-utils.test.ts | 5 +- 15 files changed, 210 insertions(+), 102 deletions(-) diff --git a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts index 981d4ead..567782e2 100644 --- a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts +++ b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts @@ -33,7 +33,6 @@ export function getCallerBaggagePairs(turnContext: TurnContext): Array<[string, [OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, from.aadObjectId], [OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, from.name], [OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, upn], - [OpenTelemetryConstants.GEN_AI_CALLER_TENANT_ID_KEY, from.tenantId], [OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, from.agenticAppBlueprintId] ]; return normalizePairs(pairs); diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index c7e88b19..4f3a371e 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -6,6 +6,11 @@ * OpenTelemetry constants for Agent 365 */ export class OpenTelemetryConstants { + // New telemetry schema feature flag + public static readonly USE_NEW_TELEMETRY_SCHEMA_ENV = 'A365_USE_NEW_TELEMETRY_SCHEMA'; + // eslint-disable-next-line no-restricted-properties + public static readonly isNewTelemetrySchemaEnabled = process.env['A365_USE_NEW_TELEMETRY_SCHEMA'] === 'true'; + // Span operation names public static readonly INVOKE_AGENT_OPERATION_NAME = 'invoke_agent'; public static readonly EXECUTE_TOOL_OPERATION_NAME = 'execute_tool'; @@ -46,9 +51,10 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_AGENT_NAME_KEY = 'gen_ai.agent.name'; public static readonly GEN_AI_AGENT_TYPE_KEY = 'gen_ai.agent.type'; public static readonly GEN_AI_AGENT_DESCRIPTION_KEY = 'gen_ai.agent.description'; - public static readonly GEN_AI_AGENT_PLATFORM_ID_KEY = 'gen_ai.agent.platformid'; + public static readonly GEN_AI_AGENT_PLATFORM_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.platform.id' : 'gen_ai.agent.platformid'; + public static readonly GEN_AI_AGENT_THOUGHT_PROCESS_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.thought.process' : 'gen_ai.agent.thought.process'; public static readonly GEN_AI_CONVERSATION_ID_KEY = 'gen_ai.conversation.id'; - public static readonly GEN_AI_CONVERSATION_ITEM_LINK_KEY = 'gen_ai.conversation.item.link'; + public static readonly GEN_AI_CONVERSATION_ITEM_LINK_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.conversation.item.link' : 'gen_ai.conversation.item.link'; public static readonly GEN_AI_TOKEN_TYPE_KEY = 'gen_ai.token.type'; public static readonly GEN_AI_USAGE_INPUT_TOKENS_KEY = 'gen_ai.usage.input_tokens'; public static readonly GEN_AI_USAGE_OUTPUT_TOKENS_KEY = 'gen_ai.usage.output_tokens'; @@ -69,36 +75,35 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_TOOL_TYPE_KEY = 'gen_ai.tool.type'; // Agent user (user tied to agent instance during creation) or caller dimensions - public static readonly GEN_AI_AGENT_USER_ID_KEY = 'gen_ai.agent.userid'; - public static readonly GEN_AI_CALLER_TENANT_ID_KEY = 'gen_ai.caller.tenantid'; - public static readonly GEN_AI_CALLER_ID_KEY = 'gen_ai.caller.id'; - public static readonly GEN_AI_CALLER_NAME_KEY = 'gen_ai.caller.name'; - public static readonly GEN_AI_CALLER_UPN_KEY = 'gen_ai.caller.upn'; - public static readonly GEN_AI_CALLER_CLIENT_IP_KEY = 'gen_ai.caller.client.ip'; + public static readonly GEN_AI_AGENT_USER_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.user.id' : 'gen_ai.agent.userid'; + public static readonly GEN_AI_CALLER_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.id' : 'gen_ai.caller.id'; + public static readonly GEN_AI_CALLER_NAME_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.name' : 'gen_ai.caller.name'; + public static readonly GEN_AI_CALLER_UPN_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.upn' : 'gen_ai.caller.upn'; + public static readonly GEN_AI_CALLER_CLIENT_IP_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'client.address' : 'gen_ai.caller.client.ip'; // Agent to Agent caller agent dimensions - public static readonly GEN_AI_CALLER_AGENT_USER_ID_KEY = 'gen_ai.caller.agent.userid'; + public static readonly GEN_AI_CALLER_AGENT_USER_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.user.id' : 'gen_ai.caller.agent.userid'; public static readonly GEN_AI_CALLER_AGENT_UPN_KEY = 'gen_ai.caller.agent.upn'; public static readonly GEN_AI_CALLER_AGENT_TENANT_ID_KEY = 'gen_ai.caller.agent.tenantid'; - public static readonly GEN_AI_CALLER_AGENT_NAME_KEY = 'gen_ai.caller.agent.name'; - public static readonly GEN_AI_CALLER_AGENT_ID_KEY = 'gen_ai.caller.agent.id'; - public static readonly GEN_AI_CALLER_AGENT_TYPE_KEY = 'gen_ai.caller.agent.type'; - public static readonly GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY = 'gen_ai.caller.agent.applicationid'; + public static readonly GEN_AI_CALLER_AGENT_NAME_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.name' : 'gen_ai.caller.agent.name'; + public static readonly GEN_AI_CALLER_AGENT_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.id' : 'gen_ai.caller.agent.id'; + public static readonly GEN_AI_CALLER_AGENT_TYPE_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.type' : 'gen_ai.caller.agent.type'; + public static readonly GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.blueprint.id' : 'gen_ai.caller.agent.applicationid'; public static readonly GEN_AI_CALLER_AGENT_CLIENT_IP_KEY = 'gen_ai.caller.agent.user.client.ip'; - public static readonly GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY = 'gen_ai.caller.agent.platformid'; + public static readonly GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.platform.id' : 'gen_ai.caller.agent.platformid'; // Agent-specific dimensions public static readonly AGENT_ID_KEY = 'gen_ai.agent.id'; public static readonly GEN_AI_TASK_ID_KEY = 'gen_ai.task.id'; - public static readonly SESSION_ID_KEY = 'session.id'; - public static readonly SESSION_DESCRIPTION_KEY = 'session.description'; + public static readonly SESSION_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.session.id' : 'session.id'; + public static readonly SESSION_DESCRIPTION_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.session.description' : 'session.description'; public static readonly GEN_AI_ICON_URI_KEY = 'gen_ai.agent365.icon_uri'; - public static readonly TENANT_ID_KEY = 'tenant.id'; + public static readonly TENANT_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.tenant.id' : 'tenant.id'; // Baggage keys public static readonly OPERATION_SOURCE_KEY = 'operation.source'; - public static readonly GEN_AI_AGENT_AUID_KEY = 'gen_ai.agent.user.id'; - public static readonly GEN_AI_AGENT_UPN_KEY = 'gen_ai.agent.upn'; - public static readonly GEN_AI_AGENT_BLUEPRINT_ID_KEY = 'gen_ai.agent.applicationid'; + public static readonly GEN_AI_AGENT_AUID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.user.id' : 'gen_ai.agent.user.id'; + public static readonly GEN_AI_AGENT_UPN_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.agent.user.upn' : 'gen_ai.agent.upn'; + public static readonly GEN_AI_AGENT_BLUEPRINT_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.agent.blueprint.id' : 'gen_ai.agent.applicationid'; public static readonly CORRELATION_ID_KEY = 'correlation.id'; public static readonly HIRING_MANAGER_ID_KEY = 'hiring.manager.id'; @@ -108,12 +113,20 @@ export class OpenTelemetryConstants { // Source metadata dimensions public static readonly GEN_AI_EXECUTION_SOURCE_ID_KEY = 'gen_ai.execution.sourceMetadata.id'; - public static readonly GEN_AI_EXECUTION_SOURCE_NAME_KEY = 'gen_ai.channel.name'; - public static readonly GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY = 'gen_ai.channel.link'; + public static readonly GEN_AI_EXECUTION_SOURCE_NAME_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.channel.name' : 'gen_ai.channel.name'; + public static readonly GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.channel.link' : 'gen_ai.channel.link'; // Custom parent id and parent name key public static readonly CUSTOM_PARENT_SPAN_ID_KEY = 'custom.parent.span.id'; public static readonly CUSTOM_SPAN_NAME_KEY = 'custom.span.name'; + + // Telemetry SDK attributes (replace operation.source when isNewTelemetrySchemaEnabled) + public static readonly TELEMETRY_SDK_NAME_KEY = 'telemetry.sdk.name'; + public static readonly TELEMETRY_SDK_LANGUAGE_KEY = 'telemetry.sdk.language'; + public static readonly TELEMETRY_SDK_VERSION_KEY = 'telemetry.sdk.version'; + public static readonly TELEMETRY_SDK_NAME_VALUE = 'Agent365Sdk'; + public static readonly TELEMETRY_SDK_LANGUAGE_VALUE = 'nodejs'; + public static readonly TELEMETRY_SDK_VERSION_VALUE = '0.0.0-placeholder'; } /** diff --git a/packages/agents-a365-observability/src/tracing/contracts.ts b/packages/agents-a365-observability/src/tracing/contracts.ts index bef4b494..6d0e6736 100644 --- a/packages/agents-a365-observability/src/tracing/contracts.ts +++ b/packages/agents-a365-observability/src/tracing/contracts.ts @@ -236,6 +236,9 @@ export interface InferenceDetails { /** Response ID from the model provider */ responseId?: string; + + /** The thought process used by the agent */ + thoughtProcess?: string; } /** diff --git a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts index 7a6f49f4..39548bcb 100644 --- a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts +++ b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts @@ -95,7 +95,9 @@ export class BaggageBuilder { * @returns Self for method chaining */ correlationId(value: string | null | undefined): BaggageBuilder { - this.set(OpenTelemetryConstants.CORRELATION_ID_KEY, value); + if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + this.set(OpenTelemetryConstants.CORRELATION_ID_KEY, value); + } return this; } @@ -125,7 +127,9 @@ export class BaggageBuilder { * @returns Self for method chaining */ hiringManagerId(value: string | null | undefined): BaggageBuilder { - this.set(OpenTelemetryConstants.HIRING_MANAGER_ID_KEY, value); + if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + this.set(OpenTelemetryConstants.HIRING_MANAGER_ID_KEY, value); + } return this; } diff --git a/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts b/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts index cd48f57e..b08b16af 100644 --- a/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts +++ b/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts @@ -69,8 +69,18 @@ export class SpanProcessor implements BaseSpanProcessor { INVOKE_AGENT_ATTRIBUTES.forEach(key => targetKeys.add(key)); } - // Set operation source - coalesce baggage value with SDK default - if (!existingAttrs.has(OpenTelemetryConstants.OPERATION_SOURCE_KEY)) { + // Set operation source or telemetry SDK attributes + if (OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + if (!existingAttrs.has(OpenTelemetryConstants.TELEMETRY_SDK_NAME_KEY)) { + span.setAttribute(OpenTelemetryConstants.TELEMETRY_SDK_NAME_KEY, OpenTelemetryConstants.TELEMETRY_SDK_NAME_VALUE); + } + if (!existingAttrs.has(OpenTelemetryConstants.TELEMETRY_SDK_LANGUAGE_KEY)) { + span.setAttribute(OpenTelemetryConstants.TELEMETRY_SDK_LANGUAGE_KEY, OpenTelemetryConstants.TELEMETRY_SDK_LANGUAGE_VALUE); + } + if (!existingAttrs.has(OpenTelemetryConstants.TELEMETRY_SDK_VERSION_KEY)) { + span.setAttribute(OpenTelemetryConstants.TELEMETRY_SDK_VERSION_KEY, OpenTelemetryConstants.TELEMETRY_SDK_VERSION_VALUE); + } + } else if (!existingAttrs.has(OpenTelemetryConstants.OPERATION_SOURCE_KEY)) { const operationSource = baggageMap.get(OpenTelemetryConstants.OPERATION_SOURCE_KEY) || OperationSource.SDK; diff --git a/packages/agents-a365-observability/src/tracing/processors/util.ts b/packages/agents-a365-observability/src/tracing/processors/util.ts index 6c70fe06..e736ed58 100644 --- a/packages/agents-a365-observability/src/tracing/processors/util.ts +++ b/packages/agents-a365-observability/src/tracing/processors/util.ts @@ -11,19 +11,19 @@ export const GENERIC_ATTRIBUTES: readonly string[] = [ consts.TENANT_ID_KEY, consts.CUSTOM_PARENT_SPAN_ID_KEY, consts.CUSTOM_SPAN_NAME_KEY, - consts.CORRELATION_ID_KEY, + ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.CORRELATION_ID_KEY]), consts.SESSION_ID_KEY, consts.GEN_AI_CONVERSATION_ID_KEY, consts.GEN_AI_CONVERSATION_ITEM_LINK_KEY, consts.GEN_AI_OPERATION_NAME_KEY, consts.GEN_AI_AGENT_ID_KEY, consts.GEN_AI_AGENT_NAME_KEY, - consts.GEN_AI_AGENT_TYPE_KEY, + ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_TYPE_KEY]), consts.GEN_AI_AGENT_DESCRIPTION_KEY, consts.SESSION_DESCRIPTION_KEY, consts.GEN_AI_AGENT_USER_ID_KEY, consts.GEN_AI_AGENT_UPN_KEY, - consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY, + ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY]), consts.GEN_AI_AGENT_AUID_KEY, consts.GEN_AI_AGENT_PLATFORM_ID_KEY, ]; @@ -36,7 +36,6 @@ export const INVOKE_AGENT_ATTRIBUTES: readonly string[] = [ consts.GEN_AI_CALLER_ID_KEY, consts.GEN_AI_CALLER_NAME_KEY, consts.GEN_AI_CALLER_UPN_KEY, - consts.GEN_AI_CALLER_TENANT_ID_KEY, consts.GEN_AI_CALLER_CLIENT_IP_KEY, // Caller Agent (A2A) attributes consts.GEN_AI_CALLER_AGENT_ID_KEY, @@ -49,8 +48,10 @@ export const INVOKE_AGENT_ATTRIBUTES: readonly string[] = [ consts.GEN_AI_CALLER_AGENT_CLIENT_IP_KEY, consts.GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY, // Execution context - consts.GEN_AI_EXECUTION_TYPE_KEY, + ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_EXECUTION_TYPE_KEY]), consts.GEN_AI_EXECUTION_SOURCE_ID_KEY, consts.GEN_AI_EXECUTION_SOURCE_NAME_KEY, consts.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, + // New schema: agent type and blueprint ID are InvokeAgent-only + ...(consts.isNewTelemetrySchemaEnabled ? [consts.GEN_AI_AGENT_TYPE_KEY, consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY] : []), ]; diff --git a/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts b/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts index ed2c3a48..9cfdf0bf 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts @@ -3,7 +3,7 @@ import { SpanKind, TimeInput } from '@opentelemetry/api'; import { OpenTelemetryScope } from './OpenTelemetryScope'; -import { ToolCallDetails, AgentDetails, TenantDetails, SourceMetadata } from '../contracts'; +import { ToolCallDetails, AgentDetails, TenantDetails, SourceMetadata, CallerDetails } from '../contracts'; import { ParentContext } from '../context/trace-context-propagation'; import { OpenTelemetryConstants } from '../constants'; @@ -24,6 +24,7 @@ export class ExecuteToolScope extends OpenTelemetryScope { * tool call after execution has already completed. * @param endTime Optional explicit end time (ms epoch, Date, or HrTime). When provided, the span will * use this timestamp when disposed instead of the current wall-clock time. + * @param callerDetails Optional caller details. * @returns A new ExecuteToolScope instance. */ public static start( @@ -34,9 +35,10 @@ export class ExecuteToolScope extends OpenTelemetryScope { sourceMetadata?: Pick, parentContext?: ParentContext, startTime?: TimeInput, - endTime?: TimeInput + endTime?: TimeInput, + callerDetails?: CallerDetails ): ExecuteToolScope { - return new ExecuteToolScope(details, agentDetails, tenantDetails, conversationId, sourceMetadata, parentContext, startTime, endTime); + return new ExecuteToolScope(details, agentDetails, tenantDetails, conversationId, sourceMetadata, parentContext, startTime, endTime, callerDetails); } private constructor( @@ -47,7 +49,8 @@ export class ExecuteToolScope extends OpenTelemetryScope { sourceMetadata?: Pick, parentContext?: ParentContext, startTime?: TimeInput, - endTime?: TimeInput + endTime?: TimeInput, + callerDetails?: CallerDetails ) { super( SpanKind.INTERNAL, @@ -57,7 +60,8 @@ export class ExecuteToolScope extends OpenTelemetryScope { tenantDetails, parentContext, startTime, - endTime + endTime, + callerDetails ); // Destructure the details object to match C# pattern diff --git a/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts index 3973cc91..fc4df2a7 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts @@ -8,7 +8,8 @@ import { InferenceDetails, AgentDetails, TenantDetails, - SourceMetadata + SourceMetadata, + CallerDetails } from '../contracts'; import { ParentContext } from '../context/trace-context-propagation'; @@ -27,6 +28,7 @@ export class InferenceScope extends OpenTelemetryScope { * Accepts a ParentSpanRef (manual traceId/spanId) or an OTel Context (e.g. from extractTraceContext). * @param startTime Optional explicit start time (ms epoch, Date, or HrTime). * @param endTime Optional explicit end time (ms epoch, Date, or HrTime). + * @param callerDetails Optional caller details. * @returns A new InferenceScope instance */ public static start( @@ -37,9 +39,10 @@ export class InferenceScope extends OpenTelemetryScope { sourceMetadata?: Pick, parentContext?: ParentContext, startTime?: TimeInput, - endTime?: TimeInput + endTime?: TimeInput, + callerDetails?: CallerDetails ): InferenceScope { - return new InferenceScope(details, agentDetails, tenantDetails, conversationId, sourceMetadata, parentContext, startTime, endTime); + return new InferenceScope(details, agentDetails, tenantDetails, conversationId, sourceMetadata, parentContext, startTime, endTime, callerDetails); } private constructor( @@ -50,7 +53,8 @@ export class InferenceScope extends OpenTelemetryScope { sourceMetadata?: Pick, parentContext?: ParentContext, startTime?: TimeInput, - endTime?: TimeInput + endTime?: TimeInput, + callerDetails?: CallerDetails ) { super( SpanKind.CLIENT, @@ -60,7 +64,8 @@ export class InferenceScope extends OpenTelemetryScope { tenantDetails, parentContext, startTime, - endTime + endTime, + callerDetails ); // Set core inference information matching C# implementation @@ -71,9 +76,10 @@ export class InferenceScope extends OpenTelemetryScope { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_OUTPUT_TOKENS_KEY, details.outputTokens?.toString()); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_RESPONSE_FINISH_REASONS_KEY, details.finishReasons?.join(',')); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_RESPONSE_ID_KEY, details.responseId); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_THOUGHT_PROCESS_KEY, details.thoughtProcess); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, conversationId); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, sourceMetadata?.name); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, sourceMetadata?.description); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, sourceMetadata?.description); } /** diff --git a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts index cc161466..a5359663 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts @@ -59,12 +59,19 @@ export class InvokeAgentScope extends OpenTelemetryScope { tenantDetails, parentContext, startTime, - endTime + endTime, + callerDetails ); // Set session ID and endpoint information this.setTagMaybe(OpenTelemetryConstants.SESSION_ID_KEY, invokeAgentDetails.sessionId); + // New schema: agent type and blueprint ID are InvokeAgent-only (base class skips them) + if (OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY, invokeAgentDetails.agentType); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, invokeAgentDetails.agentBlueprintId); + } + if (invokeAgentDetails.endpoint) { this.setTagMaybe(OpenTelemetryConstants.SERVER_ADDRESS_KEY, invokeAgentDetails.endpoint.host); @@ -77,7 +84,8 @@ export class InvokeAgentScope extends OpenTelemetryScope { // Set request-related tags const requestToUse = invokeAgentDetails.request; if (requestToUse) { - if (requestToUse.executionType) { + // gen_ai.execution.type is removed in new schema + if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled && requestToUse.executionType) { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_TYPE_KEY, requestToUse.executionType.toString()); } if (requestToUse.sourceMetadata) { @@ -89,15 +97,6 @@ export class InvokeAgentScope extends OpenTelemetryScope { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, invokeAgentDetails.conversationId); - // Set caller details tags - if (callerDetails) { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, callerDetails.callerId); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, callerDetails.callerUpn); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, callerDetails.callerName); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_TENANT_ID_KEY, callerDetails.tenantId); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY, callerDetails.callerClientIp); - } - // Set caller agent details tags if (callerAgentDetails) { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_NAME_KEY, callerAgentDetails.agentName); diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index b539af14..141cadef 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -3,7 +3,7 @@ import { trace, SpanKind, Span, SpanStatusCode, Attributes, context, AttributeValue, SpanContext, TimeInput } from '@opentelemetry/api'; import { OpenTelemetryConstants } from '../constants'; -import { AgentDetails, TenantDetails } from '../contracts'; +import { AgentDetails, TenantDetails, CallerDetails } from '../contracts'; import { createContextWithParentSpanRef } from '../context/parent-span-context'; import { ParentContext, isParentSpanRef } from '../context/trace-context-propagation'; import logger from '../../utils/logging'; @@ -46,7 +46,8 @@ export abstract class OpenTelemetryScope implements Disposable { tenantDetails?: TenantDetails, parentContext?: ParentContext, startTime?: TimeInput, - endTime?: TimeInput + endTime?: TimeInput, + callerDetails?: CallerDetails ) { // Determine the context to use for span creation let currentContext = context.active(); @@ -85,20 +86,31 @@ export abstract class OpenTelemetryScope implements Disposable { if (agentDetails) { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY, agentDetails.agentId); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_NAME_KEY, agentDetails.agentName); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY, agentDetails.agentType); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_DESCRIPTION_KEY, agentDetails.agentDescription); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_PLATFORM_ID_KEY, agentDetails.platformId); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, agentDetails.conversationId); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_ICON_URI_KEY, agentDetails.iconUri); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_AUID_KEY, agentDetails.agentAUID); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_UPN_KEY, agentDetails.agentUPN); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, agentDetails.agentBlueprintId); + + if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY, agentDetails.agentType); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, agentDetails.agentBlueprintId); + } } // Set tenant details if provided if (tenantDetails) { this.setTagMaybe(OpenTelemetryConstants.TENANT_ID_KEY, tenantDetails.tenantId); } + + // Set caller details if provided + if (callerDetails) { + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, callerDetails.callerId); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, callerDetails.callerUpn); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, callerDetails.callerName); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY, callerDetails.callerClientIp); + } } /** diff --git a/tests/observability/core/SpanProcessor.test.ts b/tests/observability/core/SpanProcessor.test.ts index eb4444d0..c0ace2d5 100644 --- a/tests/observability/core/SpanProcessor.test.ts +++ b/tests/observability/core/SpanProcessor.test.ts @@ -162,14 +162,18 @@ describe('SpanProcessor', () => { describe('attribute registry application', () => { it('should apply all generic attributes', () => { expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.TENANT_ID_KEY); - expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.CORRELATION_ID_KEY); + if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.CORRELATION_ID_KEY); + } expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY); expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.SESSION_ID_KEY); }); it('should apply invoke agent specific attributes', () => { expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY); - expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_EXECUTION_TYPE_KEY); + if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_EXECUTION_TYPE_KEY); + } }); }); diff --git a/tests/observability/core/scopes.test.ts b/tests/observability/core/scopes.test.ts index 14d7fad1..32b0a78b 100644 --- a/tests/observability/core/scopes.test.ts +++ b/tests/observability/core/scopes.test.ts @@ -224,16 +224,42 @@ describe('Scopes', () => { describe('ExecuteToolScope', () => { it('should create scope with tool details', () => { + const spy = jest.spyOn(OpenTelemetryScope.prototype as any, 'setTagMaybe'); + const callerDetails: CallerDetails = { + callerId: 'caller-tool-1', + callerUpn: 'tool.user@contoso.com', + callerName: 'Tool User', + tenantId: 'tool-tenant', + callerClientIp: '10.0.0.10' + }; const scope = ExecuteToolScope.start({ toolName: 'test-tool', arguments: '{"param": "value"}', toolCallId: 'call-123', description: 'A test tool', toolType: 'test' - }, testAgentDetails, testTenantDetails); + }, testAgentDetails, testTenantDetails, undefined, undefined, undefined, undefined, undefined, callerDetails); expect(scope).toBeInstanceOf(ExecuteToolScope); + const calls = spy.mock.calls.map(args => ({ key: args[0], val: args[1] })); + expect(calls).toEqual(expect.arrayContaining([ + expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, val: 'caller-tool-1' }), + expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, val: 'Tool User' }), + expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY, val: '10.0.0.10' }) + ])); + // Validate raw attribute key strings for schema correctness + const keySet = new Set(calls.map(c => c.key)); + if (OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + expect(keySet).toContain('microsoft.caller.id'); + expect(keySet).toContain('microsoft.caller.name'); + expect(keySet).toContain('client.address'); + } else { + expect(keySet).toContain('gen_ai.caller.id'); + expect(keySet).toContain('gen_ai.caller.name'); + expect(keySet).toContain('gen_ai.caller.client.ip'); + } scope?.dispose(); + spy.mockRestore(); }); it('should record response', () => { @@ -277,6 +303,14 @@ describe('Scopes', () => { describe('InferenceScope', () => { it('should create scope with inference details', () => { + const spy = jest.spyOn(OpenTelemetryScope.prototype as any, 'setTagMaybe'); + const callerDetails: CallerDetails = { + callerId: 'caller-inf-1', + callerUpn: 'inf.user@contoso.com', + callerName: 'Inf User', + tenantId: 'inf-tenant', + callerClientIp: '10.0.0.20' + }; const inferenceDetails: InferenceDetails = { operationName: InferenceOperationType.CHAT, model: 'gpt-4', @@ -286,11 +320,29 @@ describe('Scopes', () => { responseId: 'resp-123', finishReasons: ['stop'] }; - - const scope = InferenceScope.start(inferenceDetails, testAgentDetails, testTenantDetails); + + const scope = InferenceScope.start(inferenceDetails, testAgentDetails, testTenantDetails, undefined, undefined, undefined, undefined, undefined, callerDetails); expect(scope).toBeInstanceOf(InferenceScope); + const calls = spy.mock.calls.map(args => ({ key: args[0], val: args[1] })); + expect(calls).toEqual(expect.arrayContaining([ + expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, val: 'caller-inf-1' }), + expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, val: 'Inf User' }), + expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY, val: '10.0.0.20' }) + ])); + // Validate raw attribute key strings for schema correctness + const keySet = new Set(calls.map(c => c.key)); + if (OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + expect(keySet).toContain('microsoft.caller.id'); + expect(keySet).toContain('microsoft.caller.name'); + expect(keySet).toContain('client.address'); + } else { + expect(keySet).toContain('gen_ai.caller.id'); + expect(keySet).toContain('gen_ai.caller.name'); + expect(keySet).toContain('gen_ai.caller.client.ip'); + } scope?.dispose(); + spy.mockRestore(); }); it('should create scope with minimal details', () => { diff --git a/tests/observability/extension/hosting/BaggageBuilderUtils.test.ts b/tests/observability/extension/hosting/BaggageBuilderUtils.test.ts index f6d65821..37e117e7 100644 --- a/tests/observability/extension/hosting/BaggageBuilderUtils.test.ts +++ b/tests/observability/extension/hosting/BaggageBuilderUtils.test.ts @@ -44,7 +44,6 @@ describe('BaggageBuilderUtils', () => { expect(asObj[OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY]).toBe('aad-object-1'); expect(asObj[OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY]).toBe('User One'); expect(asObj[OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY]).toBe('agentic-user-1'); - expect(asObj[OpenTelemetryConstants.GEN_AI_CALLER_TENANT_ID_KEY]).toBe('tenant1'); expect(asObj[OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY]).toBe('agent-app-1'); expect(asObj[OpenTelemetryConstants.GEN_AI_AGENT_NAME_KEY]).toBe('Agent One'); expect(asObj[OpenTelemetryConstants.GEN_AI_AGENT_AUID_KEY]).toBe('aad-object-2'); diff --git a/tests/observability/extension/hosting/scope-utils.test.ts b/tests/observability/extension/hosting/scope-utils.test.ts index a5ad82f7..f706f962 100644 --- a/tests/observability/extension/hosting/scope-utils.test.ts +++ b/tests/observability/extension/hosting/scope-utils.test.ts @@ -61,21 +61,22 @@ describe('ScopeUtils.populateFromTurnContext', () => { const scope = ScopeUtils.populateInferenceScopeFromTurnContext(details, ctx) as InferenceScope; expect(scope).toBeInstanceOf(InferenceScope); const calls = spy.mock.calls.map(args => [args[0], args[1]]); - expect(calls).toEqual( - expect.arrayContaining([ - [OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, 'conv-A'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, 'web'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, 'https://web'], - [OpenTelemetryConstants.GEN_AI_AGENT_NAME_KEY, 'Agent One'], - [OpenTelemetryConstants.GEN_AI_AGENT_AUID_KEY, 'agent-oid'], - [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY, 'agent-1'], - [OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, 'agent-blueprint-1'], - [OpenTelemetryConstants.GEN_AI_AGENT_UPN_KEY, 'agent-upn@contoso.com'], - [OpenTelemetryConstants.GEN_AI_AGENT_DESCRIPTION_KEY, 'assistant'], - [OpenTelemetryConstants.TENANT_ID_KEY, 'tenant-123'], - [OpenTelemetryConstants.GEN_AI_INPUT_MESSAGES_KEY, 'input text'] - ]) - ); + const expected = [ + [OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, 'conv-A'], + [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, 'web'], + [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, 'https://web'], + [OpenTelemetryConstants.GEN_AI_AGENT_NAME_KEY, 'Agent One'], + [OpenTelemetryConstants.GEN_AI_AGENT_AUID_KEY, 'agent-oid'], + [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY, 'agent-1'], + [OpenTelemetryConstants.GEN_AI_AGENT_UPN_KEY, 'agent-upn@contoso.com'], + [OpenTelemetryConstants.GEN_AI_AGENT_DESCRIPTION_KEY, 'assistant'], + [OpenTelemetryConstants.TENANT_ID_KEY, 'tenant-123'], + [OpenTelemetryConstants.GEN_AI_INPUT_MESSAGES_KEY, 'input text'] + ]; + if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + expected.push([OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, 'agent-blueprint-1']); + } + expect(calls).toEqual(expect.arrayContaining(expected)); scope?.dispose(); }); @@ -124,27 +125,27 @@ describe('ScopeUtils.populateFromTurnContext', () => { const scope = ScopeUtils.populateInvokeAgentScopeFromTurnContext(details, ctx) as InvokeAgentScope; expect(scope).toBeInstanceOf(InvokeAgentScope); const calls = spy.mock.calls.map(args => [args[0], args[1]]); - expect(calls).toEqual( - expect.arrayContaining([ - [OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, 'conv-B'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, 'teams'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, 'https://teams'], - [OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, 'user-oid'], - [OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, 'Test User'], - [OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, 'user@contoso.com'], - [OpenTelemetryConstants.GEN_AI_CALLER_TENANT_ID_KEY, 'tenant-xyz'], - [OpenTelemetryConstants.GEN_AI_CALLER_AGENT_USER_ID_KEY, 'user-oid'], - [OpenTelemetryConstants.GEN_AI_CALLER_AGENT_NAME_KEY, 'Test User'], - [OpenTelemetryConstants.GEN_AI_CALLER_AGENT_ID_KEY, 'callerAgent-1'], - [OpenTelemetryConstants.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, 'caller-agentBlueprintId'], - [OpenTelemetryConstants.TENANT_ID_KEY, 'tenant-123'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_TYPE_KEY, ExecutionType.Agent2Agent.toString()], - [OpenTelemetryConstants.GEN_AI_INPUT_MESSAGES_KEY, 'invoke message'], - [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY, 'agent-1'], - [OpenTelemetryConstants.GEN_AI_AGENT_NAME_KEY, 'Agent One'], - [OpenTelemetryConstants.GEN_AI_AGENT_DESCRIPTION_KEY, 'assistant'] - ]) - ); + const expected = [ + [OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, 'conv-B'], + [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, 'teams'], + [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, 'https://teams'], + [OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, 'user-oid'], + [OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, 'Test User'], + [OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, 'user@contoso.com'], + [OpenTelemetryConstants.GEN_AI_CALLER_AGENT_USER_ID_KEY, 'user-oid'], + [OpenTelemetryConstants.GEN_AI_CALLER_AGENT_NAME_KEY, 'Test User'], + [OpenTelemetryConstants.GEN_AI_CALLER_AGENT_ID_KEY, 'callerAgent-1'], + [OpenTelemetryConstants.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, 'caller-agentBlueprintId'], + [OpenTelemetryConstants.TENANT_ID_KEY, 'tenant-123'], + [OpenTelemetryConstants.GEN_AI_INPUT_MESSAGES_KEY, 'invoke message'], + [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY, 'agent-1'], + [OpenTelemetryConstants.GEN_AI_AGENT_NAME_KEY, 'Agent One'], + [OpenTelemetryConstants.GEN_AI_AGENT_DESCRIPTION_KEY, 'assistant'] + ]; + if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { + expected.push([OpenTelemetryConstants.GEN_AI_EXECUTION_TYPE_KEY, ExecutionType.Agent2Agent.toString()]); + } + expect(calls).toEqual(expect.arrayContaining(expected)); scope?.dispose(); }); diff --git a/tests/observability/tracing/exporter-utils.test.ts b/tests/observability/tracing/exporter-utils.test.ts index 6dd9b365..4d743cd3 100644 --- a/tests/observability/tracing/exporter-utils.test.ts +++ b/tests/observability/tracing/exporter-utils.test.ts @@ -6,6 +6,7 @@ import { SpanKind, SpanStatusCode } from '@opentelemetry/api'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; import { ClusterCategory, DefaultConfigurationProvider } from '@microsoft/agents-a365-runtime'; import { ObservabilityConfiguration } from '@microsoft/agents-a365-observability/src/configuration/ObservabilityConfiguration'; +import { OpenTelemetryConstants } from '@microsoft/agents-a365-observability/src/tracing/constants'; describe('exporter/utils', () => { const originalEnv = process.env; @@ -454,8 +455,8 @@ describe('exporter/utils', () => { ended: true, status: { code: SpanStatusCode.OK }, attributes: { - ...(tenantId !== undefined && { 'tenant.id': tenantId }), - ...(agentId !== undefined && { 'gen_ai.agent.id': agentId }), + ...(tenantId !== undefined && { [OpenTelemetryConstants.TENANT_ID_KEY]: tenantId }), + ...(agentId !== undefined && { [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY]: agentId }), }, links: [], events: [], From c79dd4f84c0fed82b0d57f3d537c01ee1103c329 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Wed, 18 Feb 2026 17:47:21 -0800 Subject: [PATCH 02/19] Derive TELEMETRY_SDK_VERSION_VALUE from package.json version Add prebuild script to generate src/version.ts from package.json (same pattern as agents-a365-runtime) so the telemetry SDK version stays correct automatically instead of being hardcoded. Co-Authored-By: Claude Opus 4.6 --- packages/agents-a365-observability/package.json | 1 + packages/agents-a365-observability/src/tracing/constants.ts | 4 +++- packages/agents-a365-observability/src/version.ts | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 packages/agents-a365-observability/src/version.ts diff --git a/packages/agents-a365-observability/package.json b/packages/agents-a365-observability/package.json index 4c6028c8..74e02e11 100644 --- a/packages/agents-a365-observability/package.json +++ b/packages/agents-a365-observability/package.json @@ -6,6 +6,7 @@ "module": "dist/esm/index.js", "types": "dist/esm/index.d.ts", "scripts": { + "prebuild": "node -p \"'export const LIB_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > src/version.ts", "build:cjs": "npx tsc --project tsconfig.cjs.json", "build:esm": "npx tsc --project tsconfig.esm.json", "build": "npm run build:cjs && npm run build:esm", diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index 4f3a371e..48aec795 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -2,6 +2,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ------------------------------------------------------------------------------ +import { LIB_VERSION } from '../version'; + /** * OpenTelemetry constants for Agent 365 */ @@ -126,7 +128,7 @@ export class OpenTelemetryConstants { public static readonly TELEMETRY_SDK_VERSION_KEY = 'telemetry.sdk.version'; public static readonly TELEMETRY_SDK_NAME_VALUE = 'Agent365Sdk'; public static readonly TELEMETRY_SDK_LANGUAGE_VALUE = 'nodejs'; - public static readonly TELEMETRY_SDK_VERSION_VALUE = '0.0.0-placeholder'; + public static readonly TELEMETRY_SDK_VERSION_VALUE = LIB_VERSION; } /** diff --git a/packages/agents-a365-observability/src/version.ts b/packages/agents-a365-observability/src/version.ts new file mode 100644 index 00000000..da17395a --- /dev/null +++ b/packages/agents-a365-observability/src/version.ts @@ -0,0 +1 @@ +export const LIB_VERSION = "0.0.0-placeholder"; From f3fdb15258f57f99e923a9d944f218536cb6a6c1 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Wed, 18 Feb 2026 18:11:43 -0800 Subject: [PATCH 03/19] Add isolated-module tests for caller attribute key schema mappings Use jest.isolateModules to validate raw old/new schema key strings for caller attributes, catching regressions in constant definitions regardless of which schema is active at runtime. Also skip GEN_AI_AGENT_USER_ID_KEY from GENERIC_ATTRIBUTES in new schema to avoid duplicate propagation (collides with GEN_AI_AGENT_AUID_KEY). Co-Authored-By: Claude Opus 4.6 --- .../src/tracing/processors/util.ts | 4 ++- tests/observability/core/scopes.test.ts | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/agents-a365-observability/src/tracing/processors/util.ts b/packages/agents-a365-observability/src/tracing/processors/util.ts index e736ed58..2dab89c1 100644 --- a/packages/agents-a365-observability/src/tracing/processors/util.ts +++ b/packages/agents-a365-observability/src/tracing/processors/util.ts @@ -21,7 +21,9 @@ export const GENERIC_ATTRIBUTES: readonly string[] = [ ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_TYPE_KEY]), consts.GEN_AI_AGENT_DESCRIPTION_KEY, consts.SESSION_DESCRIPTION_KEY, - consts.GEN_AI_AGENT_USER_ID_KEY, + // In new schema, GEN_AI_AGENT_USER_ID_KEY and GEN_AI_AGENT_AUID_KEY both resolve to + // 'microsoft.a365.agent.user.id', so skip USER_ID_KEY to avoid duplicate propagation. + ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_USER_ID_KEY]), consts.GEN_AI_AGENT_UPN_KEY, ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY]), consts.GEN_AI_AGENT_AUID_KEY, diff --git a/tests/observability/core/scopes.test.ts b/tests/observability/core/scopes.test.ts index 32b0a78b..bd3d952b 100644 --- a/tests/observability/core/scopes.test.ts +++ b/tests/observability/core/scopes.test.ts @@ -563,3 +563,38 @@ describe('Scopes', () => { }); }); }); + +// Validate raw caller attribute key strings for both old and new schemas +// using jest.isolateModules to re-evaluate constants with different env var values. +describe('Caller attribute key schema mappings', () => { + const loadConstants = (useNewSchema: boolean) => { + let consts: typeof OpenTelemetryConstants; + const original = process.env['A365_USE_NEW_TELEMETRY_SCHEMA']; + process.env['A365_USE_NEW_TELEMETRY_SCHEMA'] = useNewSchema ? 'true' : ''; + jest.isolateModules(() => { + consts = require('@microsoft/agents-a365-observability').OpenTelemetryConstants; + }); + if (original === undefined) { + delete process.env['A365_USE_NEW_TELEMETRY_SCHEMA']; + } else { + process.env['A365_USE_NEW_TELEMETRY_SCHEMA'] = original; + } + return consts!; + }; + + it('old schema uses gen_ai.* caller key names', () => { + const consts = loadConstants(false); + expect(consts.GEN_AI_CALLER_ID_KEY).toBe('gen_ai.caller.id'); + expect(consts.GEN_AI_CALLER_NAME_KEY).toBe('gen_ai.caller.name'); + expect(consts.GEN_AI_CALLER_UPN_KEY).toBe('gen_ai.caller.upn'); + expect(consts.GEN_AI_CALLER_CLIENT_IP_KEY).toBe('gen_ai.caller.client.ip'); + }); + + it('new schema uses microsoft.* / client.* caller key names', () => { + const consts = loadConstants(true); + expect(consts.GEN_AI_CALLER_ID_KEY).toBe('microsoft.caller.id'); + expect(consts.GEN_AI_CALLER_NAME_KEY).toBe('microsoft.caller.name'); + expect(consts.GEN_AI_CALLER_UPN_KEY).toBe('microsoft.caller.upn'); + expect(consts.GEN_AI_CALLER_CLIENT_IP_KEY).toBe('client.address'); + }); +}); From 64c28a7b713a0bf98aeba79c9c3e56c370371cbd Mon Sep 17 00:00:00 2001 From: jsl517 Date: Wed, 18 Feb 2026 18:45:25 -0800 Subject: [PATCH 04/19] Add back gen_ai.caller.tenantid, add isolated schema tests for caller agent keys - Restore GEN_AI_CALLER_TENANT_ID_KEY and wire it through base scope, INVOKE_AGENT_ATTRIBUTES, and TurnContextUtils baggage pairs - Add isolated-module tests validating caller agent key schema mappings - Skip GEN_AI_AGENT_USER_ID_KEY from GENERIC_ATTRIBUTES in new schema to avoid duplicate propagation with GEN_AI_AGENT_AUID_KEY Co-Authored-By: Claude Opus 4.6 --- .../src/utils/TurnContextUtils.ts | 1 + .../src/tracing/constants.ts | 1 + .../src/tracing/processors/util.ts | 1 + .../src/tracing/scopes/OpenTelemetryScope.ts | 1 + tests/observability/core/scopes.test.ts | 14 ++++++++++++++ 5 files changed, 18 insertions(+) diff --git a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts index 567782e2..981d4ead 100644 --- a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts +++ b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts @@ -33,6 +33,7 @@ export function getCallerBaggagePairs(turnContext: TurnContext): Array<[string, [OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, from.aadObjectId], [OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, from.name], [OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, upn], + [OpenTelemetryConstants.GEN_AI_CALLER_TENANT_ID_KEY, from.tenantId], [OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, from.agenticAppBlueprintId] ]; return normalizePairs(pairs); diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index 48aec795..5d450e72 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -82,6 +82,7 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_CALLER_NAME_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.name' : 'gen_ai.caller.name'; public static readonly GEN_AI_CALLER_UPN_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.upn' : 'gen_ai.caller.upn'; public static readonly GEN_AI_CALLER_CLIENT_IP_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'client.address' : 'gen_ai.caller.client.ip'; + public static readonly GEN_AI_CALLER_TENANT_ID_KEY = 'gen_ai.caller.tenantid'; // Agent to Agent caller agent dimensions public static readonly GEN_AI_CALLER_AGENT_USER_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.user.id' : 'gen_ai.caller.agent.userid'; diff --git a/packages/agents-a365-observability/src/tracing/processors/util.ts b/packages/agents-a365-observability/src/tracing/processors/util.ts index 2dab89c1..3fe4a857 100644 --- a/packages/agents-a365-observability/src/tracing/processors/util.ts +++ b/packages/agents-a365-observability/src/tracing/processors/util.ts @@ -39,6 +39,7 @@ export const INVOKE_AGENT_ATTRIBUTES: readonly string[] = [ consts.GEN_AI_CALLER_NAME_KEY, consts.GEN_AI_CALLER_UPN_KEY, consts.GEN_AI_CALLER_CLIENT_IP_KEY, + consts.GEN_AI_CALLER_TENANT_ID_KEY, // Caller Agent (A2A) attributes consts.GEN_AI_CALLER_AGENT_ID_KEY, consts.GEN_AI_CALLER_AGENT_NAME_KEY, diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index 141cadef..0e1033e6 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -110,6 +110,7 @@ export abstract class OpenTelemetryScope implements Disposable { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, callerDetails.callerUpn); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, callerDetails.callerName); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY, callerDetails.callerClientIp); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_TENANT_ID_KEY, callerDetails.tenantId); } } diff --git a/tests/observability/core/scopes.test.ts b/tests/observability/core/scopes.test.ts index bd3d952b..532399dd 100644 --- a/tests/observability/core/scopes.test.ts +++ b/tests/observability/core/scopes.test.ts @@ -597,4 +597,18 @@ describe('Caller attribute key schema mappings', () => { expect(consts.GEN_AI_CALLER_UPN_KEY).toBe('microsoft.caller.upn'); expect(consts.GEN_AI_CALLER_CLIENT_IP_KEY).toBe('client.address'); }); + + it('old schema uses gen_ai.* caller agent key names', () => { + const consts = loadConstants(false); + expect(consts.GEN_AI_CALLER_AGENT_ID_KEY).toBe('gen_ai.caller.agent.id'); + expect(consts.GEN_AI_CALLER_AGENT_NAME_KEY).toBe('gen_ai.caller.agent.name'); + expect(consts.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY).toBe('gen_ai.caller.agent.applicationid'); + }); + + it('new schema uses microsoft.a365.* caller agent key names', () => { + const consts = loadConstants(true); + expect(consts.GEN_AI_CALLER_AGENT_ID_KEY).toBe('microsoft.a365.caller.agent.id'); + expect(consts.GEN_AI_CALLER_AGENT_NAME_KEY).toBe('microsoft.a365.caller.agent.name'); + expect(consts.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY).toBe('microsoft.a365.caller.agent.blueprint.id'); + }); }); From 00cd584f200c1e99a500229ff36aa91c1b4b2793 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Wed, 18 Feb 2026 18:58:15 -0800 Subject: [PATCH 05/19] Remove GEN_AI_AGENT_USER_ID_KEY constant This constant duplicated GEN_AI_AGENT_AUID_KEY functionality. The .NET SDK uses gen_ai.agent.userid as GenAiAgentAUIDKey, so only GEN_AI_AGENT_AUID_KEY is needed. Co-Authored-By: Claude Opus 4.6 --- packages/agents-a365-observability/src/tracing/constants.ts | 1 - .../agents-a365-observability/src/tracing/processors/util.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index 5d450e72..0852f789 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -77,7 +77,6 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_TOOL_TYPE_KEY = 'gen_ai.tool.type'; // Agent user (user tied to agent instance during creation) or caller dimensions - public static readonly GEN_AI_AGENT_USER_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.user.id' : 'gen_ai.agent.userid'; public static readonly GEN_AI_CALLER_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.id' : 'gen_ai.caller.id'; public static readonly GEN_AI_CALLER_NAME_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.name' : 'gen_ai.caller.name'; public static readonly GEN_AI_CALLER_UPN_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.upn' : 'gen_ai.caller.upn'; diff --git a/packages/agents-a365-observability/src/tracing/processors/util.ts b/packages/agents-a365-observability/src/tracing/processors/util.ts index 3fe4a857..567d84ac 100644 --- a/packages/agents-a365-observability/src/tracing/processors/util.ts +++ b/packages/agents-a365-observability/src/tracing/processors/util.ts @@ -21,9 +21,6 @@ export const GENERIC_ATTRIBUTES: readonly string[] = [ ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_TYPE_KEY]), consts.GEN_AI_AGENT_DESCRIPTION_KEY, consts.SESSION_DESCRIPTION_KEY, - // In new schema, GEN_AI_AGENT_USER_ID_KEY and GEN_AI_AGENT_AUID_KEY both resolve to - // 'microsoft.a365.agent.user.id', so skip USER_ID_KEY to avoid duplicate propagation. - ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_USER_ID_KEY]), consts.GEN_AI_AGENT_UPN_KEY, ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY]), consts.GEN_AI_AGENT_AUID_KEY, From 7781561c0e82ee27ab7acf2de087baf313f46f96 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Tue, 24 Feb 2026 13:16:14 -0800 Subject: [PATCH 06/19] Fix telemetry schema property names to match Common Properties doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - TELEMETRY_SDK_NAME_VALUE: Agent365Sdk → A365ObservabilitySDK - GEN_AI_AGENT_AUID_KEY: microsoft.a365.agent.user.id → microsoft.agent.user.id - GEN_AI_AGENT_BLUEPRINT_ID_KEY: microsoft.agent.blueprint.id → microsoft.a365.agent.blueprint.id Co-Authored-By: Claude Opus 4.6 --- packages/agents-a365-observability/src/tracing/constants.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index 0852f789..333e2fe4 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -103,9 +103,9 @@ export class OpenTelemetryConstants { // Baggage keys public static readonly OPERATION_SOURCE_KEY = 'operation.source'; - public static readonly GEN_AI_AGENT_AUID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.user.id' : 'gen_ai.agent.user.id'; + public static readonly GEN_AI_AGENT_AUID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.agent.user.id' : 'gen_ai.agent.user.id'; public static readonly GEN_AI_AGENT_UPN_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.agent.user.upn' : 'gen_ai.agent.upn'; - public static readonly GEN_AI_AGENT_BLUEPRINT_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.agent.blueprint.id' : 'gen_ai.agent.applicationid'; + public static readonly GEN_AI_AGENT_BLUEPRINT_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.blueprint.id' : 'gen_ai.agent.applicationid'; public static readonly CORRELATION_ID_KEY = 'correlation.id'; public static readonly HIRING_MANAGER_ID_KEY = 'hiring.manager.id'; @@ -126,7 +126,7 @@ export class OpenTelemetryConstants { public static readonly TELEMETRY_SDK_NAME_KEY = 'telemetry.sdk.name'; public static readonly TELEMETRY_SDK_LANGUAGE_KEY = 'telemetry.sdk.language'; public static readonly TELEMETRY_SDK_VERSION_KEY = 'telemetry.sdk.version'; - public static readonly TELEMETRY_SDK_NAME_VALUE = 'Agent365Sdk'; + public static readonly TELEMETRY_SDK_NAME_VALUE = 'A365ObservabilitySDK'; public static readonly TELEMETRY_SDK_LANGUAGE_VALUE = 'nodejs'; public static readonly TELEMETRY_SDK_VERSION_VALUE = LIB_VERSION; } From a083413a2786cb2cba92a4e048feb0ca56c0f9a7 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Wed, 25 Feb 2026 18:36:11 -0800 Subject: [PATCH 07/19] Remove gen_ai.response.id, rename gen_ai.event.content to gen_ai.tool.call.result, remove GEN_AI_EXECUTION_SOURCE_ID_KEY, add server.address/port to InferenceScope - Remove GEN_AI_RESPONSE_ID_KEY constant and all responseId references from InferenceScope, contracts, extensions-openai, and samples - Rename gen_ai.event.content to gen_ai.tool.call.result for GEN_AI_EVENT_CONTENT and GEN_AI_TOOL_CALL_RESULT_KEY constants - Remove GEN_AI_EXECUTION_SOURCE_ID_KEY from constants, util.ts, InvokeAgentScope, and BaggageBuilder.sourceMetadataId() - Add endpoint (server.address/server.port) support to InferenceScope and InferenceDetails contract - Update capture-post-body sample and agent.ts samples - Update all affected tests Co-Authored-By: Claude Opus 4.6 --- .../src/OpenAIAgentsTraceProcessor.ts | 4 +- .../src/Utils.ts | 4 - .../src/utils/TurnContextUtils.ts | 4 +- packages/agents-a365-observability/.gitignore | 2 + .../src/tracing/constants.ts | 83 ++++++----------- .../src/tracing/contracts.ts | 6 +- .../src/tracing/middleware/BaggageBuilder.ts | 59 +++--------- .../src/tracing/processors/SpanProcessor.ts | 27 ++---- .../src/tracing/processors/util.ts | 27 +++--- .../src/tracing/scopes/ExecuteToolScope.ts | 6 +- .../src/tracing/scopes/InferenceScope.ts | 28 +++--- .../src/tracing/scopes/InvokeAgentScope.ts | 17 +--- .../src/tracing/scopes/OpenTelemetryScope.ts | 5 - .../agents-a365-observability/src/version.ts | 1 - .../observability/core/BaggageBuilder.test.ts | 19 +--- .../observability/core/SpanProcessor.test.ts | 17 ++-- tests/observability/core/scopes.test.ts | 92 ++++++------------- .../extension/hosting/scope-utils.test.ts | 18 ++-- .../openai-agent-instrument.test.ts | 2 +- 19 files changed, 139 insertions(+), 282 deletions(-) create mode 100644 packages/agents-a365-observability/.gitignore delete mode 100644 packages/agents-a365-observability/src/version.ts diff --git a/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts b/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts index 68ce01ed..69e3d835 100644 --- a/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts +++ b/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts @@ -40,9 +40,9 @@ export class OpenAIAgentsTraceProcessor implements TracingProcessor { private readonly spanNames: Map = new Map(); private readonly keyMappings: Map = new Map([ - ['mcp_tools' + Constants.GEN_AI_RESPONSE_CONTENT_KEY, OpenTelemetryConstants.GEN_AI_EVENT_CONTENT], + ['mcp_tools' + Constants.GEN_AI_RESPONSE_CONTENT_KEY, OpenTelemetryConstants.GEN_AI_TOOL_CALL_RESULT_KEY], ['mcp_tools' + Constants.GEN_AI_REQUEST_CONTENT_KEY, OpenTelemetryConstants.GEN_AI_TOOL_ARGS_KEY], - ['function' + Constants.GEN_AI_RESPONSE_CONTENT_KEY, OpenTelemetryConstants.GEN_AI_EVENT_CONTENT], + ['function' + Constants.GEN_AI_RESPONSE_CONTENT_KEY, OpenTelemetryConstants.GEN_AI_TOOL_CALL_RESULT_KEY], ['function' + Constants.GEN_AI_REQUEST_CONTENT_KEY, OpenTelemetryConstants.GEN_AI_TOOL_ARGS_KEY], ['generation' + Constants.GEN_AI_RESPONSE_CONTENT_KEY, OpenTelemetryConstants.GEN_AI_OUTPUT_MESSAGES_KEY], ['generation' + Constants.GEN_AI_REQUEST_CONTENT_KEY, OpenTelemetryConstants.GEN_AI_INPUT_MESSAGES_KEY], diff --git a/packages/agents-a365-observability-extensions-openai/src/Utils.ts b/packages/agents-a365-observability-extensions-openai/src/Utils.ts index 54331ea7..6d8061e6 100644 --- a/packages/agents-a365-observability-extensions-openai/src/Utils.ts +++ b/packages/agents-a365-observability-extensions-openai/src/Utils.ts @@ -94,10 +94,6 @@ export function getAttributesFromGenerationSpanData(data: SpanData): Record; - if (output.id) { - attributes[OpenTelemetryConstants.GEN_AI_RESPONSE_ID_KEY] = output.id; - } } if (genData.usage) { diff --git a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts index 981d4ead..dd0ea467 100644 --- a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts +++ b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts @@ -124,8 +124,8 @@ export function getSourceMetadataBaggagePairs(turnContext: TurnContext): Array<[ return []; } const pairs: Array<[string, string | undefined]> = [ - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, turnContext.activity?.channelId], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, turnContext.activity?.channelIdSubChannel as string | undefined] + [OpenTelemetryConstants.CHANNEL_NAME_KEY, turnContext.activity?.channelId], + [OpenTelemetryConstants.CHANNEL_LINK_KEY, turnContext.activity?.channelIdSubChannel as string | undefined] ]; return normalizePairs(pairs); } diff --git a/packages/agents-a365-observability/.gitignore b/packages/agents-a365-observability/.gitignore new file mode 100644 index 00000000..2a490f05 --- /dev/null +++ b/packages/agents-a365-observability/.gitignore @@ -0,0 +1,2 @@ +# This file is generated by a prebuild script. +src/version.ts diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index 333e2fe4..68a58ca8 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -8,11 +8,6 @@ import { LIB_VERSION } from '../version'; * OpenTelemetry constants for Agent 365 */ export class OpenTelemetryConstants { - // New telemetry schema feature flag - public static readonly USE_NEW_TELEMETRY_SCHEMA_ENV = 'A365_USE_NEW_TELEMETRY_SCHEMA'; - // eslint-disable-next-line no-restricted-properties - public static readonly isNewTelemetrySchemaEnabled = process.env['A365_USE_NEW_TELEMETRY_SCHEMA'] === 'true'; - // Span operation names public static readonly INVOKE_AGENT_OPERATION_NAME = 'invoke_agent'; public static readonly EXECUTE_TOOL_OPERATION_NAME = 'execute_tool'; @@ -43,7 +38,6 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_REQUEST_MODEL_KEY = 'gen_ai.request.model'; public static readonly GEN_AI_REQUEST_TEMPERATURE_KEY = 'gen_ai.request.temperature'; public static readonly GEN_AI_REQUEST_TOP_P_KEY = 'gen_ai.request.top_p'; - public static readonly GEN_AI_RESPONSE_ID_KEY = 'gen_ai.response.id'; public static readonly GEN_AI_RESPONSE_FINISH_REASONS_KEY = 'gen_ai.response.finish_reasons'; public static readonly GEN_AI_RESPONSE_MODEL_KEY = 'gen_ai.response.model'; public static readonly GEN_AI_SYSTEM_KEY = 'gen_ai.system'; @@ -53,10 +47,10 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_AGENT_NAME_KEY = 'gen_ai.agent.name'; public static readonly GEN_AI_AGENT_TYPE_KEY = 'gen_ai.agent.type'; public static readonly GEN_AI_AGENT_DESCRIPTION_KEY = 'gen_ai.agent.description'; - public static readonly GEN_AI_AGENT_PLATFORM_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.platform.id' : 'gen_ai.agent.platformid'; - public static readonly GEN_AI_AGENT_THOUGHT_PROCESS_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.thought.process' : 'gen_ai.agent.thought.process'; + public static readonly GEN_AI_AGENT_PLATFORM_ID_KEY = 'microsoft.a365.agent.platform.id'; + public static readonly GEN_AI_AGENT_THOUGHT_PROCESS_KEY = 'microsoft.a365.agent.thought.process'; public static readonly GEN_AI_CONVERSATION_ID_KEY = 'gen_ai.conversation.id'; - public static readonly GEN_AI_CONVERSATION_ITEM_LINK_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.conversation.item.link' : 'gen_ai.conversation.item.link'; + public static readonly GEN_AI_CONVERSATION_ITEM_LINK_KEY = 'microsoft.conversation.item.link'; public static readonly GEN_AI_TOKEN_TYPE_KEY = 'gen_ai.token.type'; public static readonly GEN_AI_USAGE_INPUT_TOKENS_KEY = 'gen_ai.usage.input_tokens'; public static readonly GEN_AI_USAGE_OUTPUT_TOKENS_KEY = 'gen_ai.usage.output_tokens'; @@ -66,63 +60,62 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_SYSTEM_INSTRUCTIONS_KEY = 'gen_ai.system_instructions'; public static readonly GEN_AI_INPUT_MESSAGES_KEY = 'gen_ai.input.messages'; public static readonly GEN_AI_OUTPUT_MESSAGES_KEY = 'gen_ai.output.messages'; - public static readonly GEN_AI_EVENT_CONTENT = 'gen_ai.event.content'; + public static readonly GEN_AI_EVENT_CONTENT = 'gen_ai.tool.call.result'; // Tool execution constants public static readonly GEN_AI_TOOL_CALL_ID_KEY = 'gen_ai.tool.call.id'; public static readonly GEN_AI_TOOL_NAME_KEY = 'gen_ai.tool.name'; public static readonly GEN_AI_TOOL_DESCRIPTION_KEY = 'gen_ai.tool.description'; public static readonly GEN_AI_TOOL_ARGS_KEY = 'gen_ai.tool.call.arguments'; - public static readonly GEN_AI_TOOL_CALL_RESULT_KEY = 'gen_ai.event.content'; // GEN_AI_EVENT_CONTENT + public static readonly GEN_AI_TOOL_CALL_RESULT_KEY = 'gen_ai.tool.call.result'; public static readonly GEN_AI_TOOL_TYPE_KEY = 'gen_ai.tool.type'; // Agent user (user tied to agent instance during creation) or caller dimensions - public static readonly GEN_AI_CALLER_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.id' : 'gen_ai.caller.id'; - public static readonly GEN_AI_CALLER_NAME_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.name' : 'gen_ai.caller.name'; - public static readonly GEN_AI_CALLER_UPN_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.caller.upn' : 'gen_ai.caller.upn'; - public static readonly GEN_AI_CALLER_CLIENT_IP_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'client.address' : 'gen_ai.caller.client.ip'; + public static readonly GEN_AI_CALLER_ID_KEY = 'microsoft.caller.id'; + public static readonly GEN_AI_CALLER_NAME_KEY = 'microsoft.caller.name'; + public static readonly GEN_AI_CALLER_UPN_KEY = 'microsoft.caller.upn'; + public static readonly GEN_AI_CALLER_CLIENT_IP_KEY = 'client.address'; public static readonly GEN_AI_CALLER_TENANT_ID_KEY = 'gen_ai.caller.tenantid'; // Agent to Agent caller agent dimensions - public static readonly GEN_AI_CALLER_AGENT_USER_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.user.id' : 'gen_ai.caller.agent.userid'; + public static readonly GEN_AI_CALLER_AGENT_USER_ID_KEY = 'microsoft.a365.caller.agent.user.id'; public static readonly GEN_AI_CALLER_AGENT_UPN_KEY = 'gen_ai.caller.agent.upn'; public static readonly GEN_AI_CALLER_AGENT_TENANT_ID_KEY = 'gen_ai.caller.agent.tenantid'; - public static readonly GEN_AI_CALLER_AGENT_NAME_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.name' : 'gen_ai.caller.agent.name'; - public static readonly GEN_AI_CALLER_AGENT_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.id' : 'gen_ai.caller.agent.id'; - public static readonly GEN_AI_CALLER_AGENT_TYPE_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.type' : 'gen_ai.caller.agent.type'; - public static readonly GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.blueprint.id' : 'gen_ai.caller.agent.applicationid'; + public static readonly GEN_AI_CALLER_AGENT_NAME_KEY = 'microsoft.a365.caller.agent.name'; + public static readonly GEN_AI_CALLER_AGENT_ID_KEY = 'microsoft.a365.caller.agent.id'; + public static readonly GEN_AI_CALLER_AGENT_TYPE_KEY = 'microsoft.a365.caller.agent.type'; + public static readonly GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY = 'microsoft.a365.caller.agent.blueprint.id'; public static readonly GEN_AI_CALLER_AGENT_CLIENT_IP_KEY = 'gen_ai.caller.agent.user.client.ip'; - public static readonly GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.caller.agent.platform.id' : 'gen_ai.caller.agent.platformid'; + public static readonly GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY = 'microsoft.a365.caller.agent.platform.id'; // Agent-specific dimensions public static readonly AGENT_ID_KEY = 'gen_ai.agent.id'; public static readonly GEN_AI_TASK_ID_KEY = 'gen_ai.task.id'; - public static readonly SESSION_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.session.id' : 'session.id'; - public static readonly SESSION_DESCRIPTION_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.session.description' : 'session.description'; + public static readonly SESSION_ID_KEY = 'microsoft.session.id'; + public static readonly SESSION_DESCRIPTION_KEY = 'microsoft.session.description'; public static readonly GEN_AI_ICON_URI_KEY = 'gen_ai.agent365.icon_uri'; - public static readonly TENANT_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.tenant.id' : 'tenant.id'; + public static readonly TENANT_ID_KEY = 'microsoft.tenant.id'; // Baggage keys - public static readonly OPERATION_SOURCE_KEY = 'operation.source'; - public static readonly GEN_AI_AGENT_AUID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.agent.user.id' : 'gen_ai.agent.user.id'; - public static readonly GEN_AI_AGENT_UPN_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.agent.user.upn' : 'gen_ai.agent.upn'; - public static readonly GEN_AI_AGENT_BLUEPRINT_ID_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.a365.agent.blueprint.id' : 'gen_ai.agent.applicationid'; - public static readonly CORRELATION_ID_KEY = 'correlation.id'; - public static readonly HIRING_MANAGER_ID_KEY = 'hiring.manager.id'; + public static readonly GEN_AI_AGENT_AUID_KEY = 'microsoft.a365.agent.user.id'; + public static readonly GEN_AI_AGENT_UPN_KEY = 'microsoft.agent.user.upn'; + public static readonly GEN_AI_AGENT_BLUEPRINT_ID_KEY = 'microsoft.agent.blueprint.id'; // Execution context dimensions public static readonly GEN_AI_EXECUTION_TYPE_KEY = 'gen_ai.execution.type'; public static readonly GEN_AI_EXECUTION_PAYLOAD_KEY = 'gen_ai.execution.payload'; - // Source metadata dimensions - public static readonly GEN_AI_EXECUTION_SOURCE_ID_KEY = 'gen_ai.execution.sourceMetadata.id'; - public static readonly GEN_AI_EXECUTION_SOURCE_NAME_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.channel.name' : 'gen_ai.channel.name'; - public static readonly GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY = OpenTelemetryConstants.isNewTelemetrySchemaEnabled ? 'microsoft.channel.link' : 'gen_ai.channel.link'; + // Channel dimensions + public static readonly CHANNEL_NAME_KEY = 'microsoft.channel.name'; + public static readonly CHANNEL_LINK_KEY = 'microsoft.channel.link'; // Custom parent id and parent name key public static readonly CUSTOM_PARENT_SPAN_ID_KEY = 'custom.parent.span.id'; public static readonly CUSTOM_SPAN_NAME_KEY = 'custom.span.name'; - // Telemetry SDK attributes (replace operation.source when isNewTelemetrySchemaEnabled) + // Service attributes (server spans only) + public static readonly SERVICE_NAME_KEY = 'service.name'; + + // Telemetry SDK attributes public static readonly TELEMETRY_SDK_NAME_KEY = 'telemetry.sdk.name'; public static readonly TELEMETRY_SDK_LANGUAGE_KEY = 'telemetry.sdk.language'; public static readonly TELEMETRY_SDK_VERSION_KEY = 'telemetry.sdk.version'; @@ -130,23 +123,3 @@ export class OpenTelemetryConstants { public static readonly TELEMETRY_SDK_LANGUAGE_VALUE = 'nodejs'; public static readonly TELEMETRY_SDK_VERSION_VALUE = LIB_VERSION; } - -/** - * Enumeration representing the source of an operation. - */ -export enum OperationSource { - /** - * Operation executed by SDK. - */ - SDK = 'SDK', - - /** - * Operation executed by Gateway. - */ - GATEWAY = 'Gateway', - - /** - * Operation executed by MCP Server. - */ - MCP_SERVER = 'MCPServer', -} diff --git a/packages/agents-a365-observability/src/tracing/contracts.ts b/packages/agents-a365-observability/src/tracing/contracts.ts index 6d0e6736..85976a5b 100644 --- a/packages/agents-a365-observability/src/tracing/contracts.ts +++ b/packages/agents-a365-observability/src/tracing/contracts.ts @@ -234,11 +234,11 @@ export interface InferenceDetails { /** Array of finish reasons */ finishReasons?: string[]; - /** Response ID from the model provider */ - responseId?: string; - /** The thought process used by the agent */ thoughtProcess?: string; + + /** The endpoint for the inference call */ + endpoint?: ServiceEndpoint; } /** diff --git a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts index 39548bcb..d2c1354c 100644 --- a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts +++ b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts @@ -16,7 +16,6 @@ import { OpenTelemetryConstants } from '../constants'; * const scope = new BaggageBuilder() * .tenantId("tenant-123") * .agentId("agent-456") - * .correlationId("corr-789") * .build(); * * scope.enter(); @@ -30,12 +29,13 @@ export class BaggageBuilder { private pairs: Map = new Map(); /** - * Set the operation source baggage value. - * @param value The operation source value + * Set the service name baggage value. + * Used for server spans to identify the service (e.g., ATG, ACF). + * @param value The service name * @returns Self for method chaining */ - operationSource(value: string | null | undefined): BaggageBuilder { - this.set(OpenTelemetryConstants.OPERATION_SOURCE_KEY, value); + serviceName(value: string | null | undefined): BaggageBuilder { + this.set(OpenTelemetryConstants.SERVICE_NAME_KEY, value); return this; } @@ -89,18 +89,6 @@ export class BaggageBuilder { return this; } - /** - * Set the correlation ID baggage value. - * @param value The correlation ID - * @returns Self for method chaining - */ - correlationId(value: string | null | undefined): BaggageBuilder { - if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - this.set(OpenTelemetryConstants.CORRELATION_ID_KEY, value); - } - return this; - } - /** * Set the session ID baggage value. * @param value The session ID @@ -121,18 +109,6 @@ export class BaggageBuilder { return this; } - /** - * Set the hiring manager ID baggage value. - * @param value The hiring manager ID - * @returns Self for method chaining - */ - hiringManagerId(value: string | null | undefined): BaggageBuilder { - if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - this.set(OpenTelemetryConstants.HIRING_MANAGER_ID_KEY, value); - } - return this; - } - /** * Set the agent name baggage value. * @param value The agent name @@ -246,32 +222,22 @@ export class BaggageBuilder { } /** - * Set the execution source metadata ID (e.g., channel ID). - * @param value The source metadata ID - * @returns Self for method chaining - */ - sourceMetadataId(value: string | null | undefined): BaggageBuilder { - this.set(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_ID_KEY, value); - return this; - } - - /** - * Set the execution source metadata name (e.g., channel name). - * @param value The source metadata name + * Set the channel name (e.g., Teams, Slack). + * @param value The channel name * @returns Self for method chaining */ sourceMetadataName(value: string | null | undefined): BaggageBuilder { - this.set(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, value); + this.set(OpenTelemetryConstants.CHANNEL_NAME_KEY, value); return this; } /** - * Set the execution source metadata description (e.g., channel description). - * @param value The source metadata description + * Set the channel link/URL. + * @param value The channel link * @returns Self for method chaining */ sourceMetadataDescription(value: string | null | undefined): BaggageBuilder { - this.set(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, value); + this.set(OpenTelemetryConstants.CHANNEL_LINK_KEY, value); return this; } @@ -330,18 +296,15 @@ export class BaggageBuilder { * Convenience method to begin a request baggage scope with common fields. * @param tenantId The tenant ID * @param agentId The agent ID - * @param correlationId The correlation ID * @returns A context manager that restores the previous baggage on exit */ static setRequestContext( tenantId?: string | null, agentId?: string | null, - correlationId?: string | null, ): BaggageScope { return new BaggageBuilder() .tenantId(tenantId) .agentId(agentId) - .correlationId(correlationId) .build(); } } diff --git a/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts b/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts index b08b16af..377f836b 100644 --- a/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts +++ b/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts @@ -5,7 +5,7 @@ import { Context, propagation, Span } from '@opentelemetry/api'; import { SpanProcessor as BaseSpanProcessor } from '@opentelemetry/sdk-trace-base'; import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; -import { OpenTelemetryConstants, OperationSource } from '../constants'; +import { OpenTelemetryConstants } from '../constants'; import { GENERIC_ATTRIBUTES, INVOKE_AGENT_ATTRIBUTES } from './util'; /** @@ -69,22 +69,15 @@ export class SpanProcessor implements BaseSpanProcessor { INVOKE_AGENT_ATTRIBUTES.forEach(key => targetKeys.add(key)); } - // Set operation source or telemetry SDK attributes - if (OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - if (!existingAttrs.has(OpenTelemetryConstants.TELEMETRY_SDK_NAME_KEY)) { - span.setAttribute(OpenTelemetryConstants.TELEMETRY_SDK_NAME_KEY, OpenTelemetryConstants.TELEMETRY_SDK_NAME_VALUE); - } - if (!existingAttrs.has(OpenTelemetryConstants.TELEMETRY_SDK_LANGUAGE_KEY)) { - span.setAttribute(OpenTelemetryConstants.TELEMETRY_SDK_LANGUAGE_KEY, OpenTelemetryConstants.TELEMETRY_SDK_LANGUAGE_VALUE); - } - if (!existingAttrs.has(OpenTelemetryConstants.TELEMETRY_SDK_VERSION_KEY)) { - span.setAttribute(OpenTelemetryConstants.TELEMETRY_SDK_VERSION_KEY, OpenTelemetryConstants.TELEMETRY_SDK_VERSION_VALUE); - } - } else if (!existingAttrs.has(OpenTelemetryConstants.OPERATION_SOURCE_KEY)) { - const operationSource = - baggageMap.get(OpenTelemetryConstants.OPERATION_SOURCE_KEY) || - OperationSource.SDK; - span.setAttribute(OpenTelemetryConstants.OPERATION_SOURCE_KEY, operationSource); + // Set telemetry SDK attributes + if (!existingAttrs.has(OpenTelemetryConstants.TELEMETRY_SDK_NAME_KEY)) { + span.setAttribute(OpenTelemetryConstants.TELEMETRY_SDK_NAME_KEY, OpenTelemetryConstants.TELEMETRY_SDK_NAME_VALUE); + } + if (!existingAttrs.has(OpenTelemetryConstants.TELEMETRY_SDK_LANGUAGE_KEY)) { + span.setAttribute(OpenTelemetryConstants.TELEMETRY_SDK_LANGUAGE_KEY, OpenTelemetryConstants.TELEMETRY_SDK_LANGUAGE_VALUE); + } + if (!existingAttrs.has(OpenTelemetryConstants.TELEMETRY_SDK_VERSION_KEY)) { + span.setAttribute(OpenTelemetryConstants.TELEMETRY_SDK_VERSION_KEY, OpenTelemetryConstants.TELEMETRY_SDK_VERSION_VALUE); } // Copy baggage to span attributes diff --git a/packages/agents-a365-observability/src/tracing/processors/util.ts b/packages/agents-a365-observability/src/tracing/processors/util.ts index 567d84ac..7f6a5b8c 100644 --- a/packages/agents-a365-observability/src/tracing/processors/util.ts +++ b/packages/agents-a365-observability/src/tracing/processors/util.ts @@ -11,31 +11,32 @@ export const GENERIC_ATTRIBUTES: readonly string[] = [ consts.TENANT_ID_KEY, consts.CUSTOM_PARENT_SPAN_ID_KEY, consts.CUSTOM_SPAN_NAME_KEY, - ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.CORRELATION_ID_KEY]), consts.SESSION_ID_KEY, consts.GEN_AI_CONVERSATION_ID_KEY, consts.GEN_AI_CONVERSATION_ITEM_LINK_KEY, consts.GEN_AI_OPERATION_NAME_KEY, consts.GEN_AI_AGENT_ID_KEY, consts.GEN_AI_AGENT_NAME_KEY, - ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_TYPE_KEY]), consts.GEN_AI_AGENT_DESCRIPTION_KEY, consts.SESSION_DESCRIPTION_KEY, consts.GEN_AI_AGENT_UPN_KEY, - ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY]), consts.GEN_AI_AGENT_AUID_KEY, consts.GEN_AI_AGENT_PLATFORM_ID_KEY, + consts.SERVICE_NAME_KEY, + // Caller / Invoker attributes + consts.GEN_AI_CALLER_ID_KEY, + consts.GEN_AI_CALLER_NAME_KEY, + consts.GEN_AI_CALLER_UPN_KEY, + consts.GEN_AI_CALLER_CLIENT_IP_KEY, + // Channel attributes + consts.CHANNEL_NAME_KEY, + consts.CHANNEL_LINK_KEY, ]; /** * Invoke Agent-specific attributes */ export const INVOKE_AGENT_ATTRIBUTES: readonly string[] = [ - // Caller / Invoker attributes - consts.GEN_AI_CALLER_ID_KEY, - consts.GEN_AI_CALLER_NAME_KEY, - consts.GEN_AI_CALLER_UPN_KEY, - consts.GEN_AI_CALLER_CLIENT_IP_KEY, consts.GEN_AI_CALLER_TENANT_ID_KEY, // Caller Agent (A2A) attributes consts.GEN_AI_CALLER_AGENT_ID_KEY, @@ -47,11 +48,7 @@ export const INVOKE_AGENT_ATTRIBUTES: readonly string[] = [ consts.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, consts.GEN_AI_CALLER_AGENT_CLIENT_IP_KEY, consts.GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY, - // Execution context - ...(consts.isNewTelemetrySchemaEnabled ? [] : [consts.GEN_AI_EXECUTION_TYPE_KEY]), - consts.GEN_AI_EXECUTION_SOURCE_ID_KEY, - consts.GEN_AI_EXECUTION_SOURCE_NAME_KEY, - consts.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, - // New schema: agent type and blueprint ID are InvokeAgent-only - ...(consts.isNewTelemetrySchemaEnabled ? [consts.GEN_AI_AGENT_TYPE_KEY, consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY] : []), + // Agent type and blueprint ID are InvokeAgent-only + consts.GEN_AI_AGENT_TYPE_KEY, + consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY, ]; diff --git a/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts b/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts index 9cfdf0bf..ebf468cd 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts @@ -73,8 +73,8 @@ export class ExecuteToolScope extends OpenTelemetryScope { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_TOOL_CALL_ID_KEY, toolCallId); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_TOOL_DESCRIPTION_KEY, description); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, conversationId); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, sourceMetadata?.name); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, sourceMetadata?.description); + this.setTagMaybe(OpenTelemetryConstants.CHANNEL_NAME_KEY, sourceMetadata?.name); + this.setTagMaybe(OpenTelemetryConstants.CHANNEL_LINK_KEY, sourceMetadata?.description); // Set endpoint information if provided @@ -93,6 +93,6 @@ export class ExecuteToolScope extends OpenTelemetryScope { * @param response The tool execution response */ public recordResponse(response: string): void { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EVENT_CONTENT, response); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_TOOL_CALL_RESULT_KEY, response); } } diff --git a/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts index fc4df2a7..c4ac447b 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts @@ -9,7 +9,8 @@ import { AgentDetails, TenantDetails, SourceMetadata, - CallerDetails + CallerDetails, + ServiceEndpoint } from '../contracts'; import { ParentContext } from '../context/trace-context-propagation'; @@ -75,11 +76,20 @@ export class InferenceScope extends OpenTelemetryScope { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_INPUT_TOKENS_KEY, details.inputTokens?.toString()); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_OUTPUT_TOKENS_KEY, details.outputTokens?.toString()); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_RESPONSE_FINISH_REASONS_KEY, details.finishReasons?.join(',')); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_RESPONSE_ID_KEY, details.responseId); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_THOUGHT_PROCESS_KEY, details.thoughtProcess); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, conversationId); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, sourceMetadata?.name); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, sourceMetadata?.description); + this.setTagMaybe(OpenTelemetryConstants.CHANNEL_NAME_KEY, sourceMetadata?.name); + this.setTagMaybe(OpenTelemetryConstants.CHANNEL_LINK_KEY, sourceMetadata?.description); + + // Set endpoint information if provided + if (details.endpoint) { + this.setTagMaybe(OpenTelemetryConstants.SERVER_ADDRESS_KEY, details.endpoint.host); + + // Only record port if it is different from 443 (default HTTPS port) + if (details.endpoint.port && details.endpoint.port !== 443) { + this.setTagMaybe(OpenTelemetryConstants.SERVER_PORT_KEY, details.endpoint.port); + } + } } /** @@ -114,16 +124,6 @@ export class InferenceScope extends OpenTelemetryScope { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_OUTPUT_TOKENS_KEY, outputTokens.toString()); } - /** - * Records the response id for telemetry tracking. - * @param responseId The response ID - */ - public recordResponseId(responseId: string): void { - if (responseId && responseId.trim()) { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_RESPONSE_ID_KEY, responseId); - } - } - /** * Records the finish reasons for telemetry tracking. * @param finishReasons Array of finish reasons diff --git a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts index a5359663..6d05ac11 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts @@ -66,11 +66,9 @@ export class InvokeAgentScope extends OpenTelemetryScope { // Set session ID and endpoint information this.setTagMaybe(OpenTelemetryConstants.SESSION_ID_KEY, invokeAgentDetails.sessionId); - // New schema: agent type and blueprint ID are InvokeAgent-only (base class skips them) - if (OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY, invokeAgentDetails.agentType); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, invokeAgentDetails.agentBlueprintId); - } + // Agent type and blueprint ID are InvokeAgent-only + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY, invokeAgentDetails.agentType); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, invokeAgentDetails.agentBlueprintId); if (invokeAgentDetails.endpoint) { this.setTagMaybe(OpenTelemetryConstants.SERVER_ADDRESS_KEY, invokeAgentDetails.endpoint.host); @@ -84,14 +82,9 @@ export class InvokeAgentScope extends OpenTelemetryScope { // Set request-related tags const requestToUse = invokeAgentDetails.request; if (requestToUse) { - // gen_ai.execution.type is removed in new schema - if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled && requestToUse.executionType) { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_TYPE_KEY, requestToUse.executionType.toString()); - } if (requestToUse.sourceMetadata) { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_ID_KEY, requestToUse.sourceMetadata.id); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, requestToUse.sourceMetadata.name); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, requestToUse.sourceMetadata.description); + this.setTagMaybe(OpenTelemetryConstants.CHANNEL_NAME_KEY, requestToUse.sourceMetadata.name); + this.setTagMaybe(OpenTelemetryConstants.CHANNEL_LINK_KEY, requestToUse.sourceMetadata.description); } } diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index 0e1033e6..588aa39d 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -92,11 +92,6 @@ export abstract class OpenTelemetryScope implements Disposable { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_ICON_URI_KEY, agentDetails.iconUri); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_AUID_KEY, agentDetails.agentAUID); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_UPN_KEY, agentDetails.agentUPN); - - if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY, agentDetails.agentType); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, agentDetails.agentBlueprintId); - } } // Set tenant details if provided diff --git a/packages/agents-a365-observability/src/version.ts b/packages/agents-a365-observability/src/version.ts deleted file mode 100644 index da17395a..00000000 --- a/packages/agents-a365-observability/src/version.ts +++ /dev/null @@ -1 +0,0 @@ -export const LIB_VERSION = "0.0.0-placeholder"; diff --git a/tests/observability/core/BaggageBuilder.test.ts b/tests/observability/core/BaggageBuilder.test.ts index b4522772..96a5f296 100644 --- a/tests/observability/core/BaggageBuilder.test.ts +++ b/tests/observability/core/BaggageBuilder.test.ts @@ -25,19 +25,10 @@ describe('BaggageBuilder', () => { expect(scope).toBeInstanceOf(BaggageScope); }); - it('should set correlation ID', () => { - const builder = new BaggageBuilder(); - builder.correlationId('corr-789'); - - const scope = builder.build(); - expect(scope).toBeInstanceOf(BaggageScope); - }); - it('should chain multiple setters', () => { const builder = new BaggageBuilder() .tenantId('tenant-123') .agentId('agent-456') - .correlationId('corr-789') .agentName('TestAgent') .agentType('assistant') .agentPlatformId('platform-xyz-123') @@ -115,8 +106,7 @@ describe('BaggageBuilder', () => { const builder = new BaggageBuilder(); builder.setPairs({ [OpenTelemetryConstants.TENANT_ID_KEY]: 'tenant-123', - [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY]: null, - [OpenTelemetryConstants.CORRELATION_ID_KEY]: undefined + [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY]: null }); const scope = builder.build(); @@ -156,8 +146,7 @@ describe('BaggageBuilder', () => { it('should create scope with common fields', () => { const scope = BaggageBuilder.setRequestContext( 'tenant-123', - 'agent-456', - 'corr-789' + 'agent-456' ); expect(scope).toBeInstanceOf(BaggageScope); @@ -166,8 +155,7 @@ describe('BaggageBuilder', () => { it('should handle null values', () => { const scope = BaggageBuilder.setRequestContext( null, - 'agent-456', - null + 'agent-456' ); expect(scope).toBeInstanceOf(BaggageScope); @@ -179,7 +167,6 @@ describe('BaggageBuilder', () => { const scope = new BaggageBuilder() .tenantId('tenant-123') .agentId('agent-456') - .correlationId('corr-789') .sessionId('session-0001') .sessionDescription('My session desc') .build(); diff --git a/tests/observability/core/SpanProcessor.test.ts b/tests/observability/core/SpanProcessor.test.ts index c0ace2d5..ec79d26c 100644 --- a/tests/observability/core/SpanProcessor.test.ts +++ b/tests/observability/core/SpanProcessor.test.ts @@ -29,7 +29,6 @@ describe('SpanProcessor', () => { it('should copy generic attributes from baggage to span', () => { const baggageEntries = { [OpenTelemetryConstants.TENANT_ID_KEY]: 'tenant-123', - [OpenTelemetryConstants.CORRELATION_ID_KEY]: 'corr-456', [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY]: 'agent-789' }; @@ -162,18 +161,20 @@ describe('SpanProcessor', () => { describe('attribute registry application', () => { it('should apply all generic attributes', () => { expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.TENANT_ID_KEY); - if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.CORRELATION_ID_KEY); - } expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY); expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.SESSION_ID_KEY); + expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY); + expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY); + expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY); + expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY); + expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.CHANNEL_NAME_KEY); + expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.CHANNEL_LINK_KEY); + expect(GENERIC_ATTRIBUTES).not.toContain('correlation.id'); }); it('should apply invoke agent specific attributes', () => { - expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY); - if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_EXECUTION_TYPE_KEY); - } + expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY); + expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY); }); }); diff --git a/tests/observability/core/scopes.test.ts b/tests/observability/core/scopes.test.ts index 532399dd..51018440 100644 --- a/tests/observability/core/scopes.test.ts +++ b/tests/observability/core/scopes.test.ts @@ -249,15 +249,9 @@ describe('Scopes', () => { ])); // Validate raw attribute key strings for schema correctness const keySet = new Set(calls.map(c => c.key)); - if (OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - expect(keySet).toContain('microsoft.caller.id'); - expect(keySet).toContain('microsoft.caller.name'); - expect(keySet).toContain('client.address'); - } else { - expect(keySet).toContain('gen_ai.caller.id'); - expect(keySet).toContain('gen_ai.caller.name'); - expect(keySet).toContain('gen_ai.caller.client.ip'); - } + expect(keySet).toContain('microsoft.caller.id'); + expect(keySet).toContain('microsoft.caller.name'); + expect(keySet).toContain('client.address'); scope?.dispose(); spy.mockRestore(); }); @@ -290,8 +284,8 @@ describe('Scopes', () => { const calls = spy.mock.calls.map(args => ({ key: args[0], val: args[1] })); expect(calls).toEqual(expect.arrayContaining([ - expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, val: 'ChannelTool' }), - expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, val: 'https://channel/tool' }) + expect.objectContaining({ key: OpenTelemetryConstants.CHANNEL_NAME_KEY, val: 'ChannelTool' }), + expect.objectContaining({ key: OpenTelemetryConstants.CHANNEL_LINK_KEY, val: 'https://channel/tool' }) ])); scope?.dispose(); @@ -317,7 +311,6 @@ describe('Scopes', () => { providerName: 'openai', inputTokens: 100, outputTokens: 150, - responseId: 'resp-123', finishReasons: ['stop'] }; @@ -332,15 +325,9 @@ describe('Scopes', () => { ])); // Validate raw attribute key strings for schema correctness const keySet = new Set(calls.map(c => c.key)); - if (OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - expect(keySet).toContain('microsoft.caller.id'); - expect(keySet).toContain('microsoft.caller.name'); - expect(keySet).toContain('client.address'); - } else { - expect(keySet).toContain('gen_ai.caller.id'); - expect(keySet).toContain('gen_ai.caller.name'); - expect(keySet).toContain('gen_ai.caller.client.ip'); - } + expect(keySet).toContain('microsoft.caller.id'); + expect(keySet).toContain('microsoft.caller.name'); + expect(keySet).toContain('client.address'); scope?.dispose(); spy.mockRestore(); }); @@ -369,7 +356,6 @@ describe('Scopes', () => { expect(() => scope?.recordOutputMessages(['Generated response'])).not.toThrow(); expect(() => scope?.recordInputTokens(50)).not.toThrow(); expect(() => scope?.recordOutputTokens(100)).not.toThrow(); - expect(() => scope?.recordResponseId('resp-456')).not.toThrow(); expect(() => scope?.recordFinishReasons(['stop', 'length'])).not.toThrow(); scope?.dispose(); }); @@ -405,8 +391,8 @@ describe('Scopes', () => { const calls = spy.mock.calls.map(args => ({ key: args[0], val: args[1] })); expect(calls).toEqual(expect.arrayContaining([ - expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, val: 'ChannelInf' }), - expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, val: 'https://channel/inf' }) + expect.objectContaining({ key: OpenTelemetryConstants.CHANNEL_NAME_KEY, val: 'ChannelInf' }), + expect.objectContaining({ key: OpenTelemetryConstants.CHANNEL_LINK_KEY, val: 'https://channel/inf' }) ])); scope?.dispose(); @@ -564,51 +550,29 @@ describe('Scopes', () => { }); }); -// Validate raw caller attribute key strings for both old and new schemas -// using jest.isolateModules to re-evaluate constants with different env var values. -describe('Caller attribute key schema mappings', () => { - const loadConstants = (useNewSchema: boolean) => { - let consts: typeof OpenTelemetryConstants; - const original = process.env['A365_USE_NEW_TELEMETRY_SCHEMA']; - process.env['A365_USE_NEW_TELEMETRY_SCHEMA'] = useNewSchema ? 'true' : ''; - jest.isolateModules(() => { - consts = require('@microsoft/agents-a365-observability').OpenTelemetryConstants; - }); - if (original === undefined) { - delete process.env['A365_USE_NEW_TELEMETRY_SCHEMA']; - } else { - process.env['A365_USE_NEW_TELEMETRY_SCHEMA'] = original; - } - return consts!; - }; - - it('old schema uses gen_ai.* caller key names', () => { - const consts = loadConstants(false); - expect(consts.GEN_AI_CALLER_ID_KEY).toBe('gen_ai.caller.id'); - expect(consts.GEN_AI_CALLER_NAME_KEY).toBe('gen_ai.caller.name'); - expect(consts.GEN_AI_CALLER_UPN_KEY).toBe('gen_ai.caller.upn'); - expect(consts.GEN_AI_CALLER_CLIENT_IP_KEY).toBe('gen_ai.caller.client.ip'); +// Validate attribute key constant values use the new schema namespace. +describe('Attribute key schema values', () => { + it('caller keys use microsoft.* / client.* namespace', () => { + expect(OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY).toBe('microsoft.caller.id'); + expect(OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY).toBe('microsoft.caller.name'); + expect(OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY).toBe('microsoft.caller.upn'); + expect(OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY).toBe('client.address'); }); - it('new schema uses microsoft.* / client.* caller key names', () => { - const consts = loadConstants(true); - expect(consts.GEN_AI_CALLER_ID_KEY).toBe('microsoft.caller.id'); - expect(consts.GEN_AI_CALLER_NAME_KEY).toBe('microsoft.caller.name'); - expect(consts.GEN_AI_CALLER_UPN_KEY).toBe('microsoft.caller.upn'); - expect(consts.GEN_AI_CALLER_CLIENT_IP_KEY).toBe('client.address'); + it('caller agent keys use microsoft.a365.* namespace', () => { + expect(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_ID_KEY).toBe('microsoft.a365.caller.agent.id'); + expect(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_NAME_KEY).toBe('microsoft.a365.caller.agent.name'); + expect(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY).toBe('microsoft.a365.caller.agent.blueprint.id'); }); - it('old schema uses gen_ai.* caller agent key names', () => { - const consts = loadConstants(false); - expect(consts.GEN_AI_CALLER_AGENT_ID_KEY).toBe('gen_ai.caller.agent.id'); - expect(consts.GEN_AI_CALLER_AGENT_NAME_KEY).toBe('gen_ai.caller.agent.name'); - expect(consts.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY).toBe('gen_ai.caller.agent.applicationid'); + it('channel keys use microsoft.channel.* namespace', () => { + expect(OpenTelemetryConstants.CHANNEL_NAME_KEY).toBe('microsoft.channel.name'); + expect(OpenTelemetryConstants.CHANNEL_LINK_KEY).toBe('microsoft.channel.link'); }); - it('new schema uses microsoft.a365.* caller agent key names', () => { - const consts = loadConstants(true); - expect(consts.GEN_AI_CALLER_AGENT_ID_KEY).toBe('microsoft.a365.caller.agent.id'); - expect(consts.GEN_AI_CALLER_AGENT_NAME_KEY).toBe('microsoft.a365.caller.agent.name'); - expect(consts.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY).toBe('microsoft.a365.caller.agent.blueprint.id'); + it('session and tenant keys use microsoft.* namespace', () => { + expect(OpenTelemetryConstants.SESSION_ID_KEY).toBe('microsoft.session.id'); + expect(OpenTelemetryConstants.SESSION_DESCRIPTION_KEY).toBe('microsoft.session.description'); + expect(OpenTelemetryConstants.TENANT_ID_KEY).toBe('microsoft.tenant.id'); }); }); diff --git a/tests/observability/extension/hosting/scope-utils.test.ts b/tests/observability/extension/hosting/scope-utils.test.ts index f706f962..6522f691 100644 --- a/tests/observability/extension/hosting/scope-utils.test.ts +++ b/tests/observability/extension/hosting/scope-utils.test.ts @@ -63,8 +63,8 @@ describe('ScopeUtils.populateFromTurnContext', () => { const calls = spy.mock.calls.map(args => [args[0], args[1]]); const expected = [ [OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, 'conv-A'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, 'web'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, 'https://web'], + [OpenTelemetryConstants.CHANNEL_NAME_KEY, 'web'], + [OpenTelemetryConstants.CHANNEL_LINK_KEY, 'https://web'], [OpenTelemetryConstants.GEN_AI_AGENT_NAME_KEY, 'Agent One'], [OpenTelemetryConstants.GEN_AI_AGENT_AUID_KEY, 'agent-oid'], [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY, 'agent-1'], @@ -73,9 +73,6 @@ describe('ScopeUtils.populateFromTurnContext', () => { [OpenTelemetryConstants.TENANT_ID_KEY, 'tenant-123'], [OpenTelemetryConstants.GEN_AI_INPUT_MESSAGES_KEY, 'input text'] ]; - if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - expected.push([OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, 'agent-blueprint-1']); - } expect(calls).toEqual(expect.arrayContaining(expected)); scope?.dispose(); }); @@ -127,8 +124,8 @@ describe('ScopeUtils.populateFromTurnContext', () => { const calls = spy.mock.calls.map(args => [args[0], args[1]]); const expected = [ [OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, 'conv-B'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, 'teams'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, 'https://teams'], + [OpenTelemetryConstants.CHANNEL_NAME_KEY, 'teams'], + [OpenTelemetryConstants.CHANNEL_LINK_KEY, 'https://teams'], [OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, 'user-oid'], [OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, 'Test User'], [OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, 'user@contoso.com'], @@ -142,9 +139,6 @@ describe('ScopeUtils.populateFromTurnContext', () => { [OpenTelemetryConstants.GEN_AI_AGENT_NAME_KEY, 'Agent One'], [OpenTelemetryConstants.GEN_AI_AGENT_DESCRIPTION_KEY, 'assistant'] ]; - if (!OpenTelemetryConstants.isNewTelemetrySchemaEnabled) { - expected.push([OpenTelemetryConstants.GEN_AI_EXECUTION_TYPE_KEY, ExecutionType.Agent2Agent.toString()]); - } expect(calls).toEqual(expect.arrayContaining(expected)); scope?.dispose(); }); @@ -158,8 +152,8 @@ describe('ScopeUtils.populateFromTurnContext', () => { expect(calls).toEqual( expect.arrayContaining([ [OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, 'conv-C'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_NAME_KEY, 'cli'], - [OpenTelemetryConstants.GEN_AI_EXECUTION_SOURCE_DESCRIPTION_KEY, 'https://cli'], + [OpenTelemetryConstants.CHANNEL_NAME_KEY, 'cli'], + [OpenTelemetryConstants.CHANNEL_LINK_KEY, 'https://cli'], [OpenTelemetryConstants.GEN_AI_AGENT_AUID_KEY, 'agent-oid'], [OpenTelemetryConstants.GEN_AI_AGENT_NAME_KEY, 'Agent One'], [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY, 'agent-1'], diff --git a/tests/observability/integration/openai-agent-instrument.test.ts b/tests/observability/integration/openai-agent-instrument.test.ts index 30b70366..48c17846 100644 --- a/tests/observability/integration/openai-agent-instrument.test.ts +++ b/tests/observability/integration/openai-agent-instrument.test.ts @@ -347,7 +347,7 @@ describe("OpenAI Trace Processor Integration Tests", () => { toolSpan.attributes[OpenTelemetryConstants.GEN_AI_TOOL_ARGS_KEY], ).toBe('{"a":15,"b":27}'); expect( - toolSpan.attributes[OpenTelemetryConstants.GEN_AI_EVENT_CONTENT], + toolSpan.attributes[OpenTelemetryConstants.GEN_AI_TOOL_CALL_RESULT_KEY], ).toBe("The sum of 15 and 27 is 42"); validateParentChildRelationship(toolSpan, agentSpan!); From 33c4e2d958de36061e18d2095a21260e043afe60 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Wed, 25 Feb 2026 18:55:45 -0800 Subject: [PATCH 08/19] Remove unused ServiceEndpoint import from InferenceScope Co-Authored-By: Claude Opus 4.6 --- .../src/tracing/scopes/InferenceScope.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts index c4ac447b..ef55d5a5 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts @@ -9,8 +9,7 @@ import { AgentDetails, TenantDetails, SourceMetadata, - CallerDetails, - ServiceEndpoint + CallerDetails } from '../contracts'; import { ParentContext } from '../context/trace-context-propagation'; From 8f648a6f9505696c98b459c95efdf4629ed593a1 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Wed, 25 Feb 2026 19:33:31 -0800 Subject: [PATCH 09/19] Remove duplicate GEN_AI_EVENT_CONTENT constant, clarify .gitignore comment Co-Authored-By: Claude Opus 4.6 --- packages/agents-a365-observability/.gitignore | 2 +- packages/agents-a365-observability/src/tracing/constants.ts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/agents-a365-observability/.gitignore b/packages/agents-a365-observability/.gitignore index 2a490f05..5d015ab0 100644 --- a/packages/agents-a365-observability/.gitignore +++ b/packages/agents-a365-observability/.gitignore @@ -1,2 +1,2 @@ -# This file is generated by a prebuild script. +# The file "src/version.ts" is generated by a prebuild script and should not be committed. src/version.ts diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index 68a58ca8..b701a57d 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -60,8 +60,6 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_SYSTEM_INSTRUCTIONS_KEY = 'gen_ai.system_instructions'; public static readonly GEN_AI_INPUT_MESSAGES_KEY = 'gen_ai.input.messages'; public static readonly GEN_AI_OUTPUT_MESSAGES_KEY = 'gen_ai.output.messages'; - public static readonly GEN_AI_EVENT_CONTENT = 'gen_ai.tool.call.result'; - // Tool execution constants public static readonly GEN_AI_TOOL_CALL_ID_KEY = 'gen_ai.tool.call.id'; public static readonly GEN_AI_TOOL_NAME_KEY = 'gen_ai.tool.name'; From 92172c9a2861049cfd2a2391b7d54582fcd5bfa2 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Thu, 26 Feb 2026 12:13:49 -0800 Subject: [PATCH 10/19] Remove extra attributes and fix name mismatches per A365 schema - Remove gen_ai.system constant; replace all usages with gen_ai.provider.name - Remove gen_ai.agent.type, gen_ai.caller.tenantid, gen_ai.caller.agent.tenantid, microsoft.a365.caller.agent.type, gen_ai.caller.agent.user.client.ip, operation.duration - Rename gen_ai.caller.agent.upn to microsoft.a365.caller.agent.user.upn - Fix microsoft.a365.agent.user.id to microsoft.agent.user.id - Fix microsoft.agent.blueprint.id to microsoft.a365.agent.blueprint.id - Remove agentType and agentClientIP from contracts - Update all tests and extensions Co-Authored-By: Claude Opus 4.6 --- .../src/tracer.ts | 2 +- .../src/OpenAIAgentsTraceProcessor.ts | 2 +- .../src/utils/TurnContextUtils.ts | 1 - .../src/tracing/constants.ts | 14 +++----------- .../src/tracing/contracts.ts | 6 ------ .../src/tracing/middleware/BaggageBuilder.ts | 10 ---------- .../src/tracing/processors/util.ts | 7 +------ .../src/tracing/scopes/InvokeAgentScope.ts | 6 +----- .../src/tracing/scopes/OpenTelemetryScope.ts | 7 +------ tests/observability/core/BaggageBuilder.test.ts | 12 ------------ tests/observability/core/SpanProcessor.test.ts | 1 - tests/observability/core/agent365-exporter.test.ts | 4 +--- tests/observability/core/scopes.test.ts | 5 ----- .../integration/openai-agent-instrument.test.ts | 8 ++++---- 14 files changed, 13 insertions(+), 72 deletions(-) diff --git a/packages/agents-a365-observability-extensions-langchain/src/tracer.ts b/packages/agents-a365-observability-extensions-langchain/src/tracer.ts index 2fdb64d8..4af3ee00 100644 --- a/packages/agents-a365-observability-extensions-langchain/src/tracer.ts +++ b/packages/agents-a365-observability-extensions-langchain/src/tracer.ts @@ -63,7 +63,7 @@ export class LangChainTracer extends BaseTracer { const span = this.tracer.startSpan(spanName, { kind: SpanKind.INTERNAL, startTime, - attributes: { [OpenTelemetryConstants.GEN_AI_SYSTEM_KEY]: "langchain" }, + attributes: { [OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY]: "langchain" }, }, activeContext); this.runs[run.id] = { run, span, startTime, lastAccessTime: startTime }; diff --git a/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts b/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts index 69e3d835..4f69662b 100644 --- a/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts +++ b/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts @@ -117,7 +117,7 @@ export class OpenAIAgentsTraceProcessor implements TracingProcessor { startTime, attributes: { [OpenTelemetryConstants.GEN_AI_OPERATION_NAME_KEY]: Utils.getSpanKind(spanData), - [OpenTelemetryConstants.GEN_AI_SYSTEM_KEY]: 'openai', + [OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY]: 'openai', }, }, parentContext diff --git a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts index dd0ea467..56683425 100644 --- a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts +++ b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts @@ -33,7 +33,6 @@ export function getCallerBaggagePairs(turnContext: TurnContext): Array<[string, [OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, from.aadObjectId], [OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, from.name], [OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, upn], - [OpenTelemetryConstants.GEN_AI_CALLER_TENANT_ID_KEY, from.tenantId], [OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, from.agenticAppBlueprintId] ]; return normalizePairs(pairs); diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index b701a57d..2589a4f3 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -40,12 +40,8 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_REQUEST_TOP_P_KEY = 'gen_ai.request.top_p'; public static readonly GEN_AI_RESPONSE_FINISH_REASONS_KEY = 'gen_ai.response.finish_reasons'; public static readonly GEN_AI_RESPONSE_MODEL_KEY = 'gen_ai.response.model'; - public static readonly GEN_AI_SYSTEM_KEY = 'gen_ai.system'; - public static readonly GEN_AI_SYSTEM_VALUE = 'az.ai.agent365'; - public static readonly GEN_AI_AGENT_ID_KEY = 'gen_ai.agent.id'; public static readonly GEN_AI_AGENT_NAME_KEY = 'gen_ai.agent.name'; - public static readonly GEN_AI_AGENT_TYPE_KEY = 'gen_ai.agent.type'; public static readonly GEN_AI_AGENT_DESCRIPTION_KEY = 'gen_ai.agent.description'; public static readonly GEN_AI_AGENT_PLATFORM_ID_KEY = 'microsoft.a365.agent.platform.id'; public static readonly GEN_AI_AGENT_THOUGHT_PROCESS_KEY = 'microsoft.a365.agent.thought.process'; @@ -73,17 +69,13 @@ export class OpenTelemetryConstants { public static readonly GEN_AI_CALLER_NAME_KEY = 'microsoft.caller.name'; public static readonly GEN_AI_CALLER_UPN_KEY = 'microsoft.caller.upn'; public static readonly GEN_AI_CALLER_CLIENT_IP_KEY = 'client.address'; - public static readonly GEN_AI_CALLER_TENANT_ID_KEY = 'gen_ai.caller.tenantid'; // Agent to Agent caller agent dimensions public static readonly GEN_AI_CALLER_AGENT_USER_ID_KEY = 'microsoft.a365.caller.agent.user.id'; - public static readonly GEN_AI_CALLER_AGENT_UPN_KEY = 'gen_ai.caller.agent.upn'; - public static readonly GEN_AI_CALLER_AGENT_TENANT_ID_KEY = 'gen_ai.caller.agent.tenantid'; + public static readonly GEN_AI_CALLER_AGENT_UPN_KEY = 'microsoft.a365.caller.agent.user.upn'; public static readonly GEN_AI_CALLER_AGENT_NAME_KEY = 'microsoft.a365.caller.agent.name'; public static readonly GEN_AI_CALLER_AGENT_ID_KEY = 'microsoft.a365.caller.agent.id'; - public static readonly GEN_AI_CALLER_AGENT_TYPE_KEY = 'microsoft.a365.caller.agent.type'; public static readonly GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY = 'microsoft.a365.caller.agent.blueprint.id'; - public static readonly GEN_AI_CALLER_AGENT_CLIENT_IP_KEY = 'gen_ai.caller.agent.user.client.ip'; public static readonly GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY = 'microsoft.a365.caller.agent.platform.id'; // Agent-specific dimensions public static readonly AGENT_ID_KEY = 'gen_ai.agent.id'; @@ -94,9 +86,9 @@ export class OpenTelemetryConstants { public static readonly TENANT_ID_KEY = 'microsoft.tenant.id'; // Baggage keys - public static readonly GEN_AI_AGENT_AUID_KEY = 'microsoft.a365.agent.user.id'; + public static readonly GEN_AI_AGENT_AUID_KEY = 'microsoft.agent.user.id'; public static readonly GEN_AI_AGENT_UPN_KEY = 'microsoft.agent.user.upn'; - public static readonly GEN_AI_AGENT_BLUEPRINT_ID_KEY = 'microsoft.agent.blueprint.id'; + public static readonly GEN_AI_AGENT_BLUEPRINT_ID_KEY = 'microsoft.a365.agent.blueprint.id'; // Execution context dimensions public static readonly GEN_AI_EXECUTION_TYPE_KEY = 'gen_ai.execution.type'; diff --git a/packages/agents-a365-observability/src/tracing/contracts.ts b/packages/agents-a365-observability/src/tracing/contracts.ts index 85976a5b..fd65f8ff 100644 --- a/packages/agents-a365-observability/src/tracing/contracts.ts +++ b/packages/agents-a365-observability/src/tracing/contracts.ts @@ -104,9 +104,6 @@ export interface AgentDetails { /** The human-readable name of the AI agent */ agentName?: string; - /** Optional type of the AI agent */ - agentType?: string; - /** A description of the AI agent's purpose or capabilities */ agentDescription?: string; @@ -127,9 +124,6 @@ export interface AgentDetails { /** The tenant ID for the agent */ tenantId?: string; - - /** The client IP address for the agent user */ - agentClientIP?: string; } /** diff --git a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts index d2c1354c..6bf4fa13 100644 --- a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts +++ b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts @@ -119,16 +119,6 @@ export class BaggageBuilder { return this; } - /** - * Set the agent type baggage value. - * @param value The agent type - * @returns Self for method chaining - */ - agentType(value: string | null | undefined): BaggageBuilder { - this.set(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY, value); - return this; - } - /** * Set the agent description baggage value. * @param value The agent description diff --git a/packages/agents-a365-observability/src/tracing/processors/util.ts b/packages/agents-a365-observability/src/tracing/processors/util.ts index 7f6a5b8c..518f5340 100644 --- a/packages/agents-a365-observability/src/tracing/processors/util.ts +++ b/packages/agents-a365-observability/src/tracing/processors/util.ts @@ -37,18 +37,13 @@ export const GENERIC_ATTRIBUTES: readonly string[] = [ * Invoke Agent-specific attributes */ export const INVOKE_AGENT_ATTRIBUTES: readonly string[] = [ - consts.GEN_AI_CALLER_TENANT_ID_KEY, // Caller Agent (A2A) attributes consts.GEN_AI_CALLER_AGENT_ID_KEY, consts.GEN_AI_CALLER_AGENT_NAME_KEY, - consts.GEN_AI_CALLER_AGENT_TYPE_KEY, consts.GEN_AI_CALLER_AGENT_USER_ID_KEY, consts.GEN_AI_CALLER_AGENT_UPN_KEY, - consts.GEN_AI_CALLER_AGENT_TENANT_ID_KEY, consts.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, - consts.GEN_AI_CALLER_AGENT_CLIENT_IP_KEY, consts.GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY, - // Agent type and blueprint ID are InvokeAgent-only - consts.GEN_AI_AGENT_TYPE_KEY, + // Blueprint ID is InvokeAgent-only consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY, ]; diff --git a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts index 6d05ac11..08d35c95 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts @@ -66,8 +66,7 @@ export class InvokeAgentScope extends OpenTelemetryScope { // Set session ID and endpoint information this.setTagMaybe(OpenTelemetryConstants.SESSION_ID_KEY, invokeAgentDetails.sessionId); - // Agent type and blueprint ID are InvokeAgent-only - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY, invokeAgentDetails.agentType); + // Blueprint ID is InvokeAgent-only this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, invokeAgentDetails.agentBlueprintId); if (invokeAgentDetails.endpoint) { @@ -94,12 +93,9 @@ export class InvokeAgentScope extends OpenTelemetryScope { if (callerAgentDetails) { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_NAME_KEY, callerAgentDetails.agentName); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_ID_KEY, callerAgentDetails.agentId); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_TYPE_KEY, callerAgentDetails.agentType); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, callerAgentDetails.agentBlueprintId); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_USER_ID_KEY, callerAgentDetails.agentAUID); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_UPN_KEY, callerAgentDetails.agentUPN); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_TENANT_ID_KEY, callerAgentDetails.tenantId); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_CLIENT_IP_KEY, callerAgentDetails.agentClientIP); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY, callerAgentDetails.platformId); } } diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index 588aa39d..6092a0aa 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -69,7 +69,7 @@ export abstract class OpenTelemetryScope implements Disposable { kind, startTime, attributes: { - [OpenTelemetryConstants.GEN_AI_SYSTEM_KEY]: OpenTelemetryConstants.GEN_AI_SYSTEM_VALUE, + [OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY]: 'az.ai.agent365', [OpenTelemetryConstants.GEN_AI_OPERATION_NAME_KEY]: operationName, }, }, currentContext); @@ -105,7 +105,6 @@ export abstract class OpenTelemetryScope implements Disposable { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, callerDetails.callerUpn); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, callerDetails.callerName); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY, callerDetails.callerClientIp); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_TENANT_ID_KEY, callerDetails.tenantId); } } @@ -248,10 +247,6 @@ export abstract class OpenTelemetryScope implements Disposable { this.span.setAttributes({ [OpenTelemetryConstants.ERROR_TYPE_KEY]: this.errorType }); } - // Record duration metric (would typically use a meter here) - // For now, we'll add it as a span attribute - this.span.setAttributes({ 'operation.duration': duration }); - this.hasEnded = true; logger.info(`[A365Observability] Ending span[${this.span.spanContext().spanId}], duration: ${duration}s`); } diff --git a/tests/observability/core/BaggageBuilder.test.ts b/tests/observability/core/BaggageBuilder.test.ts index 96a5f296..0c1dacf0 100644 --- a/tests/observability/core/BaggageBuilder.test.ts +++ b/tests/observability/core/BaggageBuilder.test.ts @@ -30,7 +30,6 @@ describe('BaggageBuilder', () => { .tenantId('tenant-123') .agentId('agent-456') .agentName('TestAgent') - .agentType('assistant') .agentPlatformId('platform-xyz-123') .conversationId('conv-001'); @@ -49,17 +48,6 @@ describe('BaggageBuilder', () => { expect(bag?.getEntry(OpenTelemetryConstants.GEN_AI_AGENT_PLATFORM_ID_KEY)?.value).toBe('platform-abc-456'); }); - it('should set agent type', () => { - const builder = new BaggageBuilder(); - builder.agentType('assistant'); - - const scope = builder.build(); - expect(scope).toBeInstanceOf(BaggageScope); - - const bag = propagation.getBaggage((scope as any).contextWithBaggage); - expect(bag?.getEntry(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY)?.value).toBe('assistant'); - }); - it('should set caller agent platform ID via fluent API', () => { const builder = new BaggageBuilder(); builder.callerAgentPlatformId('caller-platform-xyz'); diff --git a/tests/observability/core/SpanProcessor.test.ts b/tests/observability/core/SpanProcessor.test.ts index ec79d26c..7020f726 100644 --- a/tests/observability/core/SpanProcessor.test.ts +++ b/tests/observability/core/SpanProcessor.test.ts @@ -173,7 +173,6 @@ describe('SpanProcessor', () => { }); it('should apply invoke agent specific attributes', () => { - expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_AGENT_TYPE_KEY); expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY); }); }); diff --git a/tests/observability/core/agent365-exporter.test.ts b/tests/observability/core/agent365-exporter.test.ts index 858eb672..d616726f 100644 --- a/tests/observability/core/agent365-exporter.test.ts +++ b/tests/observability/core/agent365-exporter.test.ts @@ -91,8 +91,7 @@ describe('Agent365Exporter', () => { makeSpan({ [OpenTelemetryConstants.TENANT_ID_KEY]: tenantId, [OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY]: agentId, - [OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY]: '10.0.0.5', - [OpenTelemetryConstants.GEN_AI_CALLER_AGENT_CLIENT_IP_KEY]: '1.0.0.5' + [OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY]: '10.0.0.5' }) ]; @@ -112,7 +111,6 @@ describe('Agent365Exporter', () => { expect(exportedSpan.attributes[OpenTelemetryConstants.TENANT_ID_KEY]).toBe(tenantId); expect(exportedSpan.attributes[OpenTelemetryConstants.GEN_AI_AGENT_ID_KEY]).toBe(agentId); expect(exportedSpan.attributes[OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY]).toBe('10.0.0.5'); - expect(exportedSpan.attributes[OpenTelemetryConstants.GEN_AI_CALLER_AGENT_CLIENT_IP_KEY]).toBe('1.0.0.5'); }); it.each([ diff --git a/tests/observability/core/scopes.test.ts b/tests/observability/core/scopes.test.ts index 51018440..ef0240d2 100644 --- a/tests/observability/core/scopes.test.ts +++ b/tests/observability/core/scopes.test.ts @@ -213,7 +213,6 @@ describe('Scopes', () => { const calls = spy.mock.calls.map(args => ({ key: args[0], val: args[1] })); expect(calls).toEqual(expect.arrayContaining([ expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY, val: '10.0.0.5' }), - expect.objectContaining({ key: OpenTelemetryConstants.GEN_AI_CALLER_AGENT_CLIENT_IP_KEY, val: '192.168.1.100' }) ])); scope1?.dispose(); @@ -478,7 +477,6 @@ describe('Scopes', () => { const span = getFinishedSpan(); expect(hrtimeToMs(span.startTime as [number, number])).toBeCloseTo(customStart, -1); expect(hrtimeToMs(span.endTime as [number, number])).toBeCloseTo(customEnd, -1); - expect(span.attributes['operation.duration']).toBeCloseTo(5.0, 1); }); it('setEndTime should override end time when called before dispose', () => { @@ -496,7 +494,6 @@ describe('Scopes', () => { const span = getFinishedSpan(); expect(hrtimeToMs(span.startTime as [number, number])).toBeCloseTo(customStart, -1); expect(hrtimeToMs(span.endTime as [number, number])).toBeCloseTo(laterEnd, -1); - expect(span.attributes['operation.duration']).toBeCloseTo(8.0, 1); }); it('should support Date objects as start and end times', () => { @@ -513,7 +510,6 @@ describe('Scopes', () => { const span = getFinishedSpan(); expect(hrtimeToMs(span.startTime as [number, number])).toBeCloseTo(customStart.getTime(), -1); expect(hrtimeToMs(span.endTime as [number, number])).toBeCloseTo(customEnd.getTime(), -1); - expect(span.attributes['operation.duration']).toBeCloseTo(5.0, 1); }); it('should support HrTime tuples as start and end times', () => { @@ -531,7 +527,6 @@ describe('Scopes', () => { const span = getFinishedSpan(); expect(hrtimeToMs(span.startTime as [number, number])).toBeCloseTo(1700000000000, -1); expect(hrtimeToMs(span.endTime as [number, number])).toBeCloseTo(1700000005500, -1); - expect(span.attributes['operation.duration']).toBeCloseTo(5.5, 1); }); it('should use wall-clock time when no custom times are provided', () => { diff --git a/tests/observability/integration/openai-agent-instrument.test.ts b/tests/observability/integration/openai-agent-instrument.test.ts index 48c17846..eb4e9120 100644 --- a/tests/observability/integration/openai-agent-instrument.test.ts +++ b/tests/observability/integration/openai-agent-instrument.test.ts @@ -141,7 +141,7 @@ describe("OpenAI Trace Processor Integration Tests", () => { ], ).toBe("chat"); expect( - generationSpan.attributes[OpenTelemetryConstants.GEN_AI_SYSTEM_KEY], + generationSpan.attributes[OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY], ).toBe("openai"); expect( generationSpan.attributes[ @@ -199,7 +199,7 @@ describe("OpenAI Trace Processor Integration Tests", () => { ], ).toBe("invoke_agent"); expect( - agentSpan.attributes[OpenTelemetryConstants.GEN_AI_SYSTEM_KEY], + agentSpan.attributes[OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY], ).toBe("openai"); expect( agentSpan?.attributes[ @@ -310,7 +310,7 @@ describe("OpenAI Trace Processor Integration Tests", () => { ], ).toBe("invoke_agent"); expect( - agentSpan.attributes[OpenTelemetryConstants.GEN_AI_SYSTEM_KEY], + agentSpan.attributes[OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY], ).toBe("openai"); console.log("✅ Agent span validated"); } @@ -335,7 +335,7 @@ describe("OpenAI Trace Processor Integration Tests", () => { toolSpan.attributes[OpenTelemetryConstants.GEN_AI_OPERATION_NAME_KEY], ).toBe("execute_tool"); expect( - toolSpan.attributes[OpenTelemetryConstants.GEN_AI_SYSTEM_KEY], + toolSpan.attributes[OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY], ).toBe("openai"); expect( toolSpan.attributes[OpenTelemetryConstants.GEN_AI_TOOL_NAME_KEY], From 9e9092c8f04746f3855767fc67ec3f5b188ea9ef Mon Sep 17 00:00:00 2001 From: jsl517 Date: Thu, 26 Feb 2026 12:32:37 -0800 Subject: [PATCH 11/19] Add agentBlueprintId to base OpenTelemetryScope (common across all spans) Schema defines microsoft.a365.agent.blueprint.id as common across all span types. Previously it was only set in InvokeAgentScope. Co-Authored-By: Claude Opus 4.6 --- .../src/tracing/scopes/OpenTelemetryScope.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index 6092a0aa..d0907aa3 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -92,6 +92,7 @@ export abstract class OpenTelemetryScope implements Disposable { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_ICON_URI_KEY, agentDetails.iconUri); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_AUID_KEY, agentDetails.agentAUID); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_UPN_KEY, agentDetails.agentUPN); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, agentDetails.agentBlueprintId); } // Set tenant details if provided From 8dae2d1df6d138682ad9db1d353f174b8ab206d3 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Thu, 26 Feb 2026 12:39:04 -0800 Subject: [PATCH 12/19] Fix attribute type mismatches per A365 schema - Emit gen_ai.usage.input_tokens and output_tokens as int (not string) - Emit gen_ai.response.finish_reasons as string[] (not comma-joined string) - Emit server.port as string (not number) across all scope types - Widen setTagMaybe to accept string[] and number[] for array attributes Co-Authored-By: Claude Opus 4.6 --- .../src/tracing/scopes/ExecuteToolScope.ts | 2 +- .../src/tracing/scopes/InferenceScope.ts | 14 +++++++------- .../src/tracing/scopes/InvokeAgentScope.ts | 2 +- .../src/tracing/scopes/OpenTelemetryScope.ts | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts b/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts index ebf468cd..5cf16670 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/ExecuteToolScope.ts @@ -83,7 +83,7 @@ export class ExecuteToolScope extends OpenTelemetryScope { // Only record port if it is different from 443 (default HTTPS port) if (endpoint.port && endpoint.port !== 443) { - this.setTagMaybe(OpenTelemetryConstants.SERVER_PORT_KEY, endpoint.port); + this.setTagMaybe(OpenTelemetryConstants.SERVER_PORT_KEY, endpoint.port.toString()); } } } diff --git a/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts index ef55d5a5..092b6b8b 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InferenceScope.ts @@ -72,9 +72,9 @@ export class InferenceScope extends OpenTelemetryScope { this.setTagMaybe(OpenTelemetryConstants.GEN_AI_OPERATION_NAME_KEY, details.operationName.toString()); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_REQUEST_MODEL_KEY, details.model); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY, details.providerName); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_INPUT_TOKENS_KEY, details.inputTokens?.toString()); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_OUTPUT_TOKENS_KEY, details.outputTokens?.toString()); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_RESPONSE_FINISH_REASONS_KEY, details.finishReasons?.join(',')); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_INPUT_TOKENS_KEY, details.inputTokens); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_OUTPUT_TOKENS_KEY, details.outputTokens); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_RESPONSE_FINISH_REASONS_KEY, details.finishReasons); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_THOUGHT_PROCESS_KEY, details.thoughtProcess); this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CONVERSATION_ID_KEY, conversationId); this.setTagMaybe(OpenTelemetryConstants.CHANNEL_NAME_KEY, sourceMetadata?.name); @@ -86,7 +86,7 @@ export class InferenceScope extends OpenTelemetryScope { // Only record port if it is different from 443 (default HTTPS port) if (details.endpoint.port && details.endpoint.port !== 443) { - this.setTagMaybe(OpenTelemetryConstants.SERVER_PORT_KEY, details.endpoint.port); + this.setTagMaybe(OpenTelemetryConstants.SERVER_PORT_KEY, details.endpoint.port.toString()); } } } @@ -112,7 +112,7 @@ export class InferenceScope extends OpenTelemetryScope { * @param inputTokens Number of input tokens */ public recordInputTokens(inputTokens: number): void { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_INPUT_TOKENS_KEY, inputTokens.toString()); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_INPUT_TOKENS_KEY, inputTokens); } /** @@ -120,7 +120,7 @@ export class InferenceScope extends OpenTelemetryScope { * @param outputTokens Number of output tokens */ public recordOutputTokens(outputTokens: number): void { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_OUTPUT_TOKENS_KEY, outputTokens.toString()); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_USAGE_OUTPUT_TOKENS_KEY, outputTokens); } /** @@ -129,7 +129,7 @@ export class InferenceScope extends OpenTelemetryScope { */ public recordFinishReasons(finishReasons: string[]): void { if (finishReasons && finishReasons.length > 0) { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_RESPONSE_FINISH_REASONS_KEY, finishReasons.join(',')); + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_RESPONSE_FINISH_REASONS_KEY, finishReasons); } } diff --git a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts index 08d35c95..80b6f9e2 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts @@ -74,7 +74,7 @@ export class InvokeAgentScope extends OpenTelemetryScope { // Only record port if it is different from 443 (default HTTPS port) if (invokeAgentDetails.endpoint.port && invokeAgentDetails.endpoint.port !== 443) { - this.setTagMaybe(OpenTelemetryConstants.SERVER_PORT_KEY, invokeAgentDetails.endpoint.port); + this.setTagMaybe(OpenTelemetryConstants.SERVER_PORT_KEY, invokeAgentDetails.endpoint.port.toString()); } } diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index d0907aa3..d63596ea 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -184,9 +184,9 @@ export abstract class OpenTelemetryScope implements Disposable { * @param name The tag name * @param value The tag value */ - protected setTagMaybe(name: string, value: T | null | undefined): void { + protected setTagMaybe(name: string, value: T | null | undefined): void { if (value != null) { - this.span.setAttributes({ [name]: value as string | number | boolean }); + this.span.setAttributes({ [name]: value as string | number | boolean | string[] | number[] }); } } From b76aaf7678eb81df01f42342118dbe77e3b1c179 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Mon, 2 Mar 2026 12:45:14 -0800 Subject: [PATCH 13/19] Move gen_ai.provider.name from base scope to InvokeAgentScope, add providerName to AgentDetails Remove hardcoded gen_ai.provider.name from OpenTelemetryScope base class. Set it dynamically in InvokeAgentScope from AgentDetails.providerName, matching InferenceScope which already uses InferenceDetails.providerName. ExecuteTool spans no longer emit gen_ai.provider.name. Co-Authored-By: Claude Opus 4.6 --- .../src/tracing/contracts.ts | 3 + .../src/tracing/scopes/InvokeAgentScope.ts | 3 + .../src/tracing/scopes/OpenTelemetryScope.ts | 1 - pnpm-lock.yaml | 482 +++++++++++++++++- 4 files changed, 487 insertions(+), 2 deletions(-) diff --git a/packages/agents-a365-observability/src/tracing/contracts.ts b/packages/agents-a365-observability/src/tracing/contracts.ts index fd65f8ff..8fa2e347 100644 --- a/packages/agents-a365-observability/src/tracing/contracts.ts +++ b/packages/agents-a365-observability/src/tracing/contracts.ts @@ -124,6 +124,9 @@ export interface AgentDetails { /** The tenant ID for the agent */ tenantId?: string; + + /** The provider name (e.g., az.ai.agent365, openai, anthropic) */ + providerName?: string; } /** diff --git a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts index 80b6f9e2..d73854ce 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts @@ -63,6 +63,9 @@ export class InvokeAgentScope extends OpenTelemetryScope { callerDetails ); + // Set provider name for agent invocation + this.setTagMaybe(OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY, invokeAgentDetails.providerName); + // Set session ID and endpoint information this.setTagMaybe(OpenTelemetryConstants.SESSION_ID_KEY, invokeAgentDetails.sessionId); diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index d63596ea..f334a558 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -69,7 +69,6 @@ export abstract class OpenTelemetryScope implements Disposable { kind, startTime, attributes: { - [OpenTelemetryConstants.GEN_AI_PROVIDER_NAME_KEY]: 'az.ai.agent365', [OpenTelemetryConstants.GEN_AI_OPERATION_NAME_KEY]: operationName, }, }, currentContext); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 23cccb37..5b8d72d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,6 +21,9 @@ catalogs: '@eslint/js': specifier: ^9.39.1 version: 9.39.1 + '@jest/globals': + specifier: ^30.2.0 + version: 30.2.0 '@langchain/core': specifier: ^1.1.8 version: 1.1.8 @@ -36,12 +39,18 @@ catalogs: '@microsoft/agents-hosting': specifier: ^1.1.0-alpha.85 version: 1.1.0-alpha.85 + '@microsoft/m365agentsplayground': + specifier: ^0.2.18 + version: 0.2.23 '@modelcontextprotocol/sdk': specifier: ^1.25.2 version: 1.25.2 '@openai/agents': specifier: ^0.4.0 version: 0.4.2 + '@openai/agents-core': + specifier: ^0.4.0 + version: 0.4.2 '@openai/agents-openai': specifier: ^0.4.0 version: 0.4.2 @@ -69,6 +78,9 @@ catalogs: '@opentelemetry/semantic-conventions': specifier: ^1.37.0 version: 1.38.0 + '@types/express': + specifier: ^5.0.0 + version: 5.0.6 '@types/jest': specifier: ^30.0.0 version: 30.0.0 @@ -108,6 +120,9 @@ catalogs: langchain: specifier: ^1.2.3 version: 1.2.3 + nodemon: + specifier: ^3.1.10 + version: 3.1.11 openai: specifier: ^4.8.0 version: 4.104.0 @@ -117,6 +132,9 @@ catalogs: ts-jest: specifier: ^29.4.5 version: 29.4.5 + tsx: + specifier: ^4.21.0 + version: 4.21.0 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -816,6 +834,64 @@ importers: specifier: 'catalog:' version: 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + tests-agent/basic-agent-sdk-sample: + dependencies: + '@microsoft/agents-a365-observability': + specifier: workspace:* + version: link:../../packages/agents-a365-observability + '@microsoft/agents-a365-observability-hosting': + specifier: workspace:* + version: link:../../packages/agents-a365-observability-hosting + '@microsoft/agents-a365-runtime': + specifier: workspace:* + version: link:../../packages/agents-a365-runtime + '@microsoft/agents-activity': + specifier: ^1.1.0-alpha.85 + version: 1.1.0-alpha.85 + '@microsoft/agents-hosting': + specifier: ^1.1.0-alpha.85 + version: 1.1.0-alpha.85 + dotenv: + specifier: ^17.2.2 + version: 17.2.3 + express: + specifier: ^5.2.0 + version: 5.2.0 + uuid: + specifier: ^10.0.0 + version: 10.0.0 + devDependencies: + '@eslint/js': + specifier: ^9.39.1 + version: 9.39.1 + '@microsoft/m365agentsplayground': + specifier: ^0.2.18 + version: 0.2.23 + '@types/express': + specifier: ^5.0.0 + version: 5.0.6 + '@types/node': + specifier: ^20.17.0 + version: 20.19.25 + '@types/uuid': + specifier: ^9.0.8 + version: 9.0.8 + eslint: + specifier: ^9.39.1 + version: 9.39.1(jiti@2.6.1) + nodemon: + specifier: ^3.1.10 + version: 3.1.11 + tsx: + specifier: ^4.21.0 + version: 4.21.0 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + typescript-eslint: + specifier: ^8.47.0 + version: 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + tests-agent/langchain-agent: dependencies: '@langchain/core': @@ -901,6 +977,91 @@ importers: specifier: ^10.9.2 version: 10.9.2(@types/node@20.19.25)(typescript@5.9.3) + tests-agent/openai-agent-auto-instrument-sample: + dependencies: + '@microsoft/agents-a365-observability': + specifier: workspace:* + version: link:../../packages/agents-a365-observability + '@microsoft/agents-a365-observability-extensions-openai': + specifier: workspace:* + version: link:../../packages/agents-a365-observability-extensions-openai + '@microsoft/agents-a365-observability-hosting': + specifier: workspace:* + version: link:../../packages/agents-a365-observability-hosting + '@microsoft/agents-a365-runtime': + specifier: workspace:* + version: link:../../packages/agents-a365-runtime + '@microsoft/agents-a365-tooling-extensions-openai': + specifier: workspace:* + version: link:../../packages/agents-a365-tooling-extensions-openai + '@microsoft/agents-activity': + specifier: 'catalog:' + version: 1.1.0-alpha.85 + '@microsoft/agents-hosting': + specifier: 'catalog:' + version: 1.1.0-alpha.85 + '@openai/agents': + specifier: 'catalog:' + version: 0.4.2(@cfworker/json-schema@4.1.1)(hono@4.11.7)(ws@8.18.3)(zod@4.1.13) + '@openai/agents-core': + specifier: 'catalog:' + version: 0.4.2(@cfworker/json-schema@4.1.1)(hono@4.11.7)(ws@8.18.3)(zod@4.1.13) + dotenv: + specifier: 'catalog:' + version: 17.2.3 + express: + specifier: 'catalog:' + version: 5.2.0 + hono: + specifier: ^4.11.7 + version: 4.11.7 + devDependencies: + '@eslint/js': + specifier: 'catalog:' + version: 9.39.1 + '@jest/globals': + specifier: 'catalog:' + version: 30.2.0 + '@microsoft/m365agentsplayground': + specifier: 'catalog:' + version: 0.2.23 + '@types/express': + specifier: 'catalog:' + version: 5.0.6 + '@types/node': + specifier: 'catalog:' + version: 20.19.25 + '@typescript-eslint/eslint-plugin': + specifier: 'catalog:' + version: 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': + specifier: 'catalog:' + version: 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + eslint: + specifier: 'catalog:' + version: 9.39.1(jiti@2.6.1) + jest: + specifier: 'catalog:' + version: 30.2.0(@types/node@20.19.25)(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3)) + nodemon: + specifier: 'catalog:' + version: 3.1.11 + rimraf: + specifier: 'catalog:' + version: 6.1.2 + ts-jest: + specifier: 'catalog:' + version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.25)(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3)))(typescript@5.9.3) + tsx: + specifier: 'catalog:' + version: 4.21.0 + typescript: + specifier: 'catalog:' + version: 5.9.3 + typescript-eslint: + specifier: 'catalog:' + version: 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + packages: '@anthropic-ai/claude-agent-sdk@0.1.47': @@ -1642,6 +1803,162 @@ packages: '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.3': + resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.0': resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2332,9 +2649,15 @@ packages: '@types/express-serve-static-core@4.19.7': resolution: {integrity: sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==} + '@types/express-serve-static-core@5.1.1': + resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==} + '@types/express@4.17.25': resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} + '@types/express@5.0.6': + resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} + '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} @@ -2386,6 +2709,9 @@ packages: '@types/serve-static@1.15.10': resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + '@types/serve-static@2.2.0': + resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} + '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -2991,6 +3317,11 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} + esbuild@0.27.3: + resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -3227,6 +3558,9 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} + get-tsconfig@4.13.6: + resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -4175,6 +4509,9 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} @@ -4418,6 +4755,11 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -5620,6 +5962,84 @@ snapshots: tslib: 2.8.1 optional: true + '@esbuild/aix-ppc64@0.27.3': + optional: true + + '@esbuild/android-arm64@0.27.3': + optional: true + + '@esbuild/android-arm@0.27.3': + optional: true + + '@esbuild/android-x64@0.27.3': + optional: true + + '@esbuild/darwin-arm64@0.27.3': + optional: true + + '@esbuild/darwin-x64@0.27.3': + optional: true + + '@esbuild/freebsd-arm64@0.27.3': + optional: true + + '@esbuild/freebsd-x64@0.27.3': + optional: true + + '@esbuild/linux-arm64@0.27.3': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.27.3': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.27.3': + optional: true + + '@esbuild/openharmony-arm64@0.27.3': + optional: true + + '@esbuild/sunos-x64@0.27.3': + optional: true + + '@esbuild/win32-arm64@0.27.3': + optional: true + + '@esbuild/win32-ia32@0.27.3': + optional: true + + '@esbuild/win32-x64@0.27.3': + optional: true + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.6.1))': dependencies: eslint: 9.39.1(jiti@2.6.1) @@ -6106,7 +6526,7 @@ snapshots: '@openai/agents-core@0.4.2(@cfworker/json-schema@4.1.1)(hono@4.11.7)(ws@8.18.3)(zod@4.1.13)': dependencies: debug: 4.4.3(supports-color@5.5.0) - openai: 6.9.1(ws@8.18.3)(zod@4.1.13) + openai: 6.22.0(ws@8.18.3)(zod@4.1.13) optionalDependencies: '@modelcontextprotocol/sdk': 1.25.2(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@4.1.13) zod: 4.1.13 @@ -6560,6 +6980,13 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 1.2.1 + '@types/express-serve-static-core@5.1.1': + dependencies: + '@types/node': 20.19.25 + '@types/qs': 6.14.0 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + '@types/express@4.17.25': dependencies: '@types/body-parser': 1.19.6 @@ -6567,6 +6994,12 @@ snapshots: '@types/qs': 6.14.0 '@types/serve-static': 1.15.10 + '@types/express@5.0.6': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 5.1.1 + '@types/serve-static': 2.2.0 + '@types/http-errors@2.0.5': {} '@types/istanbul-lib-coverage@2.0.6': {} @@ -6627,6 +7060,11 @@ snapshots: '@types/node': 20.19.25 '@types/send': 0.17.6 + '@types/serve-static@2.2.0': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 20.19.25 + '@types/stack-utils@2.0.3': {} '@types/uuid@9.0.8': {} @@ -7220,6 +7658,35 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 + esbuild@0.27.3: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 + '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -7505,6 +7972,10 @@ snapshots: get-stream@6.0.1: {} + get-tsconfig@4.13.6: + dependencies: + resolve-pkg-maps: 1.0.0 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -8588,6 +9059,8 @@ snapshots: resolve-from@5.0.0: {} + resolve-pkg-maps@1.0.0: {} + resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -8828,6 +9301,13 @@ snapshots: tslib@2.8.1: {} + tsx@4.21.0: + dependencies: + esbuild: 0.27.3 + get-tsconfig: 4.13.6 + optionalDependencies: + fsevents: 2.3.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 From 6f9e872fcf38b88d48b00dbceb19fa687e3d429d Mon Sep 17 00:00:00 2001 From: jsl517 Date: Mon, 2 Mar 2026 12:46:23 -0800 Subject: [PATCH 14/19] Revert pnpm-lock.yaml changes from previous commit Co-Authored-By: Claude Opus 4.6 --- pnpm-lock.yaml | 482 +------------------------------------------------ 1 file changed, 1 insertion(+), 481 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b8d72d5..23cccb37 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,9 +21,6 @@ catalogs: '@eslint/js': specifier: ^9.39.1 version: 9.39.1 - '@jest/globals': - specifier: ^30.2.0 - version: 30.2.0 '@langchain/core': specifier: ^1.1.8 version: 1.1.8 @@ -39,18 +36,12 @@ catalogs: '@microsoft/agents-hosting': specifier: ^1.1.0-alpha.85 version: 1.1.0-alpha.85 - '@microsoft/m365agentsplayground': - specifier: ^0.2.18 - version: 0.2.23 '@modelcontextprotocol/sdk': specifier: ^1.25.2 version: 1.25.2 '@openai/agents': specifier: ^0.4.0 version: 0.4.2 - '@openai/agents-core': - specifier: ^0.4.0 - version: 0.4.2 '@openai/agents-openai': specifier: ^0.4.0 version: 0.4.2 @@ -78,9 +69,6 @@ catalogs: '@opentelemetry/semantic-conventions': specifier: ^1.37.0 version: 1.38.0 - '@types/express': - specifier: ^5.0.0 - version: 5.0.6 '@types/jest': specifier: ^30.0.0 version: 30.0.0 @@ -120,9 +108,6 @@ catalogs: langchain: specifier: ^1.2.3 version: 1.2.3 - nodemon: - specifier: ^3.1.10 - version: 3.1.11 openai: specifier: ^4.8.0 version: 4.104.0 @@ -132,9 +117,6 @@ catalogs: ts-jest: specifier: ^29.4.5 version: 29.4.5 - tsx: - specifier: ^4.21.0 - version: 4.21.0 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -834,64 +816,6 @@ importers: specifier: 'catalog:' version: 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - tests-agent/basic-agent-sdk-sample: - dependencies: - '@microsoft/agents-a365-observability': - specifier: workspace:* - version: link:../../packages/agents-a365-observability - '@microsoft/agents-a365-observability-hosting': - specifier: workspace:* - version: link:../../packages/agents-a365-observability-hosting - '@microsoft/agents-a365-runtime': - specifier: workspace:* - version: link:../../packages/agents-a365-runtime - '@microsoft/agents-activity': - specifier: ^1.1.0-alpha.85 - version: 1.1.0-alpha.85 - '@microsoft/agents-hosting': - specifier: ^1.1.0-alpha.85 - version: 1.1.0-alpha.85 - dotenv: - specifier: ^17.2.2 - version: 17.2.3 - express: - specifier: ^5.2.0 - version: 5.2.0 - uuid: - specifier: ^10.0.0 - version: 10.0.0 - devDependencies: - '@eslint/js': - specifier: ^9.39.1 - version: 9.39.1 - '@microsoft/m365agentsplayground': - specifier: ^0.2.18 - version: 0.2.23 - '@types/express': - specifier: ^5.0.0 - version: 5.0.6 - '@types/node': - specifier: ^20.17.0 - version: 20.19.25 - '@types/uuid': - specifier: ^9.0.8 - version: 9.0.8 - eslint: - specifier: ^9.39.1 - version: 9.39.1(jiti@2.6.1) - nodemon: - specifier: ^3.1.10 - version: 3.1.11 - tsx: - specifier: ^4.21.0 - version: 4.21.0 - typescript: - specifier: ^5.9.3 - version: 5.9.3 - typescript-eslint: - specifier: ^8.47.0 - version: 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - tests-agent/langchain-agent: dependencies: '@langchain/core': @@ -977,91 +901,6 @@ importers: specifier: ^10.9.2 version: 10.9.2(@types/node@20.19.25)(typescript@5.9.3) - tests-agent/openai-agent-auto-instrument-sample: - dependencies: - '@microsoft/agents-a365-observability': - specifier: workspace:* - version: link:../../packages/agents-a365-observability - '@microsoft/agents-a365-observability-extensions-openai': - specifier: workspace:* - version: link:../../packages/agents-a365-observability-extensions-openai - '@microsoft/agents-a365-observability-hosting': - specifier: workspace:* - version: link:../../packages/agents-a365-observability-hosting - '@microsoft/agents-a365-runtime': - specifier: workspace:* - version: link:../../packages/agents-a365-runtime - '@microsoft/agents-a365-tooling-extensions-openai': - specifier: workspace:* - version: link:../../packages/agents-a365-tooling-extensions-openai - '@microsoft/agents-activity': - specifier: 'catalog:' - version: 1.1.0-alpha.85 - '@microsoft/agents-hosting': - specifier: 'catalog:' - version: 1.1.0-alpha.85 - '@openai/agents': - specifier: 'catalog:' - version: 0.4.2(@cfworker/json-schema@4.1.1)(hono@4.11.7)(ws@8.18.3)(zod@4.1.13) - '@openai/agents-core': - specifier: 'catalog:' - version: 0.4.2(@cfworker/json-schema@4.1.1)(hono@4.11.7)(ws@8.18.3)(zod@4.1.13) - dotenv: - specifier: 'catalog:' - version: 17.2.3 - express: - specifier: 'catalog:' - version: 5.2.0 - hono: - specifier: ^4.11.7 - version: 4.11.7 - devDependencies: - '@eslint/js': - specifier: 'catalog:' - version: 9.39.1 - '@jest/globals': - specifier: 'catalog:' - version: 30.2.0 - '@microsoft/m365agentsplayground': - specifier: 'catalog:' - version: 0.2.23 - '@types/express': - specifier: 'catalog:' - version: 5.0.6 - '@types/node': - specifier: 'catalog:' - version: 20.19.25 - '@typescript-eslint/eslint-plugin': - specifier: 'catalog:' - version: 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': - specifier: 'catalog:' - version: 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - eslint: - specifier: 'catalog:' - version: 9.39.1(jiti@2.6.1) - jest: - specifier: 'catalog:' - version: 30.2.0(@types/node@20.19.25)(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3)) - nodemon: - specifier: 'catalog:' - version: 3.1.11 - rimraf: - specifier: 'catalog:' - version: 6.1.2 - ts-jest: - specifier: 'catalog:' - version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.25)(ts-node@10.9.2(@types/node@20.19.25)(typescript@5.9.3)))(typescript@5.9.3) - tsx: - specifier: 'catalog:' - version: 4.21.0 - typescript: - specifier: 'catalog:' - version: 5.9.3 - typescript-eslint: - specifier: 'catalog:' - version: 8.47.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - packages: '@anthropic-ai/claude-agent-sdk@0.1.47': @@ -1803,162 +1642,6 @@ packages: '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} - '@esbuild/aix-ppc64@0.27.3': - resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.27.3': - resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.27.3': - resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.27.3': - resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.27.3': - resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.27.3': - resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.27.3': - resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.27.3': - resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.27.3': - resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.27.3': - resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.27.3': - resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.27.3': - resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.27.3': - resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.27.3': - resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.27.3': - resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.27.3': - resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.27.3': - resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.27.3': - resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.27.3': - resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.27.3': - resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.27.3': - resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.27.3': - resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.27.3': - resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.27.3': - resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.27.3': - resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.27.3': - resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@eslint-community/eslint-utils@4.9.0': resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2649,15 +2332,9 @@ packages: '@types/express-serve-static-core@4.19.7': resolution: {integrity: sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==} - '@types/express-serve-static-core@5.1.1': - resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==} - '@types/express@4.17.25': resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} - '@types/express@5.0.6': - resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} - '@types/http-errors@2.0.5': resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} @@ -2709,9 +2386,6 @@ packages: '@types/serve-static@1.15.10': resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} - '@types/serve-static@2.2.0': - resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} - '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -3317,11 +2991,6 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - esbuild@0.27.3: - resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} - engines: {node: '>=18'} - hasBin: true - escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -3558,9 +3227,6 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - get-tsconfig@4.13.6: - resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} - glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -4509,9 +4175,6 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} @@ -4755,11 +4418,6 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.21.0: - resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} - engines: {node: '>=18.0.0'} - hasBin: true - type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -5962,84 +5620,6 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.27.3': - optional: true - - '@esbuild/android-arm64@0.27.3': - optional: true - - '@esbuild/android-arm@0.27.3': - optional: true - - '@esbuild/android-x64@0.27.3': - optional: true - - '@esbuild/darwin-arm64@0.27.3': - optional: true - - '@esbuild/darwin-x64@0.27.3': - optional: true - - '@esbuild/freebsd-arm64@0.27.3': - optional: true - - '@esbuild/freebsd-x64@0.27.3': - optional: true - - '@esbuild/linux-arm64@0.27.3': - optional: true - - '@esbuild/linux-arm@0.27.3': - optional: true - - '@esbuild/linux-ia32@0.27.3': - optional: true - - '@esbuild/linux-loong64@0.27.3': - optional: true - - '@esbuild/linux-mips64el@0.27.3': - optional: true - - '@esbuild/linux-ppc64@0.27.3': - optional: true - - '@esbuild/linux-riscv64@0.27.3': - optional: true - - '@esbuild/linux-s390x@0.27.3': - optional: true - - '@esbuild/linux-x64@0.27.3': - optional: true - - '@esbuild/netbsd-arm64@0.27.3': - optional: true - - '@esbuild/netbsd-x64@0.27.3': - optional: true - - '@esbuild/openbsd-arm64@0.27.3': - optional: true - - '@esbuild/openbsd-x64@0.27.3': - optional: true - - '@esbuild/openharmony-arm64@0.27.3': - optional: true - - '@esbuild/sunos-x64@0.27.3': - optional: true - - '@esbuild/win32-arm64@0.27.3': - optional: true - - '@esbuild/win32-ia32@0.27.3': - optional: true - - '@esbuild/win32-x64@0.27.3': - optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.6.1))': dependencies: eslint: 9.39.1(jiti@2.6.1) @@ -6526,7 +6106,7 @@ snapshots: '@openai/agents-core@0.4.2(@cfworker/json-schema@4.1.1)(hono@4.11.7)(ws@8.18.3)(zod@4.1.13)': dependencies: debug: 4.4.3(supports-color@5.5.0) - openai: 6.22.0(ws@8.18.3)(zod@4.1.13) + openai: 6.9.1(ws@8.18.3)(zod@4.1.13) optionalDependencies: '@modelcontextprotocol/sdk': 1.25.2(@cfworker/json-schema@4.1.1)(hono@4.11.7)(zod@4.1.13) zod: 4.1.13 @@ -6980,13 +6560,6 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 1.2.1 - '@types/express-serve-static-core@5.1.1': - dependencies: - '@types/node': 20.19.25 - '@types/qs': 6.14.0 - '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 - '@types/express@4.17.25': dependencies: '@types/body-parser': 1.19.6 @@ -6994,12 +6567,6 @@ snapshots: '@types/qs': 6.14.0 '@types/serve-static': 1.15.10 - '@types/express@5.0.6': - dependencies: - '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 5.1.1 - '@types/serve-static': 2.2.0 - '@types/http-errors@2.0.5': {} '@types/istanbul-lib-coverage@2.0.6': {} @@ -7060,11 +6627,6 @@ snapshots: '@types/node': 20.19.25 '@types/send': 0.17.6 - '@types/serve-static@2.2.0': - dependencies: - '@types/http-errors': 2.0.5 - '@types/node': 20.19.25 - '@types/stack-utils@2.0.3': {} '@types/uuid@9.0.8': {} @@ -7658,35 +7220,6 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - esbuild@0.27.3: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.3 - '@esbuild/android-arm': 0.27.3 - '@esbuild/android-arm64': 0.27.3 - '@esbuild/android-x64': 0.27.3 - '@esbuild/darwin-arm64': 0.27.3 - '@esbuild/darwin-x64': 0.27.3 - '@esbuild/freebsd-arm64': 0.27.3 - '@esbuild/freebsd-x64': 0.27.3 - '@esbuild/linux-arm': 0.27.3 - '@esbuild/linux-arm64': 0.27.3 - '@esbuild/linux-ia32': 0.27.3 - '@esbuild/linux-loong64': 0.27.3 - '@esbuild/linux-mips64el': 0.27.3 - '@esbuild/linux-ppc64': 0.27.3 - '@esbuild/linux-riscv64': 0.27.3 - '@esbuild/linux-s390x': 0.27.3 - '@esbuild/linux-x64': 0.27.3 - '@esbuild/netbsd-arm64': 0.27.3 - '@esbuild/netbsd-x64': 0.27.3 - '@esbuild/openbsd-arm64': 0.27.3 - '@esbuild/openbsd-x64': 0.27.3 - '@esbuild/openharmony-arm64': 0.27.3 - '@esbuild/sunos-x64': 0.27.3 - '@esbuild/win32-arm64': 0.27.3 - '@esbuild/win32-ia32': 0.27.3 - '@esbuild/win32-x64': 0.27.3 - escalade@3.2.0: {} escape-html@1.0.3: {} @@ -7972,10 +7505,6 @@ snapshots: get-stream@6.0.1: {} - get-tsconfig@4.13.6: - dependencies: - resolve-pkg-maps: 1.0.0 - glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -9059,8 +8588,6 @@ snapshots: resolve-from@5.0.0: {} - resolve-pkg-maps@1.0.0: {} - resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -9301,13 +8828,6 @@ snapshots: tslib@2.8.1: {} - tsx@4.21.0: - dependencies: - esbuild: 0.27.3 - get-tsconfig: 4.13.6 - optionalDependencies: - fsevents: 2.3.3 - type-check@0.4.0: dependencies: prelude-ls: 1.2.1 From 140dd15c62071861124a74a80e8f7f6b712d3168 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Mon, 2 Mar 2026 13:51:36 -0800 Subject: [PATCH 15/19] Address Copilot review: fix copyright headers, move blueprint ID to generic attributes, add callerDetails JSDoc Co-Authored-By: Claude Opus 4.6 --- .../agents-a365-observability/src/tracing/constants.ts | 5 ++--- .../src/tracing/processors/SpanProcessor.ts | 5 ++--- .../src/tracing/processors/util.ts | 8 +++----- .../src/tracing/scopes/InvokeAgentScope.ts | 1 - .../src/tracing/scopes/OpenTelemetryScope.ts | 1 + tests/observability/core/SpanProcessor.test.ts | 6 +++++- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index 2589a4f3..ceffaeff 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -1,6 +1,5 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import { LIB_VERSION } from '../version'; diff --git a/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts b/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts index 377f836b..843c2cb0 100644 --- a/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts +++ b/packages/agents-a365-observability/src/tracing/processors/SpanProcessor.ts @@ -1,6 +1,5 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import { Context, propagation, Span } from '@opentelemetry/api'; import { SpanProcessor as BaseSpanProcessor } from '@opentelemetry/sdk-trace-base'; diff --git a/packages/agents-a365-observability/src/tracing/processors/util.ts b/packages/agents-a365-observability/src/tracing/processors/util.ts index 518f5340..5994a953 100644 --- a/packages/agents-a365-observability/src/tracing/processors/util.ts +++ b/packages/agents-a365-observability/src/tracing/processors/util.ts @@ -1,6 +1,5 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import { OpenTelemetryConstants as consts } from '../constants'; @@ -22,6 +21,7 @@ export const GENERIC_ATTRIBUTES: readonly string[] = [ consts.GEN_AI_AGENT_UPN_KEY, consts.GEN_AI_AGENT_AUID_KEY, consts.GEN_AI_AGENT_PLATFORM_ID_KEY, + consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY, consts.SERVICE_NAME_KEY, // Caller / Invoker attributes consts.GEN_AI_CALLER_ID_KEY, @@ -44,6 +44,4 @@ export const INVOKE_AGENT_ATTRIBUTES: readonly string[] = [ consts.GEN_AI_CALLER_AGENT_UPN_KEY, consts.GEN_AI_CALLER_AGENT_APPLICATION_ID_KEY, consts.GEN_AI_CALLER_AGENT_PLATFORM_ID_KEY, - // Blueprint ID is InvokeAgent-only - consts.GEN_AI_AGENT_BLUEPRINT_ID_KEY, ]; diff --git a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts index 5cecbbf6..be52b863 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/InvokeAgentScope.ts @@ -69,7 +69,6 @@ export class InvokeAgentScope extends OpenTelemetryScope { // Set session ID and endpoint information this.setTagMaybe(OpenTelemetryConstants.SESSION_ID_KEY, invokeAgentDetails.sessionId); - // Blueprint ID is InvokeAgent-only this.setTagMaybe(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY, invokeAgentDetails.agentBlueprintId); if (invokeAgentDetails.endpoint) { diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index f334a558..6e514cd0 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -37,6 +37,7 @@ export abstract class OpenTelemetryScope implements Disposable { * has already completed (e.g. a tool call whose start time was captured earlier). * @param endTime Optional explicit end time (ms epoch, Date, or HrTime). When provided the span will * use this timestamp when {@link dispose} is called instead of the current wall-clock time. + * @param callerDetails Optional caller identity details (id, upn, name, client ip). */ protected constructor( kind: SpanKind, diff --git a/tests/observability/core/SpanProcessor.test.ts b/tests/observability/core/SpanProcessor.test.ts index 7020f726..25c5890c 100644 --- a/tests/observability/core/SpanProcessor.test.ts +++ b/tests/observability/core/SpanProcessor.test.ts @@ -173,7 +173,11 @@ describe('SpanProcessor', () => { }); it('should apply invoke agent specific attributes', () => { - expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY); + expect(INVOKE_AGENT_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_CALLER_AGENT_ID_KEY); + }); + + it('should include blueprint ID in generic attributes', () => { + expect(GENERIC_ATTRIBUTES).toContain(OpenTelemetryConstants.GEN_AI_AGENT_BLUEPRINT_ID_KEY); }); }); From 121c0ef5dbe2ed28673d31034fc0b7763a9c34a8 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Mon, 2 Mar 2026 14:29:48 -0800 Subject: [PATCH 16/19] Fix remaining review issues: pass callerDetails to OutputScope base, remove dead code, fix copyright headers and stale JSDoc - OutputScope: pass callerDetails to super() instead of manual caller tagging - OutputScope: fix JSDoc removing stale "tenant" from callerDetails description - OpenTelemetryScope: remove unused finalTags variable and exception field - OpenTelemetryScope: remove unused Attributes import - TurnContextUtils: fix stale JSDoc mentioning tenant in getCallerBaggagePairs - constants.ts: remove misleading "server spans only" comment on SERVICE_NAME_KEY - Fix copyright headers in contracts.ts, BaggageBuilder.ts, OpenAIAgentsTraceProcessor.ts, Utils.ts Co-Authored-By: Claude Opus 4.6 --- .../src/OpenAIAgentsTraceProcessor.ts | 5 ++--- .../src/Utils.ts | 5 ++--- .../src/utils/TurnContextUtils.ts | 2 +- .../src/tracing/constants.ts | 2 +- .../src/tracing/contracts.ts | 5 ++--- .../src/tracing/middleware/BaggageBuilder.ts | 5 ++--- .../src/tracing/scopes/OpenTelemetryScope.ts | 6 +----- .../src/tracing/scopes/OutputScope.ts | 12 +++--------- 8 files changed, 14 insertions(+), 28 deletions(-) diff --git a/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts b/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts index 4f69662b..d04c3cbe 100644 --- a/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts +++ b/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts @@ -1,6 +1,5 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. /** * Trace processor for OpenAI Agents SDK diff --git a/packages/agents-a365-observability-extensions-openai/src/Utils.ts b/packages/agents-a365-observability-extensions-openai/src/Utils.ts index 6d8061e6..0ab6e31c 100644 --- a/packages/agents-a365-observability-extensions-openai/src/Utils.ts +++ b/packages/agents-a365-observability-extensions-openai/src/Utils.ts @@ -1,6 +1,5 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import { SpanStatusCode } from '@opentelemetry/api'; import { OpenTelemetryConstants } from '@microsoft/agents-a365-observability'; diff --git a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts index 56683425..aa1a1143 100644 --- a/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts +++ b/packages/agents-a365-observability-hosting/src/utils/TurnContextUtils.ts @@ -20,7 +20,7 @@ function normalizePairs(pairs: Array<[string, string | undefined]>): Array<[stri /** * Extracts caller-related OpenTelemetry baggage pairs from the TurnContext. * @param turnContext The current TurnContext (activity context) - * @returns Array of [key, value] pairs for caller identity and tenant + * @returns Array of [key, value] pairs for caller identity */ export function getCallerBaggagePairs(turnContext: TurnContext): Array<[string, string]> { if (!turnContext|| !turnContext.activity?.from) { diff --git a/packages/agents-a365-observability/src/tracing/constants.ts b/packages/agents-a365-observability/src/tracing/constants.ts index ceffaeff..d6fd4168 100644 --- a/packages/agents-a365-observability/src/tracing/constants.ts +++ b/packages/agents-a365-observability/src/tracing/constants.ts @@ -101,7 +101,7 @@ export class OpenTelemetryConstants { public static readonly CUSTOM_PARENT_SPAN_ID_KEY = 'custom.parent.span.id'; public static readonly CUSTOM_SPAN_NAME_KEY = 'custom.span.name'; - // Service attributes (server spans only) + // Service attributes public static readonly SERVICE_NAME_KEY = 'service.name'; // Telemetry SDK attributes diff --git a/packages/agents-a365-observability/src/tracing/contracts.ts b/packages/agents-a365-observability/src/tracing/contracts.ts index ae499d27..562c87e1 100644 --- a/packages/agents-a365-observability/src/tracing/contracts.ts +++ b/packages/agents-a365-observability/src/tracing/contracts.ts @@ -1,6 +1,5 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. /** * Represents different types of agent invocations diff --git a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts index 6bf4fa13..6166601f 100644 --- a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts +++ b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts @@ -1,6 +1,5 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. import { propagation, context as otelContext, Context } from '@opentelemetry/api'; import { OpenTelemetryConstants } from '../constants'; diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index 6e514cd0..d1730e96 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { trace, SpanKind, Span, SpanStatusCode, Attributes, context, AttributeValue, SpanContext, TimeInput } from '@opentelemetry/api'; +import { trace, SpanKind, Span, SpanStatusCode, context, AttributeValue, SpanContext, TimeInput } from '@opentelemetry/api'; import { OpenTelemetryConstants } from '../constants'; import { AgentDetails, TenantDetails, CallerDetails } from '../contracts'; import { createContextWithParentSpanRef } from '../context/parent-span-context'; @@ -19,7 +19,6 @@ export abstract class OpenTelemetryScope implements Disposable { private customStartTime?: TimeInput; private customEndTime?: TimeInput; private errorType?: string; - private exception?: Error; private hasEnded = false; /** @@ -139,7 +138,6 @@ export abstract class OpenTelemetryScope implements Disposable { this.errorType = error.constructor.name; } - this.exception = error; this.span.setStatus({ code: SpanStatusCode.ERROR, message: error.message @@ -242,9 +240,7 @@ export abstract class OpenTelemetryScope implements Disposable { const durationMs = Math.max(0, endMs - startMs); const duration = durationMs / 1000; - const finalTags:Attributes = {}; if (this.errorType) { - finalTags[OpenTelemetryConstants.ERROR_TYPE_KEY] = this.errorType; this.span.setAttributes({ [OpenTelemetryConstants.ERROR_TYPE_KEY]: this.errorType }); } diff --git a/packages/agents-a365-observability/src/tracing/scopes/OutputScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OutputScope.ts index f6f90513..9e50c119 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OutputScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OutputScope.ts @@ -19,7 +19,7 @@ export class OutputScope extends OpenTelemetryScope { * @param response The response containing initial output messages. * @param agentDetails The details of the agent producing the output. * @param tenantDetails The tenant details. - * @param callerDetails Optional caller identity details (id, upn, name, tenant, client ip). + * @param callerDetails Optional caller identity details (id, upn, name, client ip). * @param conversationId Optional conversation identifier. * @param sourceMetadata Optional source metadata; only `name` and `description` are used for tagging. * @param parentContext Optional parent context for cross-async-boundary tracing. @@ -63,7 +63,8 @@ export class OutputScope extends OpenTelemetryScope { tenantDetails, parentContext, startTime, - endTime + endTime, + callerDetails ); // Initialize accumulated messages list from the response @@ -80,13 +81,6 @@ export class OutputScope extends OpenTelemetryScope { this.setTagMaybe(OpenTelemetryConstants.CHANNEL_NAME_KEY, sourceMetadata?.name); this.setTagMaybe(OpenTelemetryConstants.CHANNEL_LINK_KEY, sourceMetadata?.description); - // Set caller details if provided - if (callerDetails) { - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_ID_KEY, callerDetails.callerId); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_UPN_KEY, callerDetails.callerUpn); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_NAME_KEY, callerDetails.callerName); - this.setTagMaybe(OpenTelemetryConstants.GEN_AI_CALLER_CLIENT_IP_KEY, callerDetails.callerClientIp); - } } /** From c9588c9cc70949f98a6532e008b43e38c8467efb Mon Sep 17 00:00:00 2001 From: jsl517 Date: Mon, 2 Mar 2026 14:36:36 -0800 Subject: [PATCH 17/19] Revert pre-existing issue fixes unrelated to this PR Co-Authored-By: Claude Opus 4.6 --- .../src/OpenAIAgentsTraceProcessor.ts | 5 +++-- .../src/Utils.ts | 5 +++-- packages/agents-a365-observability/src/tracing/contracts.ts | 5 +++-- .../src/tracing/middleware/BaggageBuilder.ts | 5 +++-- .../src/tracing/scopes/OpenTelemetryScope.ts | 6 +++++- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts b/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts index d04c3cbe..4f69662b 100644 --- a/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts +++ b/packages/agents-a365-observability-extensions-openai/src/OpenAIAgentsTraceProcessor.ts @@ -1,5 +1,6 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------------------------ /** * Trace processor for OpenAI Agents SDK diff --git a/packages/agents-a365-observability-extensions-openai/src/Utils.ts b/packages/agents-a365-observability-extensions-openai/src/Utils.ts index 0ab6e31c..6d8061e6 100644 --- a/packages/agents-a365-observability-extensions-openai/src/Utils.ts +++ b/packages/agents-a365-observability-extensions-openai/src/Utils.ts @@ -1,5 +1,6 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------------------------ import { SpanStatusCode } from '@opentelemetry/api'; import { OpenTelemetryConstants } from '@microsoft/agents-a365-observability'; diff --git a/packages/agents-a365-observability/src/tracing/contracts.ts b/packages/agents-a365-observability/src/tracing/contracts.ts index 562c87e1..ae499d27 100644 --- a/packages/agents-a365-observability/src/tracing/contracts.ts +++ b/packages/agents-a365-observability/src/tracing/contracts.ts @@ -1,5 +1,6 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------------------------ /** * Represents different types of agent invocations diff --git a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts index 6166601f..6bf4fa13 100644 --- a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts +++ b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts @@ -1,5 +1,6 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. +// ------------------------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------------------------ import { propagation, context as otelContext, Context } from '@opentelemetry/api'; import { OpenTelemetryConstants } from '../constants'; diff --git a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts index d1730e96..6e514cd0 100644 --- a/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts +++ b/packages/agents-a365-observability/src/tracing/scopes/OpenTelemetryScope.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { trace, SpanKind, Span, SpanStatusCode, context, AttributeValue, SpanContext, TimeInput } from '@opentelemetry/api'; +import { trace, SpanKind, Span, SpanStatusCode, Attributes, context, AttributeValue, SpanContext, TimeInput } from '@opentelemetry/api'; import { OpenTelemetryConstants } from '../constants'; import { AgentDetails, TenantDetails, CallerDetails } from '../contracts'; import { createContextWithParentSpanRef } from '../context/parent-span-context'; @@ -19,6 +19,7 @@ export abstract class OpenTelemetryScope implements Disposable { private customStartTime?: TimeInput; private customEndTime?: TimeInput; private errorType?: string; + private exception?: Error; private hasEnded = false; /** @@ -138,6 +139,7 @@ export abstract class OpenTelemetryScope implements Disposable { this.errorType = error.constructor.name; } + this.exception = error; this.span.setStatus({ code: SpanStatusCode.ERROR, message: error.message @@ -240,7 +242,9 @@ export abstract class OpenTelemetryScope implements Disposable { const durationMs = Math.max(0, endMs - startMs); const duration = durationMs / 1000; + const finalTags:Attributes = {}; if (this.errorType) { + finalTags[OpenTelemetryConstants.ERROR_TYPE_KEY] = this.errorType; this.span.setAttributes({ [OpenTelemetryConstants.ERROR_TYPE_KEY]: this.errorType }); } From d7bf03856dd7afeaa884e0c84addf6e77b6ef430 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Mon, 2 Mar 2026 14:47:22 -0800 Subject: [PATCH 18/19] Rename BaggageBuilder sourceMetadataName/Description to channelName/channelLink Address nikhilNava review: rename methods to match schema naming convention. Also update design doc to reflect new method names and attribute keys. Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 1 + packages/agents-a365-observability/docs/design.md | 3 ++- .../src/tracing/middleware/BaggageBuilder.ts | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccacef0d..0aa382ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - `InferenceScope.recordInputMessages()` / `recordOutputMessages()` now use JSON array format instead of comma-separated strings. - `InvokeAgentScope.recordInputMessages()` / `recordOutputMessages()` now use JSON array format instead of comma-separated strings. +- **BaggageBuilder**: Rename `sourceMetadataName()` to `channelName()` and `sourceMetadataDescription()` to `channelLink()` for consistency with schema naming. ## [1.1.0] - 2025-12-09 diff --git a/packages/agents-a365-observability/docs/design.md b/packages/agents-a365-observability/docs/design.md index 341f1d3b..0815d321 100644 --- a/packages/agents-a365-observability/docs/design.md +++ b/packages/agents-a365-observability/docs/design.md @@ -258,7 +258,8 @@ const scope2 = BaggageBuilder.setRequestContext( | `sessionId(value)` | `session_id` | | `conversationId(value)` | `gen_ai.conversation.id` | | `callerUpn(value)` | `gen_ai.caller.upn` | -| `sourceMetadataName(value)` | `gen_ai.execution.source.name` | +| `channelName(value)` | `microsoft.channel.name` | +| `channelLink(value)` | `microsoft.channel.link` | ## Data Interfaces diff --git a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts index 6bf4fa13..e3a4b15e 100644 --- a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts +++ b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts @@ -212,11 +212,11 @@ export class BaggageBuilder { } /** - * Set the channel name (e.g., Teams, Slack). + * Set the channel name (e.g., msteams, outlook). * @param value The channel name * @returns Self for method chaining */ - sourceMetadataName(value: string | null | undefined): BaggageBuilder { + channelName(value: string | null | undefined): BaggageBuilder { this.set(OpenTelemetryConstants.CHANNEL_NAME_KEY, value); return this; } @@ -226,7 +226,7 @@ export class BaggageBuilder { * @param value The channel link * @returns Self for method chaining */ - sourceMetadataDescription(value: string | null | undefined): BaggageBuilder { + channelLink(value: string | null | undefined): BaggageBuilder { this.set(OpenTelemetryConstants.CHANNEL_LINK_KEY, value); return this; } From 1798f9b2ee3f0d22037ee510c0c7a52fe68efa71 Mon Sep 17 00:00:00 2001 From: jsl517 Date: Mon, 2 Mar 2026 15:08:13 -0800 Subject: [PATCH 19/19] Revert BaggageBuilder channelName/channelLink rename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverting to sourceMetadataName/sourceMetadataDescription — the full sourceMetadata→channel rename will be done in a follow-up PR. Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 1 - packages/agents-a365-observability/docs/design.md | 3 +-- .../src/tracing/middleware/BaggageBuilder.ts | 6 +++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aa382ff..ccacef0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - `InferenceScope.recordInputMessages()` / `recordOutputMessages()` now use JSON array format instead of comma-separated strings. - `InvokeAgentScope.recordInputMessages()` / `recordOutputMessages()` now use JSON array format instead of comma-separated strings. -- **BaggageBuilder**: Rename `sourceMetadataName()` to `channelName()` and `sourceMetadataDescription()` to `channelLink()` for consistency with schema naming. ## [1.1.0] - 2025-12-09 diff --git a/packages/agents-a365-observability/docs/design.md b/packages/agents-a365-observability/docs/design.md index 0815d321..341f1d3b 100644 --- a/packages/agents-a365-observability/docs/design.md +++ b/packages/agents-a365-observability/docs/design.md @@ -258,8 +258,7 @@ const scope2 = BaggageBuilder.setRequestContext( | `sessionId(value)` | `session_id` | | `conversationId(value)` | `gen_ai.conversation.id` | | `callerUpn(value)` | `gen_ai.caller.upn` | -| `channelName(value)` | `microsoft.channel.name` | -| `channelLink(value)` | `microsoft.channel.link` | +| `sourceMetadataName(value)` | `gen_ai.execution.source.name` | ## Data Interfaces diff --git a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts index e3a4b15e..6bf4fa13 100644 --- a/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts +++ b/packages/agents-a365-observability/src/tracing/middleware/BaggageBuilder.ts @@ -212,11 +212,11 @@ export class BaggageBuilder { } /** - * Set the channel name (e.g., msteams, outlook). + * Set the channel name (e.g., Teams, Slack). * @param value The channel name * @returns Self for method chaining */ - channelName(value: string | null | undefined): BaggageBuilder { + sourceMetadataName(value: string | null | undefined): BaggageBuilder { this.set(OpenTelemetryConstants.CHANNEL_NAME_KEY, value); return this; } @@ -226,7 +226,7 @@ export class BaggageBuilder { * @param value The channel link * @returns Self for method chaining */ - channelLink(value: string | null | undefined): BaggageBuilder { + sourceMetadataDescription(value: string | null | undefined): BaggageBuilder { this.set(OpenTelemetryConstants.CHANNEL_LINK_KEY, value); return this; }