Skip to content

[Instrumentation.EntityFrameworkCore] Database metrics #2707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ OpenTelemetry.Instrumentation.EntityFrameworkCore.EntityFrameworkInstrumentation
OpenTelemetry.Instrumentation.EntityFrameworkCore.EntityFrameworkInstrumentationOptions.SetDbStatementForText.set -> void
OpenTelemetry.Instrumentation.EntityFrameworkCore.EntityFrameworkInstrumentationOptions.EnrichWithIDbCommand.get -> System.Action<System.Diagnostics.Activity!, System.Data.IDbCommand!>?
OpenTelemetry.Instrumentation.EntityFrameworkCore.EntityFrameworkInstrumentationOptions.EnrichWithIDbCommand.set -> void
OpenTelemetry.Metrics.EntityFrameworkCoreMeterProviderBuilderExtensions
OpenTelemetry.Trace.TracerProviderBuilderExtensions
static OpenTelemetry.Metrics.EntityFrameworkCoreMeterProviderBuilderExtensions.AddEntityFrameworkCoreInstrumentation(this OpenTelemetry.Metrics.MeterProviderBuilder! builder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddEntityFrameworkCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddEntityFrameworkCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder, string? name, System.Action<OpenTelemetry.Instrumentation.EntityFrameworkCore.EntityFrameworkInstrumentationOptions!>? configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddEntityFrameworkCoreInstrumentation(this OpenTelemetry.Trace.TracerProviderBuilder! builder, System.Action<OpenTelemetry.Instrumentation.EntityFrameworkCore.EntityFrameworkInstrumentationOptions!>? configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#if NET
using System.Diagnostics.CodeAnalysis;
#endif
using OpenTelemetry.Instrumentation.EntityFrameworkCore;
using OpenTelemetry.Instrumentation.EntityFrameworkCore.Implementation;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Metrics;

/// <summary>
/// Extension methods to simplify registering of dependency instrumentation.
/// </summary>
public static class EntityFrameworkCoreMeterProviderBuilderExtensions
{
/// <summary>
/// Enables EntityFrameworkCore instrumentation.
/// </summary>
/// <param name="builder"><see cref="MeterProviderBuilder"/> being configured.</param>
/// <returns>The instance of <see cref="MeterProviderBuilder"/> to chain the calls.</returns>
#if NET
// TODO [RequiresUnreferencedCode(SqlClientInstrumentation.SqlClientTrimmingUnsupportedMessage)]
#endif
public static MeterProviderBuilder AddEntityFrameworkCoreInstrumentation(this MeterProviderBuilder builder)
{
Guard.ThrowIfNull(builder);

builder.AddInstrumentation(sp =>
{
return EntityFrameworkInstrumentation.AddMetricHandle();
});

builder.AddMeter(EntityFrameworkDiagnosticListener.MeterName);

return builder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,68 @@ namespace OpenTelemetry.Instrumentation.EntityFrameworkCore;

internal class EntityFrameworkInstrumentation : IDisposable
{
public static readonly EntityFrameworkInstrumentation Instance = new();
internal static int MetricHandles;
internal static int TracingHandles;

private readonly DiagnosticSourceSubscriber diagnosticSourceSubscriber;

public EntityFrameworkInstrumentation(EntityFrameworkInstrumentationOptions? options)
public EntityFrameworkInstrumentation()
{
this.diagnosticSourceSubscriber = new DiagnosticSourceSubscriber(
name => new EntityFrameworkDiagnosticListener(name, options),
name => new EntityFrameworkDiagnosticListener(name),
listener => listener.Name == EntityFrameworkDiagnosticListener.DiagnosticSourceName,
null,
EntityFrameworkInstrumentationEventSource.Log.UnknownErrorProcessingEvent);
this.diagnosticSourceSubscriber.Subscribe();
}

public static EntityFrameworkInstrumentationOptions TracingOptions { get; set; } = new();

public static IDisposable AddMetricHandle() => new MetricHandle();

public static IDisposable AddTracingHandle() => new TracingHandle();

public void Dispose()
{
this.diagnosticSourceSubscriber?.Dispose();
}

private sealed class MetricHandle : IDisposable
{
private bool disposed;

public MetricHandle()
{
Interlocked.Increment(ref MetricHandles);
}

public void Dispose()
{
if (!this.disposed)
{
Interlocked.Decrement(ref MetricHandles);
this.disposed = true;
}
}
}

private sealed class TracingHandle : IDisposable
{
private bool disposed;

public TracingHandle()
{
Interlocked.Increment(ref TracingHandles);
}

public void Dispose()
{
if (!this.disposed)
{
Interlocked.Decrement(ref TracingHandles);
this.disposed = true;
}
}
}
}
Loading
Loading