public void CheckForceFlushWithInvalidTimeout() { var exportedItems = new List <Activity>(); using var exporter = new InMemoryExporter <Activity>(exportedItems); using var processor = new BatchExportProcessor <Activity>(exporter, maxQueueSize: 2, maxExportBatchSize: 1); Assert.Throws <ArgumentOutOfRangeException>(() => processor.ForceFlush(-2)); }
public void CheckExporterLoad() { InMemoryExporter exporter = new InMemoryExporter(); var ts = new TestScenario("test", exporter); var someMovie = ts.GetEntity <Entites.Movie>(); Assert.Equal("Back to the Future", someMovie.Title); }
public void ObservableCounterAggregationTest(bool exportDelta) { var metricItems = new List <Metric>(); var metricExporter = new InMemoryExporter <Metric>(metricItems); var metricReader = new BaseExportingMetricReader(metricExporter) { PreferredAggregationTemporality = exportDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative, }; using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}"); int i = 1; var counterLong = meter.CreateObservableCounter( "observable-counter", () => { return(new List <Measurement <long> >() { new Measurement <long>(i++ *10), }); }); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddReader(metricReader) .Build(); metricReader.Collect(); long sumReceived = GetLongSum(metricItems); Assert.Equal(10, sumReceived); metricItems.Clear(); metricReader.Collect(); sumReceived = GetLongSum(metricItems); if (exportDelta) { Assert.Equal(10, sumReceived); } else { Assert.Equal(20, sumReceived); } metricItems.Clear(); metricReader.Collect(); sumReceived = GetLongSum(metricItems); if (exportDelta) { Assert.Equal(10, sumReceived); } else { Assert.Equal(30, sumReceived); } }
public void TestInstrumentDisposal(AggregationTemporality temporality) { var metricItems = new List <Metric>(); var metricExporter = new InMemoryExporter <Metric>(metricItems); var metricReader = new BaseExportingMetricReader(metricExporter) { PreferredAggregationTemporality = temporality, }; var meter1 = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}.1"); var meter2 = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}.2"); var counter1 = meter1.CreateCounter <long>("counterFromMeter1"); var counter2 = meter2.CreateCounter <long>("counterFromMeter2"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter1.Name) .AddMeter(meter2.Name) .AddReader(metricReader) .Build(); counter1.Add(10, new KeyValuePair <string, object>("key", "value")); counter2.Add(10, new KeyValuePair <string, object>("key", "value")); metricReader.Collect(); Assert.Equal(2, metricItems.Count); metricItems.Clear(); counter1.Add(10, new KeyValuePair <string, object>("key", "value")); counter2.Add(10, new KeyValuePair <string, object>("key", "value")); meter1.Dispose(); metricReader.Collect(); Assert.Equal(2, metricItems.Count); metricItems.Clear(); counter1.Add(10, new KeyValuePair <string, object>("key", "value")); counter2.Add(10, new KeyValuePair <string, object>("key", "value")); metricReader.Collect(); Assert.Single(metricItems); metricItems.Clear(); counter1.Add(10, new KeyValuePair <string, object>("key", "value")); counter2.Add(10, new KeyValuePair <string, object>("key", "value")); meter2.Dispose(); metricReader.Collect(); Assert.Single(metricItems); metricItems.Clear(); counter1.Add(10, new KeyValuePair <string, object>("key", "value")); counter2.Add(10, new KeyValuePair <string, object>("key", "value")); metricReader.Collect(); Assert.Empty(metricItems); }
public void CheckExporterSave() { InMemoryExporter exporter = new InMemoryExporter(); var ts = new TestScenario("test", exporter); var someMovie = ts.GetEntity <Entites.Movie>(); someMovie.Title = "Back to the Future"; exporter.Save(); Assert.True(!exporter.IsNew); }
public void CheckExportedOnEnd() { var exported = new List <object>(); using var exporter = new InMemoryExporter <Activity>(new InMemoryExporterOptions { ExportedItems = exported }); using var processor = new SimpleExportProcessor <Activity>(exporter); processor.OnEnd(new Activity("start1")); Assert.Single(exported); processor.OnEnd(new Activity("start2")); Assert.Equal(2, exported.Count); }
public void CheckExportForRecordingButNotSampledActivity() { var exportedItems = new List <Activity>(); using var exporter = new InMemoryExporter <Activity>(exportedItems); using var processor = new SimpleActivityExportProcessor(exporter); var activity = new Activity("start"); activity.ActivityTraceFlags = ActivityTraceFlags.None; processor.OnEnd(activity); Assert.Empty(exportedItems); }
public void CheckShutdownExport(int timeout) { var exported = new List <object>(); using var exporter = new InMemoryExporter <Activity>(new InMemoryExporterOptions { ExportedItems = exported }); using var processor = new SimpleExportProcessor <Activity>(exporter); processor.OnEnd(new Activity("start")); // checking before shutdown Assert.Single(exported); processor.Shutdown(timeout); Assert.Single(exported); }
public void CheckForceFlushExport(int timeout) { var exported = new List <object>(); using var exporter = new InMemoryExporter <Activity>(new InMemoryExporterOptions { ExportedItems = exported }); using var processor = new SimpleExportProcessor <Activity>(exporter); processor.OnEnd(new Activity("start1")); processor.OnEnd(new Activity("start2")); // checking before force flush Assert.Equal(2, exported.Count); // forcing flush processor.ForceFlush(timeout); Assert.Equal(2, exported.Count); }
public void CheckForceFlushExport(int timeout) { var exportedItems = new List <Activity>(); using var exporter = new InMemoryExporter <Activity>(exportedItems); using var processor = new BatchActivityExportProcessor( exporter, maxQueueSize: 3, maxExportBatchSize: 3, exporterTimeoutMilliseconds: 30000); var activity1 = new Activity("start1") { ActivityTraceFlags = ActivityTraceFlags.Recorded, }; var activity2 = new Activity("start2") { ActivityTraceFlags = ActivityTraceFlags.Recorded, }; processor.OnEnd(activity1); processor.OnEnd(activity2); Assert.Equal(0, processor.ProcessedCount); // waiting to see if time is triggering the exporter Thread.Sleep(1_000); Assert.Empty(exportedItems); // forcing flush processor.ForceFlush(timeout); if (timeout == 0) { // ForceFlush(0) will trigger flush and return immediately, so let's sleep for a while Thread.Sleep(1_000); } Assert.Equal(2, exportedItems.Count); Assert.Equal(2, processor.ProcessedCount); Assert.Equal(2, processor.ReceivedCount); Assert.Equal(0, processor.DroppedCount); }
private static MeterProviderBuilder AddInMemoryExporter( MeterProviderBuilder builder, ICollection <Metric> exportedItems, MetricReaderOptions metricReaderOptions, Action <MetricReaderOptions> configureMetricReader) { configureMetricReader?.Invoke(metricReaderOptions); var metricExporter = new InMemoryExporter <Metric>(exportedItems); var metricReader = PeriodicExportingMetricReaderHelper.CreatePeriodicExportingMetricReader( metricExporter, metricReaderOptions, DefaultExportIntervalMilliseconds, DefaultExportTimeoutMilliseconds); return(builder.AddReader(metricReader)); }
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 CheckShutdownExport(int timeout) { var exportedItems = new List <Activity>(); using var exporter = new InMemoryExporter <Activity>(exportedItems); using var processor = new SimpleActivityExportProcessor(exporter); var activity = new Activity("start"); activity.ActivityTraceFlags = ActivityTraceFlags.Recorded; processor.OnEnd(activity); // checking before shutdown Assert.Single(exportedItems); processor.Shutdown(timeout); Assert.Single(exportedItems); }
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 CheckExportDrainsBatchOnFailure() { using var exporter = new InMemoryExporter <Activity>(null); using var processor = new BatchActivityExportProcessor( exporter, maxQueueSize: 3, maxExportBatchSize: 3); var activity = new Activity("start"); activity.ActivityTraceFlags = ActivityTraceFlags.Recorded; processor.OnEnd(activity); processor.OnEnd(activity); processor.OnEnd(activity); processor.Shutdown(); Assert.Equal(3, processor.ProcessedCount); // Verify batch was drained even though nothing was exported. }
public void CheckExportForRecordingButNotSampledActivity() { var exportedItems = new List <Activity>(); using var exporter = new InMemoryExporter <Activity>(exportedItems); using var processor = new BatchActivityExportProcessor( exporter, maxQueueSize: 1, maxExportBatchSize: 1); var activity = new Activity("start"); activity.ActivityTraceFlags = ActivityTraceFlags.None; processor.OnEnd(activity); processor.Shutdown(); Assert.Empty(exportedItems); Assert.Equal(0, processor.ProcessedCount); }
public void CheckExportedOnEnd() { var exportedItems = new List <Activity>(); using var exporter = new InMemoryExporter <Activity>(exportedItems); using var processor = new SimpleActivityExportProcessor(exporter); var activity1 = new Activity("start1"); activity1.ActivityTraceFlags = ActivityTraceFlags.Recorded; processor.OnEnd(activity1); Assert.Single(exportedItems); var activity2 = new Activity("start2"); activity2.ActivityTraceFlags = ActivityTraceFlags.Recorded; processor.OnEnd(activity2); Assert.Equal(2, exportedItems.Count); }
public void CheckStateCanBeSetByProcessor() { var exportedItems = new List <LogRecord>(); var exporter = new InMemoryExporter <LogRecord>(exportedItems); using var loggerFactory = LoggerFactory.Create(builder => { builder.AddOpenTelemetry(options => { options.AddProcessor(new RedactionProcessor(Field.State)); options.AddInMemoryExporter(exportedItems); }); }); var logger = loggerFactory.CreateLogger <LogRecordTest>(); logger.LogInformation($"This does not matter."); var state = exportedItems[0].State as IReadOnlyList <KeyValuePair <string, object> >; Assert.Equal("newStateKey", state[0].Key.ToString()); Assert.Equal("newStateValue", state[0].Value.ToString()); }
public void CheckStateValuesCanBeSetByProcessor() { var exportedItems = new List <LogRecord>(); var exporter = new InMemoryExporter <LogRecord>(exportedItems); using var loggerFactory = LoggerFactory.Create(builder => { builder.AddOpenTelemetry(options => { options.AddProcessor(new RedactionProcessor(Field.StateValues)); options.AddInMemoryExporter(exportedItems); options.ParseStateValues = true; }); }); var logger = loggerFactory.CreateLogger <LogRecordTest>(); logger.LogInformation("This does not matter."); var stateValue = exportedItems[0]; Assert.Equal(new KeyValuePair <string, object>("newStateValueKey", "newStateValueValue"), stateValue.StateValues[0]); }
public void CheckFormattedMessageCanBeSetByProcessor() { var exportedItems = new List <LogRecord>(); var exporter = new InMemoryExporter <LogRecord>(exportedItems); using var loggerFactory = LoggerFactory.Create(builder => { builder.AddOpenTelemetry(options => { options.AddProcessor(new RedactionProcessor(Field.FormattedMessage)); options.AddInMemoryExporter(exportedItems); options.IncludeFormattedMessage = true; }); }); var logger = loggerFactory.CreateLogger <LogRecordTest>(); logger.LogInformation("OpenTelemetry {Greeting} {Subject}!", "Hello", "World"); var item = exportedItems[0]; Assert.Equal("OpenTelemetry Good Night!", item.FormattedMessage); }
private static void VerifyResourceBuilder( Action <Resource> assert) { // Setup using var exporter = new InMemoryExporter <LogRecord>(new List <LogRecord>()); using var loggerFactory = LoggerFactory.Create(builder => { builder.AddOpenTelemetry(options => { options.AddProcessor(new SimpleLogRecordExportProcessor(exporter)); }); }); var logger = loggerFactory.CreateLogger <LoggerFactoryAndResourceBuilderTests>(); var provider = exporter.ParentProvider as OpenTelemetryLoggerProvider; Assert.NotNull(provider); var resource = provider.GetResource(); Assert.NotNull(resource); // Verify assert.Invoke(resource); }
public void CheckIfBatchIsExportingOnQueueLimit() { var exportedItems = new List <Activity>(); using var exporter = new InMemoryExporter <Activity>(exportedItems); using var processor = new BatchExportProcessor <Activity>( exporter, maxQueueSize: 1, maxExportBatchSize: 1, scheduledDelayMilliseconds: 100_000); processor.OnEnd(new Activity("start")); for (int i = 0; i < 10 && exportedItems.Count == 0; i++) { Thread.Sleep(500); } Assert.Single(exportedItems); Assert.Equal(1, processor.ProcessedCount); Assert.Equal(1, processor.ReceivedCount); Assert.Equal(0, processor.DroppedCount); }
public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpTestData.HttpOutTestCase tc) { var serverLifeTime = TestHttpServer.RunServer( (ctx) => { ctx.Response.StatusCode = tc.ResponseCode == 0 ? 200 : tc.ResponseCode; ctx.Response.OutputStream.Close(); }, out var host, out var port); var processor = new Mock <BaseProcessor <Activity> >(); tc.Url = HttpTestData.NormalizeValues(tc.Url, host, port); var metricItems = new List <Metric>(); var metricExporter = new InMemoryExporter <Metric>(metricItems); var metricReader = new BaseExportingMetricReader(metricExporter) { Temporality = AggregationTemporality.Cumulative, }; var meterProvider = Sdk.CreateMeterProviderBuilder() .AddHttpClientInstrumentation() .AddReader(metricReader) .Build(); using (serverLifeTime) using (Sdk.CreateTracerProviderBuilder() .AddHttpClientInstrumentation((opt) => { opt.SetHttpFlavor = tc.SetHttpFlavor; opt.Enrich = ActivityEnrichment; opt.RecordException = tc.RecordException.HasValue ? tc.RecordException.Value : false; }) .AddProcessor(processor.Object) .Build()) { try { using var c = new HttpClient(); var request = new HttpRequestMessage { RequestUri = new Uri(tc.Url), Method = new HttpMethod(tc.Method), Version = new Version(2, 0), }; if (tc.Headers != null) { foreach (var header in tc.Headers) { request.Headers.Add(header.Key, header.Value); } } await c.SendAsync(request); } catch (Exception) { // test case can intentionally send request that will result in exception } } meterProvider.Dispose(); var requestMetrics = metricItems .Where(metric => metric.Name == "http.client.duration") .ToArray(); Assert.Equal(5, processor.Invocations.Count); // SetParentProvider/OnStart/OnEnd/OnShutdown/Dispose called. var activity = (Activity)processor.Invocations[2].Arguments[0]; Assert.Equal(ActivityKind.Client, activity.Kind); Assert.Equal(tc.SpanName, activity.DisplayName); // Assert.Equal(tc.SpanStatus, d[span.Status.CanonicalCode]); Assert.Equal( tc.SpanStatus, activity.GetTagValue(SpanAttributeConstants.StatusCodeKey) as string); if (tc.SpanStatusHasDescription.HasValue) { var desc = activity.GetTagValue(SpanAttributeConstants.StatusDescriptionKey) as string; Assert.Equal(tc.SpanStatusHasDescription.Value, !string.IsNullOrEmpty(desc)); } var normalizedAttributes = activity.TagObjects.Where(kv => !kv.Key.StartsWith("otel.")).ToImmutableSortedDictionary(x => x.Key, x => x.Value.ToString()); var normalizedAttributesTestCase = tc.SpanAttributes.ToDictionary(x => x.Key, x => HttpTestData.NormalizeValues(x.Value, host, port)); Assert.Equal(normalizedAttributesTestCase.Count, normalizedAttributes.Count); foreach (var kv in normalizedAttributesTestCase) { Assert.Contains(activity.TagObjects, i => i.Key == kv.Key && i.Value.ToString().Equals(kv.Value, StringComparison.InvariantCultureIgnoreCase)); } if (tc.RecordException.HasValue && tc.RecordException.Value) { Assert.Single(activity.Events.Where(evt => evt.Name.Equals("exception"))); } if (tc.ResponseExpected) { Assert.Single(requestMetrics); var metric = requestMetrics[0]; Assert.NotNull(metric); Assert.True(metric.MetricType == MetricType.Histogram); var metricPoints = new List <MetricPoint>(); foreach (var p in metric.GetMetricPoints()) { metricPoints.Add(p); } Assert.Single(metricPoints); var metricPoint = metricPoints[0]; var count = metricPoint.GetHistogramCount(); var sum = metricPoint.GetHistogramSum(); Assert.Equal(1L, count); Assert.Equal(activity.Duration.TotalMilliseconds, sum); var attributes = new KeyValuePair <string, object> [metricPoint.Tags.Count]; int i = 0; foreach (var tag in metricPoint.Tags) { attributes[i++] = tag; } var method = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpMethod, tc.Method); var scheme = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpScheme, "http"); var statusCode = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpStatusCode, tc.ResponseCode == 0 ? 200 : tc.ResponseCode); var flavor = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpFlavor, "2.0"); Assert.Contains(method, attributes); Assert.Contains(scheme, attributes); Assert.Contains(statusCode, attributes); Assert.Contains(flavor, attributes); Assert.Equal(4, attributes.Length); } else { Assert.Empty(requestMetrics); } }
public void SdkSupportsMultipleReaders(AggregationTemporality aggregationTemporality, bool hasViews) { var exportedItems1 = new List <Metric>(); using var deltaExporter1 = new InMemoryExporter <Metric>(exportedItems1); using var deltaReader1 = new BaseExportingMetricReader(deltaExporter1) { Temporality = AggregationTemporality.Delta, }; var exportedItems2 = new List <Metric>(); using var deltaExporter2 = new InMemoryExporter <Metric>(exportedItems2); using var deltaReader2 = new BaseExportingMetricReader(deltaExporter2) { Temporality = aggregationTemporality, }; using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{aggregationTemporality}.{hasViews}"); var counter = meter.CreateCounter <long>("counter"); int index = 0; var values = new long[] { 100, 200, 300, 400 }; long GetValue() => values[index++]; var gauge = meter.CreateObservableGauge("gauge", () => GetValue()); var meterProviderBuilder = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddReader(deltaReader1) .AddReader(deltaReader2); if (hasViews) { meterProviderBuilder.AddView("counter", "renamedCounter"); } using var meterProvider = meterProviderBuilder.Build(); counter.Add(10, new KeyValuePair <string, object>("key", "value")); meterProvider.ForceFlush(); Assert.Equal(2, exportedItems1.Count); Assert.Equal(2, exportedItems2.Count); // Check value exported for Counter this.AssertLongSumValueForMetric(exportedItems1[0], 10); this.AssertLongSumValueForMetric(exportedItems2[0], 10); // Check value exported for Gauge this.AssertLongSumValueForMetric(exportedItems1[1], 100); this.AssertLongSumValueForMetric(exportedItems2[1], 200); exportedItems1.Clear(); exportedItems2.Clear(); counter.Add(15, new KeyValuePair <string, object>("key", "value")); meterProvider.ForceFlush(); Assert.Equal(2, exportedItems1.Count); Assert.Equal(2, exportedItems2.Count); // Check value exported for Counter this.AssertLongSumValueForMetric(exportedItems1[0], 15); if (aggregationTemporality == AggregationTemporality.Delta) { this.AssertLongSumValueForMetric(exportedItems2[0], 15); } else { this.AssertLongSumValueForMetric(exportedItems2[0], 25); } // Check value exported for Gauge this.AssertLongSumValueForMetric(exportedItems1[1], 300); this.AssertLongSumValueForMetric(exportedItems2[1], 400); }
public void MultithreadedDoubleCounterTest() { var metricItems = new List <Metric>(); var metricExporter = new InMemoryExporter <Metric>(metricItems); var metricReader = new BaseExportingMetricReader(metricExporter) { PreferredAggregationTemporality = AggregationTemporality.Cumulative, }; using var meter = new Meter(Utils.GetCurrentMethodName()); var counterDouble = meter.CreateCounter <double>("mycounter"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddReader(metricReader) .Build(); // setup args to threads. var mreToBlockUpdateThreads = new ManualResetEvent(false); var mreToEnsureAllThreadsStarted = new ManualResetEvent(false); var argToThread = new UpdateThreadArguments <double>(); argToThread.DeltaValueUpdatedByEachCall = deltaDoubleValueUpdatedByEachCall; argToThread.Counter = counterDouble; argToThread.ThreadsStartedCount = 0; argToThread.MreToBlockUpdateThread = mreToBlockUpdateThreads; argToThread.MreToEnsureAllThreadsStart = mreToEnsureAllThreadsStarted; Thread[] t = new Thread[numberOfThreads]; for (int i = 0; i < numberOfThreads; i++) { t[i] = new Thread(CounterUpdateThread <double>); t[i].Start(argToThread); } // Block until all threads started. mreToEnsureAllThreadsStarted.WaitOne(); Stopwatch sw = Stopwatch.StartNew(); // unblock all the threads. // (i.e let them start counter.Add) mreToBlockUpdateThreads.Set(); for (int i = 0; i < numberOfThreads; i++) { // wait for all threads to complete t[i].Join(); } var timeTakenInMilliseconds = sw.ElapsedMilliseconds; this.output.WriteLine($"Took {timeTakenInMilliseconds} msecs. Total threads: {numberOfThreads}, each thread doing {numberOfMetricUpdateByEachThread} recordings."); metricReader.Collect(); var sumReceived = GetDoubleSum(metricItems); var expectedSum = deltaDoubleValueUpdatedByEachCall * numberOfMetricUpdateByEachThread * numberOfThreads; var difference = Math.Abs(sumReceived - expectedSum); Assert.True(difference <= 0.0001); }
public void TestMetricPointCap(AggregationTemporality temporality) { var metricItems = new List <Metric>(); var metricExporter = new InMemoryExporter <Metric>(metricItems); int MetricPointCount() { var count = 0; foreach (var metric in metricItems) { foreach (ref var metricPoint in metric.GetMetricPoints()) { count++; } } return(count); } var metricReader = new BaseExportingMetricReader(metricExporter) { PreferredAggregationTemporality = temporality, }; using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}"); var counterLong = meter.CreateCounter <long>("mycounterCapTest"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddReader(metricReader) .Build(); // Make one Add with no tags. // as currently we reserve 0th index // for no tag point! // This may be changed later. counterLong.Add(10); for (int i = 0; i < AggregatorStore.MaxMetricPoints + 1; i++) { counterLong.Add(10, new KeyValuePair <string, object>("key", "value" + i)); } metricReader.Collect(); Assert.Equal(AggregatorStore.MaxMetricPoints, MetricPointCount()); metricItems.Clear(); counterLong.Add(10); for (int i = 0; i < AggregatorStore.MaxMetricPoints + 1; i++) { counterLong.Add(10, new KeyValuePair <string, object>("key", "value" + i)); } metricReader.Collect(); Assert.Equal(AggregatorStore.MaxMetricPoints, MetricPointCount()); counterLong.Add(10); for (int i = 0; i < AggregatorStore.MaxMetricPoints + 1; i++) { counterLong.Add(10, new KeyValuePair <string, object>("key", "value" + i)); } // These updates would be dropped. counterLong.Add(10, new KeyValuePair <string, object>("key", "valueA")); counterLong.Add(10, new KeyValuePair <string, object>("key", "valueB")); counterLong.Add(10, new KeyValuePair <string, object>("key", "valueC")); metricItems.Clear(); metricReader.Collect(); Assert.Equal(AggregatorStore.MaxMetricPoints, MetricPointCount()); }
public void CounterAggregationTest(bool exportDelta) { var metricItems = new List <Metric>(); var metricExporter = new InMemoryExporter <Metric>(metricItems); var metricReader = new BaseExportingMetricReader(metricExporter) { PreferredAggregationTemporality = exportDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative, }; using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}"); var counterLong = meter.CreateCounter <long>("mycounter"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) .AddReader(metricReader) .Build(); counterLong.Add(10); counterLong.Add(10); metricReader.Collect(); long sumReceived = GetLongSum(metricItems); Assert.Equal(20, sumReceived); metricItems.Clear(); counterLong.Add(10); counterLong.Add(10); metricReader.Collect(); sumReceived = GetLongSum(metricItems); if (exportDelta) { Assert.Equal(20, sumReceived); } else { Assert.Equal(40, sumReceived); } metricItems.Clear(); metricReader.Collect(); sumReceived = GetLongSum(metricItems); if (exportDelta) { Assert.Equal(0, sumReceived); } else { Assert.Equal(40, sumReceived); } metricItems.Clear(); counterLong.Add(40); counterLong.Add(20); metricReader.Collect(); sumReceived = GetLongSum(metricItems); if (exportDelta) { Assert.Equal(60, sumReceived); } else { Assert.Equal(100, sumReceived); } }
public async Task RequestMetricIsCaptured() { var metricItems = new List <Metric>(); var metricExporter = new InMemoryExporter <Metric>(metricItems); var metricReader = new BaseExportingMetricReader(metricExporter) { PreferredAggregationTemporality = AggregationTemporality.Cumulative, }; this.meterProvider = Sdk.CreateMeterProviderBuilder() .AddAspNetCoreInstrumentation() .AddReader(metricReader) .Build(); using (var client = this.factory.CreateClient()) { var response = await client.GetAsync("/api/values"); response.EnsureSuccessStatusCode(); } // We need to let End callback execute as it is executed AFTER response was returned. // In unit tests environment there may be a lot of parallel unit tests executed, so // giving some breezing room for the End callback to complete await Task.Delay(TimeSpan.FromSeconds(1)); this.meterProvider.Dispose(); var requestMetrics = metricItems .Where(item => item.Name == "http.server.duration") .ToArray(); Assert.True(requestMetrics.Length == 1); var metric = requestMetrics[0]; Assert.NotNull(metric); Assert.True(metric.MetricType == MetricType.Histogram); var metricPoints = new List <MetricPoint>(); foreach (var p in metric.GetMetricPoints()) { metricPoints.Add(p); } Assert.Single(metricPoints); var metricPoint = metricPoints[0]; Assert.Equal(1L, metricPoint.LongValue); Assert.True(metricPoint.DoubleValue > 0); /* * var bucket = metric.Buckets * .Where(b => * metric.PopulationSum > b.LowBoundary && * metric.PopulationSum <= b.HighBoundary) * .FirstOrDefault(); * Assert.NotEqual(default, bucket); * Assert.Equal(1, bucket.Count); */ var attributes = new KeyValuePair <string, object> [metricPoint.Keys.Length]; for (int i = 0; i < attributes.Length; i++) { attributes[i] = new KeyValuePair <string, object>(metricPoint.Keys[i], metricPoint.Values[i]); } var method = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpMethod, "GET"); var scheme = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpScheme, "http"); var statusCode = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpStatusCode, 200); var flavor = new KeyValuePair <string, object>(SemanticConventions.AttributeHttpFlavor, "HTTP/1.1"); Assert.Contains(method, attributes); Assert.Contains(scheme, attributes); Assert.Contains(statusCode, attributes); Assert.Contains(flavor, attributes); Assert.Equal(4, attributes.Length); }