Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
<ItemGroup>
<Compile Include="..\Benchmarks.OpenTelemetry.Api\*.cs" />
<Compile Include="..\Benchmarks.OpenTelemetry.Api\Trace\**\*.cs" Link="Trace\%(RecursiveDir)%(Filename)%(Extension)" />
<Compile Include="..\Benchmarks.Trace\DummyAgentWriter.cs" />
<Compile Include="..\Benchmarks.Trace\TracerHelper.cs" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
using System;
using System.Linq;
using Benchmarks.Trace;

namespace Benchmarks.OpenTelemetry.InstrumentedApi.Setup;

internal class ActivityBenchmarkSetup
{
internal void GlobalSetup()
{
TracerHelper.SetGlobalTracer();
Datadog.Trace.Activity.ActivityListener.Initialize();
}

internal void GlobalCleanup()
{
TracerHelper.CleanupGlobalTracer();
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
using System;
using System.Linq;
using Benchmarks.Trace;

namespace Benchmarks.OpenTelemetry.InstrumentedApi.Setup;

internal class TelemetrySpanBenchmarkSetup
{
internal void GlobalSetup()
{
TracerHelper.SetGlobalTracer();
Datadog.Trace.Activity.ActivityListener.Initialize();
}

internal void GlobalCleanup()
{
TracerHelper.CleanupGlobalTracer();
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
using System;
using System.Linq;
using Benchmarks.Trace;

namespace Benchmarks.OpenTelemetry.InstrumentedApi.Setup;

internal class TracerBenchmarkSetup
{
internal void GlobalSetup()
{
TracerHelper.SetGlobalTracer();
Datadog.Trace.Activity.ActivityListener.Initialize();
}

internal void GlobalCleanup()
{
TracerHelper.CleanupGlobalTracer();
}
}
246 changes: 39 additions & 207 deletions tracer/test/benchmarks/Benchmarks.Trace/ActivityBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
#nullable enable
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using BenchmarkDotNet.Attributes;
using Datadog.Trace;
using Datadog.Trace.Activity.DuckTypes;
using Datadog.Trace.Activity.Handlers;
using Datadog.Trace.Configuration;
using Datadog.Trace.DuckTyping;
using Datadog.Trace.VendoredMicrosoftCode.System.Runtime.CompilerServices.Unsafe;
using ActivityIdFormat = System.Diagnostics.ActivityIdFormat;
using ActivityKind = Datadog.Trace.Activity.DuckTypes.ActivityKind;
using ActivityListener = System.Diagnostics.ActivityListener;
using ActivitySamplingResult = System.Diagnostics.ActivitySamplingResult;
using ActivitySource = System.Diagnostics.ActivitySource;
using ActivityStatusCode = Datadog.Trace.Activity.DuckTypes.ActivityStatusCode;

namespace Benchmarks.Trace;

[MemoryDiagnoser]
[BenchmarkCategory(Constants.TracerCategory, Constants.RunOnPrs, Constants.RunOnMaster)]
public class ActivityBenchmark
{
private const string SourceName = "BenchmarkSource";
Expand All @@ -30,44 +22,73 @@ public class ActivityBenchmark
private Datadog.Trace.Activity.DuckTypes.ActivitySource _duckSource;
private ActivitySource _source;
private ActivityListener _activityListener;
private DefaultActivityHandler _handler;

[GlobalSetup]
public void GlobalSetup()
{
TracerHelper.SetGlobalTracer();
_source = new ActivitySource(SourceName);

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

ActivitySource.AddActivityListener(_activityListener);

_duckSource = new Datadog.Trace.Activity.DuckTypes.ActivitySource { Name = _source.Name, Version = _source.Version ?? string.Empty };
_handler = new();
}

[GlobalCleanup]
public void GlobalCleanup()
{
_source.Dispose();
_activityListener.Dispose();
TracerHelper.CleanupGlobalTracer();
}

[Benchmark(Baseline = true)]
public void StartStopWithChild_Baseline()
{
using var parent = CreateActivity();
using (var child = CreateActivity(parent))
{
child.Stop();
}
parent.Stop();
}

[Benchmark]
[BenchmarkCategory(Constants.TracerCategory, Constants.RunOnPrs, Constants.RunOnMaster)]
public void StartStopWithChild()
{
// unfortunately this tests some creation/setup for activity themselves
using var parent = CreateActivity();
using var child = CreateActivity(parent);
var parentMock = new MockActivity6(parent, null, _duckSource);
var childMock = new MockActivity6(child, parentMock, _duckSource);
var handler = new DefaultActivityHandler();
handler.ActivityStarted(SourceName, parentMock);
handler.ActivityStarted(SourceName, childMock);
var parentMock = parent.DuckAs<IActivity6>()!;
var childMock = child.DuckAs<IActivity6>()!;
_handler.ActivityStarted(SourceName, parentMock);
_handler.ActivityStarted(SourceName, childMock);
child.Stop();
handler.ActivityStopped(SourceName, childMock);
_handler.ActivityStopped(SourceName, childMock);
parent.Stop();
handler.ActivityStopped(SourceName, parentMock);
_handler.ActivityStopped(SourceName, parentMock);
}

private Activity CreateActivity(Activity? parent = null)
[Benchmark]
public void StartStopWithChild_Hierarchical()
{
using var parent = CreateActivity(idFormat: ActivityIdFormat.Hierarchical);
using var child = CreateActivity(parent, idFormat: ActivityIdFormat.Hierarchical);
var parentMock = parent.DuckAs<IActivity6>()!;
var childMock = child.DuckAs<IActivity6>()!;
_handler.ActivityStarted(SourceName, parentMock);
_handler.ActivityStarted(SourceName, childMock);
child.Stop();
_handler.ActivityStopped(SourceName, childMock);
parent.Stop();
_handler.ActivityStopped(SourceName, parentMock);
}

private Activity CreateActivity(Activity? parent = null, ActivityIdFormat idFormat = ActivityIdFormat.W3C)
{
var activity = parent is null
? _source.CreateActivity("parent", System.Diagnostics.ActivityKind.Internal)
Expand All @@ -79,7 +100,7 @@ private Activity CreateActivity(Activity? parent = null)
}

activity.SetStartTime(_startTime);
activity.SetIdFormat(ActivityIdFormat.W3C); // we have more logic for TraceId/SpanId activities
activity.SetIdFormat(idFormat); // we have more logic for TraceId/SpanId activities

activity.Start(); // creates necessary TraceId/SpanId that we need

Expand All @@ -91,192 +112,3 @@ private Activity CreateActivity(Activity? parent = null)
return activity;
}
}

#region MockActivity Implementations
internal class MockActivity6 : MockActivity5, IActivity6
{
private readonly Activity _activity;

public MockActivity6(Activity activity, IActivity? parent, Datadog.Trace.Activity.DuckTypes.ActivitySource source)
: base(activity, parent, source)
{
_activity = activity;
}

public ActivityStatusCode Status => Convert(_activity.Status);
public string StatusDescription => _activity.StatusDescription ?? string.Empty;

private static ActivityStatusCode Convert(System.Diagnostics.ActivityStatusCode code)
{
return code switch
{
System.Diagnostics.ActivityStatusCode.Unset => ActivityStatusCode.Unset,
System.Diagnostics.ActivityStatusCode.Ok => ActivityStatusCode.Ok,
System.Diagnostics.ActivityStatusCode.Error => ActivityStatusCode.Error,
_ => throw new ArgumentOutOfRangeException(nameof(code), code, null)
};
}

public void Stop()
{
_activity.Stop();
}
}

internal class MockActivity5 : MockW3CActivity, IActivity5
{
private readonly Activity _activity;
private string? _displayName;

public MockActivity5(Activity activity, IActivity? parent, Datadog.Trace.Activity.DuckTypes.ActivitySource source)
: base(activity, parent)
{
_activity = activity;
Source = source;
}

public string DisplayName
{
get => _displayName ?? _activity.DisplayName;
set => _displayName = value;
}

public bool IsAllDataRequested
{
get => _activity.IsAllDataRequested;
set => _activity.IsAllDataRequested = value;
}

public ActivityKind Kind => ConvertActivityKind(_activity.Kind);
public IEnumerable<KeyValuePair<string, object>> TagObjects => _activity.TagObjects!;
public Datadog.Trace.Activity.DuckTypes.ActivitySource Source { get; }
public IEnumerable Events => _activity.Events;
public IEnumerable Links => _activity.Links;

object IActivity5.AddTag(string key, object value)
{
return _activity.AddTag(key, value);
}

private static ActivityKind ConvertActivityKind(System.Diagnostics.ActivityKind kind)
{
return kind switch
{
System.Diagnostics.ActivityKind.Internal => ActivityKind.Internal,
System.Diagnostics.ActivityKind.Server => ActivityKind.Server,
System.Diagnostics.ActivityKind.Client => ActivityKind.Client,
System.Diagnostics.ActivityKind.Producer => ActivityKind.Producer,
System.Diagnostics.ActivityKind.Consumer => ActivityKind.Consumer,
_ => throw new ArgumentOutOfRangeException(nameof(kind), kind, null)
};
}
}

internal class MockW3CActivity : MockActivity, IW3CActivity
{
private readonly Activity _activity;
private string? _traceId;
private string? _spanId;
private string? _parentSpanId;
private string? _traceStateString;

public MockW3CActivity(Activity activity, IActivity? parent)
: base(activity, parent)
{
_activity = activity;
}

public string TraceId
{
get => _traceId ?? _activity.TraceId.ToString();
set => _traceId = value;
}

public string SpanId
{
get => _spanId ?? _activity.SpanId.ToString();
set => _spanId = value;
}

public string ParentSpanId
{
get => _parentSpanId ?? _activity.ParentSpanId.ToString();
set => _parentSpanId = value;
}

public string? RawId { get; set; }
public string? RawParentId { get; set; }

public string? TraceStateString
{
get => _traceStateString ?? _activity.TraceStateString;
set => _traceStateString = value;
}
}

internal class MockActivity : IActivity
{
private readonly Activity _activity;
private readonly IActivity? _parent;

public MockActivity(Activity activity, IActivity? parent)
{
_activity = activity ?? throw new ArgumentNullException(nameof(activity));
_parent = parent;
}

public object Instance => _activity;
public Type Type => typeof(Activity);
public string Id => _activity.Id ?? string.Empty;
public string ParentId => _activity.ParentId!;

public string RootId => _activity.RootId!;

public TimeSpan Duration => _activity.Duration;
public string OperationName => _activity.OperationName;
public IActivity? Parent => _parent;
public DateTime StartTimeUtc => _activity.StartTimeUtc;
public IEnumerable<KeyValuePair<string, string>> Baggage => _activity.Baggage!;
public IEnumerable<KeyValuePair<string, string>> Tags => _activity.Tags!;

public object AddBaggage(string key, string value)
{
return _activity.AddBaggage(key, value);
}

public object AddTag(string key, string value)
{
return _activity.AddTag(key, value);
}

public string GetBaggageItem(string key)
{
return _activity.GetBaggageItem(key)!;
}

public object SetEndTime(DateTime endTimeUtc)
{
return _activity.SetEndTime(endTimeUtc);
}

public object SetParentId(string parentId)
{
return _activity.SetParentId(parentId);
}

public object SetStartTime(DateTime startTimeUtc)
{
return _activity.SetStartTime(startTimeUtc);
}

public ref TReturn GetInternalDuckTypedInstance<TReturn>()
{
return ref Unsafe.As<Activity, TReturn>(ref Unsafe.AsRef(in _activity));
}

string IDuckType.ToString()
{
return _activity.ToString() ?? string.Empty;
}
}
#endregion
Loading