-
Notifications
You must be signed in to change notification settings - Fork 607
Adding proper OpenTelemetry integration via. registration helpers and better context propagation #1528
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
Adding proper OpenTelemetry integration via. registration helpers and better context propagation #1528
Changes from 8 commits
7607be6
ed4cf97
e2634d6
83e088f
7c18241
d9a7ff6
50ad871
4da85c8
904cfc9
7b937ab
64e7dc0
582bd5c
c3f2168
58fab44
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# RabbitMQ .NET Client - OpenTelemetry Instrumentation | ||
|
||
## Introduction | ||
This library makes it easy to instrument your RabbitMQ .NET Client applications with OpenTelemetry. | ||
|
||
## Examples | ||
The following examples demonstrate how to use the RabbitMQ .NET Client OpenTelemetry Instrumentation. | ||
|
||
### Basic Usage | ||
|
||
#### ASP.NET Core Configuration Example | ||
```csharp | ||
using OpenTelemetry.Trace; | ||
|
||
// Configure the OpenTelemetry SDK to trace ASP.NET Core, the RabbitMQ .NET Client and export the traces to the console. | ||
// Also configures context propagation to propagate the TraceContext and Baggage using the W3C specification. | ||
|
||
var compositeTextMapPropagator = new CompositeTextMapPropagator(new TextMapPropagator[] | ||
{ | ||
new TraceContextPropagator(), | ||
new BaggagePropagator() | ||
}); | ||
|
||
Sdk.SetDefaultTextMapPropagator(compositeTextMapPropagator); | ||
|
||
builder.Services.AddOpenTelemetry() | ||
.ConfigureResource(resource => resource | ||
.AddService(serviceName: builder.Environment.ApplicationName)) | ||
.WithTracing(tracing => tracing | ||
.AddAspNetCoreInstrumentation() | ||
.AddRabbitMQInstrumentation() | ||
.AddConsoleExporter()); | ||
``` | ||
|
||
#### Console Application Configuration Example | ||
```csharp | ||
using OpenTelemetry.Trace; | ||
|
||
// Configure the OpenTelemetry SDK to trace ASP.NET Core, the RabbitMQ .NET Client and export the traces to the console. | ||
// Also configures context propagation to propagate the TraceContext and Baggage using the W3C specification. | ||
|
||
var compositeTextMapPropagator = new CompositeTextMapPropagator(new TextMapPropagator[] | ||
{ | ||
new TraceContextPropagator(), | ||
new BaggagePropagator() | ||
}); | ||
|
||
Sdk.SetDefaultTextMapPropagator(compositeTextMapPropagator); | ||
|
||
var tracerProvider = Sdk.CreateTracerProviderBuilder() | ||
.AddRabbitMQInstrumentation() | ||
.AddConsoleExporter() | ||
.Build(); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks> | ||
<NoWarn>$(NoWarn);CS1591</NoWarn> | ||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
<AssemblyTitle>RabbitMQ OpenTelemetry Integration Package for .NET</AssemblyTitle> | ||
<Authors>VMware</Authors> | ||
<Company>VMware, Inc. or its affiliates.</Company> | ||
<Copyright>Copyright © 2007-2023 VMware, Inc. or its affiliates.</Copyright> | ||
<Description>The RabbitMQ OAuth2 Client Library for .NET enables OAuth2 token refresh for RabbitMQ.Client</Description> | ||
lukebakken marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<GenerateDocumentationFile>true</GenerateDocumentationFile> | ||
<PackageIcon>icon.png</PackageIcon> | ||
<PackageLicenseExpression>Apache-2.0 OR MPL-2.0</PackageLicenseExpression> | ||
<PackageProjectUrl>https://www.rabbitmq.com/dotnet.html</PackageProjectUrl> | ||
<PackageTags>rabbitmq, amqp, oauth2</PackageTags> | ||
<Product>RabbitMQ</Product> | ||
<PublishRepositoryUrl>true</PublishRepositoryUrl> | ||
<RepositoryUrl>https://github.com/rabbitmq/rabbitmq-dotnet-client.git</RepositoryUrl> | ||
<IncludeSymbols>true</IncludeSymbols> | ||
<SymbolPackageFormat>snupkg</SymbolPackageFormat> | ||
<AssemblyOriginatorKeyFile>../rabbit.snk</AssemblyOriginatorKeyFile> | ||
<SignAssembly>true</SignAssembly> | ||
<MinVerTagPrefix>otel-</MinVerTagPrefix> | ||
<MinVerVerbosity>minimal</MinVerVerbosity> | ||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||
<PackageOutputPath>../../packages</PackageOutputPath> | ||
<PackageReadmeFile>README.md</PackageReadmeFile> | ||
<LangVersion>7.3</LangVersion> | ||
lukebakken marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</PropertyGroup> | ||
|
||
<PropertyGroup Condition="'$(Configuration)' == 'Release' And '$(CI)' == 'true'"> | ||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild> | ||
<Deterministic>true</Deterministic> | ||
<EmbedUntrackedSources>true</EmbedUntrackedSources> | ||
</PropertyGroup> | ||
|
||
<ItemGroup Condition="'$(Configuration)' == 'Release' and '$(SourceRoot)' == ''"> | ||
<SourceRoot Include="$(MSBuildThisFileDirectory)/" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Remove="icon.png" /> | ||
<Content Include="icon.png" PackagePath="" /> | ||
<None Include="README.md" Pack="true" PackagePath="/" /> | ||
<InternalsVisibleTo Include="Unit" /> | ||
<InternalsVisibleTo Include="Benchmarks" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4" PrivateAssets="all" /> | ||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="all" /> | ||
<PackageReference Include="MinVer" Version="5.0.0" PrivateAssets="all" /> | ||
<PackageReference Include="OpenTelemetry.Api" Version="1.7.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup Condition="$(TargetFramework) == 'netstandard2.0'"> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="../RabbitMQ.Client/RabbitMQ.Client.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Text; | ||
using OpenTelemetry.Context.Propagation; | ||
using RabbitMQ.Client; | ||
|
||
namespace OpenTelemetry.Trace | ||
{ | ||
public static class OpenTelemetryExtensions | ||
{ | ||
public static TracerProviderBuilder AddRabbitMQInstrumentation(this TracerProviderBuilder builder) | ||
{ | ||
RabbitMQActivitySource.UseRoutingKeyAsOperationName = true; | ||
RabbitMQActivitySource.ContextExtractor = OpenTelemetryContextExtractor; | ||
RabbitMQActivitySource.ContextInjector = OpenTelemetryContextInjector; | ||
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why we need this part? Can it be set by default in main package? I would expect that this method will only call Alternative options is to have here the second method: public static TracerProviderBuilder AddRabbitMQInstrumentation(this TracerProviderBuilder builder, Action<RabbitMQSpecificOptions>? configure); where you can configure other methods externally. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OpenTelemetryContextInjector is OTel specific for Baggage handling, that's pretty much the only reason for the package, because we don't want to pull OpenTelemetry.API dependencies into the main library. |
||
builder.AddSource("RabbitMQ.Client.*"); | ||
return builder; | ||
} | ||
|
||
private static ActivityContext OpenTelemetryContextExtractor(IReadOnlyBasicProperties props) | ||
{ | ||
// Extract the PropagationContext of the upstream parent from the message headers. | ||
var parentContext = Propagators.DefaultTextMapPropagator.Extract(default, props.Headers, OpenTelemetryContextGetter); | ||
Baggage.Current = parentContext.Baggage; | ||
return parentContext.ActivityContext; | ||
} | ||
|
||
private static IEnumerable<string> OpenTelemetryContextGetter(IDictionary<string, object> carrier, string key) | ||
{ | ||
try | ||
{ | ||
if (carrier.TryGetValue(key, out object value) && value is byte[] bytes) | ||
{ | ||
return new[] { Encoding.UTF8.GetString(bytes) }; | ||
} | ||
} | ||
catch (Exception) | ||
{ | ||
//this.logger.LogError(ex, "Failed to extract trace context."); | ||
} | ||
|
||
return Enumerable.Empty<string>(); | ||
} | ||
|
||
private static void OpenTelemetryContextInjector(Activity activity, IDictionary<string, object> props) | ||
{ | ||
// Inject the current Activity's context into the message headers. | ||
Propagators.DefaultTextMapPropagator.Inject(new PropagationContext(activity.Context, Baggage.Current), props, OpenTelemetryContextSetter); | ||
} | ||
|
||
private static void OpenTelemetryContextSetter(IDictionary<string, object> carrier, string key, string value) | ||
{ | ||
carrier[key] = Encoding.UTF8.GetBytes(value); | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.