重要提示
要在 Agent 365 中启用可观测性,请使用 Microsoft OpenTelemetry Distro。 该发行版为整个 Microsoft 生态系统提供了一个统一的可观测性 SDK,支持 Agent 365、Microsoft Foundry、Azure Monitor 等服务。 本文所述的现有方法仍可正常使用,不会产生破坏性变更。 有关各编程语言的迁移指南,请参阅以下文档:
若要参与 Agent 365 生态系统,请为您的智能体添加 Agent 365 可观测性功能。 Agent 365 可观测性基于 OpenTelemetry (OTel) 构建,并提供了一个统一的框架,可在所有智能体平台上一致且安全地捕获遥测数据。 通过实现此必备组件,您可以让 IT 管理员在 Microsoft 管理中心中监控智能体的活动,并允许安全团队使用 Defender 和 Purview 进行合规性检查和威胁检测。
关键优势
-
端到端可视性:捕获每次智能体调用的全面遥测数据,包括会话、工具调用和异常,为您提供跨平台的完整可追溯性。
-
安全与合规支持:将统一的审计日志导入 Defender 和 Purview,为您的智能体实现高级安全场景和合规性报告。
-
跨平台灵活性:基于 OTel 标准构建,并支持 Copilot Studio、Foundry 以及未来的智能体框架等多种运行时和平台。
-
管理员的运营效率:在 Microsoft 365 管理中心提供集中式可观察性,通过基于角色的访问控制为管理智能体的 IT 团队减少故障排除时间并提升治理水平。
支持的代理
以下智能体类型支持 Agent 365 可观测性:
安装
使用以下命令安装 Agent 365 支持的语言对应的可观测性模块。
安装核心可观测性和运行时程序包。 所有使用 Agent 365 可观测性的智能体都需要这些包。
pip install microsoft-agents-a365-observability-core
pip install microsoft-agents-a365-runtime
如果您的智能体使用 Microsoft Agents Hosting 包,请安装托管集成包。 它提供中间件,可自动从 TurnContext 填充 bagage 和作用域,并包含用于可观测性导出程序的令牌缓存。
pip install microsoft-agents-a365-observability-hosting
如果您的智能体使用受支持的 AI 框架之一,请安装相应的自动instrumentation扩展,以便在无需手动instrumentation代码的情况下自动捕获遥测数据。 有关配置的详细信息,请参阅 自动instrumentation。
# For Semantic Kernel
pip install microsoft-agents-a365-observability-extensions-semantic-kernel
# For OpenAI Agents SDK
pip install microsoft-agents-a365-observability-extensions-openai
# For Microsoft Agent Framework
pip install microsoft-agents-a365-observability-extensions-agent-framework
# For LangChain
pip install microsoft-agents-a365-observability-extensions-langchain
安装核心可观测性和运行时程序包。 所有使用 Agent 365 可观测性的智能体都需要这些包。
npm install @microsoft/agents-a365-observability
npm install @microsoft/agents-a365-runtime
如果您的智能体使用 @microsoft/agents-hosting 包,请安装托管集成包。 它提供中间件,可自动从 TurnContext 填充 bagage 和作用域,并包含用于可观测性导出程序的令牌缓存。
npm install @microsoft/agents-a365-observability-hosting
如果您的智能体使用受支持的 AI 框架之一,请安装相应的自动instrumentation扩展,以便在无需手动instrumentation代码的情况下自动捕获遥测数据。 有关配置的详细信息,请参阅 自动instrumentation。
// For OpenAI Agents SDK
npm install @microsoft/agents-a365-observability-extensions-openai
// For LangChain
npm install @microsoft/agents-a365-observability-extensions-langchain
安装核心可观测性和运行时程序包。 所有使用 Agent 365 可观测性的智能体都需要此包。
dotnet add package Microsoft.Agents.A365.Observability.Runtime
如果您的智能体使用 Microsoft.Agents.A365.Observability.Hosting NuGet 包,请安装托管集成包。 它提供中间件,可自动从 TurnContext 填充 bagage,并为可观测性导出程序包含令牌缓存。
dotnet add package Microsoft.Agents.A365.Observability.Hosting
如果您的智能体使用受支持的 AI 框架之一,请安装相应的自动instrumentation扩展,以便在无需手动instrumentation代码的情况下自动捕获遥测数据。 有关配置的详细信息,请参阅 自动instrumentation。
// For Semantic Kernel
dotnet add package Microsoft.Agents.A365.Observability.Extensions.SemanticKernel
// For OpenAI
dotnet add package Microsoft.Agents.A365.Observability.Extensions.OpenAI
// For Agent Framework
dotnet add package Microsoft.Agents.A365.Observability.Extensions.AgentFramework
配置
使用以下设置为您的智能体启用并自定义 Agent 365 可观测性。
将 ENABLE_A365_OBSERVABILITY_EXPORTER 环境变量设置为 true 以启用可观测性。 此设置会将日志导出到服务,并需要提供一个 token_resolver。 否则,将使用控制台导出程序。
from microsoft_agents_a365.observability.core import configure
def token_resolver(agent_id: str, tenant_id: str) -> str | None:
# Implement secure token retrieval here
return "Bearer <token>"
configure(
service_name="my-agent-service",
service_namespace="my.namespace",
token_resolver=token_resolver,
)
在日志记录到控制台中时,不包括令牌解析程序。
您可以通过将 Agent365ExporterOptions 实例传递给 exporter_options 来自定义导出器的行为。 当提供 exporter_options 时,它优先于 token_resolver 和 cluster_category 参数。
from microsoft_agents_a365.observability.core import configure, Agent365ExporterOptions
configure(
service_name="my-agent-service",
service_namespace="my.namespace",
exporter_options=Agent365ExporterOptions(
cluster_category="prod",
token_resolver=token_resolver,
),
suppress_invoke_agent_input=True,
)
下表描述了 configure() 的可选参数。
| 参数 |
描述 |
默认值 |
logger_name |
用于调试和控制台日志输出的 Python 日志记录器的名称。 |
microsoft_agents_a365.observability.core |
exporter_options |
一个 Agent365ExporterOptions 实例,用于同时配置令牌解析器和集群类别。 |
None |
suppress_invoke_agent_input |
当 True 时,会抑制 InvokeAgent 跨度上的输入消息。 |
False |
下表描述了 Agent365ExporterOptions 的可选属性。
| 属性 |
说明 |
默认值 |
use_s2s_endpoint |
当为 True 时,使用服务到服务终结点路径。 |
False |
max_queue_size |
批处理器的最大队列大小。 |
2048 |
scheduled_delay_ms |
导出批次之间的延迟(以毫秒为单位)。 |
5000 |
exporter_timeout_ms |
导出操作的超时时间(以毫秒为单位)。 |
30000 |
max_export_batch_size |
导出操作的最大批处理大小。 |
512 |
将 ENABLE_A365_OBSERVABILITY_EXPORTER 环境变量设置为 true 以启用可观测性。 此设置将日志导出到服务,并要求提供令牌解析器。 否则,将使用控制台导出程序。
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
// Define a token resolver to authenticate with the observability service for exporting logs
const tokenResolver = (agentId, tenantId) => {
// Your token resolution logic here
return "your-token";
};
// Advanced configuration with builder pattern
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withTokenResolver((agentId, tenantId) => {
return tokenResolver(agentId, tenantId);
})
);
builder.start();
作为环境变量的替代方案,您可以通过 withConfigurationProvider 方法使用配置提供程序以编程方式配置可观测性。 如果您还使用了单独的构建器方法(例如 withExporterOptions 或 withClusterCategory),则这些单独的构建器方法的优先级高于配置提供程序中的值。
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
import { ObservabilityConfiguration } from '@microsoft/agents-a365-observability';
const configProvider = new ObservabilityConfiguration({
isObservabilityExporterEnabled: () => true,
// Set log levels as pipe-separated values (for example, 'info|warn|error')
observabilityLogLevel: () => 'info|warn|error',
});
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withConfigurationProvider(configProvider)
.withTokenResolver((agentId, tenantId) => {
return tokenResolver(agentId, tenantId);
})
);
builder.start();
您可以通过将 Agent365ExporterOptions 实例传递给 withExporterOptions 来自定义导出器的行为。 此选项允许您控制批处理、超时和路由模式。
import {
ObservabilityManager,
Agent365ExporterOptions,
} from '@microsoft/agents-a365-observability';
import { ClusterCategory } from '@microsoft/agents-a365-runtime';
const exporterOptions = new Agent365ExporterOptions();
exporterOptions.maxQueueSize = 10;
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withClusterCategory(ClusterCategory.prod)
.withExporterOptions(exporterOptions)
.withTokenResolver(tokenResolver)
);
builder.start();
下表描述了 Agent365ExporterOptions 的可选属性。
| 属性 |
说明 |
默认值 |
useS2SEndpoint |
当为 true 时,使用服务到服务终结点路径。 |
false |
maxQueueSize |
批处理器的最大队列大小。 |
2048 |
scheduledDelayMilliseconds |
导出批次之间的延迟(以毫秒为单位)。 |
5000 |
exporterTimeoutMilliseconds |
整个导出操作的超时时间(以毫秒为单位)。 |
90000 |
httpRequestTimeoutMilliseconds |
每个向后端发出的 HTTP 请求的超时时间(以毫秒为单位)。 |
30000 |
maxExportBatchSize |
导出操作的最大批处理大小。 |
512 |
您还可以提供一个实现 ILogger 接口的自定义日志器 (info, warn, error, event)。 使用 withCustomLogger 将其传递给构建器。
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withCustomLogger({
info: (message, ...args) => { /* your logging logic */ },
warn: (message, ...args) => { /* your logging logic */ },
error: (message, ...args) => { /* your logging logic */ },
event: (eventName, success, durationMs, message, details) => { /* your logging logic */ }
})
.withTokenResolver((agentId, tenantId) => {
return tokenResolver(agentId, tenantId);
})
);
builder.start();
在 appsettings.json 中将 EnableAgent365Exporter 设置为 true。
在 Program.cs 中,将 Agent365ExporterOptions 添加到服务集合中。 此更改配置了跟踪导出器用于检索令牌的委托。
使用 AddA365Tracing() 添加可观测性相关的依赖项。
using Microsoft.Agents.A365.Observability.Runtime;
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Exporters;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton(sp =>
{
return new Agent365ExporterOptions
{
TokenResolver = async (agentId, tenantId) =>
{
// It's recommended to implement caching in your token provider for performance.
var token = await tokenProvider.GetObservabilityTokenAsync(agentId, tenantId);
return token;
}
};
});
builder.AddA365Tracing();
您可以通过向 AddA365Tracing() 传递配置委托和导出程序类型来自定义导出程序行为。
builder.AddA365Tracing(
configure: tracingBuilder =>
{
// Use the builder to add extensions (e.g., WithSemanticKernel(), WithOpenAI())
},
agent365ExporterType: Agent365ExporterType.Agent365ExporterAsync
);
下表描述了 Agent365ExporterOptions 的可选属性。
| 属性 |
说明 |
默认值 |
UseS2SEndpoint |
当为 true 时,使用服务到服务终结点路径。 |
false |
MaxQueueSize |
批处理器的最大队列大小。 |
2048 |
ScheduledDelayMilliseconds |
导出批次之间的延迟(以毫秒为单位)。 |
5000 |
ExporterTimeoutMilliseconds |
导出操作的超时时间(以毫秒为单位)。 |
30000 |
MaxExportBatchSize |
导出操作的最大批处理大小。 |
512 |
负载属性
使用 BaggageBuilder 设置在请求中流经所有数据段的上下文信息。
该 SDK 实现了 SpanProcessor,可将所有非空行李条目复制到新启动的跨度中,且不会覆盖现有属性。
from microsoft_agents_a365.observability.core import BaggageBuilder
with (
BaggageBuilder()
.tenant_id("tenant-123")
.agent_id("agent-456")
.conversation_id("conv-789")
.build()
):
# Any spans started in this context will receive these as attributes
pass
要从 TurnContext 自动填充 BaggageBuilder,请在 microsoft-agents-a365-observability-hosting 包中使用 populate 辅助程序。 此帮助程序会自动从活动中提取调用者、智能体、租户、渠道和会话详细信息。
from microsoft_agents.hosting.core.turn_context import TurnContext
from microsoft_agents_a365.observability.core import BaggageBuilder
from microsoft_agents_a365.observability.hosting.scope_helpers.populate_baggage import populate
builder = BaggageBuilder()
populate(builder, turn_context)
with builder.build():
# Baggage is auto-populated from the TurnContext activity
pass
import { BaggageBuilder } from '@microsoft/agents-a365-observability';
// Create and apply baggage context
const baggageScope = new BaggageBuilder()
// Core identifiers
.tenantId('tenant-123')
.agentId('agent-456')
.conversationId('conv-789')
.build();
// Execute operations within the baggage context
baggageScope.run(() => {
// All spans created within this context will inherit the baggage values
// Invoke another agent
const agentScope = InvokeAgentScope.start(request, scopeDetails, agentDetails);
// ... agent logic
// Execute tools
const toolScope = ExecuteToolScope.start(request, toolDetails, agentDetails);
// ... tool logic
});
要从 TurnContext 自动填充 BaggageBuilder,请在 @microsoft/agents-a365-observability-hosting 包中使用 fromTurnContext 辅助程序。 此帮助程序会自动从活动中提取调用者、智能体、租户、渠道和会话详细信息。
import { BaggageBuilder } from '@microsoft/agents-a365-observability';
import { BaggageBuilderUtils } from '@microsoft/agents-a365-observability-hosting';
const baggageScope = BaggageBuilderUtils.fromTurnContext(new BaggageBuilder(), context)
.invokeAgentServer(context.activity.serviceUrl, 3978)
.build();
await baggageScope.run(async () => {
// Baggage is auto-populated from the TurnContext activity
});
using Microsoft.Agents.A365.Observability.Runtime.Common;
using var baggageScope = new BaggageBuilder()
.TenantId("tenant-123")
.AgentId("agent-456")
.ConversationId("conv-789")
.Build();
// Any spans started in this context will receive them as attributes.
若要从 ITurnContext 自动填充 BaggageBuilder,请在 Microsoft.Agents.A365.Observability.Hosting 包中使用 FromTurnContext 扩展方法。 该方法会自动从活动中提取调用者、智能体、租户、渠道和会话详细信息。
using Microsoft.Agents.A365.Observability.Runtime.Common;
using Microsoft.Agents.A365.Observability.Hosting.Extensions;
using var baggageScope = new BaggageBuilder()
.FromTurnContext(turnContext)
.Build();
负载中间件
如果您的智能体使用托管集成包,请注册 Baggage 中间件,以便自动为每个传入请求填充 Baggage。 此步骤无需在每个活动处理程序中手动调用 BaggageBuilder。
在适配器中间件集上注册 BaggageMiddleware。 它会从每个传入的 TurnContext 中自动提取呼叫方、智能体、租户、通道和对话详细信息,并将请求整合在行李作用域中。
from microsoft_agents_a365.observability.hosting import BaggageMiddleware
adapter.use(BaggageMiddleware())
或者,使用 ObservabilityHostingManager 配置 Baggage 中间件以及其他托管功能:
from microsoft_agents_a365.observability.hosting import ObservabilityHostingManager, ObservabilityHostingOptions
options = ObservabilityHostingOptions(enable_baggage=True)
ObservabilityHostingManager.configure(adapter.middleware_set, options)
中间件会跳过异步回复(ContinueConversation 事件)的行李配置,以避免覆盖源请求已设置的行李。
在适配器上注册 BaggageMiddleware。 它会从每个传入的 TurnContext 中自动提取呼叫方、智能体、租户、通道和对话详细信息,并将请求整合在行李作用域中。
import { BaggageMiddleware } from '@microsoft/agents-a365-observability-hosting';
// Option 1: Register middleware directly on the adapter
adapter.use(new BaggageMiddleware());
或者,使用 ObservabilityHostingManager 配置 Baggage 中间件以及其他托管功能:
import { ObservabilityHostingManager } from '@microsoft/agents-a365-observability-hosting';
const manager = new ObservabilityHostingManager();
manager.configure(adapter, { enableBaggage: true });
中间件会跳过异步回复(ContinueConversation 事件)的行李配置,以避免覆盖源请求已设置的行李。
在适配器上注册 BaggageTurnMiddleware。 它会从每个传入的 ITurnContext 中自动提取呼叫方、智能体、租户、通道和对话详细信息,并将请求整合在行李作用域中。
using Microsoft.Agents.A365.Observability.Hosting.Middleware;
adapter.Use(new BaggageTurnMiddleware());
中间件会跳过异步回复(ContinueConversation 事件)的行李配置,以避免覆盖源请求已设置的行李。
如果您需要 HTTP 级别的行李(例如,在 Bot Framework 管道运行前设置租户和智能体 ID),请使用 UseObservabilityRequestContext 扩展方法在 ASP.NET Core 管道中注册 ObservabilityBaggageMiddleware。 必须提供一个解析器函数,用于从 HTTP 上下文中提取租户 ID 和智能体 ID。
using Microsoft.Agents.A365.Observability.Hosting.Middleware;
app.UseObservabilityRequestContext((httpContext) =>
{
// Extract tenant and agent IDs from your request context
var tenantId = GetTenantIdFromContext(httpContext);
var agentId = GetAgentIdFromContext(httpContext);
return (tenantId, agentId);
});
令牌解析器
使用 Agent 365 导出器时,必须提供一个返回身份验证令牌的令牌解析器函数。
当您将 Agent 365 可观测性 SDK 与 Agent Hosting 框架结合使用时,可通过智能体活动中的 TurnContext 生成令牌。
以下代码片段演示了如何使用 microsoft_agents.hosting.core SDK 生成令牌。 此处生成的身份验证令牌用于将跨度导出到 A365 摄取服务。 智能体可以自行生成令牌(例如使用 Microsoft 身份验证库 (MSAL)),但必须确保该令牌具有可观测性作用域。
from microsoft_agents.activity import load_configuration_from_env
from microsoft_agents.authentication.msal import MsalConnectionManager
from microsoft_agents.hosting.aiohttp import CloudAdapter
from microsoft_agents.hosting.core import (
AgentApplication,
Authorization,
MemoryStorage,
TurnContext,
TurnState,
)
from microsoft_agents_a365.runtime import (
get_observability_authentication_scope,
)
agents_sdk_config = load_configuration_from_env(environ)
STORAGE = MemoryStorage()
CONNECTION_MANAGER = MsalConnectionManager(**agents_sdk_config)
ADAPTER = CloudAdapter(connection_manager=CONNECTION_MANAGER)
ADAPTER.use(TranscriptLoggerMiddleware(ConsoleTranscriptLogger()))
AUTHORIZATION = Authorization(STORAGE, CONNECTION_MANAGER, **agents_sdk_config)
AGENT_APP = AgentApplication[TurnState](
storage=STORAGE, adapter=ADAPTER, authorization=AUTHORIZATION, **agents_sdk_config
)
@AGENT_APP.activity("message", auth_handlers=["AGENTIC"])
async def on_message(context: TurnContext, _state: TurnState):
aau_auth_token = await AGENT_APP.auth.exchange_token(
context,
scopes=get_observability_authentication_scope(),
auth_handler_id="AGENTIC",
)
# cache this auth token and return via token resolver
对于使用 A365 CLI 构建且采用 AI 队友以及 Microsoft Agent 365 可观测性托管库包的智能体,请使用 AgenticTokenCache 自动处理令牌缓存。 在活动处理程序中,为每个智能体和租户注册一次令牌,并在可观测性配置中将 cache.get_observability_token 作为 token_resolver 传递。
from microsoft_agents_a365.observability.core import configure
from microsoft_agents_a365.observability.hosting.token_cache_helpers import (
AgenticTokenCache,
AgenticTokenStruct,
)
from microsoft_agents_a365.runtime import get_observability_authentication_scope
# Create a shared cache instance
token_cache = AgenticTokenCache()
# Use the cache as your token resolver in configure()
configure(
service_name="my-agent-service",
service_namespace="my.namespace",
token_resolver=token_cache.get_observability_token,
)
@AGENT_APP.activity("message", auth_handlers=["AGENTIC"])
async def on_message(context: TurnContext, _state: TurnState):
token_cache.register_observability(
agent_id="agent-456",
tenant_id="tenant-123",
token_generator=AgenticTokenStruct(
authorization=AGENT_APP.auth,
turn_context=context,
),
observability_scopes=get_observability_authentication_scope(),
)
以下代码片段演示了如何使用 @microsoft/agents-hosting SDK 生成令牌。 此处生成的身份验证令牌用于将跨度导出到 A365 摄取服务。 智能体可以自行生成令牌(例如使用 Microsoft 身份验证库 (MSAL)),但必须确保该令牌具有可观测性作用域。
import {
TurnState,
AgentApplication,
MemoryStorage,
TurnContext,
} from '@microsoft/agents-hosting';
import { ActivityTypes } from '@microsoft/agents-activity';
import { getObservabilityAuthenticationScope } from '@microsoft/agents-a365-runtime';
interface ConversationState {
count: number;
}
type ApplicationTurnState = TurnState<ConversationState>;
const storage = new MemoryStorage();
export const agentApplication = new AgentApplication<ApplicationTurnState>({
authorization: {
agentic: {}, // We have the type and scopes set in the .env file
},
storage,
});
agentApplication.onActivity(
ActivityTypes.Message,
async (context: TurnContext, state: ApplicationTurnState) => {
const aauAuthToken = await agentApplication.authorization.exchangeToken(context, 'agentic', {
scopes: getObservabilityAuthenticationScope()
});
// cache this auth token and return via token resolver
}
);
对于使用 AI 队友和 @microsoft/agents-a365-observability-hosting 包通过 A365 CLI 构建的智能体,请使用 AgenticTokenCacheInstance 自动处理令牌缓存。 在活动处理程序中,为每个智能体和租户调用 RefreshObservabilityToken 一次,并将 AgenticTokenCacheInstance.getObservabilityToken 作为 tokenResolver 传递到可观测性配置中。
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
import { AgenticTokenCacheInstance } from '@microsoft/agents-a365-observability-hosting';
import { getObservabilityAuthenticationScope } from '@microsoft/agents-a365-runtime';
// Use the cache as your token resolver in configure()
const builder = ObservabilityManager.configure(builder =>
builder
.withService('my-agent-service', '1.0.0')
.withTokenResolver((agentId, tenantId) =>
AgenticTokenCacheInstance.getObservabilityToken(agentId, tenantId)
)
);
builder.start();
agentApplication.onActivity(
ActivityTypes.Message,
async (context: TurnContext, state: ApplicationTurnState) => {
const agentId = context.activity.recipient?.agenticAppId || '';
const tenantId = context.activity.recipient?.tenantId || '';
await AgenticTokenCacheInstance.RefreshObservabilityToken(
agentId,
tenantId,
context,
agentApplication.authorization,
getObservabilityAuthenticationScope()
);
}
);
以下代码片段演示了如何使用 Microsoft.Agents 托管 SDK 生成令牌。 使用生成的身份验证令牌将跨度导出到 A365 摄取服务。 智能体可以自行生成令牌(例如使用 Microsoft 身份验证库 (MSAL)),但必须确保该令牌具有可观测性作用域。
通过将 Agent365ExporterOptions 与 TokenResolver 委托关联来提供令牌解析器。 该委托接收 agentId 和 tenantId 并返回一个身份验证令牌。
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Exporters;
builder.Services.AddSingleton(sp =>
{
return new Agent365ExporterOptions
{
TokenResolver = async (agentId, tenantId) =>
{
// Implement your token retrieval logic here
return await GetTokenAsync(agentId, tenantId);
}
};
});
对于使用 AI 队友和 Microsoft.Agents.A365.Observability.Hosting NuGet 包通过 A365 CLI 构建的智能体,请使用 AddAgenticTracingExporter() 方法通过依赖注入自动处理令牌缓存。
using Microsoft.Agents.A365.Observability.Hosting;
builder.Services.AddAgenticTracingExporter();
在智能体应用程序中注册该令牌。
using Microsoft.Agents.Builder;
using Microsoft.Agents.Builder.App.UserAuth;
using Microsoft.Extensions.Logging;
using Microsoft.Agents.A365.Observability.Hosting.Caching;
using Microsoft.Agents.A365.Observability.Runtime.Common;
using System;
using System.Threading.Tasks;
public class MyAgent : AgentApplication
{
private readonly IExporterTokenCache<AgenticTokenStruct> _agentTokenCache;
private readonly ILogger<MyAgent> _logger;
public MyAgent(AgentApplicationOptions options, IExporterTokenCache<AgenticTokenStruct> agentTokenCache, ILogger<MyAgent> logger)
: base(options)
{
_agentTokenCache = agentTokenCache ?? throw new ArgumentNullException(nameof(agentTokenCache));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
protected async Task MessageActivityAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
{
using var baggageScope = new BaggageBuilder()
.TenantId(turnContext.Activity.Recipient.TenantId)
.AgentId(turnContext.Activity.Recipient.AgenticAppId)
.Build();
try
{
_agentTokenCache.RegisterObservability(
turnContext.Activity.Recipient.AgenticAppId,
turnContext.Activity.Recipient.TenantId,
new AgenticTokenStruct(
userAuthorization: UserAuthorization,
turnContext: turnContext,
authHandlerName: "AGENTIC"
),
EnvironmentUtils.GetObservabilityAuthenticationScope()
);
}
catch (Exception ex)
{
_logger.LogWarning($"Error registering for observability: {ex.Message}");
}
}
}
自动检测
自动检测会自动侦听智能体框架 (SDK) 现有的跟踪遥测信号,并将其转发到 Agent 365 可观测性服务。 此功能免除了开发人员手动编写监控代码的需要,简化了配置,并确保了性能跟踪的一致性。
重要提示
自动检测仅填充标准 OTel 属性。 您必须通过 BaggageBuilder 添加特定于 Microsoft 的属性。 要查看哪些属性缺失,请将控制台的跨度输出与存储日志进行比对,以获取差异集。
多种 SDK 和平台支持自动instrumentation:
备注
对自动插桩的支持因平台和 SDK 实现而异。
语义内核
自动检测需要使用行李生成器。 使用 BaggageBuilder 设置智能体 ID 和租户 ID。
安装此包。
pip install microsoft-agents-a365-observability-extensions-semantic-kernel
配置可观测性。
from microsoft_agents_a365.observability.core import configure
from microsoft_agents_a365.observability.extensions.semantickernel.trace_instrumentor import SemanticKernelInstrumentor
# Configure observability
configure(
service_name="my-semantic-kernel-agent",
service_namespace="ai.agents"
)
# Enable auto-instrumentation
instrumentor = SemanticKernelInstrumentor()
instrumentor.instrument()
# Your Semantic Kernel code is now automatically traced
将依赖项添加到服务集合中。
using Microsoft.Agents.A365.Observability.Extensions.SemanticKernel;
builder.AddA365Tracing(configure: config => config.WithSemanticKernel());
使用 BaggageBuilder 设置 AgentId 和 TenantId。 确保创建 ChatCompletionAgent 时使用的 ID 与传递给 BaggageBuilder 的智能体 ID 一致。
using Microsoft.Agents.A365.Observability.Extensions.SemanticKernel;
using Microsoft.Agents.A365.Observability.Runtime.Common;
public class MyAgent
{
public async Task<AgentResponse> ProcessUserRequest(string userInput)
{
using var baggageScope = new BaggageBuilder()
.AgentId(<your-agent-id>) // NOTE: This will be the agent ID with which the TokenResolver delegate is invoked.
.TenantId(<your-tenant-id>) // NOTE: This will be the tenant ID with which the TokenResolver delegate is invoked.
.Build();
var chatCompletionAgent = new ChatCompletionAgent
{
// NOTE: This will be the agent ID with which the TokenResolver delegate is invoked. Should match above.
Id = <your-agent-id>,
...
};
}
}
OpenAI
自动检测需要使用行李生成器。 使用 BaggageBuilder 设置智能体 ID 和租户 ID。
安装此包。
pip install microsoft-agents-a365-observability-extensions-openai
配置可观测性。
from microsoft_agents_a365.observability.core import configure
from microsoft_agents_a365.observability.extensions.openai import OpenAIAgentsTraceInstrumentor
# Configure observability
configure(
service_name="my-openai-agent",
service_namespace="ai.agents"
)
# Enable auto-instrumentation
instrumentor = OpenAIAgentsTraceInstrumentor()
instrumentor.instrument()
# Your OpenAI Agents code is now automatically traced
安装此包。
npm install @microsoft/agents-a365-observability-extensions-openai
配置可观测性。
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
import { OpenAIAgentsTraceInstrumentor } from '@microsoft/agents-a365-observability-extensions-openai';
// Configure observability first
const sdk = ObservabilityManager.configure((builder) =>
builder
.withService('My Agent Service', '1.0.0')
);
// Create and enable the instrumentor
const instrumentor = new OpenAIAgentsTraceInstrumentor({
enabled: true,
tracerName: 'openai-agents-tracer',
tracerVersion: '1.0.0'
});
sdk.start();
instrumentor.enable();
将依赖项添加到服务集合中。
using Microsoft.Agents.A365.Observability.Extensions.OpenAI;
builder.AddA365Tracing(configure: config => config.WithOpenAI());
使用 BaggageBuilder 设置 AgentId 和 TenantId。 对于工具调用,请在 ChatToolCall 实例上使用 Trace() 启动跟踪。
using Microsoft.Agents.A365.Observability.Extensions.OpenAI;
using Microsoft.Agents.A365.Observability.Runtime.Common;
public class MyAgent
{
public async Task<AgentResponse> ProcessUserRequest(string userInput)
{
using var baggageScope = new BaggageBuilder()
.AgentId(<your-agent-id>) // NOTE: This will be the agent ID with which the TokenResolver delegate is invoked.
.TenantId(<your-tenant-id>) // NOTE: This will be the tenant ID with which the TokenResolver delegate is invoked.
.Build();
// NOTE: This will be the agent and tenant ID with which the TokenResolver delegate will be invoked.
using var scope = chatToolCall.Trace(agentId: <your-agent-id>, <your-tenant-id>);
}
}
Agent Framework
自动检测需要使用行李生成器。 使用 BaggageBuilder 设置智能体 ID 和租户 ID。
安装此包。
pip install microsoft-agents-a365-observability-extensions-agent-framework
配置可观测性。
from microsoft_agents_a365.observability.core import configure
from microsoft_agents_a365.observability.extensions.agentframework import (
AgentFrameworkInstrumentor,
)
# Configure observability
configure(
service_name="AgentFrameworkTracingWithAzureOpenAI",
service_namespace="AgentFrameworkTesting",
)
# Enable auto-instrumentation
AgentFrameworkInstrumentor().instrument()
Agent Framework 不支持 JavaScript。
将依赖项添加到服务集合中。
using Microsoft.Agents.A365.Observability.Extensions.AgentFramework;
builder.AddA365Tracing(configure: config => config.WithAgentFramework());
使用 BaggageBuilder 设置 AgentId 和 TenantId。
using Microsoft.Agents.A365.Observability.Runtime.Common;
public class MyAgent : AgentApplication
{
protected async Task MessageActivityAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
{
using var baggageScope = new BaggageBuilder()
.AgentId(<your-agent-id>) // NOTE: This will be the agent ID with which the TokenResolver delegate is invoked.
.TenantId(<your-tenant-id>) // NOTE: This will be the tenant ID with which the TokenResolver delegate is invoked.
.Build();
}
}
LangChain 框架
自动检测需要使用行李生成器。 使用 BaggageBuilder 设置智能体 ID 和租户 ID。
安装此包。
pip install microsoft-agents-a365-observability-extensions-langchain
配置可观测性。
from microsoft_agents_a365.observability.core.config import configure
from microsoft_agents_a365.observability.extensions.langchain import CustomLangChainInstrumentor
# Configure observability
configure(
service_name="my-langchain-agent",
service_namespace="ai.agents"
)
# Enable auto-instrumentation
CustomLangChainInstrumentor()
# Your LangChain code is now automatically traced
安装此包。
npm install @microsoft/agents-a365-observability-extensions-langchain
配置可观测性。
import { ObservabilityManager } from '@microsoft/agents-a365-observability';
import { LangChainTraceInstrumentor } from '@microsoft/agents-a365-observability-extensions-langchain';
import * as LangChainCallbacks from '@langchain/core/callbacks/manager';
// Configure observability first
const sdk = ObservabilityManager.configure((builder) =>
builder
.withService('My Agent Service', '1.0.0')
);
sdk.start();
// Enable LangChain auto-instrumentation
LangChainTraceInstrumentor.instrument(LangChainCallbacks);
// Your LangChain code is now automatically traced
手动检测
使用 Agent 365 可观测性 SDK 来了解智能体的内部工作原理。
该 SDK 提供了您可以启动的范围:InvokeAgentScope、ExecuteToolScope、InferenceScope 和 OutputScope。
智能体调用
在开始智能体流程时使用此作用域 通过使用“智能体调用”作用域,您可以捕获诸如当前被调用的智能体、智能体用户数据等属性。
from microsoft_agents_a365.observability.core import (
InvokeAgentScope,
InvokeAgentScopeDetails,
AgentDetails,
CallerDetails,
UserDetails,
Channel,
Request,
ServiceEndpoint,
)
agent_details = AgentDetails(
agent_id="agent-456",
agent_name="My Agent",
agent_description="An AI agent powered by Azure OpenAI",
agentic_user_id="auid-123",
agentic_user_email="agent@contoso.com",
agent_blueprint_id="blueprint-789",
tenant_id="tenant-123",
)
scope_details = InvokeAgentScopeDetails(
endpoint=ServiceEndpoint(hostname="myagent.contoso.com", port=443),
)
request = Request(
content="User asks a question",
session_id="session-42",
conversation_id="conv-xyz",
channel=Channel(name="msteams"),
)
caller_details = CallerDetails(
user_details=UserDetails(
user_id="user-123",
user_email="jane.doe@contoso.com",
user_name="Jane Doe",
),
)
with InvokeAgentScope.start(request, scope_details, agent_details, caller_details):
# Perform agent invocation logic
response = call_agent(...)
import {
InvokeAgentScope,
InvokeAgentScopeDetails,
AgentDetails,
CallerDetails,
UserDetails,
Channel,
Request,
ServiceEndpoint,
} from '@microsoft/agents-a365-observability';
// Use the same agentDetails instance across all scopes in a request
const agentDetails: AgentDetails = {
agentId: 'agent-456',
agentName: 'Email Assistant',
agentDescription: 'An AI agent powered by Azure OpenAI',
agentAuid: 'auid-123',
agentEmail: 'agent@contoso.com',
agentBlueprintId: 'blueprint-789',
tenantId: 'tenant-123',
};
const scopeDetails: InvokeAgentScopeDetails = {
endpoint: { host: 'myagent.contoso.com', port: 443 } as ServiceEndpoint,
};
// Use the same request instance across all scopes in a request
const request: Request = {
content: 'Please help me organize my emails',
sessionId: 'session-42',
conversationId: 'conv-xyz',
channel: { name: 'msteams' } as Channel,
};
// Optional: Caller details (human user, or agent-to-agent)
const callerDetails: CallerDetails = {
userDetails: {
userId: 'user-123',
userEmail: 'jane.doe@contoso.com',
userName: 'Jane Doe',
} as UserDetails,
};
const scope = InvokeAgentScope.start(request, scopeDetails, agentDetails, callerDetails);
try {
await scope.withActiveSpanAsync(async () => {
// Record input messages
scope.recordInputMessages(['Please help me organize my emails', 'Focus on urgent items']);
// Your agent invocation logic here
const response = await invokeAgent(request.content);
// Record output messages
scope.recordOutputMessages(['I found 15 urgent emails', 'Here is your organized inbox']);
});
} catch (error) {
scope.recordError(error as Error);
throw error;
} finally {
scope.dispose();
}
如果您的智能体使用 @microsoft/agents-a365-observability-hosting 包,则可以使用 ScopeUtils.populateInvokeAgentScopeFromTurnContext 来创建作用域,其中包含智能体详细信息、调用者详细信息以及从 TurnContext 自动推导出的通道信息。
import { InvokeAgentScopeDetails, AgentDetails, ServiceEndpoint } from '@microsoft/agents-a365-observability';
import { ScopeUtils } from '@microsoft/agents-a365-observability-hosting';
const agentDetails: AgentDetails = { agentId: 'agent-456' };
const scopeDetails: InvokeAgentScopeDetails = {
endpoint: { host: 'myagent.contoso.com', port: 443 } as ServiceEndpoint,
};
const scope = ScopeUtils.populateInvokeAgentScopeFromTurnContext(
agentDetails,
scopeDetails,
context, // TurnContext
authToken // authentication token string
);
try {
await scope.withActiveSpanAsync(async () => {
// Agent details, caller details, and channel are auto-populated from context
const response = await invokeAgent(context.activity.text);
scope.recordOutputMessages([response]);
});
} finally {
scope.dispose();
}
using System;
using System.Threading.Tasks;
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Contracts;
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Scopes;
public class MyAgent
{
public async Task<AgentResponse> ProcessUserRequest(string userInput)
{
var agentDetails = new AgentDetails(
agentId: "agent-456",
agentName: "MyAgent",
agentDescription: "Handles user requests.",
agenticUserId: "auid-123",
agenticUserEmail: "agent@contoso.com",
agentBlueprintId: "blueprint-789",
tenantId: "tenant-123"
);
var scopeDetails = new InvokeAgentScopeDetails(
endpoint: new Uri("https://myagent.contoso.com")
);
var request = new Request(
content: userInput,
sessionId: "session-abc",
channel: new Channel("msteams"),
conversationId: "conv-xyz"
);
var callerDetails = new CallerDetails(
userDetails: new UserDetails(
userId: "user-123",
userEmail: "jane.doe@contoso.com",
userName: "Jane Doe"
)
);
// Start the scope
using var scope = InvokeAgentScope.Start(
request: request,
scopeDetails: scopeDetails,
agentDetails: agentDetails,
callerDetails: callerDetails
);
// Record input messages
scope.RecordInputMessages(new[] { userInput });
// ... your agent logic here ...
var output = $"Processed: {userInput}";
scope.RecordOutputMessages(new[] { output });
return new AgentResponse { Content = output };
}
}
public class AgentResponse
{
public string Content { get; set; }
}
以下示例演示了如何为智能体的工具执行添加可观测性跟踪。 此跟踪会捕获遥测数据,用于监控和审计。
from microsoft_agents_a365.observability.core import (
ExecuteToolScope,
ToolCallDetails,
Request,
ServiceEndpoint,
)
# Use the same agent_details and request instances from the InvokeAgentScope example above
tool_details = ToolCallDetails(
tool_name="summarize",
tool_type="function",
tool_call_id="tc-001",
arguments="{'text': '...'}",
description="Summarize provided text",
endpoint=ServiceEndpoint(hostname="tools.contoso.com", port=8080),
)
with ExecuteToolScope.start(request, tool_details, agent_details) as scope:
result = run_tool(tool_details)
scope.record_response(result)
import { ExecuteToolScope, ToolCallDetails } from '@microsoft/agents-a365-observability';
// Use the same agentDetails and request instances from the InvokeAgentScope example above
const toolDetails: ToolCallDetails = {
toolName: 'email-search',
arguments: JSON.stringify({ query: 'from:boss@company.com', limit: 10 }),
toolCallId: 'tool-call-456',
description: 'Search emails by criteria',
toolType: 'function',
endpoint: {
host: 'tools.contoso.com',
port: 8080, // Will be recorded since not 443
protocol: 'https'
},
};
const scope = ExecuteToolScope.start(request, toolDetails, agentDetails);
try {
return await scope.withActiveSpanAsync(async () => {
// Execute the tool
const result = await searchEmails(toolDetails.arguments);
// Record the tool execution result
scope.recordResponse(result);
return result;
});
} catch (error) {
scope.recordError(error as Error);
throw error;
} finally {
scope.dispose();
}
如果您的智能体使用 @microsoft/agents-a365-observability-hosting 包,请使用 ScopeUtils.populateExecuteToolScopeFromTurnContext 来创建作用域,其中智能体详细信息将自动从 TurnContext 中推导出来。
import { ToolCallDetails } from '@microsoft/agents-a365-observability';
import { ScopeUtils } from '@microsoft/agents-a365-observability-hosting';
const toolDetails: ToolCallDetails = {
toolName: 'email-search',
arguments: JSON.stringify({ query: 'from:boss@company.com' }),
toolCallId: 'tool-call-456',
toolType: 'function',
};
const scope = ScopeUtils.populateExecuteToolScopeFromTurnContext(
toolDetails,
context, // TurnContext
authToken // authentication token string
);
try {
await scope.withActiveSpanAsync(async () => {
const result = await searchEmails(toolDetails.arguments);
scope.recordResponse(JSON.stringify(result));
});
} finally {
scope.dispose();
}
using System;
using System.Threading.Tasks;
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Contracts;
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Scopes;
// Use the same agentDetails and request instances from the InvokeAgentScope example above
var toolCallDetails = new ToolCallDetails(
toolName: "summarize",
arguments: "{\"text\": \"...\"}",
toolCallId: "tc-001",
description: "Summarize provided text",
toolType: "function",
endpoint: new Uri("https://tools.contoso.com:8080")
);
using var scope = ExecuteToolScope.Start(
request: request,
details: toolCallDetails,
agentDetails: agentDetails
);
// ... your tool logic here ...
scope.RecordResponse("{\"summary\": \"The text was summarized.\"}");
推理
以下示例演示了如何对 AI 模型推理调用进行可观测性跟踪,以捕获令牌使用情况、模型详细信息和响应元数据。
from microsoft_agents_a365.observability.core import (
InferenceScope,
InferenceCallDetails,
InferenceOperationType,
)
# Use the same agent_details and request instances from the InvokeAgentScope example above
inference_details = InferenceCallDetails(
operationName=InferenceOperationType.CHAT,
model="gpt-4o-mini",
providerName="azure-openai",
inputTokens=123,
outputTokens=456,
finishReasons=["stop"],
)
with InferenceScope.start(request, inference_details, agent_details) as scope:
completion = call_llm(...)
scope.record_output_messages([completion.text])
scope.record_input_tokens(completion.usage.input_tokens)
scope.record_output_tokens(completion.usage.output_tokens)
import { InferenceScope, InferenceDetails, InferenceOperationType } from '@microsoft/agents-a365-observability';
// Use the same agentDetails and request instances from the InvokeAgentScope example above
const inferenceDetails: InferenceDetails = {
operationName: InferenceOperationType.CHAT,
model: 'gpt-4o-mini',
providerName: 'azure-openai',
};
const scope = InferenceScope.start(request, inferenceDetails, agentDetails);
try {
return await scope.withActiveSpanAsync(async () => {
// Record input messages
scope.recordInputMessages(['Summarize the following emails for me...']);
// Call the LLM
const response = await callLLM();
// Record detailed telemetry with granular methods
scope.recordOutputMessages(['Here is your email summary...']);
scope.recordInputTokens(145);
scope.recordOutputTokens(82);
scope.recordFinishReasons(['stop']);
return response.text;
});
} catch (error) {
scope.recordError(error as Error);
throw error;
} finally {
scope.dispose();
}
如果您的智能体使用 @microsoft/agents-a365-observability-hosting 包,可以使用 ScopeUtils.populateInferenceScopeFromTurnContext 创建作用域,其中智能体详细信息将自动从 TurnContext 中推导出来。
import { InferenceDetails, InferenceOperationType } from '@microsoft/agents-a365-observability';
import { ScopeUtils } from '@microsoft/agents-a365-observability-hosting';
const inferenceDetails: InferenceDetails = {
operationName: InferenceOperationType.CHAT,
model: 'gpt-4o-mini',
providerName: 'azure-openai',
};
const scope = ScopeUtils.populateInferenceScopeFromTurnContext(
inferenceDetails,
context, // TurnContext
authToken // authentication token string
);
try {
await scope.withActiveSpanAsync(async () => {
const response = await callLLM();
scope.recordOutputMessages([response.text]);
scope.recordInputTokens(response.usage.inputTokens);
scope.recordOutputTokens(response.usage.outputTokens);
});
} finally {
scope.dispose();
}
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Contracts;
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Scopes;
// Use the same agentDetails and request instances from the InvokeAgentScope example above
var inferenceDetails = new InferenceCallDetails(
operationName: InferenceOperationType.Chat,
model: "gpt-4o-mini",
providerName: "Azure OpenAI",
inputTokens: 123,
outputTokens: 456,
finishReasons: new[] { "stop" }
);
using var scope = InferenceScope.Start(
request: request,
details: inferenceDetails,
agentDetails: agentDetails
);
// ... your inference logic here ...
scope.RecordOutputMessages(new[] { "AI response message" });
scope.RecordInputTokens(123);
scope.RecordOutputTokens(456);
输出
在 InvokeAgentScope、ExecuteToolScope 或 InferenceScope 无法同步捕获输出数据的异步场景中,请使用此作用域。 将 OutputScope 作为子作用域启动,以便在父作用域完成后记录最终输出消息。
from microsoft_agents_a365.observability.core import (
OutputScope,
Response,
SpanDetails,
)
# Use the same agent_details and request instances from the InvokeAgentScope example above
# Get the parent context from the originating scope
parent_context = invoke_scope.get_context()
response = Response(messages=["Here is your organized inbox with 15 urgent emails."])
with OutputScope.start(
request,
response,
agent_details,
span_details=SpanDetails(parent_context=parent_context),
):
# Output messages are recorded automatically from the response
pass
import { OutputScope, OutputResponse, SpanDetails } from '@microsoft/agents-a365-observability';
// Use the same agentDetails and request instances from the InvokeAgentScope example above
// Get the parent context from the originating scope
const parentContext = invokeScope.getSpanContext();
const response: OutputResponse = {
messages: ['Here is your organized inbox with 15 urgent emails.'],
};
const scope = OutputScope.start(
request,
response,
agentDetails,
undefined, // userDetails
{ parentContext } as SpanDetails
);
// Output messages are recorded automatically from the response
scope.dispose();
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Contracts;
using Microsoft.Agents.A365.Observability.Runtime.Tracing.Scopes;
// Use the same agentDetails and request instances from the InvokeAgentScope example above
// Get the parent context from the originating scope
var parentContext = invokeScope.GetActivityContext();
var response = new Response(new[] { "Here is your organized inbox with 15 urgent emails." });
using var scope = OutputScope.Start(
request: request,
response: response,
agentDetails: agentDetails,
spanDetails: new SpanDetails(parentContext: parentContext)
);
// Output messages are recorded automatically from the response
本地验证
要验证是否已成功集成可观测性 SDK,请检查智能体生成的控制台日志以及可观测性 SDK 的日志。
将 ENABLE_A365_OBSERVABILITY_EXPORTER 环境变量设置为 false。 此设置将范围(跟踪)导出到控制台。
要排查导出失败,请将 ENABLE_A365_OBSERVABILITY_EXPORTER 设置为 true 并配置应用程序启动时的调试日志记录,以启用详细日志记录:
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("microsoft_agents_a365.observability.core").setLevel(logging.DEBUG)
# Or target only the exporter:
logging.getLogger(
"microsoft_agents_a365.observability.core.exporters.agent365_exporter"
).setLevel(logging.DEBUG)
关键日志消息:
DEBUG Token resolved for agent {agentId} tenant {tenantId}
DEBUG Exporting {n} spans to {url}
DEBUG HTTP 200 - correlation ID: abc-123
ERROR Token resolution failed: {error}
ERROR HTTP 401 exporting spans - correlation ID: abc-123
INFO No spans with tenant/agent identity found; nothing exported.
将 ENABLE_A365_OBSERVABILITY_EXPORTER 环境变量设置为 false。 此设置将范围(跟踪)导出到控制台。
要排查导出失败问题,请在 .env 或 shell 中设置环境变量:
# Enable the Agent365 exporter
ENABLE_A365_OBSERVABILITY_EXPORTER=true
# Enable verbose logging
A365_OBSERVABILITY_LOG_LEVEL=info|warn|error
检查控制台输出中是否包含以下消息:
[INFO] [Agent365Exporter] Exporting 245 spans
[INFO] [Agent365Exporter] Partitioned into 3 identity groups (2 spans skipped)
[INFO] [Agent365Exporter] Token resolved successfully via tokenResolver
[EVENT] export-group succeeded in 98ms {"tenantId":"...","agentId":"...","correlationId":"abc-123"}
[ERROR] [Agent365Exporter] Failed with status 401, correlation ID: abc-123
[WARN] export-partition-span-missing-identity: 5 spans skipped due to missing tenant or agent ID
此外,您还可以使用自定义日志记录器将导出事件记录到文件中:
import { setLogger, ExporterEventNames } from '@microsoft/agents-a365-observability';
setLogger({
info: (msg, ...args) => myLogger.info(msg, ...args),
warn: (msg, ...args) => myLogger.warn(msg, ...args),
error: (msg, ...args) => myLogger.error(msg, ...args),
event: (eventType: ExporterEventNames, isSuccess: boolean, durationMs: number,
message?: string, details?: Record<string, string>) => {
myLogger.info({ eventType, isSuccess, durationMs, message, ...details });
}
});
在 appsettings.json 中将 EnableAgent365Exporter 设置为 false。 此设置将范围(跟踪)导出到控制台。
要排查导出失败,请在 appsettings.json 中配置详细日志记录:
{
"EnableAgent365Exporter": "True",
"Logging": {
"LogLevel": {
"Microsoft.Agents.A365.Observability": "Debug"
}
}
}
或者设置环境变量:
EnableAgent365Exporter=True
A365_OBSERVABILITY_DOMAIN_OVERRIDE=https://your-test-endpoint.example.com
A365_OBSERVABILITY_SCOPE_OVERRIDE=https://api.powerplatform.com/.default
关键日志消息:
info: Agent365ExporterCore: Obtained token for agent {agentId} tenant {tenantId}.
info: Agent365ExporterCore: Sending {count} spans to {requestUri} for agent {agentId} tenant {tenantId}.
info: Agent365ExporterCore: HTTP {statusCode} exporting spans. 'x-ms-correlation-id': '{correlationId}'.
error: Agent365Exporter: Exception exporting spans: {exception}
warn: Agent365ExporterCore: No token obtained for agent {agentId} tenant {tenantId}. Skipping export.
备注
如果您未在 DI 中注册 ILoggerFactory,导出程序将自动回退到控制台日志记录器。
查看导出的日志
若要在 Microsoft Purview 或 Microsoft Defender 中查看智能体遥测数据,请确保满足以下要求:
针对商店发布进行验证
重要提示
要成功通过存储验证,您的智能体 必须 实现 InvokeAgentScope、InferenceScope 和 ExecuteToolScope 作用域。 发布时需要这三个作用域。
发布前,请通过实现必需的 invoke agent、execute tool、inference 和 output 作用域,利用控制台日志验证智能体的可观测性集成。 然后将智能体日志与以下属性列表进行对比,以验证是否包含所有必需属性。 可以在每个作用域上或通过行李生成器捕获属性,并根据需要添加可选属性。
有关存储发布要求的更多信息,请参阅 存储验证指南。
InvokeAgentScope 属性
以下列表总结了启动 InvokeAgentScope 时记录的必选和可选遥测属性。
"attributes": {
"error.type": "Optional",
"microsoft.a365.agent.blueprint.id": "Required",
"gen_ai.agent.description": "Optional",
"gen_ai.agent.id": "Required",
"gen_ai.agent.name": "Required",
"microsoft.a365.agent.platform.id": "Optional",
"microsoft.agent.user.email": "Required",
"microsoft.agent.user.id": "Required",
"gen_ai.agent.version": "Optional",
"microsoft.a365.caller.agent.blueprint.id": "Optional",
"microsoft.a365.caller.agent.id": "Optional",
"microsoft.a365.caller.agent.name": "Optional",
"microsoft.a365.caller.agent.platform.id": "Optional",
"microsoft.a365.caller.agent.user.email": "Optional",
"microsoft.a365.caller.agent.user.id": "Optional",
"microsoft.a365.caller.agent.version": "Optional",
"client.address": "Required",
"user.id": "Required",
"user.name": "Optional",
"user.email": "Required",
"microsoft.channel.link": "Optional",
"microsoft.channel.name": "Required",
"gen_ai.conversation.id": "Required",
"microsoft.conversation.item.link": "Optional",
"gen_ai.input.messages": "Required",
"gen_ai.operation.name": "Required",
"gen_ai.output.messages": "Required",
"server.address": "Required",
"server.port": "Required",
"microsoft.session.id": "Optional",
"microsoft.session.description": "Optional",
"microsoft.tenant.id": "Required"
}
以下列表总结了启动 ExecuteToolScope 时记录的必选和可选遥测属性。
"attributes": {
"error.type": "Optional",
"microsoft.a365.agent.blueprint.id": "Required",
"gen_ai.agent.description": "Optional",
"gen_ai.agent.id": "Required",
"gen_ai.agent.name": "Required",
"microsoft.a365.agent.platform.id": "Optional",
"microsoft.agent.user.email": "Required",
"microsoft.agent.user.id": "Required",
"gen_ai.agent.version": "Optional",
"client.address": "Required",
"user.id": "Required",
"user.name": "Optional",
"user.email": "Required",
"microsoft.channel.link": "Optional",
"microsoft.channel.name": "Required",
"gen_ai.conversation.id": "Required",
"microsoft.conversation.item.link": "Optional",
"gen_ai.operation.name": "Required",
"gen_ai.tool.call.arguments": "Required",
"gen_ai.tool.call.id": "Required",
"gen_ai.tool.call.result": "Required",
"gen_ai.tool.description": "Optional",
"gen_ai.tool.name": "Required",
"gen_ai.tool.type": "Required",
"server.address": "Optional",
"server.port": "Optional",
"microsoft.session.id": "Optional",
"microsoft.session.description": "Optional",
"microsoft.tenant.id": "Required"
}
InferenceScope 属性
以下列表总结了启动 InferenceScope 时记录的必选和可选遥测属性。
"attributes": {
"error.type": "Optional",
"microsoft.a365.agent.blueprint.id": "Required",
"gen_ai.agent.description": "Optional",
"gen_ai.agent.id": "Required",
"gen_ai.agent.name": "Required",
"microsoft.a365.agent.platform.id": "Optional",
"microsoft.a365.agent.thought.process": "Optional",
"microsoft.agent.user.email": "Required",
"microsoft.agent.user.id": "Required",
"gen_ai.agent.version": "Optional",
"client.address": "Required",
"user.id": "Required",
"user.name": "Optional",
"user.email": "Required",
"microsoft.channel.link": "Optional",
"microsoft.channel.name": "Required",
"gen_ai.conversation.id": "Required",
"microsoft.conversation.item.link": "Optional",
"gen_ai.input.messages": "Required",
"gen_ai.operation.name": "Required",
"gen_ai.output.messages": "Required",
"gen_ai.provider.name": "Required",
"gen_ai.request.model": "Required",
"gen_ai.response.finish_reasons": "Optional",
"gen_ai.usage.input_tokens": "Optional",
"gen_ai.usage.output_tokens": "Optional",
"server.address": "Optional",
"server.port": "Optional",
"microsoft.session.description": "Optional",
"microsoft.session.id": "Optional",
"microsoft.tenant.id": "Required"
}
OutputScope 属性
以下列表总结了启动 OutputScope 时记录的必选和可选遥测属性。 在父作用域无法同步捕获输出数据的异步场景中,请使用此作用域。
"attributes": {
"microsoft.a365.agent.blueprint.id": "Required",
"gen_ai.agent.description": "Optional",
"gen_ai.agent.id": "Required",
"gen_ai.agent.name": "Required",
"microsoft.a365.agent.platform.id": "Optional",
"microsoft.agent.user.email": "Required",
"microsoft.agent.user.id": "Required",
"gen_ai.agent.version": "Optional",
"client.address": "Required",
"user.id": "Required",
"user.name": "Optional",
"user.email": "Required",
"microsoft.channel.link": "Optional",
"microsoft.channel.name": "Required",
"gen_ai.conversation.id": "Required",
"microsoft.conversation.item.link": "Optional",
"gen_ai.operation.name": "Required",
"gen_ai.output.messages": "Required",
"microsoft.session.id": "Optional",
"microsoft.session.description": "Optional",
"microsoft.tenant.id": "Required"
}
使用可观测性测试智能体
在智能体中实现可观测性后,请进行测试以确保其能正确捕获遥测数据。 请按照 测试指南 设置您的环境。 然后,请重点关注 查看可观测性日志 部分,以验证您的可观测性实现是否按预期运行。
验证:
- 转到:
https://admin.cloud.microsoft/#/agents/all
- 选择您的智能体 > 活动
- 您将看到会话和工具调用
故障排除
本节描述了在实现和使用可观测性时常见的故障。
可观测性数据未显示
症状:
- 智能体正在运行
- 管理中心中无遥测数据
- 看不到智能体活动
根本原因:
解决方案:请尝试以下步骤来解决问题:
验证可观测性导出器是否已启用
您必须明确启用 Agent 365 导出程序。 若未启用,SDK 将回退到控制台导出器,且遥测数据不会发送至服务。 有关配置的详细信息,请参阅 配置。
检查令牌解析器配置
导出程序需要一个有效的令牌解析器,该解析器会为每次导出请求返回一个持有者令牌。 如果令牌解析器缺失或返回 null,导出将静默跳过。 请确保您的代码正确实现了令牌解析器。 有关详细信息,请参阅 令牌解析器。
检查日志中的错误
启用详细日志记录,并使用 az webapp log tail 命令 在日志中搜索与可观测性相关的错误。 有关如何按平台启用日志记录的详细信息,请参阅 本地验证。
# Look for observability-related errors
az webapp log tail --name <your-app-name> --resource-group <your-resource-group> | Select-String "observability"
验证遥测数据导出
确认遥测数据按预期生成并导出。
- 添加一个控制台导出器,并检查本地是否生成了遥测数据。 有关如何使用控制台导出器以及验证输出的详细信息,请参阅 本地验证。
缺少租户 ID 或智能体 ID — 跳过跨度
症状:系统会静默丢弃数据段,且从未导出。 某些 SDK 会记录跳过的跨度数量,或显示“未找到具有租户/智能体身份的跨度”之类的消息。其他 SDK 则会在不记录日志的情况下直接丢弃这些跨度。
解决方法:
- 在导出之前,SDK 会根据租户和智能体身份对跨度进行分区。 系统会丢弃缺少租户 ID 或智能体 ID 的跨度,并且绝不会将其发送至服务。
- 在创建跨度之前,请确保
BaggageBuilder 已配置租户 ID 和智能体 ID。 这些值会通过 OpenTelemetry 上下文传播,并附加到行李作用域内创建的所有跨度上。 有关特定于平台的 API,请参阅 Baggage 属性。
- 如果您使用行李中间件,或启用托管集成包中的上下文助手来填充这些 ID,请确认
TurnContext 操作具有智能体标识的有效接收者。
令牌解析失败 — 导出被跳过或未授权
症状:令牌解析器返回 null 或引发错误。 根据 SDK 的不同,导出操作要么被完全跳过,要么请求在缺少授权头的情况下被发送,并因 HTTP 401 错误而失败。
解决方法:
- 初始化时必须使用令牌解析器。 如果缺失,导出程序在启动时会引发错误。 验证令牌解析器已提供,并返回有效的持有者令牌。
- 请确保在
BaggageBuilder 中使用了正确的租户 ID 和智能体 ID,因为这些值会被传递给令牌解析器。
- 对于 Azure 托管的智能体,请验证托管身份是否具有可观测性作用域所需的 API 权限。
HTTP 401 未授权
症状:导出因 HTTP 401 而失败。 导出程序不会对该错误进行重试。
解决方法:
- 请验证令牌受众与可观测性端点范围是否匹配。
- 检查令牌解析器是否返回委派的用户令牌、面向错误访问群体的令牌,或过期令牌。
HTTP 403 禁止访问
症状:导出因 HTTP 403 而失败。 导出程序不会对该错误进行重试。
根本原因:HTTP 403 错误可能有多种原因。 按顺序检查以下解决方法。
解决方法:
重要提示
现有智能体升级到这些包版本需要额外步骤
此步骤仅适用于升级现有智能体的情况。 新安装的智能体无需执行此步骤。 如果您正在升级到以下包版本或更高版本,则必须为您的身份(托管身份或应用注册)授予新的 Agent365.Observability.OtelWrite 权限。 如果没有此权限,遥测数据导出将因 HTTP 403 错误而失败。
| 平台 |
需要执行此步骤的最低版本 |
| .NET |
0.3-beta |
| Node.js |
0.2.0-preview.1 |
| Python |
0.3.0 |
请使用以下任一选项授予该权限。
选项 A — Agent 365 CLI(需要全局管理员帐户;请从包含 a365.config.json 的智能体项目目录中运行,或使用 --agent-name)
a365 setup permissions bot
或者,如果没有配置文件:
a365 setup permissions bot --agent-name "<agent-name>"
此命令将授予蓝图上所有缺失的权限,包括可观测性范围。
选项 B — Entra 门户(无需配置文件;需要对蓝图应用注册具有全局管理员访问权限)
- 转到 Entra 门户>应用注册>,然后选择您的蓝图应用。
- 转到 API 权限>添加权限>我的组织使用的 API>,然后搜索
9b975845-388f-4429-889e-eab1ef63949c。
- 选择委托的权限>,选中
Agent365.Observability.OtelWrite>添加权限。
- 重复步骤 2–3,此次请选择 应用权限>,勾选
Agent365.Observability.OtelWrite>添加权限。
- 单击授予管理员同意并确认。
Agent365.Observability.OtelWrite(委派)和Agent365.Observability.OtelWrite(应用程序)都应显示 Granted 状态。
HTTP 403 已禁止 - 智能体 ID 不匹配
症状:导出失败,返回 HTTP 403 错误及类似 403 Forbidden 的服务器消息,且在调用 Agent 365 跟踪端点时出现 agent-ID-mismatch 失败。
根本原因:在设置智能体详细信息时,如果使用蓝图客户端 ID 而不是智能体实例客户端 ID,会出现此错误。 导出 URL 中的智能体 ID 与令牌授权的标识不匹配,因此跟踪终结点会拒绝请求。
解决方法:
- 验证租户 ID 是否已添加到 Agent 365 的允许租户列表中。
- 使用智能体实例客户端 ID(而不是蓝图客户端 ID)设置智能体详细信息。
- 验证生成的导出 URL - 如果启用日志记录器,它会被记录。 确认 URL 中的智能体 ID 与智能体实例客户端 ID 匹配。
- 要按 SDK 启用诊断日志记录,请参阅 本地验证。
HTTP 429 或 5xx 错误 - 临时性错误
症状:导出因临时性 HTTP 状态代码(例如 429 或 5xx)而失败。
解决方法:
- 这些错误通常是临时性的,会自行解决。 Python 和 JavaScript SDK 遇到 HTTP 408、429 和 5xx 状态码时,会自动进行最多三次重试,并采用指数退避策略。 .NET SDK 不会自动重试。
- 如果错误仍然存在,请查看服务运行状况仪表板。
- 请考虑通过增加批次之间的计划延迟或增大最大导出批次大小来降低导出频率。 有关各平台的配置选项,请参阅 配置 中的
Agent365ExporterOptions 表格。
导出超时
症状:导出尝试超时。
解决方法:
- 检查与可观测性终结点的网络连接性。
- 各平台的默认超时值各不相同。 默认的 HTTP 请求超时时间为 30 秒。 某些 SDK 还设有独立的整体导出器超时,该超时涵盖包括重试在内的整个导出周期。 有关各平台的具体属性和默认值,请参阅 配置 中的
Agent365ExporterOptions 表格。
- 如果频繁发生超时,请在导出器选项中增加相应的超时值。
导出成功,但遥测数据未显示在 Defender 或 Purview 中
症状: 日志显示导出成功,但在 Microsoft Defender 或 Microsoft Purview 中无法看到遥测数据。
解决方法:
- 请确认您已满足查看导出日志的先决条件。 对于 Purview,必须启用审计功能。 对于 Defender,必须配置高级搜索。 有关详细信息,请参阅 查看导出日志。
- 遥测数据在成功导出后,可能需要几分钟才能填充。 请等待数据显示后再进行进一步排查。
要了解有关测试可观测性的更多信息,请参阅:
相关内容