Skip to content

Commit 1665ed4

Browse files
author
Timothy Mothra
authored
[AzureMonitor] more initialization tests (Azure#49109)
* saving work in progress. more tests and todos * saving work in progress. validating MeterProcessor and LogProcessor * instrumentations * update test * fix
1 parent 21ff787 commit 1665ed4

File tree

1 file changed

+218
-32
lines changed
  • sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/tests/Azure.Monitor.OpenTelemetry.AspNetCore.Tests

1 file changed

+218
-32
lines changed

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/tests/Azure.Monitor.OpenTelemetry.AspNetCore.Tests/InitializationTests.cs

Lines changed: 218 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.Reflection;
67
using System.Threading;
78
using System.Threading.Tasks;
89
using Azure.Monitor.OpenTelemetry.Exporter;
910
using Microsoft.Extensions.DependencyInjection;
1011
using Microsoft.Extensions.Hosting;
1112
using OpenTelemetry.Trace;
13+
using OpenTelemetry.Metrics;
14+
using OpenTelemetry.Logs;
1215
using Xunit;
16+
using System.Linq;
1317

1418
namespace Azure.Monitor.OpenTelemetry.AspNetCore.Tests
1519
{
@@ -30,7 +34,7 @@ public async Task VerifyCannotCallUseAzureMonitorTwice()
3034
.UseAzureMonitor()
3135
.UseAzureMonitor();
3236

33-
var serviceProvider = serviceCollection.BuildServiceProvider();
37+
var serviceProvider = serviceCollection.BuildServiceProvider();
3438

3539
await Assert.ThrowsAsync<NotSupportedException>(async () => await StartHostedServicesAsync(serviceProvider));
3640
}
@@ -77,29 +81,97 @@ public async Task VerifyCanCallAddAzureMonitorTraceExporterTwice()
7781
}
7882

7983
[Fact]
80-
public async Task VerifyCannotAddMonitorTraceExporterAndUseAzureMonitor()
84+
public async Task VerifyCanCallAddAzureMonitorMetricExporterTwice()
8185
{
8286
var serviceCollection = new ServiceCollection();
8387
serviceCollection.AddOpenTelemetry()
84-
.WithTracing(builder => builder
85-
.AddAzureMonitorTraceExporter(x => x.ConnectionString = TestConnectionString))
86-
.UseAzureMonitor(x => x.ConnectionString = TestConnectionString2);
88+
.WithMetrics(builder => builder
89+
.AddAzureMonitorMetricExporter(x => x.ConnectionString = TestConnectionString)
90+
.AddAzureMonitorMetricExporter(x => x.ConnectionString = TestConnectionString2));
8791

8892
using var serviceProvider = serviceCollection.BuildServiceProvider();
89-
await Assert.ThrowsAsync<NotSupportedException>(async () => await StartHostedServicesAsync(serviceProvider));
93+
await StartHostedServicesAsync(serviceProvider);
9094
}
9195

9296
[Fact]
93-
public async Task VerifyCannotAddMonitorTraceExporterAndUseAzureMonitorExporter()
97+
public async Task VerifyCanCallAddAzureMonitorLogExporterTwice()
9498
{
9599
var serviceCollection = new ServiceCollection();
96100
serviceCollection.AddOpenTelemetry()
101+
.WithLogging(builder => builder
102+
.AddAzureMonitorLogExporter(x => x.ConnectionString = TestConnectionString)
103+
.AddAzureMonitorLogExporter(x => x.ConnectionString = TestConnectionString2));
104+
105+
using var serviceProvider = serviceCollection.BuildServiceProvider();
106+
await StartHostedServicesAsync(serviceProvider);
107+
}
108+
109+
[Fact]
110+
public async Task VerifyCannotAddExportersAndUseAzureMonitor()
111+
{
112+
// Traces
113+
var serviceCollection1 = new ServiceCollection();
114+
serviceCollection1.AddOpenTelemetry()
115+
.WithTracing(builder => builder
116+
.AddAzureMonitorTraceExporter(x => x.ConnectionString = TestConnectionString))
117+
.UseAzureMonitor(x => x.ConnectionString = TestConnectionString2);
118+
119+
using var serviceProvider1 = serviceCollection1.BuildServiceProvider();
120+
await Assert.ThrowsAsync<NotSupportedException>(async () => await StartHostedServicesAsync(serviceProvider1));
121+
122+
// Metrics
123+
var serviceCollection2 = new ServiceCollection();
124+
serviceCollection2.AddOpenTelemetry()
125+
.WithMetrics(builder => builder
126+
.AddAzureMonitorMetricExporter(x => x.ConnectionString = TestConnectionString))
127+
.UseAzureMonitor(x => x.ConnectionString = TestConnectionString2);
128+
129+
using var serviceProvider2 = serviceCollection2.BuildServiceProvider();
130+
await Assert.ThrowsAsync<NotSupportedException>(async () => await StartHostedServicesAsync(serviceProvider2));
131+
132+
// Logs
133+
var serviceCollection3 = new ServiceCollection();
134+
serviceCollection3.AddOpenTelemetry()
135+
.WithLogging(builder => builder
136+
.AddAzureMonitorLogExporter(x => x.ConnectionString = TestConnectionString))
137+
.UseAzureMonitor(x => x.ConnectionString = TestConnectionString2);
138+
139+
using var serviceProvider3 = serviceCollection3.BuildServiceProvider();
140+
await Assert.ThrowsAsync<NotSupportedException>(async () => await StartHostedServicesAsync(serviceProvider3));
141+
}
142+
143+
[Fact]
144+
public async Task VerifyCannotAddExporterAndUseAzureMonitorExporter()
145+
{
146+
// Traces
147+
var serviceCollection1 = new ServiceCollection();
148+
serviceCollection1.AddOpenTelemetry()
97149
.WithTracing(builder => builder
98150
.AddAzureMonitorTraceExporter(x => x.ConnectionString = TestConnectionString))
99151
.UseAzureMonitorExporter(x => x.ConnectionString = TestConnectionString2);
100152

101-
using var serviceProvider = serviceCollection.BuildServiceProvider();
102-
await Assert.ThrowsAsync<NotSupportedException>(async () => await StartHostedServicesAsync(serviceProvider));
153+
using var serviceProvider1 = serviceCollection1.BuildServiceProvider();
154+
await Assert.ThrowsAsync<NotSupportedException>(async () => await StartHostedServicesAsync(serviceProvider1));
155+
156+
// Metrics
157+
var serviceCollection2 = new ServiceCollection();
158+
serviceCollection2.AddOpenTelemetry()
159+
.WithMetrics(builder => builder
160+
.AddAzureMonitorMetricExporter(x => x.ConnectionString = TestConnectionString))
161+
.UseAzureMonitorExporter(x => x.ConnectionString = TestConnectionString2);
162+
163+
using var serviceProvider2 = serviceCollection2.BuildServiceProvider();
164+
await Assert.ThrowsAsync<NotSupportedException>(async () => await StartHostedServicesAsync(serviceProvider2));
165+
166+
// Logs
167+
var serviceCollection3 = new ServiceCollection();
168+
serviceCollection3.AddOpenTelemetry()
169+
.WithLogging(builder => builder
170+
.AddAzureMonitorLogExporter(x => x.ConnectionString = TestConnectionString))
171+
.UseAzureMonitorExporter(x => x.ConnectionString = TestConnectionString2);
172+
173+
using var serviceProvider3 = serviceCollection1.BuildServiceProvider();
174+
await Assert.ThrowsAsync<NotSupportedException>(async () => await StartHostedServicesAsync(serviceProvider3));
103175
}
104176

105177
[Theory]
@@ -112,18 +184,20 @@ public async Task VerifyUseAzureMonitor(bool enableLiveMetrics)
112184
.UseAzureMonitor(options => {
113185
options.ConnectionString = TestConnectionString;
114186
options.EnableLiveMetrics = enableLiveMetrics;
115-
});
187+
});
116188

117189
using var serviceProvider = serviceCollection.BuildServiceProvider();
118190
await StartHostedServicesAsync(serviceProvider);
119191

120-
var tracerProvider = serviceProvider.GetRequiredService<TracerProvider>();
121-
EvaluateTraceProvider.Evaluate(
122-
tracerProvider: tracerProvider,
123-
expectedAzureMonitorTraceExporter: true,
192+
EvaluationHelper.EvaluateTracerProvider(
193+
serviceProvider: serviceProvider,
124194
expectedLiveMetricsProcessor: enableLiveMetrics,
125195
expectedProfilingSessionTraceProcessor: true,
126-
expectedStandardMetricsExtractionProcessor: true);
196+
hasInstrumentations: true);
197+
198+
EvaluationHelper.EvaluateMeterProvider(serviceProvider);
199+
200+
EvaluationHelper.EvaluateLoggerProvider(serviceProvider, enableLiveMetrics);
127201
}
128202

129203
[Theory]
@@ -141,13 +215,15 @@ public async Task VerifyUseAzureMonitorExporter(bool enableLiveMetrics)
141215
using var serviceProvider = serviceCollection.BuildServiceProvider();
142216
await StartHostedServicesAsync(serviceProvider);
143217

144-
var tracerProvider = serviceProvider.GetRequiredService<TracerProvider>();
145-
EvaluateTraceProvider.Evaluate(
146-
tracerProvider: tracerProvider,
147-
expectedAzureMonitorTraceExporter: true,
218+
EvaluationHelper.EvaluateTracerProvider(
219+
serviceProvider: serviceProvider,
148220
expectedLiveMetricsProcessor: enableLiveMetrics,
149221
expectedProfilingSessionTraceProcessor: false,
150-
expectedStandardMetricsExtractionProcessor: true);
222+
hasInstrumentations: false);
223+
224+
EvaluationHelper.EvaluateMeterProvider(serviceProvider);
225+
226+
EvaluationHelper.EvaluateLoggerProvider(serviceProvider, enableLiveMetrics);
151227
}
152228

153229
private static async Task StartHostedServicesAsync(ServiceProvider serviceProvider)
@@ -159,18 +235,19 @@ private static async Task StartHostedServicesAsync(ServiceProvider serviceProvid
159235
}
160236
}
161237

162-
private class EvaluateTraceProvider()
238+
private class EvaluationHelper()
163239
{
164-
private class Variables
240+
private class TracerProviderVariables
165241
{
166242
public bool foundProfilingSessionTraceProcessor;
167243
public bool foundAzureMonitorTraceExporter;
168244
public bool foundLiveMetricsProcessor;
169245
public bool foundStandardMetricsExtractionProcessor;
170246
}
171247

172-
public static void Evaluate(TracerProvider tracerProvider, bool expectedAzureMonitorTraceExporter, bool expectedLiveMetricsProcessor, bool expectedProfilingSessionTraceProcessor, bool expectedStandardMetricsExtractionProcessor)
248+
public static void EvaluateTracerProvider(IServiceProvider serviceProvider, bool expectedLiveMetricsProcessor, bool expectedProfilingSessionTraceProcessor, bool hasInstrumentations)
173249
{
250+
var tracerProvider = serviceProvider.GetRequiredService<TracerProvider>();
174251
Assert.NotNull(tracerProvider);
175252

176253
// Get TracerProviderSdk
@@ -181,19 +258,128 @@ public static void Evaluate(TracerProvider tracerProvider, bool expectedAzureMon
181258
var processor = processorProperty.GetValue(tracerProvider);
182259
Assert.NotNull(processor);
183260

184-
var variables = new Variables();
185-
186261
// Start walking the CompositeProcessor
187-
WalkCompositeProcessor(processor, variables);
188-
189-
// Final assertions
262+
var variables = new TracerProviderVariables();
263+
WalkTracerCompositeProcessor(processor, variables);
190264
Assert.Equal(expectedLiveMetricsProcessor, variables.foundLiveMetricsProcessor);
191-
Assert.Equal(expectedStandardMetricsExtractionProcessor, variables.foundStandardMetricsExtractionProcessor);
192-
Assert.Equal(expectedAzureMonitorTraceExporter, variables.foundAzureMonitorTraceExporter);
265+
Assert.True(variables.foundStandardMetricsExtractionProcessor);
266+
Assert.True(variables.foundAzureMonitorTraceExporter);
193267
Assert.Equal(expectedProfilingSessionTraceProcessor, variables.foundProfilingSessionTraceProcessor);
268+
269+
// Validate Sampler
270+
var samplerProperty = tracerProviderSdkType.GetProperty("Sampler", BindingFlags.NonPublic | BindingFlags.Instance);
271+
Assert.NotNull(samplerProperty);
272+
var sampler = samplerProperty.GetValue(tracerProvider);
273+
Assert.NotNull(sampler);
274+
Assert.Equal(nameof(Exporter.Internals.ApplicationInsightsSampler), sampler.GetType().Name);
275+
276+
// Validate Instrumentations
277+
var instrumentationsProperty = tracerProvider.GetType().GetProperty("Instrumentations", BindingFlags.NonPublic | BindingFlags.Instance);
278+
Assert.NotNull(instrumentationsProperty);
279+
280+
var instrumentations = instrumentationsProperty.GetValue(tracerProvider) as IEnumerable<object>;
281+
Assert.NotNull(instrumentations);
282+
283+
if (hasInstrumentations)
284+
{
285+
var instrumentationTypes = instrumentations.Select(i => i.GetType().Name).ToList();
286+
Assert.Contains("SqlClientInstrumentation", instrumentationTypes);
287+
Assert.Contains("AspNetCoreInstrumentation", instrumentationTypes);
288+
#if NET
289+
Assert.Contains("HttpClientInstrumentation", instrumentationTypes);
290+
291+
Assert.Equal(3, instrumentations.Count());
292+
#else
293+
Assert.Equal(2, instrumentations.Count());
294+
#endif
295+
}
296+
else
297+
{
298+
Assert.Empty(instrumentations);
299+
}
300+
}
301+
302+
public static void EvaluateMeterProvider(IServiceProvider serviceProvider)
303+
{
304+
var meterProvider = serviceProvider.GetRequiredService<MeterProvider>();
305+
Assert.NotNull(meterProvider);
306+
307+
// Get the Reader property (private) from MeterProviderSdk
308+
var readerProperty = meterProvider.GetType().GetProperty("Reader", BindingFlags.NonPublic | BindingFlags.Instance);
309+
Assert.NotNull(readerProperty);
310+
311+
var reader = readerProperty.GetValue(meterProvider);
312+
Assert.NotNull(reader);
313+
314+
// Get the Exporter property (private) from PeriodicExportingMetricReader
315+
var exporterProperty = reader.GetType().GetProperty("Exporter", BindingFlags.NonPublic | BindingFlags.Instance);
316+
Assert.NotNull(exporterProperty);
317+
318+
var exporter = exporterProperty.GetValue(reader);
319+
Assert.NotNull(exporter);
320+
321+
// Assert Exporter is of type AzureMonitorMetricExporter
322+
Assert.Equal(nameof(AzureMonitorMetricExporter), exporter.GetType().Name);
323+
}
324+
325+
public static void EvaluateLoggerProvider(IServiceProvider serviceProvider, bool liveMetricsEnabled = false)
326+
{
327+
var loggerProvider = serviceProvider.GetService<LoggerProvider>();
328+
Assert.NotNull(loggerProvider);
329+
330+
var processorProperty = loggerProvider.GetType().GetProperty("Processor", BindingFlags.Public | BindingFlags.Instance);
331+
Assert.NotNull(processorProperty);
332+
333+
var processor = processorProperty.GetValue(loggerProvider);
334+
Assert.NotNull(processor);
335+
336+
if (liveMetricsEnabled)
337+
{
338+
// When LiveMetrics is enabled, processor should be a CompositeProcessor
339+
Assert.Contains("CompositeProcessor", processor.GetType().Name);
340+
341+
// Get the first processor (LiveMetricsLogProcessor)
342+
var headField = processor.GetType().GetField("Head", BindingFlags.NonPublic | BindingFlags.Instance);
343+
Assert.NotNull(headField);
344+
var firstNode = headField.GetValue(processor);
345+
Assert.NotNull(firstNode);
346+
347+
var valueField = firstNode.GetType().GetField("Value", BindingFlags.Public | BindingFlags.Instance);
348+
var firstProcessor = valueField!.GetValue(firstNode);
349+
Assert.NotNull(firstProcessor);
350+
Assert.Contains(nameof(LiveMetrics.LiveMetricsLogProcessor), firstProcessor.GetType().Name);
351+
352+
// Get the second processor (BatchLogRecordExportProcessor & AzureMonitorLogExporter)
353+
var nextProperty = firstNode.GetType().GetProperty("Next", BindingFlags.Public | BindingFlags.Instance);
354+
var secondNode = nextProperty!.GetValue(firstNode);
355+
Assert.NotNull(secondNode);
356+
357+
var secondProcessor = valueField.GetValue(secondNode);
358+
Assert.NotNull(secondProcessor);
359+
Assert.Contains("BatchLogRecordExportProcessor", secondProcessor.GetType().Name);
360+
361+
var exporterProperty = secondProcessor.GetType().GetProperty("Exporter", BindingFlags.NonPublic | BindingFlags.Instance);
362+
Assert.NotNull(exporterProperty);
363+
364+
var exporter = exporterProperty.GetValue(secondProcessor);
365+
Assert.NotNull(exporter);
366+
Assert.Contains(nameof(AzureMonitorLogExporter), exporter.GetType().Name);
367+
}
368+
else
369+
{
370+
// When LiveMetrics is disabled, processor should be a BatchLogRecordExportProcessor
371+
Assert.Contains("BatchLogRecordExportProcessor", processor.GetType().Name);
372+
373+
var exporterProperty = processor.GetType().GetProperty("Exporter", BindingFlags.NonPublic | BindingFlags.Instance);
374+
Assert.NotNull(exporterProperty);
375+
376+
var exporter = exporterProperty.GetValue(processor);
377+
Assert.NotNull(exporter);
378+
Assert.Contains(nameof(AzureMonitorLogExporter), exporter.GetType().Name);
379+
}
194380
}
195381

196-
private static void WalkCompositeProcessor(object compositeProcessor, Variables variables)
382+
private static void WalkTracerCompositeProcessor(object compositeProcessor, TracerProviderVariables variables)
197383
{
198384
var compositeProcessorType = compositeProcessor.GetType();
199385

@@ -242,7 +428,7 @@ private static void WalkCompositeProcessor(object compositeProcessor, Variables
242428
else if (processorType.Name.Contains("CompositeProcessor"))
243429
{
244430
// Recursive step: walk inner CompositeProcessor
245-
WalkCompositeProcessor(processorValue, variables);
431+
WalkTracerCompositeProcessor(processorValue, variables);
246432
}
247433
}
248434

0 commit comments

Comments
 (0)