opentelemetry-dotnet/test/OpenTelemetry.Tests/Trace/ActivitySourceAdapterTest.cs

229 lines
9.1 KiB
C#

// <copyright file="ActivitySourceAdapterTest.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;
using System.Diagnostics;
using OpenTelemetry.Resources;
using OpenTelemetry.Tests.Shared;
using Xunit;
namespace OpenTelemetry.Trace.Tests
{
public class ActivitySourceAdapterTest : IDisposable
{
private TestSampler testSampler;
private TestActivityProcessor testProcessor;
private Resource testResource = Resources.Resources.CreateServiceResource("test-resource");
private ActivitySourceAdapter activitySourceAdapter;
static ActivitySourceAdapterTest()
{
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
Activity.ForceDefaultIdFormat = true;
}
public ActivitySourceAdapterTest()
{
this.testSampler = new TestSampler();
this.testProcessor = new TestActivityProcessor();
this.activitySourceAdapter = new ActivitySourceAdapter(this.testSampler, this.testProcessor, this.testResource);
}
[Fact]
public void ActivitySourceAdapterSetsResource()
{
var activity = new Activity("test");
activity.Start();
this.activitySourceAdapter.Start(activity);
activity.Stop();
this.activitySourceAdapter.Stop(activity);
Assert.Equal(this.testResource, activity.GetResource());
}
[Theory]
[InlineData(SamplingDecision.NotRecord)]
[InlineData(SamplingDecision.Record)]
[InlineData(SamplingDecision.RecordAndSampled)]
public void ActivitySourceAdapterCallsStartStopActivityProcessor1(SamplingDecision decision)
{
this.testSampler.SamplingAction = (samplingParameters) =>
{
return new SamplingResult(decision);
};
bool startCalled = false;
bool endCalled = false;
this.testProcessor.StartAction =
(a) =>
{
startCalled = true;
// If start is called, that means activity is sampled,
// and TraceFlag is set to Recorded.
Assert.Equal(decision == SamplingDecision.Record || decision == SamplingDecision.RecordAndSampled, a.IsAllDataRequested);
Assert.Equal(decision == SamplingDecision.RecordAndSampled ? ActivityTraceFlags.Recorded : ActivityTraceFlags.None, a.ActivityTraceFlags);
Assert.Equal(decision == SamplingDecision.RecordAndSampled, a.Recorded);
};
this.testProcessor.EndAction =
(a) =>
{
endCalled = true;
};
var activity = new Activity("test");
activity.Start();
this.activitySourceAdapter.Start(activity);
activity.Stop();
this.activitySourceAdapter.Stop(activity);
Assert.Equal(activity.IsAllDataRequested, startCalled);
Assert.Equal(activity.IsAllDataRequested, endCalled);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public void ActivitySourceAdapterCallsStartStopActivityProcessor2(bool isSampled)
{
this.testSampler.SamplingAction = (samplingParameters) =>
{
return new SamplingResult(isSampled);
};
bool startCalled = false;
bool endCalled = false;
this.testProcessor.StartAction =
(a) =>
{
startCalled = true;
// If start is called, that means activity is sampled,
// and TraceFlag is set to Recorded.
Assert.Equal(isSampled, a.IsAllDataRequested);
Assert.Equal(isSampled ? ActivityTraceFlags.Recorded : ActivityTraceFlags.None, a.ActivityTraceFlags);
Assert.Equal(isSampled, a.Recorded);
};
this.testProcessor.EndAction =
(a) =>
{
endCalled = true;
};
var activity = new Activity("test");
activity.Start();
this.activitySourceAdapter.Start(activity);
activity.Stop();
this.activitySourceAdapter.Stop(activity);
Assert.Equal(isSampled, startCalled);
Assert.Equal(isSampled, endCalled);
}
[Fact]
public void ActivitySourceAdapterPopulatesSamplingParamsCorrectlyForRootActivity()
{
this.testSampler.SamplingAction = (samplingParameters) =>
{
Assert.Equal(default, samplingParameters.ParentContext);
return new SamplingResult(SamplingDecision.RecordAndSampled);
};
// Start activity without setting parent. i.e it'll have null parent
// and becomes root activity
var activity = new Activity("test");
activity.Start();
this.activitySourceAdapter.Start(activity);
activity.Stop();
this.activitySourceAdapter.Stop(activity);
}
[Theory]
[InlineData(ActivityTraceFlags.None)]
[InlineData(ActivityTraceFlags.Recorded)]
public void ActivitySourceAdapterPopulatesSamplingParamsCorrectlyForActivityWithRemoteParent(ActivityTraceFlags traceFlags)
{
var parentTraceId = ActivityTraceId.CreateRandom();
var parentSpanId = ActivitySpanId.CreateRandom();
var parentTraceFlag = (traceFlags == ActivityTraceFlags.Recorded) ? "01" : "00";
string remoteParentId = $"00-{parentTraceId}-{parentSpanId}-{parentTraceFlag}";
string tracestate = "a=b;c=d";
this.testSampler.SamplingAction = (samplingParameters) =>
{
Assert.Equal(parentTraceId, samplingParameters.ParentContext.TraceId);
Assert.Equal(parentSpanId, samplingParameters.ParentContext.SpanId);
Assert.Equal(traceFlags, samplingParameters.ParentContext.TraceFlags);
Assert.Equal(tracestate, samplingParameters.ParentContext.TraceState);
return new SamplingResult(SamplingDecision.RecordAndSampled);
};
// Create an activity with remote parent id.
// The sampling parameters are expected to be that of the
// parent context i.e the remote parent.
var activity = new Activity("test").SetParentId(remoteParentId);
activity.TraceStateString = tracestate;
activity.Start();
this.activitySourceAdapter.Start(activity);
activity.Stop();
this.activitySourceAdapter.Stop(activity);
}
[Theory]
[InlineData(ActivityTraceFlags.None)]
[InlineData(ActivityTraceFlags.Recorded)]
public void ActivitySourceAdapterPopulatesSamplingParamsCorrectlyForActivityWithInProcParent(ActivityTraceFlags traceFlags)
{
// Create some parent activity.
string tracestate = "a=b;c=d";
var activityLocalParent = new Activity("testParent");
activityLocalParent.ActivityTraceFlags = traceFlags;
activityLocalParent.TraceStateString = tracestate;
activityLocalParent.Start();
this.testSampler.SamplingAction = (samplingParameters) =>
{
Assert.Equal(activityLocalParent.TraceId, samplingParameters.ParentContext.TraceId);
Assert.Equal(activityLocalParent.SpanId, samplingParameters.ParentContext.SpanId);
Assert.Equal(activityLocalParent.ActivityTraceFlags, samplingParameters.ParentContext.TraceFlags);
Assert.Equal(tracestate, samplingParameters.ParentContext.TraceState);
return new SamplingResult(SamplingDecision.RecordAndSampled);
};
// This activity will have a inproc parent.
// activity.Parent will be equal to the activity created at the beginning of this test.
// Sampling parameters are expected to be that of the parentContext.
// i.e of the parent Activity
var activity = new Activity("test");
activity.Start();
this.activitySourceAdapter.Start(activity);
activity.Stop();
this.activitySourceAdapter.Stop(activity);
activityLocalParent.Stop();
}
public void Dispose()
{
Activity.Current = null;
this.testProcessor.Dispose();
GC.SuppressFinalize(this);
}
}
}