Skip to content

adding sample for tracing custom attributes #51020

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions sdk/ai/Azure.AI.Projects/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ See [full set of Agents samples](https://github.com/Azure/azure-sdk-for-net/tree
- [Connections operations](#connections-operations)
- [Dataset operations](#dataset-operations)
- [Indexes operations](#indexes-operations)
- [Tracing](#tracing)
- [Adding custom attributes](#adding-custom-attributes)
- [Troubleshooting](#troubleshooting)
- [Next steps](#next-steps)
- [Contributing](#contributing)
Expand Down Expand Up @@ -360,6 +362,48 @@ Console.WriteLine("Delete the Index version created above:");
indexesClient.Delete(name: indexName, version: indexVersion);
```

## Tracing

### Adding custom attributes

You can enhance telemetry data by adding custom attributes to activities through implementing a custom processor. This allows you to enrich trace data with application-specific context.

The following example demonstrates how to create a custom processor that:
- Adds a `custom.session_id` attribute to all activities
- Adds `custom.operation_type` and `custom.priority` attributes specifically to 'GetWeather' activities:
```C# Snippet:AI_Projects_TelemetryCustomAttributeProcessor
// Custom processor that adds attributes to spans
public class CustomAttributeProcessor : BaseProcessor<Activity>
{
public override void OnStart(Activity activity)
{
// Add custom attributes to all spans
activity.SetTag("custom.session_id", "session_123");

// Add specific attributes based on span name
if (activity.DisplayName == "GetWeather")
{
activity.SetTag("custom.operation_type", "weather_query");
activity.SetTag("custom.priority", "normal");
}

base.OnStart(activity);
}
}
```

Configure the processor into use like so:
```C# Snippet:AI_Projects_TelemetryAddCustomAttributeProcessor
// Setup tracing to console with custom processor
var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("SimpleTracingSample")
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService("WeatherApp", "1.0.0"))
.AddProcessor(new CustomAttributeProcessor())
.AddConsoleExporter()
.Build();
```

## Troubleshooting

Any operation that fails will throw a [RequestFailedException][RequestFailedException]. The exception's `code` will hold the HTTP response status code. The exception's `message` contains a detailed message that may be helpful in diagnosing the issue:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Azure.AI.Agents.Persistent" VersionOverride="1.0.0"/>
<PackageReference Include="Azure.AI.Agents.Persistent" VersionOverride="1.0.0" />
<PackageReference Include="Azure.AI.OpenAI" VersionOverride="2.2.0-beta.4" />
<PackageReference Include="Azure.AI.Inference" />
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" />
<PackageReference Include="NUnit" />
<PackageReference Include="NUnit3TestAdapter" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Moq" />
<PackageReference Include="Azure.ResourceManager" />
<PackageReference Include="Azure.ResourceManager.CognitiveServices" />
<PackageReference Include="OpenTelemetry.Exporter.Console" />
<PackageReference Include="System.Linq.Async" />
<PackageReference Include="System.Text.Json" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#nullable disable

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core.TestFramework;
using Azure.Monitor.OpenTelemetry.Exporter;
using NUnit.Framework;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

namespace Azure.AI.Projects.Tests
{
public partial class Sample_Telemetry_CustomAttributes : SamplesBase<AIProjectsTestEnvironment>
{
#region Snippet:AI_Projects_TelemetryCustomAttributeProcessor
// Custom processor that adds attributes to spans
public class CustomAttributeProcessor : BaseProcessor<Activity>
{
public override void OnStart(Activity activity)
{
// Add custom attributes to all spans
activity.SetTag("custom.session_id", "session_123");

// Add specific attributes based on span name
if (activity.DisplayName == "GetWeather")
{
activity.SetTag("custom.operation_type", "weather_query");
activity.SetTag("custom.priority", "normal");
}

base.OnStart(activity);
}
}
#endregion

public class WeatherService
{
private static readonly ActivitySource ActivitySource = new("SimpleTracingSample");

public async Task<string> GetWeatherAsync(string location)
{
using var activity = ActivitySource.StartActivity("GetWeather");
activity?.SetTag("weather.location", location);

// Simulate some work
await Task.Delay(100);

var result = "It is sunny";
activity?.SetTag("weather.result", result);

return result;
}

public string GetWeather(string location)
{
using var activity = ActivitySource.StartActivity("GetWeather");
activity?.SetTag("weather.location", location);

var result = "It is sunny";
activity?.SetTag("weather.result", result);

return result;
}
}

[Test]
[AsyncOnly]
public async Task TracingCustomAttributesExample()
{
#region Snippet:AI_Projects_TelemetryAddCustomAttributeProcessor
// Setup tracing to console with custom processor
var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("SimpleTracingSample")
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService("WeatherApp", "1.0.0"))
.AddProcessor(new CustomAttributeProcessor())
.AddConsoleExporter()
.Build();
#endregion

var weatherService = new WeatherService();

Console.WriteLine("Calling async GetWeatherAsync...");
var asyncResult = await weatherService.GetWeatherAsync("Portland");
Console.WriteLine($"Result: {asyncResult}\n");

// Cleanup
tracerProvider?.Dispose();
}

[Test]
[SyncOnly]
public void TracingCustomAttributesExampleSync()
{
// Setup tracing to console with custom processor
var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("SimpleTracingSample")
.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService("WeatherApp", "1.0.0"))
.AddProcessor(new CustomAttributeProcessor())
.AddConsoleExporter()
.Build();

var weatherService = new WeatherService();

// Test sync version
Console.WriteLine("Calling sync GetWeather...");
var syncResult = weatherService.GetWeather("Seattle");
Console.WriteLine($"Result: {syncResult}\n");

// Cleanup
tracerProvider?.Dispose();
Console.WriteLine("Check console output above for spans with custom attributes!");
}
}
}