Skip to content

Commit d016bb1

Browse files
authored
Opentracing shim noop cases (#4668)
1 parent 358a1cd commit d016bb1

File tree

10 files changed

+217
-61
lines changed

10 files changed

+217
-61
lines changed

src/OpenTelemetry.Shims.OpenTracing/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
* Fix: Do not raise `ArgumentException` if `Activity` behind the shim span
6+
has an invalid context.
7+
([#2787](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2787))
8+
59
## 1.5.0-beta.1
610

711
Released 2023-Jun-05

src/OpenTelemetry.Shims.OpenTracing/SpanContextShim.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@ internal sealed class SpanContextShim : ISpanContext
2222
{
2323
public SpanContextShim(in Trace.SpanContext spanContext)
2424
{
25-
if (!spanContext.IsValid)
26-
{
27-
throw new ArgumentException($"Invalid '{nameof(Trace.SpanContext)}'", nameof(spanContext));
28-
}
29-
3025
this.SpanContext = spanContext;
3126
}
3227

src/OpenTelemetry.Shims.OpenTracing/SpanShim.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,11 @@ public SpanShim(TelemetrySpan span)
4545
{
4646
Guard.ThrowIfNull(span);
4747

48-
if (!span.Context.IsValid)
49-
{
50-
throw new ArgumentException($"Invalid '{nameof(SpanContext)}'", nameof(span.Context));
51-
}
52-
5348
this.Span = span;
5449
this.spanContextShim = new SpanContextShim(this.Span.Context);
5550
}
5651

52+
/// <inheritdoc/>
5753
public ISpanContext Context => this.spanContextShim;
5854

5955
public TelemetrySpan Span { get; private set; }
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// <copyright file="IntegrationTests.cs" company="OpenTelemetry Authors">
2+
// Copyright The OpenTelemetry Authors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// </copyright>
16+
17+
using System.Diagnostics;
18+
using OpenTelemetry.Context.Propagation;
19+
using OpenTelemetry.Trace;
20+
using OpenTracing;
21+
using Xunit;
22+
23+
namespace OpenTelemetry.Shims.OpenTracing.Tests
24+
{
25+
public class IntegrationTests
26+
{
27+
private const string ChildActivitySource = "ChildActivitySource";
28+
private const string ParentActivitySource = "ParentActivitySource";
29+
private const string ShimTracerName = "OpenTracing.Shim";
30+
31+
[Theory]
32+
[InlineData(SamplingDecision.Drop, SamplingDecision.Drop, SamplingDecision.Drop)]
33+
[InlineData(SamplingDecision.Drop, SamplingDecision.RecordAndSample, SamplingDecision.Drop)]
34+
[InlineData(SamplingDecision.Drop, SamplingDecision.RecordOnly, SamplingDecision.Drop)]
35+
[InlineData(SamplingDecision.RecordOnly, SamplingDecision.RecordAndSample, SamplingDecision.RecordOnly)]
36+
[InlineData(SamplingDecision.RecordAndSample, SamplingDecision.RecordOnly, SamplingDecision.RecordAndSample)]
37+
[InlineData(SamplingDecision.RecordAndSample, SamplingDecision.Drop, SamplingDecision.RecordAndSample)]
38+
public void WithActivities(
39+
SamplingDecision parentActivitySamplingDecision,
40+
SamplingDecision shimSamplingDecision,
41+
SamplingDecision childActivitySamplingDecision)
42+
{
43+
var exportedSpans = new List<Activity>();
44+
45+
const string ParentActivityName = "ParentActivity";
46+
const string ShimActivityName = "ShimActivity";
47+
const string ChildActivityName = "ChildActivity";
48+
49+
var testSampler = new TestSampler((samplingParameters) =>
50+
samplingParameters.Name switch
51+
{
52+
ParentActivityName => parentActivitySamplingDecision,
53+
ShimActivityName => shimSamplingDecision,
54+
ChildActivityName => childActivitySamplingDecision,
55+
_ => SamplingDecision.Drop,
56+
});
57+
58+
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
59+
.AddInMemoryExporter(exportedSpans)
60+
.SetSampler(testSampler)
61+
.When(
62+
parentActivitySamplingDecision == SamplingDecision.RecordAndSample,
63+
b => b.AddSource(ParentActivitySource))
64+
.When(
65+
shimSamplingDecision == SamplingDecision.RecordAndSample,
66+
b => b.AddSource(ShimTracerName))
67+
.When(
68+
childActivitySamplingDecision == SamplingDecision.RecordAndSample,
69+
b => b.AddSource(ChildActivitySource))
70+
.Build();
71+
72+
ITracer otTracer = new TracerShim(
73+
tracerProvider.GetTracer(ShimTracerName),
74+
Propagators.DefaultTextMapPropagator);
75+
76+
// Real usage requires a call OpenTracing.Util.GlobalTracer.Register(otTracer),
77+
// however, that can only happen once per process, we don't do it here so we
78+
// can run multiple tests in the same process.
79+
80+
using var parentActivitySource = new ActivitySource(ParentActivitySource);
81+
using var childActivitySource = new ActivitySource(ChildActivitySource);
82+
83+
using (var parentActivity = parentActivitySource.StartActivity(ParentActivityName))
84+
{
85+
using (IScope parentScope = otTracer.BuildSpan(ShimActivityName).StartActive())
86+
{
87+
parentScope.Span.SetTag("parent", true);
88+
89+
using var childActivity = childActivitySource.StartActivity(ChildActivityName);
90+
}
91+
}
92+
93+
var expectedExportedSpans = new string[]
94+
{
95+
childActivitySamplingDecision == SamplingDecision.RecordAndSample ? ChildActivityName : null,
96+
shimSamplingDecision == SamplingDecision.RecordAndSample ? ShimActivityName : null,
97+
parentActivitySamplingDecision == SamplingDecision.RecordAndSample ? ParentActivityName : null,
98+
}
99+
.Where(s => s is not null)
100+
.ToList();
101+
102+
for (int i = 0; i < expectedExportedSpans.Count; i++)
103+
{
104+
Assert.Equal(expectedExportedSpans[i], exportedSpans[i].DisplayName);
105+
}
106+
107+
if (childActivitySamplingDecision == SamplingDecision.RecordAndSample)
108+
{
109+
if (shimSamplingDecision == SamplingDecision.RecordAndSample)
110+
{
111+
Assert.Same(exportedSpans[1], exportedSpans[0].Parent);
112+
}
113+
}
114+
}
115+
116+
private class TestSampler : Sampler
117+
{
118+
private readonly Func<SamplingParameters, SamplingDecision> shouldSampleDelegate;
119+
120+
public TestSampler(Func<SamplingParameters, SamplingDecision> shouldSampleDelegate)
121+
{
122+
this.shouldSampleDelegate = shouldSampleDelegate;
123+
}
124+
125+
public override SamplingResult ShouldSample(in SamplingParameters samplingParameters)
126+
{
127+
return new SamplingResult(this.shouldSampleDelegate(samplingParameters));
128+
}
129+
}
130+
}
131+
132+
[System.Diagnostics.CodeAnalysis.SuppressMessage(
133+
"StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Local use only")]
134+
internal static class ConditionalTracerProviderBuilderExtension
135+
{
136+
public static TracerProviderBuilder When(
137+
this TracerProviderBuilder builder,
138+
bool condition,
139+
Func<TracerProviderBuilder, TracerProviderBuilder> conditionalDelegate)
140+
{
141+
if (condition)
142+
{
143+
builder = conditionalDelegate(builder);
144+
}
145+
146+
return builder;
147+
}
148+
}
149+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// <copyright file="ListenAndSampleAllActivitySources.cs" company="OpenTelemetry Authors">
2+
// Copyright The OpenTelemetry Authors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// </copyright>
16+
17+
using System.Diagnostics;
18+
using Xunit;
19+
20+
namespace OpenTelemetry.Shims.OpenTracing.Tests
21+
{
22+
[CollectionDefinition(nameof(ListenAndSampleAllActivitySources))]
23+
public sealed class ListenAndSampleAllActivitySources : ICollectionFixture<ListenAndSampleAllActivitySources.Fixture>
24+
{
25+
public sealed class Fixture : IDisposable
26+
{
27+
private readonly ActivityListener listener;
28+
29+
public Fixture()
30+
{
31+
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
32+
Activity.ForceDefaultIdFormat = true;
33+
34+
this.listener = new ActivityListener
35+
{
36+
ShouldListenTo = _ => true,
37+
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
38+
};
39+
40+
ActivitySource.AddActivityListener(this.listener);
41+
}
42+
43+
public void Dispose()
44+
{
45+
this.listener.Dispose();
46+
}
47+
}
48+
}
49+
}

test/OpenTelemetry.Shims.OpenTracing.Tests/OpenTelemetry.Shims.OpenTracing.Tests.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<Description>Unit test project for OpenTelemetry.Shims.OpenTracing</Description>
44
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
55
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
6-
6+
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
77
<!-- this is temporary. will remove in future PR. -->
88
<Nullable>disable</Nullable>
99
</PropertyGroup>
@@ -19,6 +19,8 @@
1919
</ItemGroup>
2020

2121
<ItemGroup>
22+
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry\OpenTelemetry.csproj" />
23+
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.InMemory\OpenTelemetry.Exporter.InMemory.csproj" />
2224
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Shims.OpenTracing\OpenTelemetry.Shims.OpenTracing.csproj" />
2325
</ItemGroup>
2426
</Project>

test/OpenTelemetry.Shims.OpenTracing.Tests/ScopeManagerShimTests.cs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,12 @@
2121

2222
namespace OpenTelemetry.Shims.OpenTracing.Tests
2323
{
24+
[Collection(nameof(ListenAndSampleAllActivitySources))]
2425
public class ScopeManagerShimTests
2526
{
2627
private const string SpanName = "MySpanName/1";
2728
private const string TracerName = "defaultactivitysource";
2829

29-
static ScopeManagerShimTests()
30-
{
31-
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
32-
Activity.ForceDefaultIdFormat = true;
33-
34-
var listener = new ActivityListener
35-
{
36-
ShouldListenTo = _ => true,
37-
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
38-
};
39-
40-
ActivitySource.AddActivityListener(listener);
41-
}
42-
4330
[Fact]
4431
public void CtorArgumentValidation()
4532
{

test/OpenTelemetry.Shims.OpenTracing.Tests/SpanBuilderShimTests.cs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,13 @@
2020

2121
namespace OpenTelemetry.Shims.OpenTracing.Tests
2222
{
23+
[Collection(nameof(ListenAndSampleAllActivitySources))]
2324
public class SpanBuilderShimTests
2425
{
2526
private const string SpanName1 = "MySpanName/1";
2627
private const string SpanName2 = "MySpanName/2";
2728
private const string TracerName = "defaultactivitysource";
2829

29-
static SpanBuilderShimTests()
30-
{
31-
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
32-
Activity.ForceDefaultIdFormat = true;
33-
34-
var listener = new ActivityListener
35-
{
36-
ShouldListenTo = _ => true,
37-
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
38-
};
39-
40-
ActivitySource.AddActivityListener(listener);
41-
}
42-
4330
[Fact]
4431
public void CtorArgumentValidation()
4532
{

test/OpenTelemetry.Shims.OpenTracing.Tests/SpanContextShimTests.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,6 @@ namespace OpenTelemetry.Shims.OpenTracing.Tests
2222
{
2323
public class SpanContextShimTests
2424
{
25-
[Fact]
26-
public void CtorArgumentValidation()
27-
{
28-
Assert.Throws<ArgumentException>(() => new SpanContextShim(default));
29-
Assert.Throws<ArgumentException>(() => new SpanContextShim(new SpanContext(default, default, ActivityTraceFlags.None)));
30-
}
31-
3225
[Fact]
3326
public void GetTraceId()
3427
{

test/OpenTelemetry.Shims.OpenTracing.Tests/SpanShimTests.cs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,18 @@
1414
// limitations under the License.
1515
// </copyright>
1616

17-
using System.Diagnostics;
1817
using OpenTelemetry.Trace;
1918
using OpenTracing.Tag;
2019
using Xunit;
2120

2221
namespace OpenTelemetry.Shims.OpenTracing.Tests
2322
{
23+
[Collection(nameof(ListenAndSampleAllActivitySources))]
2424
public class SpanShimTests
2525
{
2626
private const string SpanName = "MySpanName/1";
2727
private const string TracerName = "defaultactivitysource";
2828

29-
static SpanShimTests()
30-
{
31-
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
32-
Activity.ForceDefaultIdFormat = true;
33-
34-
var listener = new ActivityListener
35-
{
36-
ShouldListenTo = _ => true,
37-
Sample = (ref ActivityCreationOptions<ActivityContext> options) => ActivitySamplingResult.AllData,
38-
};
39-
40-
ActivitySource.AddActivityListener(listener);
41-
}
42-
4329
[Fact]
4430
public void CtorArgumentValidation()
4531
{
@@ -73,6 +59,14 @@ public void FinishSpanUsingSpecificTimestamp()
7359
var tracer = TracerProvider.Default.GetTracer(TracerName);
7460
var shim = new SpanShim(tracer.StartSpan(SpanName));
7561

62+
#if NETFRAMEWORK
63+
// Under the hood the Activity start time uses DateTime.UtcNow, which
64+
// doesn't have the same precision as DateTimeOffset.UtcNow on the .NET Framework.
65+
// Add a sleep big enough to ensure that the test doesn't break due to the
66+
// low resolution of DateTime.UtcNow on the .NET Framework.
67+
Thread.Sleep(TimeSpan.FromMilliseconds(20));
68+
#endif
69+
7670
var endTime = DateTimeOffset.UtcNow;
7771
shim.Finish(endTime);
7872

0 commit comments

Comments
 (0)