Add Support for HttpSemanticConvention breaking changes. (#4504)

This commit is contained in:
Timothy Mothra 2023-05-23 18:19:28 -07:00 committed by GitHub
parent f4f4469f21
commit 47d88e17a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 138 additions and 0 deletions

View File

@ -0,0 +1,66 @@
// <copyright file="HttpSemanticConventionHelper.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace OpenTelemetry.Internal;
/// <summary>
/// Helper class for Http Semantic Conventions.
/// </summary>
/// <remarks>
/// Due to a breaking change in the semantic convention, affected instrumentation libraries
/// must inspect an environment variable to determine which attributes to emit.
/// This is expected to be removed when the instrumentation libraries reach Stable.
/// <see href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md"/>.
/// </remarks>
internal static class HttpSemanticConventionHelper
{
[Flags]
internal enum HttpSemanticConvention
{
/// <summary>
/// Instructs an instrumentation library to emit the old experimental HTTP attributes.
/// </summary>
Old = 0x1,
/// <summary>
/// Instructs an instrumentation library to emit the new, stable Http attributes.
/// </summary>
New = 0x2,
/// <summary>
/// Instructs an instrumentation library to emit both the old and new attributes.
/// </summary>
Dupe = Old | New,
}
public static HttpSemanticConvention GetSemanticConventionOptIn()
{
try
{
var envVarValue = Environment.GetEnvironmentVariable("OTEL_SEMCONV_STABILITY_OPT_IN");
return envVarValue?.ToLowerInvariant() switch
{
"http" => HttpSemanticConvention.New,
"http/dup" => HttpSemanticConvention.Dupe,
_ => HttpSemanticConvention.Old,
};
}
catch
{
return HttpSemanticConvention.Old;
}
}
}

View File

@ -29,6 +29,7 @@ using OpenTelemetry.Instrumentation.GrpcNetClient;
#endif
using OpenTelemetry.Internal;
using OpenTelemetry.Trace;
using static OpenTelemetry.Internal.HttpSemanticConventionHelper;
namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation
{
@ -62,6 +63,7 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation
#endif
private readonly PropertyFetcher<Exception> stopExceptionFetcher = new("Exception");
private readonly AspNetCoreInstrumentationOptions options;
private readonly HttpSemanticConvention httpSemanticConvention;
public HttpInListener(AspNetCoreInstrumentationOptions options)
: base(DiagnosticSourceName)
@ -69,6 +71,8 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Implementation
Guard.ThrowIfNull(options);
this.options = options;
this.httpSemanticConvention = GetSemanticConventionOptIn();
}
public override void OnEventWritten(string name, object payload)

View File

@ -14,6 +14,7 @@
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.GrpcNetClient\GrpcTagHelper.cs" Link="Includes\GrpcTagHelper.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.GrpcNetClient\StatusCanonicalCode.cs" Link="Includes\StatusCanonicalCode.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" Link="Includes\Guard.cs" />
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\HttpSemanticConventionHelper.cs" Link="Includes\HttpSemanticConventionHelper.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -0,0 +1,67 @@
// <copyright file="HttpSemanticConventionHelperTest.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Xunit;
using static OpenTelemetry.Internal.HttpSemanticConventionHelper;
namespace OpenTelemetry.Api.Tests.Internal;
public class HttpSemanticConventionHelperTest
{
[Fact]
public void VerifyFlags()
{
var testValue = HttpSemanticConvention.Dupe;
Assert.True(testValue.HasFlag(HttpSemanticConvention.Old));
Assert.True(testValue.HasFlag(HttpSemanticConvention.New));
testValue = HttpSemanticConvention.Old;
Assert.True(testValue.HasFlag(HttpSemanticConvention.Old));
Assert.False(testValue.HasFlag(HttpSemanticConvention.New));
testValue = HttpSemanticConvention.New;
Assert.False(testValue.HasFlag(HttpSemanticConvention.Old));
Assert.True(testValue.HasFlag(HttpSemanticConvention.New));
}
[Fact]
public void VerifyGetSemanticConventionOptIn()
{
this.RunTestWithEnvironmentVariable(null, HttpSemanticConvention.Old);
this.RunTestWithEnvironmentVariable(string.Empty, HttpSemanticConvention.Old);
this.RunTestWithEnvironmentVariable("junk", HttpSemanticConvention.Old);
this.RunTestWithEnvironmentVariable("none", HttpSemanticConvention.Old);
this.RunTestWithEnvironmentVariable("NONE", HttpSemanticConvention.Old);
this.RunTestWithEnvironmentVariable("http", HttpSemanticConvention.New);
this.RunTestWithEnvironmentVariable("HTTP", HttpSemanticConvention.New);
this.RunTestWithEnvironmentVariable("http/dup", HttpSemanticConvention.Dupe);
this.RunTestWithEnvironmentVariable("HTTP/DUP", HttpSemanticConvention.Dupe);
}
private void RunTestWithEnvironmentVariable(string value, HttpSemanticConvention expected)
{
try
{
Environment.SetEnvironmentVariable("OTEL_SEMCONV_STABILITY_OPT_IN", value);
Assert.Equal(expected, GetSemanticConventionOptIn());
}
finally
{
Environment.SetEnvironmentVariable("OTEL_SEMCONV_STABILITY_OPT_IN", null);
}
}
}