247 lines
8.9 KiB
C#
247 lines
8.9 KiB
C#
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
using System.Diagnostics.Metrics;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Configuration.Memory;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Diagnostics.Metrics;
|
|
using Microsoft.Extensions.Options;
|
|
using OpenTelemetry.Internal;
|
|
using OpenTelemetry.Logs;
|
|
using OpenTelemetry.Metrics;
|
|
using OpenTelemetry.Metrics.Tests;
|
|
using OpenTelemetry.Tests;
|
|
using OpenTelemetry.Trace;
|
|
using Xunit;
|
|
|
|
namespace OpenTelemetry.Extensions.Hosting.Tests;
|
|
|
|
public class OpenTelemetryMetricsBuilderExtensionsTests
|
|
{
|
|
[Theory]
|
|
[InlineData(false)]
|
|
[InlineData(true)]
|
|
public void EnableMetricsTest(bool useWithMetricsStyle)
|
|
{
|
|
using var meter = new Meter(Utils.GetCurrentMethodName());
|
|
List<Metric> exportedItems = new();
|
|
|
|
using (var host = MetricTestsBase.BuildHost(
|
|
useWithMetricsStyle,
|
|
configureMetricsBuilder: builder => builder.EnableMetrics(meter.Name),
|
|
configureMeterProviderBuilder: builder => builder.AddInMemoryExporter(exportedItems)))
|
|
{
|
|
var counter = meter.CreateCounter<long>("TestCounter");
|
|
counter.Add(1);
|
|
}
|
|
|
|
AssertSingleMetricWithLongSum(exportedItems);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(false)]
|
|
[InlineData(true)]
|
|
public void EnableMetricsWithAddMeterTest(bool useWithMetricsStyle)
|
|
{
|
|
using var meter = new Meter(Utils.GetCurrentMethodName());
|
|
List<Metric> exportedItems = new();
|
|
|
|
using (var host = MetricTestsBase.BuildHost(
|
|
useWithMetricsStyle,
|
|
configureMetricsBuilder: builder => builder.EnableMetrics(meter.Name),
|
|
configureMeterProviderBuilder: builder => builder
|
|
.AddSdkMeter(meter.Name)
|
|
.AddInMemoryExporter(exportedItems)))
|
|
{
|
|
var counter = meter.CreateCounter<long>("TestCounter");
|
|
counter.Add(1);
|
|
}
|
|
|
|
AssertSingleMetricWithLongSum(exportedItems);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(false, MetricReaderTemporalityPreference.Delta)]
|
|
[InlineData(true, MetricReaderTemporalityPreference.Delta)]
|
|
[InlineData(false, MetricReaderTemporalityPreference.Cumulative)]
|
|
[InlineData(true, MetricReaderTemporalityPreference.Cumulative)]
|
|
public void ReloadOfMetricsViaIConfigurationWithExportCleanupTest(bool useWithMetricsStyle, MetricReaderTemporalityPreference temporalityPreference)
|
|
{
|
|
using var inMemoryEventListener = new InMemoryEventListener(OpenTelemetrySdkEventSource.Log);
|
|
|
|
using var meter = new Meter(Utils.GetCurrentMethodName());
|
|
List<Metric> exportedItems = new();
|
|
|
|
var source = new MemoryConfigurationSource();
|
|
var memory = new MemoryConfigurationProvider(source);
|
|
var configuration = new ConfigurationRoot([memory]);
|
|
|
|
using var host = MetricTestsBase.BuildHost(
|
|
useWithMetricsStyle,
|
|
configureAppConfiguration: (context, builder) => builder.AddConfiguration(configuration),
|
|
configureMeterProviderBuilder: builder => builder
|
|
.AddInMemoryExporter(exportedItems, reader => reader.TemporalityPreference = temporalityPreference));
|
|
|
|
var meterProvider = host.Services.GetRequiredService<MeterProvider>();
|
|
var options = host.Services.GetRequiredService<IOptionsMonitor<MetricsOptions>>();
|
|
|
|
var counter = meter.CreateCounter<long>("TestCounter");
|
|
counter.Add(1);
|
|
|
|
meterProvider.ForceFlush();
|
|
|
|
Assert.Empty(exportedItems);
|
|
|
|
memory.Set($"Metrics:EnabledMetrics:{meter.Name}:Default", "true");
|
|
|
|
configuration.Reload();
|
|
|
|
counter.Add(1);
|
|
|
|
meterProvider.ForceFlush();
|
|
|
|
AssertSingleMetricWithLongSum(exportedItems);
|
|
|
|
exportedItems.Clear();
|
|
|
|
memory.Set($"Metrics:EnabledMetrics:{meter.Name}:Default", "false");
|
|
|
|
configuration.Reload();
|
|
|
|
counter.Add(1);
|
|
|
|
meterProvider.ForceFlush();
|
|
|
|
if (temporalityPreference == MetricReaderTemporalityPreference.Cumulative)
|
|
{
|
|
// Note: When in Cumulative the metric shows up on the export
|
|
// immediately after being deactivated and then is ignored.
|
|
AssertSingleMetricWithLongSum(exportedItems);
|
|
|
|
meterProvider.ForceFlush();
|
|
exportedItems.Clear();
|
|
Assert.Empty(exportedItems);
|
|
}
|
|
else
|
|
{
|
|
Assert.Empty(exportedItems);
|
|
}
|
|
|
|
memory.Set($"Metrics:OpenTelemetry:EnabledMetrics:{meter.Name}:Default", "true");
|
|
|
|
configuration.Reload();
|
|
|
|
counter.Add(1);
|
|
|
|
meterProvider.ForceFlush();
|
|
|
|
AssertSingleMetricWithLongSum(exportedItems);
|
|
|
|
var duplicateMetricInstrumentEvents = inMemoryEventListener.Events.Where((e) => e.EventId == 38);
|
|
|
|
// Note: We currently log a duplicate warning anytime a metric is reactivated.
|
|
Assert.Single(duplicateMetricInstrumentEvents);
|
|
|
|
var metricInstrumentDeactivatedEvents = inMemoryEventListener.Events.Where((e) => e.EventId == 52);
|
|
|
|
Assert.Single(metricInstrumentDeactivatedEvents);
|
|
|
|
var metricInstrumentRemovedEvents = inMemoryEventListener.Events.Where((e) => e.EventId == 53);
|
|
|
|
Assert.Single(metricInstrumentRemovedEvents);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(false, MetricReaderTemporalityPreference.Delta)]
|
|
[InlineData(true, MetricReaderTemporalityPreference.Delta)]
|
|
[InlineData(false, MetricReaderTemporalityPreference.Cumulative)]
|
|
[InlineData(true, MetricReaderTemporalityPreference.Cumulative)]
|
|
public void ReloadOfMetricsViaIConfigurationWithoutExportCleanupTest(bool useWithMetricsStyle, MetricReaderTemporalityPreference temporalityPreference)
|
|
{
|
|
using var inMemoryEventListener = new InMemoryEventListener(OpenTelemetrySdkEventSource.Log);
|
|
|
|
using var meter = new Meter(Utils.GetCurrentMethodName());
|
|
List<Metric> exportedItems = new();
|
|
|
|
var source = new MemoryConfigurationSource();
|
|
var memory = new MemoryConfigurationProvider(source);
|
|
memory.Set($"Metrics:EnabledMetrics:{meter.Name}:Default", "true");
|
|
var configuration = new ConfigurationRoot([memory]);
|
|
|
|
using var host = MetricTestsBase.BuildHost(
|
|
useWithMetricsStyle,
|
|
configureAppConfiguration: (context, builder) => builder.AddConfiguration(configuration),
|
|
configureMeterProviderBuilder: builder => builder
|
|
.AddInMemoryExporter(exportedItems, reader => reader.TemporalityPreference = temporalityPreference));
|
|
|
|
var meterProvider = host.Services.GetRequiredService<MeterProvider>();
|
|
var options = host.Services.GetRequiredService<IOptionsMonitor<MetricsOptions>>();
|
|
|
|
var counter = meter.CreateCounter<long>("TestCounter");
|
|
counter.Add(1);
|
|
|
|
memory.Set($"Metrics:EnabledMetrics:{meter.Name}:Default", "false");
|
|
configuration.Reload();
|
|
counter.Add(1);
|
|
|
|
memory.Set($"Metrics:EnabledMetrics:{meter.Name}:Default", "true");
|
|
configuration.Reload();
|
|
counter.Add(1);
|
|
|
|
meterProvider.ForceFlush();
|
|
|
|
// Note: We end up with 2 of the same metric being exported. This is
|
|
// because the current behavior when something is deactivated is to
|
|
// remove the metric. The next publish creates a new metric.
|
|
Assert.Equal(2, exportedItems.Count);
|
|
|
|
AssertMetricWithLongSum(exportedItems[0]);
|
|
AssertMetricWithLongSum(exportedItems[1]);
|
|
|
|
exportedItems.Clear();
|
|
|
|
counter.Add(1);
|
|
|
|
meterProvider.ForceFlush();
|
|
|
|
AssertSingleMetricWithLongSum(
|
|
exportedItems,
|
|
expectedValue: temporalityPreference == MetricReaderTemporalityPreference.Delta ? 1 : 2);
|
|
|
|
var duplicateMetricInstrumentEvents = inMemoryEventListener.Events.Where((e) => e.EventId == 38);
|
|
|
|
// Note: We currently log a duplicate warning anytime a metric is reactivated.
|
|
Assert.Single(duplicateMetricInstrumentEvents);
|
|
|
|
var metricInstrumentDeactivatedEvents = inMemoryEventListener.Events.Where((e) => e.EventId == 52);
|
|
|
|
Assert.Single(metricInstrumentDeactivatedEvents);
|
|
|
|
var metricInstrumentRemovedEvents = inMemoryEventListener.Events.Where((e) => e.EventId == 53);
|
|
|
|
Assert.Single(metricInstrumentRemovedEvents);
|
|
}
|
|
|
|
private static void AssertSingleMetricWithLongSum(List<Metric> exportedItems, long expectedValue = 1)
|
|
{
|
|
Assert.Single(exportedItems);
|
|
|
|
AssertMetricWithLongSum(exportedItems[0], expectedValue);
|
|
}
|
|
|
|
private static void AssertMetricWithLongSum(Metric metric, long expectedValue = 1)
|
|
{
|
|
List<MetricPoint> metricPoints = new();
|
|
foreach (ref readonly var mp in metric.GetMetricPoints())
|
|
{
|
|
metricPoints.Add(mp);
|
|
}
|
|
|
|
Assert.Single(metricPoints);
|
|
|
|
var metricPoint = metricPoints[0];
|
|
Assert.Equal(expectedValue, metricPoint.GetSumLong());
|
|
}
|
|
}
|