diff --git a/cmd/verifyexamples/examples.go b/cmd/verifyexamples/examples.go index fb3394cd..ad5a7e5c 100644 --- a/cmd/verifyexamples/examples.go +++ b/cmd/verifyexamples/examples.go @@ -812,6 +812,17 @@ var agentsExamples = []ExampleDefinition{ "The output should not contain error messages or stack traces.", }, }, + { + Name: "02_agents_observability_step01_agent_tracing", + ProjectPath: "examples/02-agents/observability/step01_agent_tracing", + RequiredEnvironmentVariables: []string{"FOUNDRY_PROJECT_ENDPOINT"}, + OptionalEnvironmentVariables: []string{"FOUNDRY_MODEL"}, + ExpectedOutputDescription: []string{ + "The output should contain a joke about a pirate from the agent.", + "The output should also contain an OpenTelemetry span printed to stdout for the agent run (an invoke_agent gen_ai span).", + "The output should not contain error messages or stack traces.", + }, + }, { Name: "02_agents_harness_step01_loop", ProjectPath: "examples/02-agents/harness/step01_loop", diff --git a/examples/02-agents/observability/step01_agent_tracing/main.go b/examples/02-agents/observability/step01_agent_tracing/main.go new file mode 100644 index 00000000..2cca1912 --- /dev/null +++ b/examples/02-agents/observability/step01_agent_tracing/main.go @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft. All rights reserved. + +package main + +import ( + "context" + + "github.com/microsoft/agent-framework-go/agent" + "github.com/microsoft/agent-framework-go/examples/internal/demo" + "github.com/microsoft/agent-framework-go/provider/foundryprovider" + "github.com/microsoft/agent-framework-go/provider/otelprovider" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +var logger = demo.NewLogger( + "Agent OpenTelemetry", + "This sample shows how to trace an agent run with OpenTelemetry. The otelprovider "+ + "middleware emits a gen_ai invoke_agent span (model, usage, finish reason) that "+ + "is exported here to stdout.", + "Model", demo.FoundryModel, +) + +func main() { + // Set up an OpenTelemetry tracer that prints spans to stdout, and install it + // as the global tracer provider so the otel middleware records to it. + exporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint()) + if err != nil { + demo.Panic(err) + } + tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter)) + otel.SetTracerProvider(tp) + defer func() { _ = tp.Shutdown(context.Background()) }() + + token := demo.FoundryTokenCredential() + + // The otelprovider middleware wraps the agent run in a gen_ai span. + a := foundryprovider.NewAgent( + demo.FoundryProjectEndpoint, + token, + foundryprovider.ModelDeployment(demo.FoundryModel), + foundryprovider.AgentConfig{ + Instructions: "You are good at telling jokes.", + Config: agent.Config{ + Name: "Joker", + Middlewares: []agent.Middleware{ + otelprovider.NewMiddleware(otelprovider.MiddlewareConfig{}), + logger, // for logging agent interactions + }, + }, + }, + ) + + ctx := context.Background() + resp, err := a.RunText(ctx, "Tell me a joke about a pirate.").Collect() + demo.Response(resp, err) +}