Skip to content

[bug] - Memory leak #5922

Description

@LGouellec

Package

OpenTelemetry

Package Version

Package Name Version
OpenTelemetry.Api 1.9.0
OpenTelemetry 1.9.0
OpenTelemetry.Exporter.Prometheus.HttpListener 1.9.0-beta.2
OpenTelemetry.Extensions.Hosting 1.9.0
OpenTelemetry.Instrumentation.Runtime 1.9.0

Runtime Version

net8.0

Description

I need to Dispose(..) often my Meter instance, because today Meter doesn't provide a way to delete an existing metric dynamically. See : dotnet/runtime#83822.

When I hit meter.Dispose(), the dotnet runtime will notify each instrument perviously created that they are not longer published.
See: https://github.com/dotnet/runtime/blob/9e59acb298c20658788567e0c6f0793fe97d37f6/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Meter.cs#L519

The OpenTelemetry MetricReader (in my case BaseExportingMetricReader) must deactivateMetric :
See:

internal static void DeactivateMetric(Metric metric)

But it seems there is a memory leak, because when I run my program for a long time, the memory still growing. When I debug my app, I see a lot of MetricPoint[] instances unreleased. More time my application run, more memory consumption is required only for MetricPoint[] instances.
It seems when meter.Dispose() is called, the open telemetry metrics are not released properly.

Screen of my debugger at 10 min uptimes :
image

Screen of my debugger at 60 min uptimes (122 Mb of MetricsPoint[] )
image

Steps to Reproduce

    public static void Main(string[] args)
    {
        Meter meter = null;
        var meterProviderBuilder = Sdk
            .CreateMeterProviderBuilder()
            .AddMeter("Test")
            .SetResourceBuilder(
                ResourceBuilder.CreateDefault()
                    .AddService(serviceName: "Test"));
        
        meterProviderBuilder.AddPrometheusHttpListener();
        meterProviderBuilder.AddRuntimeInstrumentation();
        
        var tracerProvider = meterProviderBuilder.Build();
        
        while(true){
            meter?.Dispose();
            meter = new Meter("Test");
            var rd = new Random();
            
            meter.CreateObservableGauge(
                "requests", 
                () => new[] {
                    new Measurement<double>(rd.NextDouble() * rd.Next(100))
                },
                description: "Request per second");
            
             // will see after couple of minutes that the MetricReader contains a lot of MetricPoint[], even if we dispose the Meter after each iteration
            Thread.Sleep(200);
        }
    }

Expected Result

All perviously MetricPoint released

Actual Result

Memory leak

Additional Context

No response

Metadata

Metadata

Labels

pkg:OpenTelemetryIssues related to OpenTelemetry NuGet packagequestionFurther information is requested

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions