Skip to content

Commit 8b12e7e

Browse files
committed
Added ActivityEnrichmentScope to OpenTelemetry extensions.
1 parent 39c5f5e commit 8b12e7e

20 files changed

+822
-8
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Diagnostics;
3+
4+
namespace Macross.OpenTelemetry.Extensions
5+
{
6+
internal sealed class ActionActivityEnrichmentScope : ActivityEnrichmentScopeBase
7+
{
8+
public Action<Activity> EnrichmentAction { get; private set; }
9+
10+
public ActionActivityEnrichmentScope(Action<Activity> enrichmentAction, EnrichmentScopeTarget target)
11+
: base(target)
12+
{
13+
EnrichmentAction = enrichmentAction ?? throw new ArgumentNullException(nameof(enrichmentAction));
14+
}
15+
16+
public override void Enrich(Activity activity)
17+
=> EnrichmentAction?.Invoke(activity);
18+
19+
protected override void Dispose(bool isDisposing)
20+
{
21+
EnrichmentAction = null!;
22+
23+
base.Dispose(isDisposing);
24+
}
25+
}
26+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace System.Diagnostics
2+
{
3+
/// <summary>
4+
/// A callback function for enriching an <see cref="Activity"/> using some known state.
5+
/// </summary>
6+
/// <typeparam name="TState">State type.</typeparam>
7+
/// <param name="activity"><see cref="Activity"/> being enriched.</param>
8+
/// <param name="state">State.</param>
9+
public delegate void ActivityEnricher<TState>(Activity activity, TState state);
10+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Macross.OpenTelemetry.Extensions;
2+
3+
namespace System.Diagnostics
4+
{
5+
/// <summary>
6+
/// A class for enriching the data of <see cref="Activity"/> objects.
7+
/// </summary>
8+
public static class ActivityEnrichmentScope
9+
{
10+
/// <summary>
11+
/// Registers an action that will be called to enrich the next <see cref="Activity"/> processed under the current scope if it has been sampled.
12+
/// </summary>
13+
/// <param name="enrichmentAction">Action to be called.</param>
14+
/// <param name="target">The target for the enrichment scope.</param>
15+
/// <returns><see cref="IDisposable"/> to cancel the enrichment scope.</returns>
16+
public static IDisposable Begin(Action<Activity> enrichmentAction, EnrichmentScopeTarget target = EnrichmentScopeTarget.AllChildren)
17+
=> new ActionActivityEnrichmentScope(enrichmentAction, target);
18+
19+
/// <summary>
20+
/// Registers an <see cref="ActivityEnricher{TState}"/> that will be called to enrich the next <see cref="Activity"/> processed under the current scope if it has been sampled.
21+
/// </summary>
22+
/// <typeparam name="TState">State type.</typeparam>
23+
/// <param name="activityEnricher"><see cref="ActivityEnricher{TState}"/> to be called.</param>
24+
/// <param name="state">The state to pass to the <see cref="ActivityEnricher{TState}"/>.</param>
25+
/// <param name="target">The target for the enrichment scope.</param>
26+
/// <returns><see cref="IDisposable"/> to cancel the enrichment scope.</returns>
27+
public static IDisposable Begin<TState>(ActivityEnricher<TState> activityEnricher, TState state, EnrichmentScopeTarget target = EnrichmentScopeTarget.AllChildren)
28+
=> new GenericActivityEnrichmentScope<TState>(activityEnricher, state, target);
29+
}
30+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Diagnostics;
3+
4+
using OpenTelemetry.Context;
5+
6+
namespace Macross.OpenTelemetry.Extensions
7+
{
8+
internal abstract class ActivityEnrichmentScopeBase : IDisposable
9+
{
10+
private static readonly RuntimeContextSlot<ActivityEnrichmentScopeBase?> s_RuntimeContextSlot = RuntimeContext.RegisterSlot<ActivityEnrichmentScopeBase?>("otel.activity_enrichment_scope");
11+
12+
public static ActivityEnrichmentScopeBase? Current => s_RuntimeContextSlot.Get();
13+
14+
private bool _Disposed;
15+
16+
public ActivityEnrichmentScopeBase? Parent { get; private set; }
17+
18+
public ActivityEnrichmentScopeBase? Child { get; private set; }
19+
20+
public EnrichmentScopeTarget EnrichmentTarget { get; private set; }
21+
22+
protected ActivityEnrichmentScopeBase(EnrichmentScopeTarget target)
23+
{
24+
EnrichmentTarget = target;
25+
26+
Parent = Current;
27+
if (Parent != null)
28+
{
29+
Parent.Child = this;
30+
}
31+
32+
s_RuntimeContextSlot.Set(this);
33+
}
34+
35+
public void Dispose()
36+
{
37+
if (!_Disposed)
38+
{
39+
Dispose(true);
40+
_Disposed = true;
41+
}
42+
}
43+
44+
public abstract void Enrich(Activity activity);
45+
46+
protected virtual void Dispose(bool isDisposing)
47+
{
48+
if (Parent?.Child == this)
49+
{
50+
Parent.Child = Child;
51+
}
52+
53+
if (Child?.Parent == this)
54+
{
55+
Child.Parent = Parent;
56+
}
57+
58+
if (s_RuntimeContextSlot.Get() == this)
59+
{
60+
s_RuntimeContextSlot.Set(Parent);
61+
}
62+
63+
Parent = null;
64+
Child = null;
65+
}
66+
}
67+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Diagnostics;
3+
4+
using OpenTelemetry;
5+
6+
namespace Macross.OpenTelemetry.Extensions
7+
{
8+
internal class ActivityEnrichmentScopeProcessor : BaseProcessor<Activity>
9+
{
10+
/// <inheritdoc/>
11+
public override void OnEnd(Activity activity)
12+
{
13+
ActivityEnrichmentScopeBase? scope = ActivityEnrichmentScopeBase.Current;
14+
while (scope != null)
15+
{
16+
try
17+
{
18+
scope.Enrich(activity);
19+
}
20+
#pragma warning disable CA1031 // Do not catch general exception types
21+
catch (Exception ex)
22+
#pragma warning restore CA1031 // Do not catch general exception types
23+
{
24+
OpenTelemetryExtensionsEventSource.Log.SpanProcessorException(nameof(ActivityEnrichmentScopeProcessor), ex);
25+
}
26+
27+
ActivityEnrichmentScopeBase? nextParent = scope.Parent;
28+
29+
if (scope.EnrichmentTarget == EnrichmentScopeTarget.FirstChild)
30+
{
31+
scope.Dispose();
32+
}
33+
34+
scope = nextParent;
35+
}
36+
}
37+
}
38+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace System.Diagnostics
2+
{
3+
/// <summary>
4+
/// Describes the target of an enrichment scope.
5+
/// </summary>
6+
public enum EnrichmentScopeTarget
7+
{
8+
/// <summary>
9+
/// The first child created under the scope will be enriched and then the scope will automatically be closed.
10+
/// </summary>
11+
FirstChild,
12+
13+
/// <summary>
14+
/// All child objects created under the scope will be enriched until the scope is closed.
15+
/// </summary>
16+
AllChildren,
17+
}
18+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Diagnostics;
3+
4+
namespace Macross.OpenTelemetry.Extensions
5+
{
6+
internal sealed class GenericActivityEnrichmentScope<TState> : ActivityEnrichmentScopeBase
7+
{
8+
private readonly TState _State;
9+
10+
public ActivityEnricher<TState> ActivityEnricher { get; private set; }
11+
12+
public GenericActivityEnrichmentScope(ActivityEnricher<TState> activityEnricher, TState state, EnrichmentScopeTarget target)
13+
: base(target)
14+
{
15+
ActivityEnricher = activityEnricher ?? throw new ArgumentNullException(nameof(activityEnricher));
16+
_State = state;
17+
}
18+
19+
public override void Enrich(Activity activity)
20+
=> ActivityEnricher?.Invoke(activity, _State);
21+
22+
protected override void Dispose(bool isDisposing)
23+
{
24+
ActivityEnricher = null!;
25+
26+
base.Dispose(isDisposing);
27+
}
28+
}
29+
}

ClassLibraries/Macross.OpenTelemetry.Extensions/Code/Extensions/OpenTelemetryServiceCollectionExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.Diagnostics;
33
using System.Diagnostics.Tracing;
44

5-
using Macross.OpenTelemetry;
5+
using Macross.OpenTelemetry.Extensions;
66

77
namespace Microsoft.Extensions.DependencyInjection
88
{
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Diagnostics;
2+
3+
using Macross.OpenTelemetry.Extensions;
4+
5+
namespace OpenTelemetry.Trace
6+
{
7+
/// <summary>
8+
/// Contains extension methods for the <see cref="TracerProviderBuilder"/> class.
9+
/// </summary>
10+
public static class TracerProviderBuilderExtensions
11+
{
12+
/// <summary>
13+
/// Adds a <see cref="BaseProcessor{T}"/> which will enrich <see cref="Activity"/> objects created while inside an <see cref="ActivityEnrichmentScope"/>.
14+
/// </summary>
15+
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
16+
/// <returns>Returns the supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
17+
public static TracerProviderBuilder AddActivityEnrichmentScopeProcessor(this TracerProviderBuilder tracerProviderBuilder)
18+
#pragma warning disable CA2000 // Dispose objects before losing scope
19+
=> tracerProviderBuilder.AddProcessor(new ActivityEnrichmentScopeProcessor());
20+
#pragma warning restore CA2000 // Dispose objects before losing scope
21+
}
22+
}

ClassLibraries/Macross.OpenTelemetry.Extensions/Code/Macross.OpenTelemetry.Extensions.csproj

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@
1515
Commonly Used Extensions:
1616
IServiceCollection.AddOpenTelemetryEventLogging
1717
IServiceCollection.AddActivityTraceListener
18+
TracerProviderBuilder.AddActivityEnrichmentScopeProcessor
1819
</Description>
1920
<Product>Macross.OpenTelemetry.Extensions</Product>
2021
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
2122
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
2223
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
2324
<VersionPrefix>1.0.0</VersionPrefix>
24-
<VersionSuffix>beta2</VersionSuffix>
25+
<VersionSuffix>beta3</VersionSuffix>
2526
<FileVersion>$(VersionPrefix)</FileVersion>
2627
<PackageProjectUrl>https://github.com/Macross-Software/core/tree/develop/ClassLibraries/Macross.OpenTelemetry.Extensions</PackageProjectUrl>
2728
</PropertyGroup>
@@ -40,9 +41,7 @@
4041

4142
<ItemGroup>
4243
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="2.1.0" />
43-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.1.0" />
44-
<PackageReference Include="Microsoft.Extensions.Options" Version="2.1.0" />
45-
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="5.0.0" />
44+
<PackageReference Include="OpenTelemetry" Version="1.0.1" />
4645
</ItemGroup>
4746

4847
</Project>

0 commit comments

Comments
 (0)