Skip to content

Commit

Permalink
Opentracing shim noop cases (#4668)
Browse files Browse the repository at this point in the history
  • Loading branch information
pjanotti authored Jul 21, 2023
1 parent 358a1cd commit d016bb1
Show file tree
Hide file tree
Showing 10 changed files with 217 additions and 61 deletions.
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

* Fix: Do not raise `ArgumentException` if `Activity` behind the shim span
has an invalid context.
([#2787](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2787))

## 1.5.0-beta.1

Released 2023-Jun-05
Expand Down
5 changes: 0 additions & 5 deletions src/OpenTelemetry.Shims.OpenTracing/SpanContextShim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ internal sealed class SpanContextShim : ISpanContext
{
public SpanContextShim(in Trace.SpanContext spanContext)
{
if (!spanContext.IsValid)
{
throw new ArgumentException($"Invalid '{nameof(Trace.SpanContext)}'", nameof(spanContext));
}

this.SpanContext = spanContext;
}

Expand Down
6 changes: 1 addition & 5 deletions src/OpenTelemetry.Shims.OpenTracing/SpanShim.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,11 @@ public SpanShim(TelemetrySpan span)
{
Guard.ThrowIfNull(span);

if (!span.Context.IsValid)
{
throw new ArgumentException($"Invalid '{nameof(SpanContext)}'", nameof(span.Context));
}

this.Span = span;
this.spanContextShim = new SpanContextShim(this.Span.Context);
}

/// <inheritdoc/>
public ISpanContext Context => this.spanContextShim;

public TelemetrySpan Span { get; private set; }
Expand Down
149 changes: 149 additions & 0 deletions test/OpenTelemetry.Shims.OpenTracing.Tests/IntegrationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// <copyright file="IntegrationTests.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 System.Diagnostics;
using OpenTelemetry.Context.Propagation;
using OpenTelemetry.Trace;
using OpenTracing;
using Xunit;

namespace OpenTelemetry.Shims.OpenTracing.Tests
{
public class IntegrationTests
{
private const string ChildActivitySource = "ChildActivitySource";
private const string ParentActivitySource = "ParentActivitySource";
private const string ShimTracerName = "OpenTracing.Shim";

[Theory]
[InlineData(SamplingDecision.Drop, SamplingDecision.Drop, SamplingDecision.Drop)]
[InlineData(SamplingDecision.Drop, SamplingDecision.RecordAndSample, SamplingDecision.Drop)]
[InlineData(SamplingDecision.Drop, SamplingDecision.RecordOnly, SamplingDecision.Drop)]
[InlineData(SamplingDecision.RecordOnly, SamplingDecision.RecordAndSample, SamplingDecision.RecordOnly)]
[InlineData(SamplingDecision.RecordAndSample, SamplingDecision.RecordOnly, SamplingDecision.RecordAndSample)]
[InlineData(SamplingDecision.RecordAndSample, SamplingDecision.Drop, SamplingDecision.RecordAndSample)]
public void WithActivities(
SamplingDecision parentActivitySamplingDecision,
SamplingDecision shimSamplingDecision,
SamplingDecision childActivitySamplingDecision)
{
var exportedSpans = new List<Activity>();

const string ParentActivityName = "ParentActivity";
const string ShimActivityName = "ShimActivity";
const string ChildActivityName = "ChildActivity";

var testSampler = new TestSampler((samplingParameters) =>
samplingParameters.Name switch
{
ParentActivityName => parentActivitySamplingDecision,
ShimActivityName => shimSamplingDecision,
ChildActivityName => childActivitySamplingDecision,
_ => SamplingDecision.Drop,
});

using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddInMemoryExporter(exportedSpans)
.SetSampler(testSampler)
.When(
parentActivitySamplingDecision == SamplingDecision.RecordAndSample,
b => b.AddSource(ParentActivitySource))
.When(
shimSamplingDecision == SamplingDecision.RecordAndSample,
b => b.AddSource(ShimTracerName))
.When(
childActivitySamplingDecision == SamplingDecision.RecordAndSample,
b => b.AddSource(ChildActivitySource))
.Build();

ITracer otTracer = new TracerShim(
tracerProvider.GetTracer(ShimTracerName),
Propagators.DefaultTextMapPropagator);

// Real usage requires a call OpenTracing.Util.GlobalTracer.Register(otTracer),
// however, that can only happen once per process, we don't do it here so we
// can run multiple tests in the same process.

using var parentActivitySource = new ActivitySource(ParentActivitySource);
using var childActivitySource = new ActivitySource(ChildActivitySource);

using (var parentActivity = parentActivitySource.StartActivity(ParentActivityName))
{
using (IScope parentScope = otTracer.BuildSpan(ShimActivityName).StartActive())
{
parentScope.Span.SetTag("parent", true);

using var childActivity = childActivitySource.StartActivity(ChildActivityName);
}
}

var expectedExportedSpans = new string[]
{
childActivitySamplingDecision == SamplingDecision.RecordAndSample ? ChildActivityName : null,
shimSamplingDecision == SamplingDecision.RecordAndSample ? ShimActivityName : null,
parentActivitySamplingDecision == SamplingDecision.RecordAndSample ? ParentActivityName : null,
}
.Where(s => s is not null)
.ToList();

for (int i = 0; i < expectedExportedSpans.Count; i++)
{
Assert.Equal(expectedExportedSpans[i], exportedSpans[i].DisplayName);
}

if (childActivitySamplingDecision == SamplingDecision.RecordAndSample)
{
if (shimSamplingDecision == SamplingDecision.RecordAndSample)
{
Assert.Same(exportedSpans[1], exportedSpans[0].Parent);
}
}
}

private class TestSampler : Sampler
{
private readonly Func<SamplingParameters, SamplingDecision> shouldSampleDelegate;

public TestSampler(Func<SamplingParameters, SamplingDecision> shouldSampleDelegate)
{
this.shouldSampleDelegate = shouldSampleDelegate;
}

public override SamplingResult ShouldSample(in SamplingParameters samplingParameters)
{
return new SamplingResult(this.shouldSampleDelegate(samplingParameters));
}
}
}

[System.Diagnostics.CodeAnalysis.SuppressMessage(
"StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Local use only")]
internal static class ConditionalTracerProviderBuilderExtension
{
public static TracerProviderBuilder When(
this TracerProviderBuilder builder,
bool condition,
Func<TracerProviderBuilder, TracerProviderBuilder> conditionalDelegate)
{
if (condition)
{
builder = conditionalDelegate(builder);
}

return builder;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// <copyright file="ListenAndSampleAllActivitySources.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 System.Diagnostics;
using Xunit;

namespace OpenTelemetry.Shims.OpenTracing.Tests
{
[CollectionDefinition(nameof(ListenAndSampleAllActivitySources))]
public sealed class ListenAndSampleAllActivitySources : ICollectionFixture<ListenAndSampleAllActivitySources.Fixture>
{
public sealed class Fixture : IDisposable
{
private readonly ActivityListener listener;

public Fixture()
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
Activity.ForceDefaultIdFormat = true;

this.listener = new ActivityListener
{
ShouldListenTo = _ => true,
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
};

ActivitySource.AddActivityListener(this.listener);
}

public void Dispose()
{
this.listener.Dispose();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<Description>Unit test project for OpenTelemetry.Shims.OpenTracing</Description>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>

<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<!-- this is temporary. will remove in future PR. -->
<Nullable>disable</Nullable>
</PropertyGroup>
Expand All @@ -19,6 +19,8 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Shims.OpenTracing\OpenTelemetry.Shims.OpenTracing.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,12 @@

namespace OpenTelemetry.Shims.OpenTracing.Tests
{
[Collection(nameof(ListenAndSampleAllActivitySources))]
public class ScopeManagerShimTests
{
private const string SpanName = "MySpanName/1";
private const string TracerName = "defaultactivitysource";

static ScopeManagerShimTests()
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
Activity.ForceDefaultIdFormat = true;

var listener = new ActivityListener
{
ShouldListenTo = _ => true,
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
};

ActivitySource.AddActivityListener(listener);
}

[Fact]
public void CtorArgumentValidation()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,13 @@

namespace OpenTelemetry.Shims.OpenTracing.Tests
{
[Collection(nameof(ListenAndSampleAllActivitySources))]
public class SpanBuilderShimTests
{
private const string SpanName1 = "MySpanName/1";
private const string SpanName2 = "MySpanName/2";
private const string TracerName = "defaultactivitysource";

static SpanBuilderShimTests()
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
Activity.ForceDefaultIdFormat = true;

var listener = new ActivityListener
{
ShouldListenTo = _ => true,
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
};

ActivitySource.AddActivityListener(listener);
}

[Fact]
public void CtorArgumentValidation()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,6 @@ namespace OpenTelemetry.Shims.OpenTracing.Tests
{
public class SpanContextShimTests
{
[Fact]
public void CtorArgumentValidation()
{
Assert.Throws<ArgumentException>(() => new SpanContextShim(default));
Assert.Throws<ArgumentException>(() => new SpanContextShim(new SpanContext(default, default, ActivityTraceFlags.None)));
}

[Fact]
public void GetTraceId()
{
Expand Down
24 changes: 9 additions & 15 deletions test/OpenTelemetry.Shims.OpenTracing.Tests/SpanShimTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,18 @@
// limitations under the License.
// </copyright>

using System.Diagnostics;
using OpenTelemetry.Trace;
using OpenTracing.Tag;
using Xunit;

namespace OpenTelemetry.Shims.OpenTracing.Tests
{
[Collection(nameof(ListenAndSampleAllActivitySources))]
public class SpanShimTests
{
private const string SpanName = "MySpanName/1";
private const string TracerName = "defaultactivitysource";

static SpanShimTests()
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
Activity.ForceDefaultIdFormat = true;

var listener = new ActivityListener
{
ShouldListenTo = _ => true,
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
};

ActivitySource.AddActivityListener(listener);
}

[Fact]
public void CtorArgumentValidation()
{
Expand Down Expand Up @@ -73,6 +59,14 @@ public void FinishSpanUsingSpecificTimestamp()
var tracer = TracerProvider.Default.GetTracer(TracerName);
var shim = new SpanShim(tracer.StartSpan(SpanName));

#if NETFRAMEWORK
// Under the hood the Activity start time uses DateTime.UtcNow, which
// doesn't have the same precision as DateTimeOffset.UtcNow on the .NET Framework.
// Add a sleep big enough to ensure that the test doesn't break due to the
// low resolution of DateTime.UtcNow on the .NET Framework.
Thread.Sleep(TimeSpan.FromMilliseconds(20));
#endif

var endTime = DateTimeOffset.UtcNow;
shim.Finish(endTime);

Expand Down

0 comments on commit d016bb1

Please sign in to comment.