public void TestAddOtlpExporter_SetsCorrectMetricReaderDefaults() { if (Environment.Version.Major == 3) { // Adding the OtlpExporter creates a GrpcChannel. // This switch must be set before creating a GrpcChannel when calling an insecure HTTP/2 endpoint. // See: https://docs.microsoft.com/aspnet/core/grpc/troubleshoot#call-insecure-grpc-services-with-net-core-client AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); } var meterProvider = Sdk.CreateMeterProviderBuilder() .AddOtlpExporter() .Build(); CheckMetricReaderDefaults(); meterProvider.Dispose(); meterProvider = Sdk.CreateMeterProviderBuilder() .AddOtlpExporter((exporterOptions, metricReaderOptions) => { metricReaderOptions.PeriodicExportingMetricReaderOptions = null; }) .Build(); CheckMetricReaderDefaults(); meterProvider.Dispose(); void CheckMetricReaderDefaults() { var bindingFlags = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance; var metricReader = typeof(MetricReader) .Assembly .GetType("OpenTelemetry.Metrics.MeterProviderSdk") .GetField("reader", bindingFlags) .GetValue(meterProvider) as PeriodicExportingMetricReader; Assert.NotNull(metricReader); var exportIntervalMilliseconds = (int)typeof(PeriodicExportingMetricReader) .GetField("ExportIntervalMilliseconds", bindingFlags) .GetValue(metricReader); Assert.Equal(60000, exportIntervalMilliseconds); } }
/// <summary>add MagicOnion Telemetry.</summary> public static IServiceCollection AddMagicOnionOpenTelemetry(this IServiceCollection services, MagicOnionOpenTelemetryOptions options, Action <MagicOnionOpenTelemetryOptions, MagicOnionOpenTelemetryMeterFactoryOption> configureMeterProvider, Action <MagicOnionOpenTelemetryOptions, IServiceProvider, TracerProviderBuilder> configureTracerProvider) { if (options == null) { throw new ArgumentNullException(nameof(options)); } services.AddSingleton(options); // configure MeterFactory if (configureMeterProvider != null) { var meterFactoryOption = new MagicOnionOpenTelemetryMeterFactoryOption(); configureMeterProvider(options, meterFactoryOption); MeterProvider.SetDefault(Sdk.CreateMeterProviderBuilder() .SetProcessor(meterFactoryOption.MetricProcessor) .SetExporter(meterFactoryOption.MetricExporter) .SetPushInterval(meterFactoryOption.MetricPushInterval) .Build()); services.AddSingleton(meterFactoryOption.MetricExporter); services.AddSingleton(MeterProvider.Default); } // configure TracerFactory if (configureTracerProvider != null) { if (string.IsNullOrEmpty(options.ActivitySourceName)) { throw new NullReferenceException(nameof(options.ActivitySourceName)); } var tracerFactory = services.AddOpenTelemetryTracerProvider((provider, builder) => { // ActivitySourceName must match to TracerName. builder.AddSource(options.ActivitySourceName); configureTracerProvider(options, provider, builder); }); services.AddSingleton(tracerFactory); services.AddSingleton(new ActivitySource(options.ActivitySourceName)); } return(services); }
public async Task PrometheusExporterMiddlewareIntegration_MeterProvider() { using MeterProvider meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(MeterName) .AddPrometheusExporter() .Build(); await RunPrometheusExporterMiddlewareIntegrationTest( "/metrics", app => app.UseOpenTelemetryPrometheusScrapingEndpoint( meterProvider: meterProvider, predicate: null, path: null, configureBranchedPipeline: null), registerMeterProvider : false).ConfigureAwait(false); }
internal static object Run(int port) { /* prometheus.yml * * global: * scrape_interval: 1s * evaluation_interval: 1s * * scrape_configs: * - job_name: "opentelemetry" * static_configs: * - targets: ["localhost:9184"] */ using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(MyMeter.Name) .AddPrometheusExporter(opt => { opt.StartHttpListener = true; opt.HttpListenerPrefixes = new string[] { $"http://localhost:{port}/" }; }) .Build(); var process = Process.GetCurrentProcess(); MyMeter.CreateObservableCounter("thread.cpu_time", () => GetThreadCpuTime(process), "ms"); using var token = new CancellationTokenSource(); Task.Run(() => { while (!token.IsCancellationRequested) { Counter.Add(9.9, new("name", "apple"), new("color", "red")); Counter.Add(99.9, new("name", "lemon"), new("color", "yellow")); MyHistogram.Record(ThreadLocalRandom.Value.Next(1, 1500), new("tag1", "value1"), new("tag2", "value2")); Task.Delay(10).Wait(); } }); System.Console.WriteLine($"PrometheusExporter is listening on http://localhost:{port}/metrics/"); System.Console.WriteLine($"Press any key to exit..."); System.Console.ReadKey(); token.Cancel(); return(null); }
public void MeterProvider_SetDefault() { var meterProvider = Sdk.CreateMeterProviderBuilder().Build(); MeterProvider.SetDefault(meterProvider); var defaultMeter = MeterProvider.Default.GetMeter(string.Empty); Assert.NotNull(defaultMeter); Assert.IsType <MeterSdk>(defaultMeter); Assert.NotSame(defaultMeter, MeterProvider.Default.GetMeter("named meter")); var counter = defaultMeter.CreateDoubleCounter("ctr"); Assert.IsType <DoubleCounterMetricSdk>(counter); }
public void Setup() { this.meter = new Meter(Utils.GetCurrentMethodName()); var exportedItems = new List <Metric>(); var reader = new PeriodicExportingMetricReader(new InMemoryExporter <Metric>(exportedItems), 1000) { Temporality = this.AggregationTemporality, }; this.provider = Sdk.CreateMeterProviderBuilder() .AddMeter(this.meter.Name) // All instruments from this meter are enabled. .AddReader(reader) .Build(); this.counter = this.meter.CreateCounter <long>("counter"); }
public void GaugeDoubleSubnormal() { var buffer = new byte[85000]; var metrics = new List <Metric>(); using var meter = new Meter(Utils.GetCurrentMethodName()); using var provider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddInMemoryExporter(metrics) .Build(); meter.CreateObservableGauge("test_gauge", () => new List <Measurement <double> > { new(double.NegativeInfinity, new("x", "1"), new("y", "2")), new(double.PositiveInfinity, new("x", "3"), new("y", "4")), new(double.NaN, new("x", "5"), new("y", "6")), });
public void SetupSdkProviderWithNoReader(bool hasViews) { // This test ensures that MeterProviderSdk can be set up without any reader using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{hasViews}"); var meterProviderBuilder = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name); if (hasViews) { meterProviderBuilder.AddView("counter", "renamedCounter"); } using var meterProvider = meterProviderBuilder.Build(); var counter = meter.CreateCounter <long>("counter"); counter.Add(10, new KeyValuePair <string, object>("key", "value")); }
public void ObserverCallbackExceptionTest() { using var meter = new Meter("ObserverCallbackErrorTest"); var exportedItems = new List <Metric>(); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddInMemoryExporter(exportedItems) .Build(); var measurement = new Measurement <int>(100, new("name", "apple"), new("color", "red")); meter.CreateObservableGauge("myGauge", () => measurement); meter.CreateObservableGauge <long>("myBadGauge", observeValues: () => throw new Exception("gauge read error")); meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Equal(2, exportedItems.Count); var metric = exportedItems[0]; Assert.Equal("myGauge", metric.Name); List <MetricPoint> metricPoints = new List <MetricPoint>(); foreach (ref var mp in metric.GetMetricPoints()) { metricPoints.Add(mp); } Assert.Single(metricPoints); var metricPoint = metricPoints[0]; Assert.Equal(100, metricPoint.LongValue); Assert.NotNull(metricPoint.Keys); Assert.NotNull(metricPoint.Values); metric = exportedItems[1]; Assert.Equal("myBadGauge", metric.Name); metricPoints.Clear(); foreach (ref var mp in metric.GetMetricPoints()) { metricPoints.Add(mp); } Assert.Empty(metricPoints); }
public void DuplicateInstrumentNamesFromDifferentMetersAreAllowed(AggregationTemporality temporality, bool hasView) { var metricItems = new List <Metric>(); var metricExporter = new InMemoryExporter <Metric>(metricItems); var metricReader = new BaseExportingMetricReader(metricExporter) { PreferredAggregationTemporality = temporality, }; using var meter1 = new Meter($"{Utils.GetCurrentMethodName()}.1.{temporality}"); using var meter2 = new Meter($"{Utils.GetCurrentMethodName()}.2.{temporality}"); var meterProviderBuilder = Sdk.CreateMeterProviderBuilder() .AddMeter(meter1.Name) .AddMeter(meter2.Name) .AddReader(metricReader); if (hasView) { meterProviderBuilder.AddView("name1", new MetricStreamConfiguration() { Description = "description" }); } using var meterProvider = meterProviderBuilder.Build(); // Expecting one metric stream. var counterLong = meter1.CreateCounter <long>("name1"); counterLong.Add(10); metricReader.Collect(); Assert.Single(metricItems); // The following will not be ignored // as it is the same metric name but different meter. var anotherCounterSameNameDiffMeter = meter2.CreateCounter <long>("name1"); anotherCounterSameNameDiffMeter.Add(10); counterLong.Add(10); metricItems.Clear(); metricReader.Collect(); Assert.Equal(2, metricItems.Count); }
public void ViewToRenameMetricConditionally() { using var meter1 = new Meter($"{Utils.GetCurrentMethodName()}.1"); using var meter2 = new Meter($"{Utils.GetCurrentMethodName()}.2"); var exportedItems = new List <Metric>(); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter1.Name) .AddMeter(meter2.Name) .AddView((instrument) => { if (instrument.Meter.Name.Equals(meter2.Name, StringComparison.OrdinalIgnoreCase) && instrument.Name.Equals("name1", StringComparison.OrdinalIgnoreCase)) { return(new MetricStreamConfiguration() { Name = "name1_Renamed", Description = "new description" }); } else { return(null); } }) .AddInMemoryExporter(exportedItems) .Build(); // Without views only 1 stream would be // exported (the 2nd one gets dropped due to // name conflict). Due to renaming with Views, // we expect 2 metric streams here. var counter1 = meter1.CreateCounter <long>("name1", "unit", "original_description"); var counter2 = meter2.CreateCounter <long>("name1", "unit", "original_description"); counter1.Add(10); counter2.Add(10); meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Equal(2, exportedItems.Count); Assert.Equal("name1", exportedItems[0].Name); Assert.Equal("name1_Renamed", exportedItems[1].Name); Assert.Equal("original_description", exportedItems[0].Description); Assert.Equal("new description", exportedItems[1].Description); }
public void FlushMetricExporterTest(ExportModes mode) { BaseExporter <Metric> exporter = null; switch (mode) { case ExportModes.Push: exporter = new PushOnlyMetricExporter(); break; case ExportModes.Pull: exporter = new PullOnlyMetricExporter(); break; case ExportModes.Pull | ExportModes.Push: exporter = new PushPullMetricExporter(); break; } var reader = new BaseExportingMetricReader(exporter); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddReader(reader) .Build(); switch (mode) { case ExportModes.Push: Assert.True(reader.Collect()); Assert.True(meterProvider.ForceFlush()); break; case ExportModes.Pull: Assert.False(reader.Collect()); Assert.False(meterProvider.ForceFlush()); Assert.True((exporter as IPullMetricExporter).Collect(-1)); break; case ExportModes.Pull | ExportModes.Push: Assert.True(reader.Collect()); Assert.True(meterProvider.ForceFlush()); break; } }
public void DuplicateInstrumentNamesFromSameMeterAreNotAllowed(AggregationTemporality temporality, bool hasView) { var metricItems = new List <Metric>(); var metricExporter = new InMemoryExporter <Metric>(metricItems); var metricReader = new BaseExportingMetricReader(metricExporter) { PreferredAggregationTemporality = temporality, }; using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}"); var meterProviderBuilder = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddReader(metricReader); if (hasView) { meterProviderBuilder.AddView("name1", new MetricStreamConfiguration() { Description = "description" }); } using var meterProvider = meterProviderBuilder.Build(); // Expecting one metric stream. var counterLong = meter.CreateCounter <long>("name1"); counterLong.Add(10); metricReader.Collect(); Assert.Single(metricItems); // The following will be ignored as // metric of same name exists. // Metric stream will remain one. var anotherCounterSameName = meter.CreateCounter <long>("name1"); anotherCounterSameName.Add(10); counterLong.Add(10); metricItems.Clear(); metricReader.Collect(); Assert.Single(metricItems); }
public void MeterProvider_UpdateDefault_CachedTracer() { var defaultMeter = MeterProvider.Default.GetMeter(string.Empty); var noOpCounter = defaultMeter.CreateDoubleCounter("ctr"); Assert.IsType <NoopCounterMetric <double> >(noOpCounter); var meterProvider = Sdk.CreateMeterProviderBuilder().Build(); MeterProvider.SetDefault(meterProvider); var counter = defaultMeter.CreateDoubleCounter("ctr"); Assert.IsType <DoubleCounterMetricSdk>(counter); var newdefaultMeter = MeterProvider.Default.GetMeter(string.Empty); Assert.NotSame(defaultMeter, newdefaultMeter); Assert.IsType <MeterSdk>(newdefaultMeter); }
public static void Main(string[] args) { using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter("MyCompany.MyProduct.MyLibrary") .AddPrometheusExporter(options => { options.StartHttpListener = true; }) .Build(); Console.WriteLine("Press any key to exit"); while (!Console.KeyAvailable) { Thread.Sleep(1000); MyFruitCounter.Add(1, new("name", "apple"), new("color", "red")); MyFruitCounter.Add(2, new("name", "lemon"), new("color", "yellow")); MyFruitCounter.Add(1, new("name", "lemon"), new("color", "yellow")); MyFruitCounter.Add(2, new("name", "apple"), new("color", "green")); MyFruitCounter.Add(5, new("name", "apple"), new("color", "red")); MyFruitCounter.Add(4, new("name", "lemon"), new("color", "yellow")); } }
public void UserHttpFactoryCalled() { OtlpExporterOptions options = new OtlpExporterOptions(); var defaultFactory = options.HttpClientFactory; int invocations = 0; options.Protocol = OtlpExportProtocol.HttpProtobuf; options.HttpClientFactory = () => { invocations++; return(defaultFactory()); }; using (var exporter = new OtlpMetricExporter(options)) { Assert.Equal(1, invocations); } using (var provider = Sdk.CreateMeterProviderBuilder() .AddOtlpExporter(o => { o.Protocol = OtlpExportProtocol.HttpProtobuf; o.HttpClientFactory = options.HttpClientFactory; }) .Build()) { Assert.Equal(2, invocations); } options.HttpClientFactory = null; Assert.Throws <InvalidOperationException>(() => { using var exporter = new OtlpMetricExporter(options); }); options.HttpClientFactory = () => null; Assert.Throws <InvalidOperationException>(() => { using var exporter = new OtlpMetricExporter(options); }); }
public static void Main() { for (int i = 0; i < ArraySize; i++) { DimensionValues[i] = $"DimValue{i}"; } using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(TestMeter.Name) .AddPrometheusExporter(options => { options.StartHttpListener = true; options.HttpListenerPrefixes = new string[] { $"http://localhost:9185/" }; options.ScrapeResponseCacheDurationMilliseconds = 0; }) .Build(); Stress(prometheusPort: 9184); }
public void ValidateZeroDimension(MetricType metricType) { var metrics = new List <Metric>(); using var meter = new Meter(nameof(ValidateZeroDimension)); using var provider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddInMemoryExporter(metrics) .Build(); var dataPointType = DataPointType.Aggregation; string name = null; if (metricType == MetricType.DoubleSum) { name = "TestDoubleCounter"; var doubleCounter = meter.CreateCounter <double>(name); doubleCounter.Add(123.45); } else if (metricType == MetricType.DoubleGauge) { name = "TestGauge"; meter.CreateObservableGauge(name, () => 123.45); dataPointType = DataPointType.Measurement; } provider.ForceFlush(); var enumerator = metrics[0].GetMetricPoints().GetEnumerator(); enumerator.MoveNext(); var metricPoint = enumerator.Current; var metricData = new MetricsData(Version, metrics[0], ref metricPoint); Assert.Equal(2, metricData.Version); Assert.Equal(name, metricData.Metrics.First().Name); Assert.Equal(123.45, metricData.Metrics.First().Value); Assert.Equal(dataPointType, metricData.Metrics.First().DataPointType); // Properties will contain _MS.AggregationIntervalMs Assert.Equal(1, metricData.Properties.Count); }
public void ObservableInstrumentCallbacksInvokedForEachReaders(bool hasViews) { var exportedItems1 = new List <Metric>(); var exportedItems2 = new List <Metric>(); using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{hasViews}"); int callbackInvocationCount = 0; var gauge = meter.CreateObservableGauge("gauge", () => { callbackInvocationCount++; return(10 * callbackInvocationCount); }); var meterProviderBuilder = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddInMemoryExporter(exportedItems1) .AddInMemoryExporter(exportedItems2); if (hasViews) { meterProviderBuilder.AddView("gauge", "renamedGauge"); } using var meterProvider = meterProviderBuilder.Build(); meterProvider.ForceFlush(); // VALIDATE Assert.Equal(2, callbackInvocationCount); Assert.Single(exportedItems1); Assert.Single(exportedItems2); if (hasViews) { Assert.Equal("renamedGauge", exportedItems1[0].Name); Assert.Equal("renamedGauge", exportedItems2[0].Name); } else { Assert.Equal("gauge", exportedItems1[0].Name); Assert.Equal("gauge", exportedItems2[0].Name); } }
public void GlobalSetup() { this.meter = new Meter(Utils.GetCurrentMethodName()); this.meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(this.meter.Name) .AddInMemoryExporter(this.metrics) .Build(); var counter = this.meter.CreateCounter <long>("counter_name_1", "long", "counter_name_1_description"); counter.Add(18, new("label1", "value1"), new("label2", "value2")); var gauge = this.meter.CreateObservableGauge("gauge_name_1", () => 18.0D, "long", "gauge_name_1_description"); var histogram = this.meter.CreateHistogram <long>("histogram_name_1", "long", "histogram_name_1_description"); histogram.Record(100, new("label1", "value1"), new("label2", "value2")); this.meterProvider.ForceFlush(); }
public void InstrumentWithInvalidNameIsIgnoredTest(string instrumentName) { var exportedItems = new List <Metric>(); using var meter = new Meter("InstrumentWithInvalidNameIsIgnoredTest"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddInMemoryExporter(exportedItems) .Build(); var counterLong = meter.CreateCounter <long>(instrumentName); counterLong.Add(10); meterProvider.ForceFlush(MaxTimeToAllowForFlush); // instrument should have been ignored // as its name does not comply with the specification Assert.Empty(exportedItems); }
public void ViewConflict_TwoInstruments_ConflictAvoidedBecauseSecondInstrumentIsDropped() { var exportedItems = new List <Metric>(); using var meter = new Meter($"{Utils.GetCurrentMethodName()}"); var meterProviderBuilder = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddView((instrument) => { if (instrument.Name == "name") { return(new MetricStreamConfiguration { Name = "othername" }); } else { return(MetricStreamConfiguration.Drop); } }) .AddInMemoryExporter(exportedItems); using var meterProvider = meterProviderBuilder.Build(); var instrument1 = meter.CreateCounter <long>("name"); var instrument2 = meter.CreateCounter <long>("othername"); instrument1.Add(10); instrument2.Add(20); meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Single(exportedItems); var metric1 = new List <Metric>() { exportedItems[0] }; Assert.Equal("othername", exportedItems[0].Name); Assert.Equal(10, GetLongSum(metric1)); }
public void ViewToDropSingleInstrumentObservableGauge() { using var meter = new Meter(Utils.GetCurrentMethodName()); var exportedItems = new List <Metric>(); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddView("observableGaugeNotInteresting", MetricStreamConfiguration.Drop) .AddInMemoryExporter(exportedItems) .Build(); // Expecting one metric stream. meter.CreateObservableGauge("observableGaugeNotInteresting", () => { return(10); }, "ms"); meter.CreateObservableGauge("observableGaugeInteresting", () => { return(10); }, "ms"); meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Single(exportedItems); var metric = exportedItems[0]; Assert.Equal("observableGaugeInteresting", metric.Name); }
public void ViewToProduceMultipleStreamsFromInstrument() { using var meter = new Meter(Utils.GetCurrentMethodName()); var exportedItems = new List <Metric>(); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddView("name1", "renamedStream1") .AddView("name1", "renamedStream2") .AddInMemoryExporter(exportedItems) .Build(); // Expecting two metric stream. var counterLong = meter.CreateCounter <long>("name1"); counterLong.Add(10); meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Equal(2, exportedItems.Count); Assert.Equal("renamedStream1", exportedItems[0].Name); Assert.Equal("renamedStream2", exportedItems[1].Name); }
public void ViewToRenameMetric() { using var meter = new Meter(Utils.GetCurrentMethodName()); var exportedItems = new List <Metric>(); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddView("name1", "renamed") .AddInMemoryExporter(exportedItems) .Build(); // Expecting one metric stream. var counterLong = meter.CreateCounter <long>("name1"); counterLong.Add(10); meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Single(exportedItems); var metric = exportedItems[0]; Assert.Equal("renamed", metric.Name); }
public void ProcessMetricsAreCaptured() { var exportedItems = new List <Metric>(); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddRuntimeMetrics(options => { options.ProcessEnabled = true; }) .AddInMemoryExporter(exportedItems) .Build(); // simple CPU spinning var spinDuration = DateTime.UtcNow.AddMilliseconds(10); while (DateTime.UtcNow < spinDuration) { } meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Equal(4, exportedItems.Count); var cpuTimeMetric = exportedItems.First(i => i.Name == "process.cpu.time"); var sumReceived = GetDoubleSum(cpuTimeMetric); Assert.True(sumReceived > 0); var cpuCountMetric = exportedItems.First(i => i.Name == "process.cpu.count"); Assert.Equal(Environment.ProcessorCount, (int)GetLongSum(cpuCountMetric)); var memoryMetric = exportedItems.First(i => i.Name == "process.memory.usage"); Assert.True(GetLongSum(memoryMetric) > 0); var virtualMemoryMetric = exportedItems.First(i => i.Name == "process.memory.virtual"); Assert.True(GetLongSum(virtualMemoryMetric) > 0); }
public static async Task Main(string[] args) { using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddSource("TestMeter") .AddConsoleExporter() .Build(); ObservableGauge <long> gauge = MyMeter.CreateObservableGauge <long>( "Gauge", () => { var tag1 = new KeyValuePair <string, object>("tag1", "value1"); var tag2 = new KeyValuePair <string, object>("tag2", "value2"); return(new List <Measurement <long> >() { new Measurement <long>(RandomGenerator.Next(1, 1000), tag1, tag2), }); }); await Task.Delay(10000); }
public void ViewWithNullCustomNameTakesInstrumentName() { var exportedItems = new List <Metric>(); using var meter = new Meter("ViewToRenameMetricConditionallyTest"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddView((instrument) => { if (instrument.Name.Equals("name1", StringComparison.OrdinalIgnoreCase)) { // null View name return(new MetricStreamConfiguration() { }); } else { return(null); } }) .AddInMemoryExporter(exportedItems) .Build(); // Expecting one metric stream. // Since the View name was null, the instrument name was used instead var counter1 = meter.CreateCounter <long>("name1", "unit", "original_description"); counter1.Add(10); meterProvider.ForceFlush(MaxTimeToAllowForFlush); // Expecting one metric stream. Assert.Single(exportedItems); var metric = exportedItems[0]; Assert.Equal(counter1.Name, metric.Name); }
public void ViewWithValidNameConditionally(string viewNewName) { using var meter1 = new Meter("ViewToRenameMetricConditionallyTest"); var exportedItems = new List <Metric>(); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter1.Name) .AddView((instrument) => { if (instrument.Meter.Name.Equals(meter1.Name, StringComparison.OrdinalIgnoreCase) && instrument.Name.Equals("name1", StringComparison.OrdinalIgnoreCase)) { // invalid instrument name as per the spec return(new MetricStreamConfiguration() { Name = viewNewName, Description = "new description" }); } else { return(null); } }) .AddInMemoryExporter(exportedItems) .Build(); // Expecting one metric stream. var counter1 = meter1.CreateCounter <long>("name1", "unit", "original_description"); counter1.Add(10); meterProvider.ForceFlush(MaxTimeToAllowForFlush); // Expecting one metric stream. Assert.Single(exportedItems); var metric = exportedItems[0]; Assert.Equal(viewNewName, metric.Name); }
public void ViewWithInvalidNameIgnoredConditionally(string viewNewName) { using var meter1 = new Meter("ViewToRenameMetricConditionallyTest"); var exportedItems = new List <Metric>(); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter1.Name) // since here it's a func, we can't validate the name right away // so the view is allowed to be added, but upon instrument creation it's going to be ignored. .AddView((instrument) => { if (instrument.Meter.Name.Equals(meter1.Name, StringComparison.OrdinalIgnoreCase) && instrument.Name.Equals("name1", StringComparison.OrdinalIgnoreCase)) { // invalid instrument name as per the spec return(new MetricStreamConfiguration() { Name = viewNewName, Description = "new description" }); } else { return(null); } }) .AddInMemoryExporter(exportedItems) .Build(); // Because the MetricStreamName passed is invalid, the view is ignored, // and default aggregation is used. var counter1 = meter1.CreateCounter <long>("name1", "unit", "original_description"); counter1.Add(10); meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Single(exportedItems); }