Skip to content

Commit

Permalink
[Instrumentation.GrpcNetClient] Support only stable HTTP semantic con…
Browse files Browse the repository at this point in the history
…vention (#5259)

Co-authored-by: Reiley Yang <[email protected]>
Co-authored-by: Cijo Thomas <[email protected]>
Co-authored-by: Alan West <[email protected]>
  • Loading branch information
4 people authored Jan 27, 2024
1 parent 512c7dc commit 0b9cf42
Show file tree
Hide file tree
Showing 7 changed files with 16 additions and 261 deletions.
6 changes: 6 additions & 0 deletions src/OpenTelemetry.Instrumentation.GrpcNetClient/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
[issue](https://github.com/open-telemetry/opentelemetry-dotnet/issues/5092)
for details and workaround.
([#5077](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5077))
* Removed support for the `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable
which toggled the use of the new conventions for the
[server, client, and shared network attributes](https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/general/attributes.md#server-client-and-shared-network-attributes).
Now that this suite of attributes are stable, this instrumentation will only
emit the new attributes.
([#5259](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5259))

## 1.6.0-beta.3

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0

using System.Diagnostics;
using Microsoft.Extensions.Configuration;
using static OpenTelemetry.Internal.HttpSemanticConventionHelper;

namespace OpenTelemetry.Instrumentation.GrpcNetClient;

Expand All @@ -12,23 +10,6 @@ namespace OpenTelemetry.Instrumentation.GrpcNetClient;
/// </summary>
public class GrpcClientInstrumentationOptions
{
internal readonly HttpSemanticConvention HttpSemanticConvention;

/// <summary>
/// Initializes a new instance of the <see cref="GrpcClientInstrumentationOptions"/> class.
/// </summary>
public GrpcClientInstrumentationOptions()
: this(new ConfigurationBuilder().AddEnvironmentVariables().Build())
{
}

internal GrpcClientInstrumentationOptions(IConfiguration configuration)
{
Debug.Assert(configuration != null, "configuration was null");

this.HttpSemanticConvention = GetSemanticConventionOptIn(configuration);
}

/// <summary>
/// Gets or sets a value indicating whether down stream instrumentation is suppressed (disabled).
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using OpenTelemetry.Context.Propagation;
using OpenTelemetry.Instrumentation.Http;
using OpenTelemetry.Trace;
using static OpenTelemetry.Internal.HttpSemanticConventionHelper;

namespace OpenTelemetry.Instrumentation.GrpcNetClient.Implementation;

Expand All @@ -27,17 +26,11 @@ internal sealed class GrpcClientDiagnosticListener : ListenerHandler
private static readonly PropertyFetcher<HttpResponseMessage> StopResponseFetcher = new("Response");

private readonly GrpcClientInstrumentationOptions options;
private readonly bool emitOldAttributes;
private readonly bool emitNewAttributes;

public GrpcClientDiagnosticListener(GrpcClientInstrumentationOptions options)
: base("Grpc.Net.Client")
{
this.options = options;

this.emitOldAttributes = this.options.HttpSemanticConvention.HasFlag(HttpSemanticConvention.Old);

this.emitNewAttributes = this.options.HttpSemanticConvention.HasFlag(HttpSemanticConvention.New);
}

public override void OnEventWritten(string name, object payload)
Expand Down Expand Up @@ -133,35 +126,18 @@ public void OnStartActivity(Activity activity, object payload)
}

var uriHostNameType = Uri.CheckHostName(request.RequestUri.Host);
if (this.emitOldAttributes)
{
if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6)
{
activity.SetTag(SemanticConventions.AttributeNetPeerIp, request.RequestUri.Host);
}
else
{
activity.SetTag(SemanticConventions.AttributeNetPeerName, request.RequestUri.Host);
}

activity.SetTag(SemanticConventions.AttributeNetPeerPort, request.RequestUri.Port);
if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6)
{
activity.SetTag(SemanticConventions.AttributeServerSocketAddress, request.RequestUri.Host);
}

// see the spec https://github.com/open-telemetry/semantic-conventions/blob/v1.21.0/docs/http/http-spans.md
if (this.emitNewAttributes)
else
{
if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6)
{
activity.SetTag(SemanticConventions.AttributeServerSocketAddress, request.RequestUri.Host);
}
else
{
activity.SetTag(SemanticConventions.AttributeServerAddress, request.RequestUri.Host);
}

activity.SetTag(SemanticConventions.AttributeServerPort, request.RequestUri.Port);
activity.SetTag(SemanticConventions.AttributeServerAddress, request.RequestUri.Host);
}

activity.SetTag(SemanticConventions.AttributeServerPort, request.RequestUri.Port);

try
{
this.options.EnrichWithHttpRequestMessage?.Invoke(activity, request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
<ItemGroup>
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.Http\HttpRequestMessageContextPropagation.cs" Link="Includes\HttpRequestMessageContextPropagation.cs" />
<Compile Include="$(RepoRoot)\src\Shared\Guard.cs" Link="Includes\Guard.cs" />
<Compile Include="$(RepoRoot)\src\Shared\EnvironmentVariables\*.cs" Link="Includes\EnvironmentVariables\%(Filename).cs" />
<Compile Include="$(RepoRoot)\src\Shared\HttpSemanticConventionHelper.cs" Link="Includes\HttpSemanticConventionHelper.cs" />
<Compile Include="$(RepoRoot)\src\Shared\Options\*.cs" Link="Includes\Options\%(Filename).cs" />
<Compile Include="$(RepoRoot)\src\Shared\Shims\NullableAttributes.cs" Link="Includes\Shims\NullableAttributes.cs" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,10 @@ public static TracerProviderBuilder AddGrpcClientInstrumentation(

name ??= Options.DefaultName;

builder.ConfigureServices(services =>
if (configure != null)
{
if (configure != null)
{
services.Configure(name, configure);
}

services.RegisterOptionsFactory(configuration => new GrpcClientInstrumentationOptions(configuration));
});
builder.ConfigureServices(services => services.Configure(name, configure));
}

builder.AddSource(GrpcClientDiagnosticListener.ActivitySourceName);
builder.AddLegacySource("Grpc.Net.Client.GrpcOut");
Expand Down
198 changes: 0 additions & 198 deletions test/OpenTelemetry.Instrumentation.Grpc.Tests/GrpcTests.client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Grpc.Core;
#endif
using Grpc.Net.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
#if !NETFRAMEWORK
using OpenTelemetry.Context.Propagation;
Expand Down Expand Up @@ -91,213 +90,16 @@ public void GrpcClientCallsAreCollectedSuccessfully(string baseAddress, bool sho

if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6)
{
Assert.Equal(uri.Host, activity.GetTagValue(SemanticConventions.AttributeNetPeerIp));
Assert.Null(activity.GetTagValue(SemanticConventions.AttributeNetPeerName));
}
else
{
Assert.Null(activity.GetTagValue(SemanticConventions.AttributeNetPeerIp));
Assert.Equal(uri.Host, activity.GetTagValue(SemanticConventions.AttributeNetPeerName));
}

Assert.Equal(uri.Port, activity.GetTagValue(SemanticConventions.AttributeNetPeerPort));
Assert.Equal(Status.Unset, activity.GetStatus());

// Tags added by the library then removed from the instrumentation
Assert.Null(activity.GetTagValue(GrpcTagHelper.GrpcMethodTagName));
Assert.Null(activity.GetTagValue(GrpcTagHelper.GrpcStatusCodeTagName));
Assert.Equal(0, activity.GetTagValue(SemanticConventions.AttributeRpcGrpcStatusCode));

if (shouldEnrich)
{
Assert.True(enrichWithHttpRequestMessageCalled);
Assert.True(enrichWithHttpResponseMessageCalled);
}
}

[Theory]
[InlineData("http://localhost")]
[InlineData("http://localhost", false)]
[InlineData("http://127.0.0.1")]
[InlineData("http://127.0.0.1", false)]
[InlineData("http://[::1]")]
[InlineData("http://[::1]", false)]
public void GrpcClientCallsAreCollectedSuccessfully_New(string baseAddress, bool shouldEnrich = true)
{
var config = new KeyValuePair<string, string>[] { new("OTEL_SEMCONV_STABILITY_OPT_IN", "http") };
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(config)
.Build();

bool enrichWithHttpRequestMessageCalled = false;
bool enrichWithHttpResponseMessageCalled = false;

var uri = new Uri($"{baseAddress}:1234");
var uriHostNameType = Uri.CheckHostName(uri.Host);

using var httpClient = ClientTestHelpers.CreateTestClient(async request =>
{
var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply());
var response = ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent, grpcStatusCode: global::Grpc.Core.StatusCode.OK);
response.TrailingHeaders().Add("grpc-message", "value");
return response;
});

var exportedItems = new List<Activity>();

using var parent = new Activity("parent")
.SetIdFormat(ActivityIdFormat.W3C)
.Start();

using (Sdk.CreateTracerProviderBuilder()
.SetSampler(new AlwaysOnSampler())
.ConfigureServices(services => services.AddSingleton<IConfiguration>(configuration))
.AddGrpcClientInstrumentation(options =>
{
if (shouldEnrich)
{
options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => { enrichWithHttpRequestMessageCalled = true; };
options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => { enrichWithHttpResponseMessageCalled = true; };
}
})
.AddInMemoryExporter(exportedItems)
.Build())
{
var channel = GrpcChannel.ForAddress(uri, new GrpcChannelOptions
{
HttpClient = httpClient,
});
var client = new Greeter.GreeterClient(channel);
var rs = client.SayHello(new HelloRequest());
}

Assert.Single(exportedItems);
var activity = exportedItems[0];

ValidateGrpcActivity(activity);
Assert.Equal(parent.TraceId, activity.Context.TraceId);
Assert.Equal(parent.SpanId, activity.ParentSpanId);
Assert.NotEqual(parent.SpanId, activity.Context.SpanId);
Assert.NotEqual(default, activity.Context.SpanId);

Assert.Equal($"greet.Greeter/SayHello", activity.DisplayName);
Assert.Equal("grpc", activity.GetTagValue(SemanticConventions.AttributeRpcSystem));
Assert.Equal("greet.Greeter", activity.GetTagValue(SemanticConventions.AttributeRpcService));
Assert.Equal("SayHello", activity.GetTagValue(SemanticConventions.AttributeRpcMethod));

if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6)
{
Assert.Equal(uri.Host, activity.GetTagValue(SemanticConventions.AttributeServerSocketAddress));
Assert.Null(activity.GetTagValue(SemanticConventions.AttributeServerAddress));
}
else
{
Assert.Null(activity.GetTagValue(SemanticConventions.AttributeServerSocketAddress));
Assert.Equal(uri.Host, activity.GetTagValue(SemanticConventions.AttributeServerAddress));
}

Assert.Equal(uri.Port, activity.GetTagValue(SemanticConventions.AttributeServerPort));
Assert.Equal(Status.Unset, activity.GetStatus());

// Tags added by the library then removed from the instrumentation
Assert.Null(activity.GetTagValue(GrpcTagHelper.GrpcMethodTagName));
Assert.Null(activity.GetTagValue(GrpcTagHelper.GrpcStatusCodeTagName));
Assert.Equal(0, activity.GetTagValue(SemanticConventions.AttributeRpcGrpcStatusCode));

if (shouldEnrich)
{
Assert.True(enrichWithHttpRequestMessageCalled);
Assert.True(enrichWithHttpResponseMessageCalled);
}
}

[Theory]
[InlineData("http://localhost")]
[InlineData("http://localhost", false)]
[InlineData("http://127.0.0.1")]
[InlineData("http://127.0.0.1", false)]
[InlineData("http://[::1]")]
[InlineData("http://[::1]", false)]
public void GrpcClientCallsAreCollectedSuccessfully_Dupe(string baseAddress, bool shouldEnrich = true)
{
var config = new KeyValuePair<string, string>[] { new("OTEL_SEMCONV_STABILITY_OPT_IN", "http/dup") };
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(config)
.Build();

bool enrichWithHttpRequestMessageCalled = false;
bool enrichWithHttpResponseMessageCalled = false;

var uri = new Uri($"{baseAddress}:1234");
var uriHostNameType = Uri.CheckHostName(uri.Host);

using var httpClient = ClientTestHelpers.CreateTestClient(async request =>
{
var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply());
var response = ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent, grpcStatusCode: global::Grpc.Core.StatusCode.OK);
response.TrailingHeaders().Add("grpc-message", "value");
return response;
});

var exportedItems = new List<Activity>();

using var parent = new Activity("parent")
.SetIdFormat(ActivityIdFormat.W3C)
.Start();

using (Sdk.CreateTracerProviderBuilder()
.SetSampler(new AlwaysOnSampler())
.ConfigureServices(services => services.AddSingleton<IConfiguration>(configuration))
.AddGrpcClientInstrumentation(options =>
{
if (shouldEnrich)
{
options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) => { enrichWithHttpRequestMessageCalled = true; };
options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) => { enrichWithHttpResponseMessageCalled = true; };
}
})
.AddInMemoryExporter(exportedItems)
.Build())
{
var channel = GrpcChannel.ForAddress(uri, new GrpcChannelOptions
{
HttpClient = httpClient,
});
var client = new Greeter.GreeterClient(channel);
var rs = client.SayHello(new HelloRequest());
}

Assert.Single(exportedItems);
var activity = exportedItems[0];

ValidateGrpcActivity(activity);
Assert.Equal(parent.TraceId, activity.Context.TraceId);
Assert.Equal(parent.SpanId, activity.ParentSpanId);
Assert.NotEqual(parent.SpanId, activity.Context.SpanId);
Assert.NotEqual(default, activity.Context.SpanId);

Assert.Equal($"greet.Greeter/SayHello", activity.DisplayName);
Assert.Equal("grpc", activity.GetTagValue(SemanticConventions.AttributeRpcSystem));
Assert.Equal("greet.Greeter", activity.GetTagValue(SemanticConventions.AttributeRpcService));
Assert.Equal("SayHello", activity.GetTagValue(SemanticConventions.AttributeRpcMethod));

if (uriHostNameType == UriHostNameType.IPv4 || uriHostNameType == UriHostNameType.IPv6)
{
Assert.Equal(uri.Host, activity.GetTagValue(SemanticConventions.AttributeNetPeerIp));
Assert.Null(activity.GetTagValue(SemanticConventions.AttributeNetPeerName));
Assert.Equal(uri.Host, activity.GetTagValue(SemanticConventions.AttributeServerSocketAddress));
Assert.Null(activity.GetTagValue(SemanticConventions.AttributeServerAddress));
}
else
{
Assert.Null(activity.GetTagValue(SemanticConventions.AttributeNetPeerIp));
Assert.Equal(uri.Host, activity.GetTagValue(SemanticConventions.AttributeNetPeerName));
Assert.Null(activity.GetTagValue(SemanticConventions.AttributeServerSocketAddress));
Assert.Equal(uri.Host, activity.GetTagValue(SemanticConventions.AttributeServerAddress));
}

Assert.Equal(uri.Port, activity.GetTagValue(SemanticConventions.AttributeServerPort));
Assert.Equal(uri.Port, activity.GetTagValue(SemanticConventions.AttributeNetPeerPort));
Assert.Equal(Status.Unset, activity.GetStatus());

// Tags added by the library then removed from the instrumentation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
using OpenTelemetry.Instrumentation.GrpcNetClient;
using OpenTelemetry.Trace;
using Xunit;
using static OpenTelemetry.Internal.HttpSemanticConventionHelper;
using Status = OpenTelemetry.Trace.Status;

namespace OpenTelemetry.Instrumentation.Grpc.Tests;
Expand Down Expand Up @@ -43,7 +42,6 @@ public void GrpcAspNetCoreInstrumentationAddsCorrectAttributes(string enableGrpc
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string>
{
[SemanticConventionOptInKeyName] = "http",
["OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_ENABLE_GRPC_INSTRUMENTATION"] = enableGrpcAspNetCoreSupport,
})
.Build();
Expand Down Expand Up @@ -116,7 +114,6 @@ public void GrpcAspNetCoreInstrumentationAddsCorrectAttributesWhenItCreatesNewAc
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string>
{
[SemanticConventionOptInKeyName] = "http",
["OTEL_DOTNET_EXPERIMENTAL_ASPNETCORE_ENABLE_GRPC_INSTRUMENTATION"] = enableGrpcAspNetCoreSupport,
})
.Build();
Expand Down

0 comments on commit 0b9cf42

Please sign in to comment.