mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Add Azure Monitor OpenTelemetry Exporter samples (#1231)
* Add Azure Monitor OpenTelemetry Exporter to enhance observability in agent samples * add another sample code for application isnights
This commit is contained in:
committed by
GitHub
Unverified
parent
127bf68748
commit
362652b966
@@ -113,6 +113,7 @@
|
||||
<Project Path="samples/GettingStarted/Workflows/HumanInTheLoop/HumanInTheLoopBasic/HumanInTheLoopBasic.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/GettingStarted/Workflows/Observability/">
|
||||
<Project Path="samples/GettingStarted/Workflows/Observability/ApplicationInsights/ApplicationInsights.csproj" />
|
||||
<Project Path="samples/GettingStarted/Workflows/Observability/AspireDashboard/AspireDashboard.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/GettingStarted/Workflows/Visualization/">
|
||||
|
||||
+1
@@ -11,6 +11,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" />
|
||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
|
||||
<PackageReference Include="OpenTelemetry" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Console" />
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Azure.Monitor.OpenTelemetry.Exporter;
|
||||
using Microsoft.Agents.AI;
|
||||
using OpenAI;
|
||||
using OpenTelemetry;
|
||||
@@ -11,6 +12,7 @@ using OpenTelemetry.Trace;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
var applicationInsightsConnectionString = Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING");
|
||||
|
||||
const string JokerName = "Joker";
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
@@ -18,10 +20,14 @@ const string JokerInstructions = "You are good at telling jokes.";
|
||||
// Create TracerProvider with console exporter
|
||||
// This will output the telemetry data to the console.
|
||||
string sourceName = Guid.NewGuid().ToString("N");
|
||||
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
||||
var tracerProviderBuilder = Sdk.CreateTracerProviderBuilder()
|
||||
.AddSource(sourceName)
|
||||
.AddConsoleExporter()
|
||||
.Build();
|
||||
.AddConsoleExporter();
|
||||
if (!string.IsNullOrWhiteSpace(applicationInsightsConnectionString))
|
||||
{
|
||||
tracerProviderBuilder.AddAzureMonitorTraceExporter(options => options.ConnectionString = applicationInsightsConnectionString);
|
||||
}
|
||||
using var tracerProvider = tracerProviderBuilder.Build();
|
||||
|
||||
// Create the agent, and enable OpenTelemetry instrumentation.
|
||||
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" />
|
||||
<PackageReference Include="OpenTelemetry" />
|
||||
<PackageReference Include="System.Diagnostics.DiagnosticSource" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.Workflows\Microsoft.Agents.AI.Workflows.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Diagnostics;
|
||||
using Azure.Monitor.OpenTelemetry.Exporter;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Agents.AI.Workflows.Reflection;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
namespace WorkflowObservabilitySample;
|
||||
|
||||
/// <summary>
|
||||
/// This sample shows how to enable observability in a workflow and send the traces
|
||||
/// to be visualized in Application Insights.
|
||||
///
|
||||
/// In this example, we create a simple text processing pipeline that:
|
||||
/// 1. Takes input text and converts it to uppercase using an UppercaseExecutor
|
||||
/// 2. Takes the uppercase text and reverses it using a ReverseTextExecutor
|
||||
///
|
||||
/// The executors are connected sequentially, so data flows from one to the next in order.
|
||||
/// For input "Hello, World!", the workflow produces "!DLROW ,OLLEH".
|
||||
/// </summary>
|
||||
public static class Program
|
||||
{
|
||||
private const string SourceName = "Workflow.ApplicationInsightsSample";
|
||||
private static readonly ActivitySource s_activitySource = new(SourceName);
|
||||
|
||||
private static async Task Main()
|
||||
{
|
||||
var applicationInsightsConnectionString = Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING") ?? throw new InvalidOperationException("APPLICATIONINSIGHTS_CONNECTION_STRING is not set.");
|
||||
|
||||
var resourceBuilder = ResourceBuilder
|
||||
.CreateDefault()
|
||||
.AddService("WorkflowSample");
|
||||
|
||||
using var traceProvider = Sdk.CreateTracerProviderBuilder()
|
||||
.SetResourceBuilder(resourceBuilder)
|
||||
.AddSource("Microsoft.Agents.AI.Workflows*")
|
||||
.AddSource(SourceName)
|
||||
.AddAzureMonitorTraceExporter(options => options.ConnectionString = applicationInsightsConnectionString)
|
||||
.Build();
|
||||
|
||||
// Start a root activity for the application
|
||||
using var activity = s_activitySource.StartActivity("main");
|
||||
Console.WriteLine($"Operation/Trace ID: {Activity.Current?.TraceId}");
|
||||
|
||||
// Create the executors
|
||||
UppercaseExecutor uppercase = new();
|
||||
ReverseTextExecutor reverse = new();
|
||||
|
||||
// Build the workflow by connecting executors sequentially
|
||||
var workflow = new WorkflowBuilder(uppercase)
|
||||
.AddEdge(uppercase, reverse)
|
||||
.Build();
|
||||
|
||||
// Execute the workflow with input data
|
||||
Run run = await InProcessExecution.RunAsync(workflow, "Hello, World!");
|
||||
foreach (WorkflowEvent evt in run.NewEvents)
|
||||
{
|
||||
if (evt is ExecutorCompletedEvent executorComplete)
|
||||
{
|
||||
Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// First executor: converts input text to uppercase.
|
||||
/// </summary>
|
||||
internal sealed class UppercaseExecutor() : ReflectingExecutor<UppercaseExecutor>("UppercaseExecutor"), IMessageHandler<string, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Processes the input message by converting it to uppercase.
|
||||
/// </summary>
|
||||
/// <param name="message">The input text to convert</param>
|
||||
/// <param name="context">Workflow context for accessing workflow services and adding events</param>
|
||||
/// <returns>The input text converted to uppercase</returns>
|
||||
public async ValueTask<string> HandleAsync(string message, IWorkflowContext context) =>
|
||||
message.ToUpperInvariant(); // The return value will be sent as a message along an edge to subsequent executors
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Second executor: reverses the input text and completes the workflow.
|
||||
/// </summary>
|
||||
internal sealed class ReverseTextExecutor() : ReflectingExecutor<ReverseTextExecutor>("ReverseTextExecutor"), IMessageHandler<string, string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Processes the input message by reversing the text.
|
||||
/// </summary>
|
||||
/// <param name="message">The input text to reverse</param>
|
||||
/// <param name="context">Workflow context for accessing workflow services and adding events</param>
|
||||
/// <returns>The input text reversed</returns>
|
||||
public async ValueTask<string> HandleAsync(string message, IWorkflowContext context) => new string(message.Reverse().ToArray());
|
||||
}
|
||||
Reference in New Issue
Block a user