[DependencyInjection] Introduce new package and refactor SDK (#3923)

This commit is contained in:
Mikel Blanchard 2022-12-08 15:24:44 -08:00 committed by GitHub
parent f0f5158ba1
commit 9836d3addb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 3169 additions and 2102 deletions

View File

@ -238,9 +238,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "redaction", "docs\logs\reda
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.OpenTelemetryProtocol.Grpc", "src\OpenTelemetry.Exporter.OpenTelemetryProtocol.Grpc\OpenTelemetry.Exporter.OpenTelemetryProtocol.Grpc.csproj", "{7263001A-49F8-4C3C-AAA8-998F12DAAF64}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetry.Exporter.Console.Tests", "test\OpenTelemetry.Exporter.Console.Tests\OpenTelemetry.Exporter.Console.Tests.csproj", "{011E70E1-152A-47BB-AF83-12DD12B125ED}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Exporter.Console.Tests", "test\OpenTelemetry.Exporter.Console.Tests\OpenTelemetry.Exporter.Console.Tests.csproj", "{011E70E1-152A-47BB-AF83-12DD12B125ED}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "getting-started-jaeger", "docs\trace\getting-started-jaeger\getting-started-jaeger.csproj", "{329AD438-6D15-4432-99BE-B0E85F00B3CB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.DependencyInjection", "src\OpenTelemetry.Extensions.DependencyInjection\OpenTelemetry.Extensions.DependencyInjection.csproj", "{171A87CB-393C-4296-913F-E704CD8CEAE9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Extensions.DependencyInjection.Tests", "test\OpenTelemetry.Extensions.DependencyInjection.Tests\OpenTelemetry.Extensions.DependencyInjection.Tests.csproj", "{662476AA-5875-4E74-B992-DDF309168EFB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -500,10 +502,14 @@ Global
{011E70E1-152A-47BB-AF83-12DD12B125ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{011E70E1-152A-47BB-AF83-12DD12B125ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{011E70E1-152A-47BB-AF83-12DD12B125ED}.Release|Any CPU.Build.0 = Release|Any CPU
{329AD438-6D15-4432-99BE-B0E85F00B3CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{329AD438-6D15-4432-99BE-B0E85F00B3CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{329AD438-6D15-4432-99BE-B0E85F00B3CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{329AD438-6D15-4432-99BE-B0E85F00B3CB}.Release|Any CPU.Build.0 = Release|Any CPU
{171A87CB-393C-4296-913F-E704CD8CEAE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{171A87CB-393C-4296-913F-E704CD8CEAE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{171A87CB-393C-4296-913F-E704CD8CEAE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{171A87CB-393C-4296-913F-E704CD8CEAE9}.Release|Any CPU.Build.0 = Release|Any CPU
{662476AA-5875-4E74-B992-DDF309168EFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{662476AA-5875-4E74-B992-DDF309168EFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{662476AA-5875-4E74-B992-DDF309168EFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{662476AA-5875-4E74-B992-DDF309168EFB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -541,7 +547,6 @@ Global
{9A07D215-90AC-4BAF-BCDB-73D74FD3A5C5} = {3862190B-E2C5-418E-AFDC-DB281FB5C705}
{5FDAF679-DE5A-4C73-A49B-8ABCF2399229} = {77C7929A-2EED-4AA6-8705-B5C443C8AA0F}
{A2DF46DE-50D7-4887-8C9D-4BD79CA19FAA} = {3862190B-E2C5-418E-AFDC-DB281FB5C705}
{329AD438-6D15-4432-99BE-B0E85F00B3CB} = {5B7FB835-3FFF-4BC2-99C5-A5B5FAE3C818}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {55639B5C-0770-4A22-AB56-859604650521}

View File

@ -35,6 +35,7 @@
<MicrosoftCodeAnalysisAnalyzersPkgVer>[3.3.3]</MicrosoftCodeAnalysisAnalyzersPkgVer>
<MicrosoftCodeCoveragePkgVer>[17.3.0]</MicrosoftCodeCoveragePkgVer>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPkgVer>[3.1.0,)</MicrosoftExtensionsConfigurationEnvironmentVariablesPkgVer>
<MicrosoftExtensionsDependencyInjectionAbstractionsPkgVer>[3.1.0,)</MicrosoftExtensionsDependencyInjectionAbstractionsPkgVer>
<MicrosoftExtensionsHostingAbstractionsPkgVer>[2.1.0,)</MicrosoftExtensionsHostingAbstractionsPkgVer>
<MicrosoftExtensionsLoggingPkgVer>[3.1.0,)</MicrosoftExtensionsLoggingPkgVer>
<MicrosoftExtensionsLoggingConfigurationPkgVer>[3.1.0,)</MicrosoftExtensionsLoggingConfigurationPkgVer>

View File

@ -411,21 +411,24 @@ var appBuilder = WebApplication.CreateBuilder(args);
appBuilder.Services.AddSingleton<MyCustomService>();
appBuilder.Services.AddOpenTelemetryTracing(builder => builder
.AddProcessor<MyCustomProcessor>();
appBuilder.Services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddProcessor<MyCustomProcessor>())
.StartWithHost();
```
When using the `AddOpenTelemetryTracing` method the `TracerProvider` does not
own its `IServiceCollection` and instead registers into an existing collection
(typically the collection used is the one managed by the application host). The
`TracerProviderBuilder` will be able to access all services registered into that
collection. For lifecycle management, an [IHostedService
When using the `AddOpenTelemetry` & `WithTracing` extension methods the
`TracerProvider` does not own its `IServiceCollection` and instead registers
into an existing collection (typically the collection used is the one managed by
the application host). The `TracerProviderBuilder` will be able to access all
services registered into that collection. For lifecycle management, the
`StartWithHost` registers an [IHostedService
](https://learn.microsoft.com/dotnet/api/microsoft.extensions.hosting.ihostedservice)
is used to automatically start the `TracerProvider` when the host starts and the
host will automatically shutdown and dispose the `TracerProvider` when it is
shutdown.
which is used to automatically start the `TracerProvider` when the host starts
and the host will automatically shutdown and dispose the `TracerProvider` when
it is shutdown.
**Note:** Multiple calls to `AddOpenTelemetryTracing` will configure the same
**Note:** Multiple calls to `WithTracing` will configure the same
`TracerProvider`. Only a single `TraceProvider` may exist in an
`IServiceCollection` \ `IServiceProvider`.
@ -451,15 +454,17 @@ shutdown.
```csharp
var appBuilder = WebApplication.CreateBuilder(args);
appBuilder.Services.AddOpenTelemetryTracing(builder => builder
.ConfigureBuilder((sp, builder) =>
{
builder.AddProcessor(
new MyCustomProcessor(
// Note: This example uses the final IServiceProvider once it is available.
sp.GetRequiredService<MyCustomService>(),
sp.GetRequiredService<IOptions<MyOptions>>().Value));
}));
appBuilder.Services.AddOpenTelemetry()
.WithTracing(builder => builder
.ConfigureBuilder((sp, builder) =>
{
builder.AddProcessor(
new MyCustomProcessor(
// Note: This example uses the final IServiceProvider once it is available.
sp.GetRequiredService<MyCustomService>(),
sp.GetRequiredService<IOptions<MyOptions>>().Value));
}))
.StartWithHost();
```
**Note:** `ConfigureBuilder` is an advanced API and is expected to be used
@ -612,8 +617,9 @@ var appBuilder = WebApplication.CreateBuilder(args);
appBuilder.Services.Configure<JaegerExporterOptions>(
appBuilder.Configuration.GetSection("OpenTelemetry:Jaeger"));
appBuilder.Services.AddOpenTelemetryTracing(
builder => builder.AddJaegerExporter());
appBuilder.Services.AddOpenTelemetry()
.WithTracing(builder => builder.AddJaegerExporter())
.StartWithHost();
```
The OpenTelemetry .NET SDK supports running multiple `TracerProvider`s inside
@ -654,7 +660,9 @@ appBuilder.Services.Configure<JaegerExporterOptions>(
"JaegerSecondary",
appBuilder.Configuration.GetSection("OpenTelemetry:JaegerSecondary"));
appBuilder.Services.AddOpenTelemetryTracing(builder => builder
.AddJaegerExporter(name: "JaegerPrimary", configure: null)
.AddJaegerExporter(name: "JaegerSecondary", configure: null));
appBuilder.Services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddJaegerExporter(name: "JaegerPrimary", configure: null)
.AddJaegerExporter(name: "JaegerSecondary", configure: null))
.StartWithHost();
```

View File

@ -530,7 +530,7 @@ the target type for registration extension methods.
The following example shows how a library might enable tracing and metric
support using an `IServiceCollection` extension by calling
`ConfigureOpenTelemetryTracing`.
`ConfigureOpenTelemetryTracerProvider`.
```csharp
using Microsoft.Extensions.DependencyInjection.Extensions;
@ -563,7 +563,7 @@ namespace Microsoft.Extensions.DependencyInjection
}
// Configure OpenTelemetry tracing.
services.ConfigureOpenTelemetryTracing(builder => builder.ConfigureBuilder((sp, builder) =>
services.ConfigureOpenTelemetryTracerProvider((sp, builder) =>
{
var options = sp.GetRequiredService<IOptionsMonitor<MyLibraryOptions>>().Get(name);
if (options.EnableTracing)
@ -573,7 +573,7 @@ namespace Microsoft.Extensions.DependencyInjection
}));
// Configure OpenTelemetry metrics.
services.ConfigureOpenTelemetryMetrics(builder => builder.ConfigureBuilder((sp, builder) =>
services.ConfigureOpenTelemetryMeterProvider((sp, builder) =>
{
var options = sp.GetRequiredService<IOptionsMonitor<MyLibraryOptions>>().Get(name);
if (options.EnableMetrics)
@ -614,13 +614,12 @@ single `AddMyLibrary` extension to configure the library itself and optionally
turn on OpenTelemetry integration for multiple signals (tracing & metrics in
this case).
**Note:** `ConfigureOpenTelemetryTracing` does not automatically start
OpenTelemetry. The host is responsible for either calling
`AddOpenTelemetryTracing` in the
**Note:** `ConfigureOpenTelemetryTracerProvider` does not automatically start
OpenTelemetry. The host is responsible for either calling `StartWithHost` in the
[OpenTelemetry.Extensions.Hosting](../../../src/OpenTelemetry.Extensions.Hosting/README.md)
package, calling `Build` when using the `Sdk.CreateTracerProviderBuilder`
method, or by accessing the `TracerProvider` from the `IServiceCollection` where
`ConfigureOpenTelemetryTracing` was performed.
`ConfigureOpenTelemetryTracerProvider` was performed.
When providing `IServiceCollection` registration extensions:

View File

@ -15,6 +15,7 @@
// </copyright>
using System.Reflection;
using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Instrumentation.AspNetCore;
using OpenTelemetry.Logs;
@ -22,83 +23,122 @@ using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
var builder = WebApplication.CreateBuilder(args);
var appBuilder = WebApplication.CreateBuilder(args);
// OpenTelemetry
var assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown";
// Note: Switch between Zipkin/Jaeger/OTLP/Console by setting UseTracingExporter in appsettings.json.
var tracingExporter = appBuilder.Configuration.GetValue<string>("UseTracingExporter").ToLowerInvariant();
// Switch between Zipkin/Jaeger/OTLP/Console by setting UseTracingExporter in appsettings.json.
var tracingExporter = builder.Configuration.GetValue<string>("UseTracingExporter").ToLowerInvariant();
// Note: Switch between Prometheus/OTLP/Console by setting UseMetricsExporter in appsettings.json.
var metricsExporter = appBuilder.Configuration.GetValue<string>("UseMetricsExporter").ToLowerInvariant();
var serviceName = tracingExporter switch
{
"jaeger" => builder.Configuration.GetValue<string>("Jaeger:ServiceName"),
"zipkin" => builder.Configuration.GetValue<string>("Zipkin:ServiceName"),
"otlp" => builder.Configuration.GetValue<string>("Otlp:ServiceName"),
_ => "AspNetCoreExampleService",
};
// Note: Switch between Console/OTLP by setting UseLogExporter in appsettings.json.
var logExporter = appBuilder.Configuration.GetValue<string>("UseLogExporter").ToLowerInvariant();
// Build a resource configuration action to set service information.
Action<ResourceBuilder> configureResource = r => r.AddService(
serviceName, serviceVersion: assemblyVersion, serviceInstanceId: Environment.MachineName);
serviceName: appBuilder.Configuration.GetValue<string>("ServiceName"),
serviceVersion: Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown",
serviceInstanceId: Environment.MachineName);
// Traces
builder.Services.AddOpenTelemetryTracing(options =>
{
options
.ConfigureResource(configureResource)
.SetSampler(new AlwaysOnSampler())
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation();
switch (tracingExporter)
// Configure OpenTelemetry tracing & metrics with auto-start using the
// StartWithHost extension from OpenTelemetry.Extensions.Hosting.
appBuilder.Services.AddOpenTelemetry()
.ConfigureResource(configureResource)
.WithTracing(builder =>
{
case "jaeger":
options.AddJaegerExporter();
// Tracing
builder.Services.Configure<JaegerExporterOptions>(builder.Configuration.GetSection("Jaeger"));
builder
.SetSampler(new AlwaysOnSampler())
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation();
// Customize the HttpClient that will be used when JaegerExporter is configured for HTTP transport.
builder.Services.AddHttpClient("JaegerExporter", configureClient: (client) => client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value"));
break;
// Use IConfiguration binding for AspNetCore instrumentation options.
appBuilder.Services.Configure<AspNetCoreInstrumentationOptions>(appBuilder.Configuration.GetSection("AspNetCoreInstrumentation"));
case "zipkin":
options.AddZipkinExporter();
switch (tracingExporter)
{
case "jaeger":
builder.AddJaegerExporter();
builder.Services.Configure<ZipkinExporterOptions>(builder.Configuration.GetSection("Zipkin"));
break;
case "otlp":
options.AddOtlpExporter(otlpOptions =>
builder.ConfigureServices(services =>
{
otlpOptions.Endpoint = new Uri(builder.Configuration.GetValue<string>("Otlp:Endpoint"));
// Use IConfiguration binding for Jaeger exporter options.
services.Configure<JaegerExporterOptions>(appBuilder.Configuration.GetSection("Jaeger"));
// Customize the HttpClient that will be used when JaegerExporter is configured for HTTP transport.
services.AddHttpClient("JaegerExporter", configureClient: (client) => client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value"));
});
break;
break;
default:
options.AddConsoleExporter();
case "zipkin":
builder.AddZipkinExporter();
break;
}
});
builder.ConfigureServices(services =>
{
// Use IConfiguration binding for Zipkin exporter options.
services.Configure<ZipkinExporterOptions>(appBuilder.Configuration.GetSection("Zipkin"));
});
break;
// For options which can be bound from IConfiguration.
builder.Services.Configure<AspNetCoreInstrumentationOptions>(builder.Configuration.GetSection("AspNetCoreInstrumentation"));
case "otlp":
builder.AddOtlpExporter(otlpOptions =>
{
// Use IConfiguration directly for Otlp exporter endpoint option.
otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue<string>("Otlp:Endpoint"));
});
break;
// Logging
builder.Logging.ClearProviders();
default:
builder.AddConsoleExporter();
break;
}
})
.WithMetrics(builder =>
{
// Metrics
builder.Logging.AddOpenTelemetry(options =>
builder
.AddRuntimeInstrumentation()
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation();
switch (metricsExporter)
{
case "prometheus":
builder.AddPrometheusExporter();
break;
case "otlp":
builder.AddOtlpExporter(otlpOptions =>
{
// Use IConfiguration directly for Otlp exporter endpoint option.
otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue<string>("Otlp:Endpoint"));
});
break;
default:
builder.AddConsoleExporter();
break;
}
})
.StartWithHost();
// Clear default logging providers used by WebApplication host.
appBuilder.Logging.ClearProviders();
// Configure OpenTelemetry Logging.
appBuilder.Logging.AddOpenTelemetry(options =>
{
// Note: See appsettings.json Logging:OpenTelemetry section for configuration.
options.ConfigureResource(configureResource);
// Switch between Console/OTLP by setting UseLogExporter in appsettings.json.
var logExporter = builder.Configuration.GetValue<string>("UseLogExporter").ToLowerInvariant();
switch (logExporter)
{
case "otlp":
options.AddOtlpExporter(otlpOptions =>
{
otlpOptions.Endpoint = new Uri(builder.Configuration.GetValue<string>("Otlp:Endpoint"));
// Use IConfiguration directly for Otlp exporter endpoint option.
otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue<string>("Otlp:Endpoint"));
});
break;
default:
@ -107,52 +147,14 @@ builder.Logging.AddOpenTelemetry(options =>
}
});
builder.Services.Configure<OpenTelemetryLoggerOptions>(opt =>
{
opt.IncludeScopes = true;
opt.ParseStateValues = true;
opt.IncludeFormattedMessage = true;
});
appBuilder.Services.AddControllers();
// Metrics
// Switch between Prometheus/OTLP/Console by setting UseMetricsExporter in appsettings.json.
var metricsExporter = builder.Configuration.GetValue<string>("UseMetricsExporter").ToLowerInvariant();
appBuilder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenTelemetryMetrics(options =>
{
options.ConfigureResource(configureResource)
.AddRuntimeInstrumentation()
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation();
appBuilder.Services.AddSwaggerGen();
switch (metricsExporter)
{
case "prometheus":
options.AddPrometheusExporter();
break;
case "otlp":
options.AddOtlpExporter(otlpOptions =>
{
otlpOptions.Endpoint = new Uri(builder.Configuration.GetValue<string>("Otlp:Endpoint"));
});
break;
default:
options.AddConsoleExporter();
break;
}
});
var app = appBuilder.Build();
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
@ -165,6 +167,7 @@ app.UseAuthorization();
app.MapControllers();
// Configure OpenTelemetry Prometheus AspNetCore middleware scrape endpoint if enabled.
if (metricsExporter.Equals("prometheus", StringComparison.OrdinalIgnoreCase))
{
app.UseOpenTelemetryPrometheusScrapingEndpoint();

View File

@ -1,27 +1,29 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
"Default": "Information"
},
"OpenTelemetry": {
"IncludeFormattedMessage": true,
"IncludeScopes": true,
"ParseStateValues": true
}
},
"ServiceName": "otel-test",
"AllowedHosts": "*",
"UseTracingExporter": "console",
"UseMetricsExporter": "console",
"UseLogExporter": "console",
"Jaeger": {
"ServiceName": "jaeger-test",
"AgentHost": "localhost",
"AgentPort": 6831,
"Endpoint": "http://localhost:14268",
"Protocol": "UdpCompactThrift"
},
"Zipkin": {
"ServiceName": "zipkin-test",
"Endpoint": "http://localhost:9411/api/v2/spans"
},
"Otlp": {
"ServiceName": "otlp-test",
"Endpoint": "http://localhost:4317"
},
"AspNetCoreInstrumentation": {

View File

@ -21,6 +21,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
@ -39,34 +40,36 @@ namespace Examples.GrpcService
{
services.AddGrpc();
// Switch between Jaeger/Zipkin by setting UseExporter in appsettings.json.
var exporter = this.Configuration.GetValue<string>("UseExporter").ToLowerInvariant();
switch (exporter)
{
case "jaeger":
services.AddOpenTelemetryTracing((builder) => builder
.ConfigureResource(r => r.AddService(this.Configuration.GetValue<string>("Jaeger:ServiceName")))
.AddAspNetCoreInstrumentation()
.AddJaegerExporter(jaegerOptions =>
{
jaegerOptions.AgentHost = this.Configuration.GetValue<string>("Jaeger:Host");
jaegerOptions.AgentPort = this.Configuration.GetValue<int>("Jaeger:Port");
}));
break;
case "zipkin":
services.AddOpenTelemetryTracing((builder) => builder
.AddAspNetCoreInstrumentation()
.AddZipkinExporter(zipkinOptions =>
{
zipkinOptions.Endpoint = new Uri(this.Configuration.GetValue<string>("Zipkin:Endpoint"));
}));
break;
default:
services.AddOpenTelemetryTracing((builder) => builder
.AddAspNetCoreInstrumentation()
.AddConsoleExporter());
break;
}
services.AddOpenTelemetry()
.WithTracing(builder =>
{
builder
.ConfigureResource(r => r.AddService(this.Configuration.GetValue<string>("ServiceName")))
.AddAspNetCoreInstrumentation();
// Switch between Jaeger/Zipkin/Console by setting UseExporter in appsettings.json.
var exporter = this.Configuration.GetValue<string>("UseExporter").ToLowerInvariant();
switch (exporter)
{
case "jaeger":
builder.AddJaegerExporter(jaegerOptions =>
{
jaegerOptions.AgentHost = this.Configuration.GetValue<string>("Jaeger:Host");
jaegerOptions.AgentPort = this.Configuration.GetValue<int>("Jaeger:Port");
});
break;
case "zipkin":
builder.AddZipkinExporter(zipkinOptions =>
{
zipkinOptions.Endpoint = new Uri(this.Configuration.GetValue<string>("Zipkin:Endpoint"));
});
break;
default:
builder.AddConsoleExporter();
break;
}
})
.StartWithHost();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

View File

@ -12,14 +12,13 @@
"Protocols": "Http2"
}
},
"ServiceName": "otel-test",
"UseExporter": "console",
"Jaeger": {
"ServiceName": "jaeger-test",
"Host": "localhost",
"Port": 6831
},
"Zipkin": {
"ServiceName": "zipkin-test",
"Endpoint": "http://localhost:9411/api/v2/spans"
}
}

View File

@ -20,6 +20,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenTelemetry;
using OpenTelemetry.Trace;
using Utils.Messaging;
@ -40,14 +41,16 @@ namespace WebApi
services.AddSingleton<MessageSender>();
services.AddOpenTelemetryTracing((builder) => builder
.AddAspNetCoreInstrumentation()
.AddSource(nameof(MessageSender))
.AddZipkinExporter(b =>
{
var zipkinHostName = Environment.GetEnvironmentVariable("ZIPKIN_HOSTNAME") ?? "localhost";
b.Endpoint = new Uri($"http://{zipkinHostName}:9411/api/v2/spans");
}));
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddAspNetCoreInstrumentation()
.AddSource(nameof(MessageSender))
.AddZipkinExporter(b =>
{
var zipkinHostName = Environment.GetEnvironmentVariable("ZIPKIN_HOSTNAME") ?? "localhost";
b.Endpoint = new Uri($"http://{zipkinHostName}:9411/api/v2/spans");
}))
.StartWithHost();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

View File

@ -17,6 +17,7 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenTelemetry;
using OpenTelemetry.Trace;
using Utils.Messaging;
@ -37,16 +38,15 @@ namespace WorkerService
services.AddSingleton<MessageReceiver>();
services.AddOpenTelemetryTracing(builder =>
{
builder
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddSource(nameof(MessageReceiver))
.AddZipkinExporter(b =>
{
var zipkinHostName = Environment.GetEnvironmentVariable("ZIPKIN_HOSTNAME") ?? "localhost";
b.Endpoint = new Uri($"http://{zipkinHostName}:9411/api/v2/spans");
});
});
}))
.StartWithHost();
});
}
}

View File

@ -90,17 +90,19 @@ who want to configure the `HttpClient` used by the `JaegerExporter` when
implementation if you want to customize the generated `HttpClient`:
```csharp
services.AddOpenTelemetryTracing((builder) => builder
.AddJaegerExporter(o =>
{
o.Protocol = JaegerExportProtocol.HttpBinaryThrift;
o.HttpClientFactory = () =>
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddJaegerExporter(o =>
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value");
return client;
};
}));
o.Protocol = JaegerExportProtocol.HttpBinaryThrift;
o.HttpClientFactory = () =>
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value");
return client;
};
}))
.StartWithHost();
```
For users using

View File

@ -127,17 +127,19 @@ function with your own implementation if you want to customize the generated
`HttpClient`:
```csharp
services.AddOpenTelemetryTracing((builder) => builder
.AddOtlpExporter(o =>
{
o.Protocol = OtlpExportProtocol.HttpProtobuf;
o.HttpClientFactory = () =>
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddOtlpExporter(o =>
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value");
return client;
};
}));
o.Protocol = OtlpExportProtocol.HttpProtobuf;
o.HttpClientFactory = () =>
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value");
return client;
};
}))
.StartWithHost();
```
For users using

View File

@ -26,10 +26,10 @@ dotnet add package --prerelease OpenTelemetry.Exporter.Prometheus.AspNetCore
package on .NET 6.0+:
```csharp
services.AddOpenTelemetryMetrics(builder =>
{
builder.AddPrometheusExporter();
});
services.AddOpenTelemetry()
.WithMetrics(builder => builder
.AddPrometheusExporter())
.StartWithHost();
```
* Or configure directly:

View File

@ -83,13 +83,15 @@ replace the function with your own implementation if you want to customize the
generated `HttpClient`:
```csharp
services.AddOpenTelemetryTracing((builder) => builder
.AddZipkinExporter(o => o.HttpClientFactory = () =>
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value");
return client;
}));
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddZipkinExporter(o => o.HttpClientFactory = () =>
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("X-MyCustomHeader", "value");
return client;
}))
.StartWithHost();
```
For users using

View File

@ -0,0 +1,30 @@
OpenTelemetry.Metrics.IConfigureMeterProviderBuilder
OpenTelemetry.Metrics.IConfigureMeterProviderBuilder.ConfigureBuilder(System.IServiceProvider! serviceProvider, OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> void
OpenTelemetry.Metrics.IMeterProviderBuilder
OpenTelemetry.Metrics.IMeterProviderBuilder.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.IMeterProviderBuilder.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.IMeterProviderBuilder.Provider.get -> OpenTelemetry.Metrics.MeterProvider?
OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions
OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMetricsServiceCollectionExtensions
OpenTelemetry.Trace.IConfigureTracerProviderBuilder
OpenTelemetry.Trace.IConfigureTracerProviderBuilder.ConfigureBuilder(System.IServiceProvider! serviceProvider, OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> void
OpenTelemetry.Trace.ITracerProviderBuilder
OpenTelemetry.Trace.ITracerProviderBuilder.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Trace.ITracerProviderBuilder.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Trace.ITracerProviderBuilder.Provider.get -> OpenTelemetry.Trace.TracerProvider?
OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions
OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracingServiceCollectionExtensions
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Func<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Func<System.IServiceProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, T! instrumentation) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMetricsServiceCollectionExtensions.ConfigureOpenTelemetryMeterProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Func<System.IServiceProvider!, OpenTelemetry.Trace.TracerProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Func<System.IServiceProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, T! instrumentation) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracingServiceCollectionExtensions.ConfigureOpenTelemetryTracerProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!

View File

@ -0,0 +1,30 @@
OpenTelemetry.Metrics.IConfigureMeterProviderBuilder
OpenTelemetry.Metrics.IConfigureMeterProviderBuilder.ConfigureBuilder(System.IServiceProvider! serviceProvider, OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> void
OpenTelemetry.Metrics.IMeterProviderBuilder
OpenTelemetry.Metrics.IMeterProviderBuilder.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.IMeterProviderBuilder.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.IMeterProviderBuilder.Provider.get -> OpenTelemetry.Metrics.MeterProvider?
OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions
OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMetricsServiceCollectionExtensions
OpenTelemetry.Trace.IConfigureTracerProviderBuilder
OpenTelemetry.Trace.IConfigureTracerProviderBuilder.ConfigureBuilder(System.IServiceProvider! serviceProvider, OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> void
OpenTelemetry.Trace.ITracerProviderBuilder
OpenTelemetry.Trace.ITracerProviderBuilder.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Trace.ITracerProviderBuilder.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Trace.ITracerProviderBuilder.Provider.get -> OpenTelemetry.Trace.TracerProvider?
OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions
OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracingServiceCollectionExtensions
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Func<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Func<System.IServiceProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, T! instrumentation) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.OpenTelemetryDependencyInjectionMetricsServiceCollectionExtensions.ConfigureOpenTelemetryMeterProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Func<System.IServiceProvider!, OpenTelemetry.Trace.TracerProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Func<System.IServiceProvider!, T!>! instrumentationFactory) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, T! instrumentation) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.OpenTelemetryDependencyInjectionTracingServiceCollectionExtensions.ConfigureOpenTelemetryTracerProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!

View File

@ -0,0 +1,33 @@
// <copyright file="AssemblyInfo.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.DependencyInjection.Tests" + AssemblyInfo.PublicKey)]
#if SIGNED
internal static class AssemblyInfo
{
public const string PublicKey = ", PublicKey=002400000480000094000000060200000024000052534131000400000100010051C1562A090FB0C9F391012A32198B5E5D9A60E9B80FA2D7B434C9E5CCB7259BD606E66F9660676AFC6692B8CDC6793D190904551D2103B7B22FA636DCBB8208839785BA402EA08FC00C8F1500CCEF28BBF599AA64FFB1E1D5DC1BF3420A3777BADFE697856E9D52070A50C3EA5821C80BEF17CA3ACFFA28F89DD413F096F898";
public const string MoqPublicKey = ", PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7";
}
#else
internal static class AssemblyInfo
{
public const string PublicKey = "";
public const string MoqPublicKey = "";
}
#endif

View File

@ -0,0 +1,5 @@
# Changelog
## Unreleased
Initial release.

View File

@ -0,0 +1,30 @@
// <copyright file="IConfigureMeterProviderBuilder.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace OpenTelemetry.Metrics;
/// <summary>
/// Represents something that configures the <see cref="MeterProviderBuilder"/> type.
/// </summary>
public interface IConfigureMeterProviderBuilder
{
/// <summary>
/// Invoked to configure a <see cref="MeterProviderBuilder"/> instance.
/// </summary>
/// <param name="serviceProvider"><see cref="IServiceProvider"/>.</param>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
void ConfigureBuilder(IServiceProvider serviceProvider, MeterProviderBuilder meterProviderBuilder);
}

View File

@ -0,0 +1,58 @@
// <copyright file="IMeterProviderBuilder.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
namespace OpenTelemetry.Metrics;
/// <summary>
/// Describes a <see cref="MeterProviderBuilder"/> backed by an <see cref="IServiceCollection"/>.
/// </summary>
public interface IMeterProviderBuilder : IDeferredMeterProviderBuilder
{
/// <summary>
/// Gets the <see cref="MeterProvider"/> being constructed by the builder.
/// </summary>
/// <remarks>
/// Note: <see cref="Provider"/> should return <see langword="null"/> until
/// construction has started and the <see cref="IServiceCollection"/> has
/// closed.
/// </remarks>
MeterProvider? Provider { get; }
/// <summary>
/// Register a callback action to configure the <see
/// cref="IServiceCollection"/> where metric services are configured.
/// </summary>
/// <remarks>
/// Note: Metric services are only available during the application
/// configuration phase. This method should throw a <see
/// cref="NotSupportedException"/> if services are configured after the
/// application <see cref="IServiceProvider"/> has been created.
/// </remarks>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
MeterProviderBuilder ConfigureServices(Action<IServiceCollection> configure);
/// <summary>
/// Register a callback action to configure the <see
/// cref="MeterProviderBuilder"/> once the application <see
/// cref="IServiceProvider"/> is available.
/// </summary>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
MeterProviderBuilder ConfigureBuilder(Action<IServiceProvider, MeterProviderBuilder> configure);
}

View File

@ -0,0 +1,161 @@
// <copyright file="OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Metrics;
/// <summary>
/// Contains extension methods for the <see cref="MeterProviderBuilder"/> class.
/// </summary>
public static class OpenTelemetryDependencyInjectionMeterProviderBuilderExtensions
{
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <remarks>
/// Note: The type specified by <typeparamref name="T"/> will be
/// registered as a singleton service into application services.
/// </remarks>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddInstrumentation<T>(this MeterProviderBuilder meterProviderBuilder)
where T : class
{
meterProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
builder.AddInstrumentation(() => sp.GetRequiredService<T>());
});
return meterProviderBuilder;
}
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <param name="instrumentation">Instrumentation instance.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddInstrumentation<T>(this MeterProviderBuilder meterProviderBuilder, T instrumentation)
where T : class
{
Guard.ThrowIfNull(instrumentation);
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
builder.AddInstrumentation(() => instrumentation);
});
return meterProviderBuilder;
}
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <param name="instrumentationFactory">Instrumentation factory.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddInstrumentation<T>(
this MeterProviderBuilder meterProviderBuilder,
Func<IServiceProvider, T> instrumentationFactory)
where T : class
{
Guard.ThrowIfNull(instrumentationFactory);
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
builder.AddInstrumentation(() => instrumentationFactory(sp));
});
return meterProviderBuilder;
}
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <param name="instrumentationFactory">Instrumentation factory.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddInstrumentation<T>(
this MeterProviderBuilder meterProviderBuilder,
Func<IServiceProvider, MeterProvider, T> instrumentationFactory)
where T : class
{
Guard.ThrowIfNull(instrumentationFactory);
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
if (builder is IMeterProviderBuilder iMeterProviderBuilder
&& iMeterProviderBuilder.Provider != null)
{
builder.AddInstrumentation(() => instrumentationFactory(sp, iMeterProviderBuilder.Provider));
}
});
return meterProviderBuilder;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="IServiceCollection"/> where tracing services are configured.
/// </summary>
/// <remarks>
/// Note: Tracing services are only available during the application
/// configuration phase.
/// </remarks>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder ConfigureServices(
this MeterProviderBuilder meterProviderBuilder,
Action<IServiceCollection> configure)
{
if (meterProviderBuilder is IMeterProviderBuilder iMeterProviderBuilder)
{
iMeterProviderBuilder.ConfigureServices(configure);
}
return meterProviderBuilder;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="MeterProviderBuilder"/> once the application <see
/// cref="IServiceProvider"/> is available.
/// </summary>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder ConfigureBuilder(
this MeterProviderBuilder meterProviderBuilder,
Action<IServiceProvider, MeterProviderBuilder> configure)
{
if (meterProviderBuilder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder)
{
deferredMeterProviderBuilder.Configure(configure);
}
return meterProviderBuilder;
}
}

View File

@ -0,0 +1,85 @@
// <copyright file="OpenTelemetryDependencyInjectionMetricsServiceCollectionExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Metrics;
/// <summary>
/// Extension methods for setting up OpenTelemetry Metrics services in an <see cref="IServiceCollection" />.
/// </summary>
public static class OpenTelemetryDependencyInjectionMetricsServiceCollectionExtensions
{
/// <summary>
/// Registers an action used to configure the OpenTelemetry <see
/// cref="MeterProviderBuilder"/> used to create the <see
/// cref="MeterProvider"/> for the <see cref="IServiceCollection"/> being
/// configured.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>This is safe to be called multiple times and by library authors.
/// Each registered configuration action will be applied
/// sequentially.</item>
/// <item>A <see cref="MeterProvider"/> will not be created automatically
/// using this method. To begin collecting metrics use the
/// <c>IServiceCollection.AddOpenTelemetry</c> extension in the
/// <c>OpenTelemetry</c> package.</item>
/// </list>
/// </remarks>
/// <param name="services">The <see cref="IServiceCollection" /> to add
/// services to.</param>
/// <param name="configure">Callback action to configure the <see
/// cref="MeterProviderBuilder"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls
/// can be chained.</returns>
public static IServiceCollection ConfigureOpenTelemetryMeterProvider(
this IServiceCollection services,
Action<IServiceProvider, MeterProviderBuilder> configure)
{
RegisterBuildAction(services, configure);
return services;
}
private static void RegisterBuildAction(IServiceCollection services, Action<IServiceProvider, MeterProviderBuilder> configure)
{
Guard.ThrowIfNull(services);
Guard.ThrowIfNull(configure);
services.AddSingleton<IConfigureMeterProviderBuilder>(
new ConfigureMeterProviderBuilderCallbackWrapper(configure));
}
private sealed class ConfigureMeterProviderBuilderCallbackWrapper : IConfigureMeterProviderBuilder
{
private readonly Action<IServiceProvider, MeterProviderBuilder> configure;
public ConfigureMeterProviderBuilderCallbackWrapper(Action<IServiceProvider, MeterProviderBuilder> configure)
{
Guard.ThrowIfNull(configure);
this.configure = configure;
}
public void ConfigureBuilder(IServiceProvider serviceProvider, MeterProviderBuilder meterProviderBuilder)
{
this.configure(serviceProvider, meterProviderBuilder);
}
}
}

View File

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
<Description>Contains extensions to register OpenTelemetry in applications using Microsoft.Extensions.DependencyInjection</Description>
<RootNamespace>OpenTelemetry</RootNamespace>
<MinVerTagPrefix>core-</MinVerTagPrefix>
</PropertyGroup>
<!--Do not run ApiCompat for netstandard2.0/net462 as this is newly added. Remove this property once we have released a stable version.-->
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'net462'">
<RunApiCompat>false</RunApiCompat>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(RepoRoot)\src\OpenTelemetry.Api\Internal\Guard.cs" Link="Includes\Guard.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Api\OpenTelemetry.Api.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(MicrosoftExtensionsDependencyInjectionAbstractionsPkgVer)" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,25 @@
# OpenTelemetry.Extensions.DependencyInjection
[![NuGet](https://img.shields.io/nuget/v/OpenTelemetry.Extensions.DependencyInjection.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.DependencyInjection)
[![NuGet](https://img.shields.io/nuget/dt/OpenTelemetry.Extensions.DependencyInjection.svg)](https://www.nuget.org/packages/OpenTelemetry.Extensions.DependencyInjection)
## Installation
```shell
dotnet add package --prerelease OpenTelemetry.Extensions.DependencyInjection
```
## Overview
The OpenTelemetry.Extensions.DependencyInjection package provides extension
methods and helpers for building `TracerProvider`s and `MeterProvider`s using
the Microsoft.Extensions.DependencyInjection API.
The Microsoft.Extensions.DependencyInjection package is primarily intended for
library authors who need to integrate with the OpenTelemetry SDK. For more
details see: [Registration extension method guidance for library
authors](../../docs/trace/extending-the-sdk/README.md#registration-extension-method-guidance-for-library-authors).
## References
* [OpenTelemetry Project](https://opentelemetry.io/)

View File

@ -0,0 +1,30 @@
// <copyright file="IConfigureTracerProviderBuilder.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace OpenTelemetry.Trace;
/// <summary>
/// Represents something that configures the <see cref="TracerProviderBuilder"/> type.
/// </summary>
public interface IConfigureTracerProviderBuilder
{
/// <summary>
/// Invoked to configure a <see cref="TracerProviderBuilder"/> instance.
/// </summary>
/// <param name="serviceProvider"><see cref="IServiceProvider"/>.</param>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
void ConfigureBuilder(IServiceProvider serviceProvider, TracerProviderBuilder tracerProviderBuilder);
}

View File

@ -0,0 +1,58 @@
// <copyright file="ITracerProviderBuilder.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
namespace OpenTelemetry.Trace;
/// <summary>
/// Describes a <see cref="TracerProviderBuilder"/> backed by an <see cref="IServiceCollection"/>.
/// </summary>
public interface ITracerProviderBuilder : IDeferredTracerProviderBuilder
{
/// <summary>
/// Gets the <see cref="TracerProvider"/> being constructed by the builder.
/// </summary>
/// <remarks>
/// Note: <see cref="Provider"/> should return <see langword="null"/> until
/// construction has started and the <see cref="IServiceCollection"/> has
/// closed.
/// </remarks>
TracerProvider? Provider { get; }
/// <summary>
/// Register a callback action to configure the <see
/// cref="IServiceCollection"/> where tracing services are configured.
/// </summary>
/// <remarks>
/// Note: Tracing services are only available during the application
/// configuration phase. This method should throw a <see
/// cref="NotSupportedException"/> if services are configured after the
/// application <see cref="IServiceProvider"/> has been created.
/// </remarks>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
TracerProviderBuilder ConfigureServices(Action<IServiceCollection> configure);
/// <summary>
/// Register a callback action to configure the <see
/// cref="TracerProviderBuilder"/> once the application <see
/// cref="IServiceProvider"/> is available.
/// </summary>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
TracerProviderBuilder ConfigureBuilder(Action<IServiceProvider, TracerProviderBuilder> configure);
}

View File

@ -0,0 +1,161 @@
// <copyright file="OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Trace;
/// <summary>
/// Contains extension methods for the <see cref="TracerProviderBuilder"/> class.
/// </summary>
public static class OpenTelemetryDependencyInjectionTracerProviderBuilderExtensions
{
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <remarks>
/// Note: The type specified by <typeparamref name="T"/> will be
/// registered as a singleton service into application services.
/// </remarks>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddInstrumentation<T>(this TracerProviderBuilder tracerProviderBuilder)
where T : class
{
tracerProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
builder.AddInstrumentation(() => sp.GetRequiredService<T>());
});
return tracerProviderBuilder;
}
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <param name="instrumentation">Instrumentation instance.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddInstrumentation<T>(this TracerProviderBuilder tracerProviderBuilder, T instrumentation)
where T : class
{
Guard.ThrowIfNull(instrumentation);
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
builder.AddInstrumentation(() => instrumentation);
});
return tracerProviderBuilder;
}
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <param name="instrumentationFactory">Instrumentation factory.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddInstrumentation<T>(
this TracerProviderBuilder tracerProviderBuilder,
Func<IServiceProvider, T> instrumentationFactory)
where T : class
{
Guard.ThrowIfNull(instrumentationFactory);
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
builder.AddInstrumentation(() => instrumentationFactory(sp));
});
return tracerProviderBuilder;
}
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <param name="instrumentationFactory">Instrumentation factory.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddInstrumentation<T>(
this TracerProviderBuilder tracerProviderBuilder,
Func<IServiceProvider, TracerProvider, T> instrumentationFactory)
where T : class
{
Guard.ThrowIfNull(instrumentationFactory);
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
if (tracerProviderBuilder is ITracerProviderBuilder iTracerProviderBuilder
&& iTracerProviderBuilder.Provider != null)
{
builder.AddInstrumentation(() => instrumentationFactory(sp, iTracerProviderBuilder.Provider));
}
});
return tracerProviderBuilder;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="IServiceCollection"/> where tracing services are configured.
/// </summary>
/// <remarks>
/// Note: Tracing services are only available during the application
/// configuration phase.
/// </remarks>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder ConfigureServices(
this TracerProviderBuilder tracerProviderBuilder,
Action<IServiceCollection> configure)
{
if (tracerProviderBuilder is ITracerProviderBuilder iTracerProviderBuilder)
{
iTracerProviderBuilder.ConfigureServices(configure);
}
return tracerProviderBuilder;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="TracerProviderBuilder"/> once the application <see
/// cref="IServiceProvider"/> is available.
/// </summary>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder ConfigureBuilder(
this TracerProviderBuilder tracerProviderBuilder,
Action<IServiceProvider, TracerProviderBuilder> configure)
{
if (tracerProviderBuilder is IDeferredTracerProviderBuilder deferredTracerProviderBuilder)
{
deferredTracerProviderBuilder.Configure(configure);
}
return tracerProviderBuilder;
}
}

View File

@ -0,0 +1,85 @@
// <copyright file="OpenTelemetryDependencyInjectionTracingServiceCollectionExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Trace;
/// <summary>
/// Extension methods for setting up OpenTelemetry tracing services in an <see cref="IServiceCollection" />.
/// </summary>
public static class OpenTelemetryDependencyInjectionTracingServiceCollectionExtensions
{
/// <summary>
/// Registers an action used to configure the OpenTelemetry <see
/// cref="TracerProviderBuilder"/> used to create the <see
/// cref="TracerProvider"/> for the <see cref="IServiceCollection"/> being
/// configured.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>This is safe to be called multiple times and by library authors.
/// Each registered configuration action will be applied
/// sequentially.</item>
/// <item>A <see cref="TracerProvider"/> will not be created automatically
/// using this method. To begin collecting metrics use the
/// <c>IServiceCollection.AddOpenTelemetry</c> extension in the
/// <c>OpenTelemetry</c> package.</item>
/// </list>
/// </remarks>
/// <param name="services">The <see cref="IServiceCollection" /> to add
/// services to.</param>
/// <param name="configure">Callback action to configure the <see
/// cref="TracerProviderBuilder"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls
/// can be chained.</returns>
public static IServiceCollection ConfigureOpenTelemetryTracerProvider(
this IServiceCollection services,
Action<IServiceProvider, TracerProviderBuilder> configure)
{
RegisterBuildAction(services, configure);
return services;
}
private static void RegisterBuildAction(IServiceCollection services, Action<IServiceProvider, TracerProviderBuilder> configure)
{
Guard.ThrowIfNull(services);
Guard.ThrowIfNull(configure);
services.AddSingleton<IConfigureTracerProviderBuilder>(
new ConfigureTracerProviderBuilderCallbackWrapper(configure));
}
private sealed class ConfigureTracerProviderBuilderCallbackWrapper : IConfigureTracerProviderBuilder
{
private readonly Action<IServiceProvider, TracerProviderBuilder> configure;
public ConfigureTracerProviderBuilderCallbackWrapper(Action<IServiceProvider, TracerProviderBuilder> configure)
{
Guard.ThrowIfNull(configure);
this.configure = configure;
}
public void ConfigureBuilder(IServiceProvider serviceProvider, TracerProviderBuilder tracerProviderBuilder)
{
this.configure(serviceProvider, tracerProviderBuilder);
}
}
}

View File

@ -1,5 +1,6 @@
Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions
OpenTelemetry.Metrics.MeterProviderBuilderExtensions
OpenTelemetry.OpenTelemetryBuilderHostingExtensions
OpenTelemetry.Trace.TracerProviderBuilderExtensions
static Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions.AddOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
static Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions.AddOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder> configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
@ -7,5 +8,6 @@ static Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions.
static Microsoft.Extensions.DependencyInjection.OpenTelemetryServicesExtensions.AddOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder> configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.Configure(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Action<System.IServiceProvider, OpenTelemetry.Metrics.MeterProviderBuilder> configure) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.GetServices(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> Microsoft.Extensions.DependencyInjection.IServiceCollection
static OpenTelemetry.OpenTelemetryBuilderHostingExtensions.StartWithHost(this OpenTelemetry.OpenTelemetryBuilder builder) -> OpenTelemetry.OpenTelemetryBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.Configure(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder, System.Action<System.IServiceProvider, OpenTelemetry.Trace.TracerProviderBuilder> configure) -> OpenTelemetry.Trace.TracerProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.GetServices(this OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder) -> Microsoft.Extensions.DependencyInjection.IServiceCollection

View File

@ -2,6 +2,9 @@
## Unreleased
* Added the `OpenTelemetryBuilder.StartWithHost` extension.
([#3923](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3923))
## 1.0.0-rc9.9
Released 2022-Nov-07

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<Description>Contains extensions to register and start OpenTelemetry in applications using Microsoft.Extensions.Hosting</Description>
<Description>Contains extensions to start OpenTelemetry in applications using Microsoft.Extensions.Hosting</Description>
<RootNamespace>OpenTelemetry</RootNamespace>
<!-- this is temporary. will remove in future PR. -->

View File

@ -0,0 +1,54 @@
// <copyright file="OpenTelemetryBuilderHostingExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using OpenTelemetry.Extensions.Hosting.Implementation;
using OpenTelemetry.Internal;
namespace OpenTelemetry;
/// <summary>
/// Contains hosting extension methods for the <see
/// cref="OpenTelemetryBuilder"/> class.
/// </summary>
public static class OpenTelemetryBuilderHostingExtensions
{
/// <summary>
/// Registers an <see cref="IHostedService"/> to automatically start all
/// configured OpenTelemetry services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks>
/// Note: This is safe to be called multiple times. Only a single <see
/// cref="IHostedService"/> will be created for a given <see
/// cref="IServiceCollection"/>. This should generally be called by hosting
/// application code and NOT library authors.
/// </remarks>
/// <param name="builder"><see cref="OpenTelemetryBuilder"/>.</param>
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
/// calls.</returns>
public static OpenTelemetryBuilder StartWithHost(this OpenTelemetryBuilder builder)
{
Guard.ThrowIfNull(builder);
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<IHostedService, TelemetryHostedService>());
return builder;
}
}

View File

@ -14,121 +14,114 @@
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using OpenTelemetry.Extensions.Hosting.Implementation;
using OpenTelemetry.Internal;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
namespace Microsoft.Extensions.DependencyInjection
namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// Extension methods for setting up OpenTelemetry services in an <see
/// cref="IServiceCollection" />.
/// </summary>
public static class OpenTelemetryServicesExtensions
{
/// <summary>
/// Extension methods for setting up OpenTelemetry services in an <see
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start tracing services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
public static class OpenTelemetryServicesExtensions
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>
/// This is safe to be called multiple times. Only a single <see
/// cref="TracerProvider"/> will be created for a given <see
/// cref="IServiceCollection"/>.
/// </item>
/// <item>
/// This method should be called by application host code. Library
/// authors should call <see
/// cref="OpenTelemetryDependencyInjectionTracingServiceCollectionExtensions.ConfigureOpenTelemetryTracerProvider(IServiceCollection, Action{IServiceProvider, TracerProviderBuilder})"/>
/// instead.
/// </item>
/// </list>
/// </remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
[Obsolete("Use the AddOpenTelemetry().WithTracing(configure).StartWithHost() pattern instead. This method will be removed in a future version.")]
public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection services)
=> AddOpenTelemetryTracing(services, b => { });
/// <summary>
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start tracing services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks><inheritdoc
/// cref="AddOpenTelemetryTracing(IServiceCollection)"
/// path="/remarks"/></remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <param name="configure">Callback action to configure the <see
/// cref="TracerProviderBuilder"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
[Obsolete("Use the AddOpenTelemetry().WithTracing(configure).StartWithHost() pattern instead. This method will be removed in a future version.")]
public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection services, Action<TracerProviderBuilder> configure)
{
/// <summary>
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start tracing services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>
/// This is safe to be called multiple times. Only a single <see
/// cref="TracerProvider"/> will be created for a given <see
/// cref="IServiceCollection"/>.
/// </item>
/// <item>
/// This method should be called by application host code. Library
/// authors should call <see
/// cref="TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(IServiceCollection)"/>
/// instead.
/// </item>
/// </list>
/// </remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection services)
=> AddOpenTelemetryTracing(services, b => { });
services.AddOpenTelemetry().WithTracing(configure).StartWithHost();
/// <summary>
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start tracing services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks><inheritdoc
/// cref="AddOpenTelemetryTracing(IServiceCollection)"
/// path="/remarks"/></remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <param name="configure">Callback action to configure the <see
/// cref="TracerProviderBuilder"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
public static IServiceCollection AddOpenTelemetryTracing(this IServiceCollection services, Action<TracerProviderBuilder> configure)
{
Guard.ThrowIfNull(services);
return services;
}
services.ConfigureOpenTelemetryTracing(configure);
/// <summary>
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start metric services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>
/// This is safe to be called multiple times. Only a single <see
/// cref="MeterProvider"/> will be created for a given <see
/// cref="IServiceCollection"/>.
/// </item>
/// <item>
/// This method should be called by application host code. Library
/// authors should call <see
/// cref="OpenTelemetryDependencyInjectionMetricsServiceCollectionExtensions.ConfigureOpenTelemetryMeterProvider(IServiceCollection, Action{IServiceProvider, MeterProviderBuilder})"/>
/// instead.
/// </item>
/// </list>
/// </remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
[Obsolete("Use the AddOpenTelemetry().WithMetrics(configure).StartWithHost() pattern instead. This method will be removed in a future version.")]
public static IServiceCollection AddOpenTelemetryMetrics(this IServiceCollection services)
=> AddOpenTelemetryMetrics(services, b => { });
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, TelemetryHostedService>());
/// <summary>
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start metric services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks><inheritdoc
/// cref="AddOpenTelemetryMetrics(IServiceCollection)"
/// path="/remarks"/></remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <param name="configure">Callback action to configure the <see
/// cref="TracerProviderBuilder"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
[Obsolete("Use the AddOpenTelemetry().WithMetrics(configure).StartWithHost() pattern instead. This method will be removed in a future version.")]
public static IServiceCollection AddOpenTelemetryMetrics(this IServiceCollection services, Action<MeterProviderBuilder> configure)
{
services.AddOpenTelemetry().WithMetrics(configure).StartWithHost();
return services;
}
/// <summary>
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start metric services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>
/// This is safe to be called multiple times. Only a single <see
/// cref="MeterProvider"/> will be created for a given <see
/// cref="IServiceCollection"/>.
/// </item>
/// <item>
/// This method should be called by application host code. Library
/// authors should call <see
/// cref="MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(IServiceCollection)"/>
/// instead.
/// </item>
/// </list>
/// </remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
public static IServiceCollection AddOpenTelemetryMetrics(this IServiceCollection services)
=> AddOpenTelemetryMetrics(services, b => { });
/// <summary>
/// Configure OpenTelemetry and register a <see cref="IHostedService"/>
/// to automatically start metric services in the supplied <see
/// cref="IServiceCollection" />.
/// </summary>
/// <remarks><inheritdoc
/// cref="AddOpenTelemetryMetrics(IServiceCollection)"
/// path="/remarks"/></remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <param name="configure">Callback action to configure the <see
/// cref="TracerProviderBuilder"/>.</param>
/// <returns>Supplied <see cref="IServiceCollection"/> for chaining
/// calls.</returns>
public static IServiceCollection AddOpenTelemetryMetrics(this IServiceCollection services, Action<MeterProviderBuilder> configure)
{
Guard.ThrowIfNull(services);
services.ConfigureOpenTelemetryMetrics(configure);
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, TelemetryHostedService>());
return services;
}
return services;
}
}

View File

@ -21,8 +21,16 @@ and metrics (`MeterProvider`) in [ASP.NET
## Extension method reference
**Note:** The below extension methods target
`Microsoft.Extensions.DependencyInjection.IServiceCollection`.
### Current OpenTelemetry SDK v1.4.0 and newer extensions
Targeting `OpenTelemetry.OpenTelemetryBuilder`:
* `StartWithHost`: Registers an
[IHostedService](https://learn.microsoft.com/dotnet/api/microsoft.extensions.hosting.ihostedservice)
to automatically start tracing and/or metric services in the supplied
[IServiceCollection](https://learn.microsoft.com/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection).
### Obsolete OpenTelemetry SDK pre-1.4.0 extensions
**Note:** The below extension methods should be called by application host code
only. Library authors see: [Registration extension method guidance for library
@ -37,6 +45,8 @@ and [Building a
MeterProvider](../../docs/metrics/customizing-the-sdk/README.md#building-a-meterprovider)
for more details.
Targeting `Microsoft.Extensions.DependencyInjection.IServiceCollection`:
* `AddOpenTelemetryTracing`: Configure OpenTelemetry and register an
[IHostedService](https://learn.microsoft.com/dotnet/api/microsoft.extensions.hosting.ihostedservice)
to automatically start tracing services in the supplied
@ -60,11 +70,10 @@ using OpenTelemetry.Trace;
var appBuilder = WebApplication.CreateBuilder(args);
appBuilder.Services.AddOpenTelemetryTracing(
builder => builder.AddConsoleExporter());
appBuilder.Services.AddOpenTelemetryMetrics(
builder => builder.AddConsoleExporter());
appBuilder.Services.AddOpenTelemetry()
.WithTracing(builder => builder.AddConsoleExporter())
.WithMetrics(builder => builder.AddConsoleExporter())
.StartWithHost();
var app = appBuilder.Build();

View File

@ -55,10 +55,11 @@ using OpenTelemetry.Trace;
public void ConfigureServices(IServiceCollection services)
{
services.AddOpenTelemetryTracing((builder) => builder
.AddAspNetCoreInstrumentation()
.AddJaegerExporter()
);
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddAspNetCoreInstrumentation()
.AddJaegerExporter())
.StartWithHost();
}
```
@ -84,10 +85,11 @@ services.Configure<AspNetCoreInstrumentationOptions>(options =>
};
});
services.AddOpenTelemetryTracing((builder) => builder
.AddAspNetCoreInstrumentation()
.AddJaegerExporter()
);
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddAspNetCoreInstrumentation()
.AddJaegerExporter())
.StartWithHost();
```
### Filter
@ -103,14 +105,15 @@ The following code snippet shows how to use `Filter` to only allow GET
requests.
```csharp
services.AddOpenTelemetryTracing((builder) => builder
.AddAspNetCoreInstrumentation((options) => options.Filter = httpContext =>
{
// only collect telemetry about HTTP GET requests
return httpContext.Request.Method.Equals("GET");
})
.AddJaegerExporter()
);
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddAspNetCoreInstrumentation((options) => options.Filter = httpContext =>
{
// only collect telemetry about HTTP GET requests
return httpContext.Request.Method.Equals("GET");
})
.AddJaegerExporter())
.StartWithHost();
```
It is important to note that this `Filter` option is specific to this
@ -131,24 +134,24 @@ The following code snippet shows how to enrich the activity using all 3
different options.
```csharp
services.AddOpenTelemetryTracing((builder) =>
{
builder.AddAspNetCoreInstrumentation(o =>
{
o.EnrichWithHttpRequest = (activity, httpRequest) =>
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddAspNetCoreInstrumentation(o =>
{
activity.SetTag("requestProtocol", httpRequest.Protocol);
};
o.EnrichWithHttpResponse = (activity, httpResponse) =>
{
activity.SetTag("responseLength", httpResponse.ContentLength);
};
o.EnrichWithException = (activity, exception) =>
{
activity.SetTag("exceptionType", exception.GetType().ToString());
};
})
});
o.EnrichWithHttpRequest = (activity, httpRequest) =>
{
activity.SetTag("requestProtocol", httpRequest.Protocol);
};
o.EnrichWithHttpResponse = (activity, httpResponse) =>
{
activity.SetTag("responseLength", httpResponse.ContentLength);
};
o.EnrichWithException = (activity, exception) =>
{
activity.SetTag("exceptionType", exception.GetType().ToString());
};
}))
.StartWithHost();
```
[Processor](../../docs/trace/extending-the-sdk/README.md#processor),

View File

@ -108,20 +108,20 @@ can be enriched), the name of the event, and the actual raw object. The
following code snippet shows how to add additional tags using these options.
```csharp
services.AddOpenTelemetryTracing((builder) =>
{
builder
.AddGrpcClientInstrumentation((options) =>
{
options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) =>
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddGrpcClientInstrumentation(options =>
{
activity.SetTag("requestVersion", httpRequestMessage.Version);
};
options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) =>
{
activity.SetTag("responseVersion", httpResponseMessage.Version);
};
})
options.EnrichWithHttpRequestMessage = (activity, httpRequestMessage) =>
{
activity.SetTag("requestVersion", httpRequestMessage.Version);
};
options.EnrichWithHttpResponseMessage = (activity, httpResponseMessage) =>
{
activity.SetTag("responseVersion", httpResponseMessage.Version);
};
})
.StartWithHost();
```
[Processor](../../docs/trace/extending-the-sdk/README.md#processor),

View File

@ -1,5 +1,3 @@
Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions
Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions
OpenTelemetry.Logs.LogRecord.CategoryName.set -> void
OpenTelemetry.Logs.LogRecord.EventId.set -> void
OpenTelemetry.Logs.LogRecord.Exception.set -> void
@ -14,27 +12,30 @@ OpenTelemetry.Metrics.HistogramConfiguration
OpenTelemetry.Metrics.HistogramConfiguration.HistogramConfiguration() -> void
OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.get -> bool
OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.set -> void
OpenTelemetry.Metrics.MeterProviderBuilderBase.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.MeterProviderBuilderBase.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.MetricPoint.TryGetHistogramMinMaxValues(out double min, out double max) -> bool
OpenTelemetry.OpenTelemetryBuilder
OpenTelemetry.OpenTelemetryBuilder.ConfigureResource(System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
OpenTelemetry.OpenTelemetryBuilder.WithMetrics() -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithMetrics(System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithTracing() -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithTracing(System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.Resources.ResourceBuilder.AddDetector(System.Func<System.IServiceProvider?, OpenTelemetry.Resources.IResourceDetector!>! resourceDetectorFactory) -> OpenTelemetry.Resources.ResourceBuilder!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Trace.TracerProviderBuilderBase.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Trace.TracerProviderBuilderBase.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.OpenTelemetryServiceCollectionExtensions
static OpenTelemetry.OpenTelemetryServiceCollectionExtensions.AddOpenTelemetry(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> OpenTelemetry.OpenTelemetryBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string?
OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string! traceStateString) -> void
OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string!, object!>>? attributes, string? traceStateString) -> void
*REMOVED*static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Metrics.MetricType.LongSumNonMonotonic = 138 -> OpenTelemetry.Metrics.MetricType

View File

@ -1,5 +1,3 @@
Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions
Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions
OpenTelemetry.Logs.LogRecord.CategoryName.set -> void
OpenTelemetry.Logs.LogRecord.EventId.set -> void
OpenTelemetry.Logs.LogRecord.Exception.set -> void
@ -14,27 +12,30 @@ OpenTelemetry.Metrics.HistogramConfiguration
OpenTelemetry.Metrics.HistogramConfiguration.HistogramConfiguration() -> void
OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.get -> bool
OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.set -> void
OpenTelemetry.Metrics.MeterProviderBuilderBase.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.MeterProviderBuilderBase.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.MetricPoint.TryGetHistogramMinMaxValues(out double min, out double max) -> bool
OpenTelemetry.OpenTelemetryBuilder
OpenTelemetry.OpenTelemetryBuilder.ConfigureResource(System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
OpenTelemetry.OpenTelemetryBuilder.WithMetrics() -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithMetrics(System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithTracing() -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithTracing(System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.Resources.ResourceBuilder.AddDetector(System.Func<System.IServiceProvider?, OpenTelemetry.Resources.IResourceDetector!>! resourceDetectorFactory) -> OpenTelemetry.Resources.ResourceBuilder!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Trace.TracerProviderBuilderBase.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Trace.TracerProviderBuilderBase.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.OpenTelemetryServiceCollectionExtensions
static OpenTelemetry.OpenTelemetryServiceCollectionExtensions.AddOpenTelemetry(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> OpenTelemetry.OpenTelemetryBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string?
OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string! traceStateString) -> void
OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string!, object!>>? attributes, string? traceStateString) -> void
*REMOVED*static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Metrics.MetricType.LongSumNonMonotonic = 138 -> OpenTelemetry.Metrics.MetricType

View File

@ -1,5 +1,3 @@
Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions
Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions
OpenTelemetry.Logs.LogRecord.CategoryName.set -> void
OpenTelemetry.Logs.LogRecord.EventId.set -> void
OpenTelemetry.Logs.LogRecord.Exception.set -> void
@ -14,27 +12,30 @@ OpenTelemetry.Metrics.HistogramConfiguration
OpenTelemetry.Metrics.HistogramConfiguration.HistogramConfiguration() -> void
OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.get -> bool
OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.set -> void
OpenTelemetry.Metrics.MeterProviderBuilderBase.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.MeterProviderBuilderBase.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.MetricPoint.TryGetHistogramMinMaxValues(out double min, out double max) -> bool
OpenTelemetry.OpenTelemetryBuilder
OpenTelemetry.OpenTelemetryBuilder.ConfigureResource(System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
OpenTelemetry.OpenTelemetryBuilder.WithMetrics() -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithMetrics(System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithTracing() -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithTracing(System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.Resources.ResourceBuilder.AddDetector(System.Func<System.IServiceProvider?, OpenTelemetry.Resources.IResourceDetector!>! resourceDetectorFactory) -> OpenTelemetry.Resources.ResourceBuilder!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Trace.TracerProviderBuilderBase.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Trace.TracerProviderBuilderBase.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.OpenTelemetryServiceCollectionExtensions
static OpenTelemetry.OpenTelemetryServiceCollectionExtensions.AddOpenTelemetry(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> OpenTelemetry.OpenTelemetryBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string?
OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string! traceStateString) -> void
OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string!, object!>>? attributes, string? traceStateString) -> void
*REMOVED*static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Metrics.MetricType.LongSumNonMonotonic = 138 -> OpenTelemetry.Metrics.MetricType

View File

@ -1,5 +1,3 @@
Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions
Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions
OpenTelemetry.Logs.LogRecord.CategoryName.set -> void
OpenTelemetry.Logs.LogRecord.EventId.set -> void
OpenTelemetry.Logs.LogRecord.Exception.set -> void
@ -14,27 +12,30 @@ OpenTelemetry.Metrics.HistogramConfiguration
OpenTelemetry.Metrics.HistogramConfiguration.HistogramConfiguration() -> void
OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.get -> bool
OpenTelemetry.Metrics.HistogramConfiguration.RecordMinMax.set -> void
OpenTelemetry.Metrics.MeterProviderBuilderBase.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.MeterProviderBuilderBase.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Metrics.MetricPoint.TryGetHistogramMinMaxValues(out double min, out double max) -> bool
OpenTelemetry.OpenTelemetryBuilder
OpenTelemetry.OpenTelemetryBuilder.ConfigureResource(System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.Services.get -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
OpenTelemetry.OpenTelemetryBuilder.WithMetrics() -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithMetrics(System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithTracing() -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.OpenTelemetryBuilder.WithTracing(System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.OpenTelemetryBuilder!
OpenTelemetry.Resources.ResourceBuilder.AddDetector(System.Func<System.IServiceProvider?, OpenTelemetry.Resources.IResourceDetector!>! resourceDetectorFactory) -> OpenTelemetry.Resources.ResourceBuilder!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.MeterProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryMetrics(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Trace.TracerProviderBuilderBase.ConfigureBuilder(System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Trace.TracerProviderBuilderBase.ConfigureServices(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.OpenTelemetryServiceCollectionExtensions
static OpenTelemetry.OpenTelemetryServiceCollectionExtensions.AddOpenTelemetry(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> OpenTelemetry.OpenTelemetryBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddReader<T>(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Metrics.MeterProviderBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
OpenTelemetry.Trace.SamplingResult.TraceStateString.get -> string?
OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, string! traceStateString) -> void
OpenTelemetry.Trace.SamplingResult.SamplingResult(OpenTelemetry.Trace.SamplingDecision decision, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string!, object!>>? attributes, string? traceStateString) -> void
*REMOVED*static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure = null) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddInstrumentation<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddProcessor<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureBuilder(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<System.IServiceProvider!, OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureServices(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.SetSampler<T>(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder) -> OpenTelemetry.Trace.TracerProviderBuilder!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Metrics.MeterProviderBuilder!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Metrics.MetricType.LongSumNonMonotonic = 138 -> OpenTelemetry.Metrics.MetricType

View File

@ -21,6 +21,5 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.Prometheus.HttpListener.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("OpenTelemetry.Extensions.Hosting.Tests" + AssemblyInfo.PublicKey)]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyInfo.MoqPublicKey)]
[assembly: InternalsVisibleTo("Benchmarks" + AssemblyInfo.PublicKey)]

View File

@ -7,6 +7,11 @@
`AddEnvironmentVariableDetector` extension (Logs)
([#3889](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3889))
* Refactored `AddInstrumentation`, `ConfigureServices` and `ConfigureBuilder`
APIs into the OpenTelemetry.Extensions.DependencyInjection package and added
the `IServiceCollection.AddOpenTelemetry` API
([#3923](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3923))
## 1.4.0-beta.3
Released 2022-Nov-07

View File

@ -1,82 +0,0 @@
// <copyright file="ProviderBuilderServiceCollectionCallbackHelper.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#nullable enable
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
namespace OpenTelemetry;
internal static class ProviderBuilderServiceCollectionCallbackHelper<TBuilder, TProvider, TState>
where TState : ProviderBuilderState<TBuilder, TProvider>
{
public static IServiceCollection RegisterConfigureBuilderCallback(
IServiceCollection services,
Action<IServiceProvider, TBuilder> configure)
{
Debug.Assert(configure != null, "configure was null");
return RegisterConfigureStateCallback(
services,
(sp, state) => configure!(sp, state.Builder));
}
public static IServiceCollection RegisterConfigureStateCallback(
IServiceCollection services,
Action<IServiceProvider, TState> configure)
{
Debug.Assert(services != null, "services was null");
Debug.Assert(configure != null, "configure was null");
return services!.AddSingleton(
new ConfigureProviderBuilderStateCallbackRegistration(configure!));
}
public static void InvokeRegisteredConfigureStateCallbacks(
IServiceProvider serviceProvider,
TState state)
{
Debug.Assert(serviceProvider != null, "serviceProvider was null");
Debug.Assert(state != null, "state was null");
var callbackRegistrations = serviceProvider!.GetServices<ConfigureProviderBuilderStateCallbackRegistration>();
foreach (var callbackRegistration in callbackRegistrations)
{
callbackRegistration.Configure(serviceProvider!, state!);
}
}
private sealed class ConfigureProviderBuilderStateCallbackRegistration
{
private readonly Action<IServiceProvider, TState> configure;
public ConfigureProviderBuilderStateCallbackRegistration(
Action<IServiceProvider, TState> configure)
{
this.configure = configure;
}
public void Configure(IServiceProvider serviceProvider, TState state)
{
Debug.Assert(serviceProvider != null, "serviceProvider was null");
Debug.Assert(state != null, "state was null");
this.configure(serviceProvider!, state!);
}
}
}

View File

@ -19,6 +19,7 @@
using System.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
@ -29,28 +30,32 @@ internal static class ProviderBuilderServiceCollectionExtensions
{
public static IServiceCollection AddOpenTelemetryMeterProviderBuilderServices(this IServiceCollection services)
{
services.AddOpenTelemetryProviderBuilderServices();
Debug.Assert(services != null, "services was null");
services.TryAddSingleton<MeterProviderBuilderState>();
services.RegisterOptionsFactory(configuration => new MetricReaderOptions(configuration));
services!.TryAddSingleton<MeterProviderBuilderSdk>();
services!.RegisterOptionsFactory(configuration => new MetricReaderOptions(configuration));
return services;
return services!;
}
public static IServiceCollection AddOpenTelemetryTracerProviderBuilderServices(this IServiceCollection services)
{
services.AddOpenTelemetryProviderBuilderServices();
Debug.Assert(services != null, "services was null");
services.TryAddSingleton<TracerProviderBuilderState>();
services.RegisterOptionsFactory(configuration => new BatchExportActivityProcessorOptions(configuration));
services!.TryAddSingleton<TracerProviderBuilderSdk>();
services!.RegisterOptionsFactory(configuration => new BatchExportActivityProcessorOptions(configuration));
return services;
return services!;
}
private static IServiceCollection AddOpenTelemetryProviderBuilderServices(this IServiceCollection services)
public static IServiceCollection AddOpenTelemetrySharedProviderBuilderServices(this IServiceCollection services)
{
Debug.Assert(services != null, "services was null");
// Accessing Sdk class is just to trigger its static ctor,
// which sets default Propagators and default Activity Id format
_ = Sdk.SuppressInstrumentation;
services.AddOptions();
// Note: When using a host builder IConfiguration is automatically
@ -58,7 +63,8 @@ internal static class ProviderBuilderServiceCollectionExtensions
// Sdk.Create* style or when manually creating a ServiceCollection. The
// point of this registration is to make IConfiguration available in
// those cases.
services!.TryAddSingleton<IConfiguration>(sp => new ConfigurationBuilder().AddEnvironmentVariables().Build());
services!.TryAddSingleton<IConfiguration>(
sp => new ConfigurationBuilder().AddEnvironmentVariables().Build());
return services!;
}

View File

@ -1,105 +0,0 @@
// <copyright file="ProviderBuilderState.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#nullable enable
using System.Diagnostics;
using OpenTelemetry.Resources;
namespace OpenTelemetry;
internal abstract class ProviderBuilderState<TBuilder, TProvider>
{
private TProvider? provider;
protected ProviderBuilderState(IServiceProvider serviceProvider)
{
Debug.Assert(serviceProvider != null, "serviceProvider was null");
this.ServiceProvider = serviceProvider!;
}
public IServiceProvider ServiceProvider { get; }
public abstract TBuilder Builder { get; }
public TProvider Provider
{
get => this.provider ?? throw new InvalidOperationException("Provider has not been set on state.");
}
public List<InstrumentationRegistration> Instrumentation { get; } = new();
public ResourceBuilder? ResourceBuilder { get; protected set; }
public void RegisterProvider(string providerTypeName, TProvider provider)
{
Debug.Assert(provider != null, "provider was null");
if (this.provider != null)
{
throw new NotSupportedException($"{providerTypeName} cannot be accessed while build is executing.");
}
this.provider = provider;
}
public void AddInstrumentation(
string instrumentationName,
string instrumentationVersion,
object instrumentation)
{
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationName), "instrumentationName was null or whitespace");
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationVersion), "instrumentationVersion was null or whitespace");
Debug.Assert(instrumentation != null, "instrumentation was null");
this.Instrumentation.Add(
new InstrumentationRegistration(
instrumentationName,
instrumentationVersion,
instrumentation!));
}
public void ConfigureResource(Action<ResourceBuilder> configure)
{
Debug.Assert(configure != null, "configure was null");
var resourceBuilder = this.ResourceBuilder ??= ResourceBuilder.CreateDefault();
configure!(resourceBuilder);
}
public void SetResourceBuilder(ResourceBuilder resourceBuilder)
{
Debug.Assert(resourceBuilder != null, "resourceBuilder was null");
this.ResourceBuilder = resourceBuilder;
}
internal readonly struct InstrumentationRegistration
{
public readonly string Name;
public readonly string Version;
public readonly object Instance;
internal InstrumentationRegistration(string name, string version, object instance)
{
this.Name = name;
this.Version = version;
this.Instance = instance;
}
}
}

View File

@ -16,299 +16,147 @@
#nullable enable
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Text.RegularExpressions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper<
OpenTelemetry.Metrics.MeterProviderBuilderSdk,
OpenTelemetry.Metrics.MeterProviderSdk,
OpenTelemetry.Metrics.MeterProviderBuilderState>;
namespace OpenTelemetry.Metrics;
namespace OpenTelemetry.Metrics
/// <summary>
/// Contains methods for building <see cref="MeterProvider"/> instances.
/// </summary>
public class MeterProviderBuilderBase : MeterProviderBuilder, IMeterProviderBuilder
{
/// <summary>
/// Contains methods for building <see cref="MeterProvider"/> instances.
/// </summary>
public abstract class MeterProviderBuilderBase : MeterProviderBuilder, IDeferredMeterProviderBuilder
private readonly bool allowBuild;
private IServiceCollection? services;
public MeterProviderBuilderBase()
{
internal readonly MeterProviderBuilderState? State;
private const string DefaultInstrumentationVersion = "1.0.0.0";
var services = new ServiceCollection();
private readonly bool ownsServices;
private IServiceCollection? services;
services
.AddOpenTelemetrySharedProviderBuilderServices()
.AddOpenTelemetryMeterProviderBuilderServices()
.TryAddSingleton<MeterProvider>(
sp => throw new NotSupportedException("Self-contained MeterProvider cannot be accessed using the application IServiceProvider call Build instead."));
// This ctor is for a builder created from MeterProviderBuilderState which
// happens after the service provider has been created.
internal MeterProviderBuilderBase(MeterProviderBuilderState state)
services.ConfigureOpenTelemetryMeterProvider((sp, builder) => this.services = null);
this.services = services;
this.allowBuild = true;
}
internal MeterProviderBuilderBase(IServiceCollection services)
{
Guard.ThrowIfNull(services);
services
.AddOpenTelemetryMeterProviderBuilderServices()
.TryAddSingleton<MeterProvider>(sp => new MeterProviderSdk(sp, ownsServiceProvider: false));
services.ConfigureOpenTelemetryMeterProvider((sp, builder) => this.services = null);
this.services = services;
this.allowBuild = false;
}
/// <inheritdoc />
MeterProvider? IMeterProviderBuilder.Provider => null;
/// <inheritdoc />
public override MeterProviderBuilder AddInstrumentation<TInstrumentation>(Func<TInstrumentation> instrumentationFactory)
{
Guard.ThrowIfNull(instrumentationFactory);
this.ConfigureBuilder((sp, builder) =>
{
Debug.Assert(state != null, "state was null");
builder.AddInstrumentation(instrumentationFactory);
});
this.State = state;
return this;
}
/// <inheritdoc />
public override MeterProviderBuilder AddMeter(params string[] names)
{
Guard.ThrowIfNull(names);
this.ConfigureBuilder((sp, builder) =>
{
builder.AddMeter(names);
});
return this;
}
/// <inheritdoc />
public MeterProviderBuilder ConfigureBuilder(Action<IServiceProvider, MeterProviderBuilder> configure)
{
var services = this.services;
if (services == null)
{
throw new NotSupportedException("Builder cannot be configured during MeterProvider construction.");
}
// This ctor is for ConfigureOpenTelemetryMetrics +
// AddOpenTelemetryMetrics scenarios where the builder is bound to an
// external service collection.
internal MeterProviderBuilderBase(IServiceCollection services)
services.ConfigureOpenTelemetryMeterProvider(configure);
return this;
}
/// <inheritdoc />
public MeterProviderBuilder ConfigureServices(Action<IServiceCollection> configure)
{
Guard.ThrowIfNull(configure);
var services = this.services;
if (services == null)
{
Guard.ThrowIfNull(services);
services.AddOpenTelemetryMeterProviderBuilderServices();
services.TryAddSingleton<MeterProvider>(sp => new MeterProviderSdk(sp, ownsServiceProvider: false));
this.services = services;
this.ownsServices = false;
throw new NotSupportedException("Services cannot be configured during MeterProvider construction.");
}
// This ctor is for Sdk.CreateMeterProviderBuilder where the builder
// owns its services and service provider.
protected MeterProviderBuilderBase()
configure(services);
return this;
}
/// <inheritdoc />
MeterProviderBuilder IDeferredMeterProviderBuilder.Configure(Action<IServiceProvider, MeterProviderBuilder> configure)
=> this.ConfigureBuilder(configure);
internal MeterProvider InvokeBuild()
=> this.Build();
/// <summary>
/// Run the configured actions to initialize the <see cref="MeterProvider"/>.
/// </summary>
/// <returns><see cref="MeterProvider"/>.</returns>
protected MeterProvider Build()
{
if (!this.allowBuild)
{
var services = new ServiceCollection();
services.AddOpenTelemetryMeterProviderBuilderServices();
services.AddSingleton<MeterProvider>(
sp => throw new NotSupportedException("External MeterProvider created through Sdk.CreateMeterProviderBuilder cannot be accessed using service provider."));
this.services = services;
this.ownsServices = true;
throw new NotSupportedException("A MeterProviderBuilder bound to external service cannot be built directly. Access the MeterProvider using the application IServiceProvider instead.");
}
/// <inheritdoc />
public override MeterProviderBuilder AddInstrumentation<TInstrumentation>(Func<TInstrumentation> instrumentationFactory)
{
Guard.ThrowIfNull(instrumentationFactory);
var services = this.services;
return this.AddInstrumentation((sp) => instrumentationFactory());
if (services == null)
{
throw new NotSupportedException("MeterProviderBuilder build method cannot be called multiple times.");
}
/// <inheritdoc />
public override MeterProviderBuilder AddMeter(params string[] names)
{
Guard.ThrowIfNull(names);
return this.ConfigureState((sp, state) => state.AddMeter(names));
}
/// <inheritdoc />
MeterProviderBuilder IDeferredMeterProviderBuilder.Configure(
Action<IServiceProvider, MeterProviderBuilder> configure)
{
Guard.ThrowIfNull(configure);
if (this.State != null)
{
configure(this.State.ServiceProvider, this);
}
else
{
this.ConfigureServices(services
=> CallbackHelper.RegisterConfigureBuilderCallback(services, configure));
}
return this;
}
internal MeterProviderBuilder AddInstrumentation<T>()
where T : class
{
this.TryAddSingleton<T>();
this.AddInstrumentation((sp) => sp.GetRequiredService<T>());
return this;
}
internal MeterProviderBuilder AddReader<T>()
where T : MetricReader
{
this.TryAddSingleton<T>();
this.ConfigureState((sp, state) => state.AddReader(sp.GetRequiredService<T>()));
return this;
}
internal MeterProviderBuilder AddReader(MetricReader reader)
{
Guard.ThrowIfNull(reader);
return this.ConfigureState((sp, state) => state.AddReader(reader));
}
internal MeterProviderBuilder AddView(string instrumentName, string name)
{
if (!MeterProviderBuilderSdk.IsValidInstrumentName(name))
{
throw new ArgumentException($"Custom view name {name} is invalid.", nameof(name));
}
if (instrumentName.IndexOf('*') != -1)
{
throw new ArgumentException(
$"Instrument selection criteria is invalid. Instrument name '{instrumentName}' " +
$"contains a wildcard character. This is not allowed when using a view to " +
$"rename a metric stream as it would lead to conflicting metric stream names.",
nameof(instrumentName));
}
return this.AddView(
instrumentName,
new MetricStreamConfiguration
{
Name = name,
});
}
internal MeterProviderBuilder AddView(string instrumentName, MetricStreamConfiguration metricStreamConfiguration)
{
Guard.ThrowIfNullOrWhitespace(instrumentName);
Guard.ThrowIfNull(metricStreamConfiguration);
if (metricStreamConfiguration.Name != null && instrumentName.IndexOf('*') != -1)
{
throw new ArgumentException(
$"Instrument selection criteria is invalid. Instrument name '{instrumentName}' " +
$"contains a wildcard character. This is not allowed when using a view to " +
$"rename a metric stream as it would lead to conflicting metric stream names.",
nameof(instrumentName));
}
if (instrumentName.IndexOf('*') != -1)
{
var pattern = '^' + Regex.Escape(instrumentName).Replace("\\*", ".*");
var regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
return this.AddView(instrument => regex.IsMatch(instrument.Name) ? metricStreamConfiguration : null);
}
else
{
return this.AddView(instrument => instrument.Name.Equals(instrumentName, StringComparison.OrdinalIgnoreCase) ? metricStreamConfiguration : null);
}
}
internal MeterProviderBuilder AddView(Func<Instrument, MetricStreamConfiguration?> viewConfig)
{
Guard.ThrowIfNull(viewConfig);
this.ConfigureState((sp, state) => state.AddView(viewConfig));
return this;
}
internal MeterProviderBuilder ConfigureResource(Action<ResourceBuilder> configure)
{
Guard.ThrowIfNull(configure);
return this.ConfigureState((sp, state) => state.ConfigureResource(configure));
}
internal MeterProviderBuilder ConfigureServices(Action<IServiceCollection> configure)
{
Guard.ThrowIfNull(configure);
var services = this.services;
if (services == null)
{
throw new NotSupportedException("Services cannot be configured after ServiceProvider has been created.");
}
configure(services);
return this;
}
internal MeterProvider InvokeBuild()
=> this.Build();
internal MeterProviderBuilder SetMaxMetricStreams(int maxMetricStreams)
{
Guard.ThrowIfOutOfRange(maxMetricStreams, min: 1);
return this.ConfigureState((sp, state) => state.MaxMetricStreams = maxMetricStreams);
}
internal MeterProviderBuilder SetMaxMetricPointsPerMetricStream(int maxMetricPointsPerMetricStream)
{
Guard.ThrowIfOutOfRange(maxMetricPointsPerMetricStream, min: 1);
return this.ConfigureState((sp, state) => state.MaxMetricPointsPerMetricStream = maxMetricPointsPerMetricStream);
}
internal MeterProviderBuilder SetResourceBuilder(ResourceBuilder resourceBuilder)
{
Guard.ThrowIfNull(resourceBuilder);
return this.ConfigureState((sp, state) => state.SetResourceBuilder(resourceBuilder));
}
/// <summary>
/// Run the configured actions to initialize the <see cref="MeterProvider"/>.
/// </summary>
/// <returns><see cref="MeterProvider"/>.</returns>
protected MeterProvider Build()
{
if (!this.ownsServices || this.State != null)
{
throw new NotSupportedException("Build cannot be called directly on MeterProviderBuilder tied to external services.");
}
var services = this.services;
if (services == null)
{
throw new NotSupportedException("MeterProviderBuilder build method cannot be called multiple times.");
}
this.services = null;
this.services = null;
#if DEBUG
bool validateScopes = true;
bool validateScopes = true;
#else
bool validateScopes = false;
bool validateScopes = false;
#endif
var serviceProvider = services.BuildServiceProvider(validateScopes);
var serviceProvider = services.BuildServiceProvider(validateScopes);
return new MeterProviderSdk(serviceProvider, ownsServiceProvider: true);
}
private MeterProviderBuilder AddInstrumentation<T>(Func<IServiceProvider, T> instrumentationFactory)
where T : class
{
this.ConfigureState((sp, state)
=> state.AddInstrumentation(
typeof(T).Name,
typeof(T).Assembly.GetName().Version?.ToString() ?? DefaultInstrumentationVersion,
instrumentationFactory(sp)));
return this;
}
private MeterProviderBuilder ConfigureState(Action<IServiceProvider, MeterProviderBuilderState> configure)
{
Debug.Assert(configure != null, "configure was null");
if (this.State != null)
{
configure!(this.State.ServiceProvider, this.State);
}
else
{
this.ConfigureServices(services => CallbackHelper.RegisterConfigureStateCallback(services, configure!));
}
return this;
}
private void TryAddSingleton<T>()
where T : class
{
var services = this.services;
services?.TryAddSingleton<T>();
}
return new MeterProviderSdk(serviceProvider, ownsServiceProvider: true);
}
}

View File

@ -17,7 +17,10 @@
#nullable enable
using System.Diagnostics.Metrics;
using System.Text.RegularExpressions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
namespace OpenTelemetry.Metrics
@ -27,27 +30,6 @@ namespace OpenTelemetry.Metrics
/// </summary>
public static class MeterProviderBuilderExtensions
{
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <remarks>
/// Note: The type specified by <typeparamref name="T"/> will be
/// registered as a singleton service into application services.
/// </remarks>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddInstrumentation<T>(this MeterProviderBuilder meterProviderBuilder)
where T : class
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
{
meterProviderBuilderBase.AddInstrumentation<T>();
}
return meterProviderBuilder;
}
/// <summary>
/// Adds a reader to the provider.
/// </summary>
@ -56,10 +38,15 @@ namespace OpenTelemetry.Metrics
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddReader(this MeterProviderBuilder meterProviderBuilder, MetricReader reader)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
Guard.ThrowIfNull(reader);
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
meterProviderBuilderBase.AddReader(reader);
}
if (builder is MeterProviderBuilderSdk meterProviderBuilderSdk)
{
meterProviderBuilderSdk.AddReader(reader);
}
});
return meterProviderBuilder;
}
@ -77,10 +64,15 @@ namespace OpenTelemetry.Metrics
public static MeterProviderBuilder AddReader<T>(this MeterProviderBuilder meterProviderBuilder)
where T : MetricReader
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
meterProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
meterProviderBuilderBase.AddReader<T>();
}
if (builder is MeterProviderBuilderSdk meterProviderBuilderSdk)
{
meterProviderBuilderSdk.AddReader(sp.GetRequiredService<T>());
}
});
return meterProviderBuilder;
}
@ -96,11 +88,22 @@ namespace OpenTelemetry.Metrics
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddView(this MeterProviderBuilder meterProviderBuilder, string instrumentName, string name)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
if (!MeterProviderBuilderSdk.IsValidInstrumentName(name))
{
meterProviderBuilderBase.AddView(instrumentName, name);
throw new ArgumentException($"Custom view name {name} is invalid.", nameof(name));
}
if (instrumentName.IndexOf('*') != -1)
{
throw new ArgumentException(
$"Instrument selection criteria is invalid. Instrument name '{instrumentName}' " +
$"contains a wildcard character. This is not allowed when using a view to " +
$"rename a metric stream as it would lead to conflicting metric stream names.",
nameof(instrumentName));
}
meterProviderBuilder.AddView(instrumentName, new MetricStreamConfiguration { Name = name });
return meterProviderBuilder;
}
@ -115,11 +118,35 @@ namespace OpenTelemetry.Metrics
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddView(this MeterProviderBuilder meterProviderBuilder, string instrumentName, MetricStreamConfiguration metricStreamConfiguration)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
Guard.ThrowIfNullOrWhitespace(instrumentName);
Guard.ThrowIfNull(metricStreamConfiguration);
if (metricStreamConfiguration.Name != null && instrumentName.IndexOf('*') != -1)
{
meterProviderBuilderBase.AddView(instrumentName, metricStreamConfiguration);
throw new ArgumentException(
$"Instrument selection criteria is invalid. Instrument name '{instrumentName}' " +
$"contains a wildcard character. This is not allowed when using a view to " +
$"rename a metric stream as it would lead to conflicting metric stream names.",
nameof(instrumentName));
}
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
if (builder is MeterProviderBuilderSdk meterProviderBuilderSdk)
{
if (instrumentName.IndexOf('*') != -1)
{
var pattern = '^' + Regex.Escape(instrumentName).Replace("\\*", ".*");
var regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
meterProviderBuilderSdk.AddView(instrument => regex.IsMatch(instrument.Name) ? metricStreamConfiguration : null);
}
else
{
meterProviderBuilderSdk.AddView(instrument => instrument.Name.Equals(instrumentName, StringComparison.OrdinalIgnoreCase) ? metricStreamConfiguration : null);
}
}
});
return meterProviderBuilder;
}
@ -141,10 +168,15 @@ namespace OpenTelemetry.Metrics
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder AddView(this MeterProviderBuilder meterProviderBuilder, Func<Instrument, MetricStreamConfiguration?> viewConfig)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
Guard.ThrowIfNull(viewConfig);
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
meterProviderBuilderBase.AddView(viewConfig);
}
if (builder is MeterProviderBuilderSdk meterProviderBuilderSdk)
{
meterProviderBuilderSdk.AddView(viewConfig);
}
});
return meterProviderBuilder;
}
@ -165,10 +197,15 @@ namespace OpenTelemetry.Metrics
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder SetMaxMetricStreams(this MeterProviderBuilder meterProviderBuilder, int maxMetricStreams)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
Guard.ThrowIfOutOfRange(maxMetricStreams, min: 1);
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
meterProviderBuilderBase.SetMaxMetricStreams(maxMetricStreams);
}
if (builder is MeterProviderBuilderSdk meterProviderBuilderSdk)
{
meterProviderBuilderSdk.SetMaxMetricStreams(maxMetricStreams);
}
});
return meterProviderBuilder;
}
@ -188,10 +225,15 @@ namespace OpenTelemetry.Metrics
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder SetMaxMetricPointsPerMetricStream(this MeterProviderBuilder meterProviderBuilder, int maxMetricPointsPerMetricStream)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
Guard.ThrowIfOutOfRange(maxMetricPointsPerMetricStream, min: 1);
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
meterProviderBuilderBase.SetMaxMetricPointsPerMetricStream(maxMetricPointsPerMetricStream);
}
if (builder is MeterProviderBuilderSdk meterProviderBuilderSdk)
{
meterProviderBuilderSdk.SetMaxMetricPointsPerMetricStream(maxMetricPointsPerMetricStream);
}
});
return meterProviderBuilder;
}
@ -207,10 +249,13 @@ namespace OpenTelemetry.Metrics
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder SetResourceBuilder(this MeterProviderBuilder meterProviderBuilder, ResourceBuilder resourceBuilder)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
meterProviderBuilderBase.SetResourceBuilder(resourceBuilder);
}
if (builder is MeterProviderBuilderSdk meterProviderBuilderSdk)
{
meterProviderBuilderSdk.SetResourceBuilder(resourceBuilder);
}
});
return meterProviderBuilder;
}
@ -224,53 +269,13 @@ namespace OpenTelemetry.Metrics
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder ConfigureResource(this MeterProviderBuilder meterProviderBuilder, Action<ResourceBuilder> configure)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
{
meterProviderBuilderBase.ConfigureResource(configure);
}
return meterProviderBuilder;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="IServiceCollection"/> where metric services are configured.
/// </summary>
/// <remarks>
/// Note: Metric services are only available during the application
/// configuration phase.
/// </remarks>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder ConfigureServices(
this MeterProviderBuilder meterProviderBuilder,
Action<IServiceCollection> configure)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
{
meterProviderBuilderBase.ConfigureServices(configure);
}
return meterProviderBuilder;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="MeterProviderBuilder"/> once the application <see
/// cref="IServiceProvider"/> is available.
/// </summary>
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
public static MeterProviderBuilder ConfigureBuilder(
this MeterProviderBuilder meterProviderBuilder,
Action<IServiceProvider, MeterProviderBuilder> configure)
{
if (meterProviderBuilder is IDeferredMeterProviderBuilder deferredMeterProviderBuilder)
{
deferredMeterProviderBuilder.Configure(configure);
}
if (builder is MeterProviderBuilderSdk meterProviderBuilderSdk)
{
meterProviderBuilderSdk.ConfigureResource(configure);
}
});
return meterProviderBuilder;
}

View File

@ -16,29 +16,50 @@
#nullable enable
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Text.RegularExpressions;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
namespace OpenTelemetry.Metrics
{
internal sealed class MeterProviderBuilderSdk : MeterProviderBuilderBase
/// <summary>
/// Stores state used to build a <see cref="MeterProvider"/>.
/// </summary>
internal sealed class MeterProviderBuilderSdk : MeterProviderBuilder, IMeterProviderBuilder
{
public const int MaxMetricsDefault = 1000;
public const int MaxMetricPointsPerMetricDefault = 2000;
private const string DefaultInstrumentationVersion = "1.0.0.0";
private static readonly Regex InstrumentNameRegex = new(
@"^[a-z][a-z0-9-._]{0,62}$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public MeterProviderBuilderSdk()
private readonly IServiceProvider serviceProvider;
private MeterProviderSdk? meterProvider;
public MeterProviderBuilderSdk(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public MeterProviderBuilderSdk(IServiceCollection services)
: base(services)
{
}
public List<InstrumentationRegistration> Instrumentation { get; } = new();
public MeterProviderBuilderSdk(MeterProviderBuilderState state)
: base(state)
{
}
public ResourceBuilder? ResourceBuilder { get; private set; }
public MeterProvider? Provider => this.meterProvider;
public List<MetricReader> Readers { get; } = new();
public List<string> MeterSources { get; } = new();
public List<Func<Instrument, MetricStreamConfiguration?>> ViewConfigs { get; } = new();
public int MaxMetricStreams { get; private set; } = MaxMetricsDefault;
public int MaxMetricPointsPerMetricStream { get; private set; } = MaxMetricPointsPerMetricDefault;
/// <summary>
/// Returns whether the given instrument name is valid according to the specification.
@ -72,5 +93,143 @@ namespace OpenTelemetry.Metrics
return InstrumentNameRegex.IsMatch(customViewName);
}
public void RegisterProvider(MeterProviderSdk meterProvider)
{
Debug.Assert(meterProvider != null, "meterProvider was null");
if (this.meterProvider != null)
{
throw new NotSupportedException("MeterProvider cannot be accessed while build is executing.");
}
this.meterProvider = meterProvider;
}
public override MeterProviderBuilder AddInstrumentation<TInstrumentation>(
Func<TInstrumentation> instrumentationFactory)
{
Debug.Assert(instrumentationFactory != null, "instrumentationFactory was null");
return this.AddInstrumentation(
typeof(TInstrumentation).Name,
typeof(TInstrumentation).Assembly.GetName().Version?.ToString() ?? DefaultInstrumentationVersion,
instrumentationFactory!());
}
public MeterProviderBuilder AddInstrumentation(
string instrumentationName,
string instrumentationVersion,
object instrumentation)
{
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationName), "instrumentationName was null or whitespace");
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationVersion), "instrumentationVersion was null or whitespace");
Debug.Assert(instrumentation != null, "instrumentation was null");
this.Instrumentation.Add(
new InstrumentationRegistration(
instrumentationName,
instrumentationVersion,
instrumentation!));
return this;
}
public MeterProviderBuilder ConfigureResource(Action<ResourceBuilder> configure)
{
Debug.Assert(configure != null, "configure was null");
var resourceBuilder = this.ResourceBuilder ??= ResourceBuilder.CreateDefault();
configure!(resourceBuilder);
return this;
}
public MeterProviderBuilder SetResourceBuilder(ResourceBuilder resourceBuilder)
{
Debug.Assert(resourceBuilder != null, "resourceBuilder was null");
this.ResourceBuilder = resourceBuilder;
return this;
}
public override MeterProviderBuilder AddMeter(params string[] names)
{
Debug.Assert(names != null, "names was null");
foreach (var name in names!)
{
Guard.ThrowIfNullOrWhitespace(name);
this.MeterSources.Add(name);
}
return this;
}
public MeterProviderBuilder AddReader(MetricReader reader)
{
Debug.Assert(reader != null, "reader was null");
this.Readers.Add(reader!);
return this;
}
public MeterProviderBuilder AddView(Func<Instrument, MetricStreamConfiguration?> viewConfig)
{
Debug.Assert(viewConfig != null, "viewConfig was null");
this.ViewConfigs.Add(viewConfig!);
return this;
}
public MeterProviderBuilder SetMaxMetricStreams(int maxMetricStreams)
{
this.MaxMetricStreams = maxMetricStreams;
return this;
}
public MeterProviderBuilder SetMaxMetricPointsPerMetricStream(int maxMetricPointsPerMetricStream)
{
this.MaxMetricPointsPerMetricStream = maxMetricPointsPerMetricStream;
return this;
}
public MeterProviderBuilder ConfigureBuilder(Action<IServiceProvider, MeterProviderBuilder> configure)
{
Debug.Assert(configure != null, "configure was null");
configure!(this.serviceProvider, this);
return this;
}
public MeterProviderBuilder ConfigureServices(Action<IServiceCollection> configure)
{
throw new NotSupportedException("Services cannot be configured after ServiceProvider has been created.");
}
MeterProviderBuilder IDeferredMeterProviderBuilder.Configure(Action<IServiceProvider, MeterProviderBuilder> configure)
=> this.ConfigureBuilder(configure);
internal readonly struct InstrumentationRegistration
{
public readonly string Name;
public readonly string Version;
public readonly object Instance;
internal InstrumentationRegistration(string name, string version, object instance)
{
this.Name = name;
this.Version = version;
this.Instance = instance;
}
}
}
}

View File

@ -1,76 +0,0 @@
// <copyright file="MeterProviderBuilderServiceCollectionExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#nullable enable
using OpenTelemetry;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// Extension methods for setting up OpenTelemetry Metrics services in an <see cref="IServiceCollection" />.
/// </summary>
public static class MeterProviderBuilderServiceCollectionExtensions
{
/// <summary>
/// Configures OpenTelemetry Metrics services in the supplied <see cref="IServiceCollection" />.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>A <see cref="MeterProvider"/> will not be created automatically
/// using this method. Either use the
/// <c>IServiceCollection.AddOpenTelemetryMetrics</c> extension in the
/// <c>OpenTelemetry.Extensions.Hosting</c> package or access the <see
/// cref="MeterProvider"/> through the application <see
/// cref="IServiceProvider"/> to begin collecting traces.</item>
/// <item>This is safe to be called multiple times and by library authors.
/// Only a single <see cref="MeterProvider"/> will be created for a given
/// <see cref="IServiceCollection"/>.</item>
/// </list>
/// </remarks>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection ConfigureOpenTelemetryMetrics(this IServiceCollection services)
=> ConfigureOpenTelemetryMetrics(services, (b) => { });
/// <summary>
/// Configures OpenTelemetry Metrics services in the supplied <see cref="IServiceCollection" />.
/// </summary>
/// <remarks><inheritdoc cref="ConfigureOpenTelemetryMetrics(IServiceCollection)" path="/remarks"/></remarks>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <param name="configure">Callback action to configure the <see cref="MeterProviderBuilder"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection ConfigureOpenTelemetryMetrics(this IServiceCollection services, Action<MeterProviderBuilder> configure)
{
Guard.ThrowIfNull(services);
Guard.ThrowIfNull(configure);
// Accessing Sdk class is just to trigger its static ctor,
// which sets default Propagators and default Activity Id format
_ = Sdk.SuppressInstrumentation;
// Note: We need to create a builder even if there is no configure
// because the builder will register services
var builder = new MeterProviderBuilderSdk(services);
configure(builder);
return services;
}
}

View File

@ -1,79 +0,0 @@
// <copyright file="MeterProviderBuilderState.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#nullable enable
using System.Diagnostics;
using System.Diagnostics.Metrics;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Metrics
{
/// <summary>
/// Stores state used to build a <see cref="MeterProvider"/>.
/// </summary>
internal sealed class MeterProviderBuilderState : ProviderBuilderState<MeterProviderBuilderSdk, MeterProviderSdk>
{
public const int MaxMetricsDefault = 1000;
public const int MaxMetricPointsPerMetricDefault = 2000;
private MeterProviderBuilderSdk? builder;
public MeterProviderBuilderState(IServiceProvider serviceProvider)
: base(serviceProvider)
{
}
public override MeterProviderBuilderSdk Builder
=> this.builder ??= new MeterProviderBuilderSdk(this);
public List<MetricReader> Readers { get; } = new();
public List<string> MeterSources { get; } = new();
public List<Func<Instrument, MetricStreamConfiguration?>> ViewConfigs { get; } = new();
public int MaxMetricStreams { get; set; } = MaxMetricsDefault;
public int MaxMetricPointsPerMetricStream { get; set; } = MaxMetricPointsPerMetricDefault;
public void AddMeter(params string[] names)
{
Debug.Assert(names != null, "names was null");
foreach (var name in names!)
{
Guard.ThrowIfNullOrWhitespace(name);
this.MeterSources.Add(name);
}
}
public void AddReader(MetricReader reader)
{
Debug.Assert(reader != null, "reader was null");
this.Readers.Add(reader!);
}
public void AddView(Func<Instrument, MetricStreamConfiguration?> viewConfig)
{
Debug.Assert(viewConfig != null, "viewConfig was null");
this.ViewConfigs.Add(viewConfig!);
}
}
}

View File

@ -23,11 +23,6 @@ using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper<
OpenTelemetry.Metrics.MeterProviderBuilderSdk,
OpenTelemetry.Metrics.MeterProviderSdk,
OpenTelemetry.Metrics.MeterProviderBuilderState>;
namespace OpenTelemetry.Metrics
{
internal sealed class MeterProviderSdk : MeterProvider
@ -50,8 +45,8 @@ namespace OpenTelemetry.Metrics
{
Debug.Assert(serviceProvider != null, "serviceProvider was null");
var state = serviceProvider!.GetRequiredService<MeterProviderBuilderState>();
state.RegisterProvider(nameof(MeterProvider), this);
var state = serviceProvider!.GetRequiredService<MeterProviderBuilderSdk>();
state.RegisterProvider(this);
this.ServiceProvider = serviceProvider!;
@ -63,9 +58,11 @@ namespace OpenTelemetry.Metrics
OpenTelemetrySdkEventSource.Log.MeterProviderSdkEvent("Building MeterProvider.");
CallbackHelper.InvokeRegisteredConfigureStateCallbacks(
serviceProvider!,
state);
var configureProviderBuilders = serviceProvider!.GetServices<IConfigureMeterProviderBuilder>();
foreach (var configureProviderBuilder in configureProviderBuilders)
{
configureProviderBuilder.ConfigureBuilder(serviceProvider!, state);
}
StringBuilder exportersAdded = new StringBuilder();
StringBuilder instrumentationFactoriesAdded = new StringBuilder();

View File

@ -27,7 +27,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Api\OpenTelemetry.Api.csproj" />
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.DependencyInjection\OpenTelemetry.Extensions.DependencyInjection.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,154 @@
// <copyright file="OpenTelemetryBuilder.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#nullable enable
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Internal;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
namespace OpenTelemetry;
/// <summary>
/// Contains methods for configuring the OpenTelemetry SDK inside an <see
/// cref="IServiceCollection"/>.
/// </summary>
public class OpenTelemetryBuilder
{
internal OpenTelemetryBuilder(IServiceCollection services)
{
Guard.ThrowIfNull(services);
services.AddOpenTelemetrySharedProviderBuilderServices();
this.Services = services;
}
/// <summary>
/// Gets the <see cref="IServiceCollection"/> behind the builder.
/// </summary>
public IServiceCollection Services { get; }
/// <summary>
/// Registers an action to configure the <see cref="ResourceBuilder"/>s used
/// by tracing and metrics.
/// </summary>
/// <remarks>
/// Note: This is safe to be called multiple times and by library authors.
/// Each registered configuration action will be applied sequentially.
/// </remarks>
/// <param name="configure"><see cref="ResourceBuilder"/> configuration
/// action.</param>
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
/// calls.</returns>
public OpenTelemetryBuilder ConfigureResource(
Action<ResourceBuilder> configure)
{
Guard.ThrowIfNull(configure);
this.Services.ConfigureOpenTelemetryMeterProvider(
(sp, builder) => builder.ConfigureResource(configure));
this.Services.ConfigureOpenTelemetryTracerProvider(
(sp, builder) => builder.ConfigureResource(configure));
return this;
}
/// <summary>
/// Adds metric services into the builder.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>A <see cref="MeterProvider"/> will not be created automatically
/// using this method. To begin collecting metrics either use the
/// <c>OpenTelemetryBuilder.StartWithHost</c> extension in the
/// <c>OpenTelemetry.Extensions.Hosting</c> package or access the <see
/// cref="MeterProvider"/> through the application <see
/// cref="IServiceProvider"/>.</item>
/// <item>This is safe to be called multiple times and by library authors.
/// Only a single <see cref="MeterProvider"/> will be created for a given
/// <see cref="IServiceCollection"/>.</item>
/// </list>
/// </remarks>
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
/// calls.</returns>
public OpenTelemetryBuilder WithMetrics()
=> this.WithMetrics(b => { });
/// <summary>
/// Adds metric services into the builder.
/// </summary>
/// <remarks><inheritdoc cref="WithMetrics()" path="/remarks"/></remarks>
/// <param name="configure"><see cref="MeterProviderBuilder"/>
/// configuration callback.</param>
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
/// calls.</returns>
public OpenTelemetryBuilder WithMetrics(Action<MeterProviderBuilder> configure)
{
Guard.ThrowIfNull(configure);
var builder = new MeterProviderBuilderBase(this.Services);
configure(builder);
return this;
}
/// <summary>
/// Adds tracing services into the builder.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>A <see cref="TracerProvider"/> will not be created automatically
/// using this method. To begin collecting traces either use the
/// <c>OpenTelemetryBuilder.StartWithHost</c> extension in the
/// <c>OpenTelemetry.Extensions.Hosting</c> package or access the <see
/// cref="TracerProvider"/> through the application <see
/// cref="IServiceProvider"/>.</item>
/// <item>This is safe to be called multiple times and by library authors.
/// Only a single <see cref="TracerProvider"/> will be created for a given
/// <see cref="IServiceCollection"/>.</item>
/// </list>
/// </remarks>
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
/// calls.</returns>
public OpenTelemetryBuilder WithTracing()
=> this.WithTracing(b => { });
/// <summary>
/// Adds tracing services into the builder.
/// </summary>
/// <remarks><inheritdoc cref="WithTracing()" path="/remarks"/></remarks>
/// <param name="configure"><see cref="TracerProviderBuilder"/>
/// configuration callback.</param>
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
/// calls.</returns>
public OpenTelemetryBuilder WithTracing(Action<TracerProviderBuilder> configure)
{
Guard.ThrowIfNull(configure);
var builder = new TracerProviderBuilderBase(this.Services);
configure(builder);
return this;
}
}

View File

@ -0,0 +1,55 @@
// <copyright file="OpenTelemetryServiceCollectionExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#nullable enable
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
namespace OpenTelemetry;
/// <summary>
/// Contains <see cref="IServiceCollection"/> extension methods for registering OpenTelemetry SDK artifacts.
/// </summary>
public static class OpenTelemetryServiceCollectionExtensions
{
/// <summary>
/// Adds OpenTelemetry SDK services into the supplied <see
/// cref="IServiceCollection"/>.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>A <see cref="TracerProvider"/> and/or <see cref="MeterProvider"/>
/// will not be created automatically using this method. To begin collecting
/// traces and/or metrics either use the
/// <c>OpenTelemetryBuilder.StartWithHost</c> extension in the
/// <c>OpenTelemetry.Extensions.Hosting</c> package or access the <see
/// cref="TracerProvider"/> and/or <see cref="MeterProvider"/> through the
/// application <see cref="IServiceProvider"/>.</item>
/// <item>This is safe to be called multiple times and by library authors.
/// Only a single <see cref="TracerProvider"/> and/or <see
/// cref="MeterProvider"/> will be created for a given <see
/// cref="IServiceCollection"/>.</item>
/// </list>
/// </remarks>
/// <param name="services"><see cref="IServiceCollection"/>.</param>
/// <returns>The supplied <see cref="OpenTelemetryBuilder"/> for chaining
/// calls.</returns>
public static OpenTelemetryBuilder AddOpenTelemetry(this IServiceCollection services)
=> new(services);
}

View File

@ -68,7 +68,7 @@ namespace OpenTelemetry
/// <returns><see cref="MeterProviderBuilder"/> instance, which is used to build a <see cref="MeterProvider"/>.</returns>
public static MeterProviderBuilder CreateMeterProviderBuilder()
{
return new MeterProviderBuilderSdk();
return new MeterProviderBuilderBase();
}
/// <summary>
@ -81,7 +81,7 @@ namespace OpenTelemetry
/// <returns><see cref="TracerProviderBuilder"/> instance, which is used to build a <see cref="TracerProvider"/>.</returns>
public static TracerProviderBuilder CreateTracerProviderBuilder()
{
return new TracerProviderBuilderSdk();
return new TracerProviderBuilderBase();
}
}
}

View File

@ -16,279 +16,191 @@
#nullable enable
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper<
OpenTelemetry.Trace.TracerProviderBuilderSdk,
OpenTelemetry.Trace.TracerProviderSdk,
OpenTelemetry.Trace.TracerProviderBuilderState>;
namespace OpenTelemetry.Trace;
namespace OpenTelemetry.Trace
/// <summary>
/// Contains methods for building <see cref="TracerProvider"/> instances.
/// </summary>
public class TracerProviderBuilderBase : TracerProviderBuilder, ITracerProviderBuilder
{
private readonly bool allowBuild;
private IServiceCollection? services;
/// <summary>
/// Contains methods for building <see cref="TracerProvider"/> instances.
/// Initializes a new instance of the <see cref="TracerProviderBuilderBase"/> class.
/// </summary>
public abstract class TracerProviderBuilderBase : TracerProviderBuilder, IDeferredTracerProviderBuilder
public TracerProviderBuilderBase()
{
internal readonly TracerProviderBuilderState? State;
private const string DefaultInstrumentationVersion = "1.0.0.0";
var services = new ServiceCollection();
private readonly bool ownsServices;
private IServiceCollection? services;
services
.AddOpenTelemetrySharedProviderBuilderServices()
.AddOpenTelemetryTracerProviderBuilderServices()
.TryAddSingleton<TracerProvider>(
sp => throw new NotSupportedException("Self-contained TracerProvider cannot be accessed using the application IServiceProvider call Build instead."));
// This ctor is for a builder created from TracerProviderBuilderState which
// happens after the service provider has been created.
internal TracerProviderBuilderBase(TracerProviderBuilderState state)
services.ConfigureOpenTelemetryTracerProvider((sp, builder) => this.services = null);
this.services = services;
this.allowBuild = true;
}
internal TracerProviderBuilderBase(IServiceCollection services)
{
Guard.ThrowIfNull(services);
services
.AddOpenTelemetryTracerProviderBuilderServices()
.TryAddSingleton<TracerProvider>(sp => new TracerProviderSdk(sp, ownsServiceProvider: false));
services.ConfigureOpenTelemetryTracerProvider((sp, builder) => this.services = null);
this.services = services;
this.allowBuild = false;
}
/// <inheritdoc />
TracerProvider? ITracerProviderBuilder.Provider => null;
/// <inheritdoc />
public override TracerProviderBuilder AddInstrumentation<TInstrumentation>(Func<TInstrumentation> instrumentationFactory)
{
Guard.ThrowIfNull(instrumentationFactory);
this.ConfigureBuilder((sp, builder) =>
{
Debug.Assert(state != null, "state was null");
builder.AddInstrumentation(instrumentationFactory);
});
this.State = state;
return this;
}
/// <inheritdoc />
public override TracerProviderBuilder AddSource(params string[] names)
{
Guard.ThrowIfNull(names);
this.ConfigureBuilder((sp, builder) =>
{
builder.AddSource(names);
});
return this;
}
/// <inheritdoc />
public override TracerProviderBuilder AddLegacySource(string operationName)
{
Guard.ThrowIfNullOrWhitespace(operationName);
this.ConfigureBuilder((sp, builder) =>
{
builder.AddLegacySource(operationName);
});
return this;
}
/// <inheritdoc />
public TracerProviderBuilder ConfigureBuilder(Action<IServiceProvider, TracerProviderBuilder> configure)
{
var services = this.services;
if (services == null)
{
throw new NotSupportedException("Builder cannot be configured during TracerProvider construction.");
}
// This ctor is for ConfigureOpenTelemetryTracing +
// AddOpenTelemetryTracing scenarios where the builder is bound to an
// external service collection.
internal TracerProviderBuilderBase(IServiceCollection services)
services.ConfigureOpenTelemetryTracerProvider(configure);
return this;
}
/// <inheritdoc />
public TracerProviderBuilder ConfigureServices(Action<IServiceCollection> configure)
{
Guard.ThrowIfNull(configure);
var services = this.services;
if (services == null)
{
Guard.ThrowIfNull(services);
services.AddOpenTelemetryTracerProviderBuilderServices();
services.TryAddSingleton<TracerProvider>(sp => new TracerProviderSdk(sp, ownsServiceProvider: false));
this.services = services;
this.ownsServices = false;
throw new NotSupportedException("Services cannot be configured during TracerProvider construction.");
}
// This ctor is for Sdk.CreateTracerProviderBuilder where the builder
// owns its services and service provider.
protected TracerProviderBuilderBase()
configure(services);
return this;
}
/// <inheritdoc />
TracerProviderBuilder IDeferredTracerProviderBuilder.Configure(Action<IServiceProvider, TracerProviderBuilder> configure)
=> this.ConfigureBuilder(configure);
internal TracerProvider InvokeBuild()
=> this.Build();
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>d
/// <param name="instrumentationName">Instrumentation name.</param>
/// <param name="instrumentationVersion">Instrumentation version.</param>
/// <param name="instrumentationFactory">Function that builds instrumentation.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
protected TracerProviderBuilder AddInstrumentation(
string instrumentationName,
string instrumentationVersion,
Func<object> instrumentationFactory)
{
Guard.ThrowIfNullOrWhitespace(instrumentationName);
Guard.ThrowIfNullOrWhitespace(instrumentationVersion);
Guard.ThrowIfNull(instrumentationFactory);
return this.ConfigureBuilder((sp, builder) =>
{
var services = new ServiceCollection();
services.AddOpenTelemetryTracerProviderBuilderServices();
services.AddSingleton<TracerProvider>(
sp => throw new NotSupportedException("External TracerProvider created through Sdk.CreateTracerProviderBuilder cannot be accessed using service provider."));
this.services = services;
this.ownsServices = true;
}
/// <inheritdoc />
public override TracerProviderBuilder AddInstrumentation<TInstrumentation>(
Func<TInstrumentation> instrumentationFactory)
where TInstrumentation : class
{
Guard.ThrowIfNull(instrumentationFactory);
return this.AddInstrumentation((sp) => instrumentationFactory());
}
/// <inheritdoc />
public override TracerProviderBuilder AddSource(params string[] names)
{
Guard.ThrowIfNull(names);
return this.ConfigureState((sp, state) => state.AddSource(names));
}
/// <inheritdoc />
public override TracerProviderBuilder AddLegacySource(string operationName)
{
Guard.ThrowIfNullOrWhitespace(operationName);
return this.ConfigureState((sp, state) => state.AddLegacySource(operationName));
}
/// <inheritdoc />
TracerProviderBuilder IDeferredTracerProviderBuilder.Configure(
Action<IServiceProvider, TracerProviderBuilder> configure)
{
Guard.ThrowIfNull(configure);
if (this.State != null)
if (builder is TracerProviderBuilderSdk tracerProviderBuilderState)
{
configure(this.State.ServiceProvider, this);
}
else
{
this.ConfigureServices(services
=> CallbackHelper.RegisterConfigureBuilderCallback(services, configure));
}
return this;
}
internal TracerProviderBuilder AddInstrumentation<T>()
where T : class
{
this.TryAddSingleton<T>();
this.AddInstrumentation((sp) => sp.GetRequiredService<T>());
return this;
}
internal TracerProviderBuilder AddProcessor<T>()
where T : BaseProcessor<Activity>
{
this.TryAddSingleton<T>();
this.ConfigureState((sp, state) => state.AddProcessor(sp.GetRequiredService<T>()));
return this;
}
internal TracerProviderBuilder AddProcessor(BaseProcessor<Activity> processor)
{
Guard.ThrowIfNull(processor);
return this.ConfigureState((sp, state) => state.AddProcessor(processor));
}
internal TracerProviderBuilder ConfigureResource(Action<ResourceBuilder> configure)
{
Guard.ThrowIfNull(configure);
return this.ConfigureState((sp, state) => state.ConfigureResource(configure));
}
internal TracerProviderBuilder ConfigureServices(Action<IServiceCollection> configure)
{
Guard.ThrowIfNull(configure);
var services = this.services;
if (services == null)
{
throw new NotSupportedException("Services cannot be configured after ServiceProvider has been created.");
}
configure(services);
return this;
}
internal TracerProvider InvokeBuild()
=> this.Build();
internal TracerProviderBuilder SetErrorStatusOnException(bool enabled)
{
return this.ConfigureState((sp, state) => state.SetErrorStatusOnException = enabled);
}
internal TracerProviderBuilder SetResourceBuilder(ResourceBuilder resourceBuilder)
{
Guard.ThrowIfNull(resourceBuilder);
return this.ConfigureState((sp, state) => state.SetResourceBuilder(resourceBuilder));
}
internal TracerProviderBuilder SetSampler<T>()
where T : Sampler
{
this.TryAddSingleton<T>();
this.ConfigureState((sp, state) => state.SetSampler(sp.GetRequiredService<T>()));
return this;
}
internal TracerProviderBuilder SetSampler(Sampler sampler)
{
Guard.ThrowIfNull(sampler);
return this.ConfigureState((sp, state) => state.SetSampler(sampler));
}
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>d
/// <param name="instrumentationName">Instrumentation name.</param>
/// <param name="instrumentationVersion">Instrumentation version.</param>
/// <param name="instrumentationFactory">Function that builds instrumentation.</param>
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
protected TracerProviderBuilder AddInstrumentation(
string instrumentationName,
string instrumentationVersion,
Func<object> instrumentationFactory)
{
Guard.ThrowIfNullOrWhitespace(instrumentationName);
Guard.ThrowIfNullOrWhitespace(instrumentationVersion);
Guard.ThrowIfNull(instrumentationFactory);
return this.ConfigureState((sp, state)
=> state.AddInstrumentation(
tracerProviderBuilderState.AddInstrumentation(
instrumentationName,
instrumentationVersion,
instrumentationFactory()));
instrumentationFactory);
}
});
}
/// <summary>
/// Run the configured actions to initialize the <see cref="TracerProvider"/>.
/// </summary>
/// <returns><see cref="TracerProvider"/>.</returns>
protected TracerProvider Build()
{
if (!this.allowBuild)
{
throw new NotSupportedException("A TracerProviderBuilder bound to external service cannot be built directly. Access the TracerProvider using the application IServiceProvider instead.");
}
/// <summary>
/// Run the configured actions to initialize the <see cref="TracerProvider"/>.
/// </summary>
/// <returns><see cref="TracerProvider"/>.</returns>
protected TracerProvider Build()
var services = this.services;
if (services == null)
{
if (!this.ownsServices || this.State != null)
{
throw new NotSupportedException("Build cannot be called directly on TracerProviderBuilder tied to external services.");
}
throw new NotSupportedException("TracerProviderBuilder build method cannot be called multiple times.");
}
var services = this.services;
if (services == null)
{
throw new NotSupportedException("TracerProviderBuilder build method cannot be called multiple times.");
}
this.services = null;
this.services = null;
#if DEBUG
bool validateScopes = true;
bool validateScopes = true;
#else
bool validateScopes = false;
bool validateScopes = false;
#endif
var serviceProvider = services.BuildServiceProvider(validateScopes);
var serviceProvider = services.BuildServiceProvider(validateScopes);
return new TracerProviderSdk(serviceProvider, ownsServiceProvider: true);
}
private TracerProviderBuilder AddInstrumentation<T>(Func<IServiceProvider, T> instrumentationFactory)
where T : class
{
this.ConfigureState((sp, state)
=> state.AddInstrumentation(
typeof(T).Name,
typeof(T).Assembly.GetName().Version?.ToString() ?? DefaultInstrumentationVersion,
instrumentationFactory(sp)));
return this;
}
private TracerProviderBuilder ConfigureState(Action<IServiceProvider, TracerProviderBuilderState> configure)
{
Debug.Assert(configure != null, "configure was null");
if (this.State != null)
{
configure!(this.State.ServiceProvider, this.State);
}
else
{
this.ConfigureServices(services =>
CallbackHelper.RegisterConfigureStateCallback(services, configure!));
}
return this;
}
private void TryAddSingleton<T>()
where T : class
{
var services = this.services;
services?.TryAddSingleton<T>();
}
return new TracerProviderSdk(serviceProvider, ownsServiceProvider: true);
}
}

View File

@ -18,6 +18,8 @@
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
namespace OpenTelemetry.Trace
@ -36,10 +38,13 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder SetErrorStatusOnException(this TracerProviderBuilder tracerProviderBuilder, bool enabled = true)
{
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
tracerProviderBuilderBase.SetErrorStatusOnException(enabled);
}
if (builder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
{
tracerProviderBuilderSdk.SetErrorStatusOnException(enabled);
}
});
return tracerProviderBuilder;
}
@ -52,10 +57,15 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder SetSampler(this TracerProviderBuilder tracerProviderBuilder, Sampler sampler)
{
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
Guard.ThrowIfNull(sampler);
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
tracerProviderBuilderBase.SetSampler(sampler);
}
if (builder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
{
tracerProviderBuilderSdk.SetSampler(sampler);
}
});
return tracerProviderBuilder;
}
@ -73,10 +83,15 @@ namespace OpenTelemetry.Trace
public static TracerProviderBuilder SetSampler<T>(this TracerProviderBuilder tracerProviderBuilder)
where T : Sampler
{
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
tracerProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
tracerProviderBuilderBase.SetSampler<T>();
}
if (builder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
{
tracerProviderBuilderSdk.SetSampler(sp.GetRequiredService<T>());
}
});
return tracerProviderBuilder;
}
@ -92,10 +107,15 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder SetResourceBuilder(this TracerProviderBuilder tracerProviderBuilder, ResourceBuilder resourceBuilder)
{
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
Guard.ThrowIfNull(resourceBuilder);
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
tracerProviderBuilderBase.SetResourceBuilder(resourceBuilder);
}
if (builder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
{
tracerProviderBuilderSdk.SetResourceBuilder(resourceBuilder);
}
});
return tracerProviderBuilder;
}
@ -109,10 +129,15 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder ConfigureResource(this TracerProviderBuilder tracerProviderBuilder, Action<ResourceBuilder> configure)
{
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
Guard.ThrowIfNull(configure);
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
tracerProviderBuilderBase.ConfigureResource(configure);
}
if (builder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
{
tracerProviderBuilderSdk.ConfigureResource(configure);
}
});
return tracerProviderBuilder;
}
@ -125,10 +150,15 @@ namespace OpenTelemetry.Trace
/// <returns>Returns <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddProcessor(this TracerProviderBuilder tracerProviderBuilder, BaseProcessor<Activity> processor)
{
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
Guard.ThrowIfNull(processor);
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
tracerProviderBuilderBase.AddProcessor(processor);
}
if (builder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
{
tracerProviderBuilderSdk.AddProcessor(processor);
}
});
return tracerProviderBuilder;
}
@ -146,74 +176,15 @@ namespace OpenTelemetry.Trace
public static TracerProviderBuilder AddProcessor<T>(this TracerProviderBuilder tracerProviderBuilder)
where T : BaseProcessor<Activity>
{
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
tracerProviderBuilder.ConfigureServices(services => services.TryAddSingleton<T>());
tracerProviderBuilder.ConfigureBuilder((sp, builder) =>
{
tracerProviderBuilderBase.AddProcessor<T>();
}
return tracerProviderBuilder;
}
/// <summary>
/// Adds instrumentation to the provider.
/// </summary>
/// <remarks>
/// Note: The type specified by <typeparamref name="T"/> will be
/// registered as a singleton service into application services.
/// </remarks>
/// <typeparam name="T">Instrumentation type.</typeparam>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder AddInstrumentation<T>(this TracerProviderBuilder tracerProviderBuilder)
where T : class
{
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
{
tracerProviderBuilderBase.AddInstrumentation<T>();
}
return tracerProviderBuilder;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="IServiceCollection"/> where tracing services are configured.
/// </summary>
/// <remarks>
/// Note: Tracing services are only available during the application
/// configuration phase.
/// </remarks>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder ConfigureServices(
this TracerProviderBuilder tracerProviderBuilder,
Action<IServiceCollection> configure)
{
if (tracerProviderBuilder is TracerProviderBuilderBase tracerProviderBuilderBase)
{
tracerProviderBuilderBase.ConfigureServices(configure);
}
return tracerProviderBuilder;
}
/// <summary>
/// Register a callback action to configure the <see
/// cref="TracerProviderBuilder"/> once the application <see
/// cref="IServiceProvider"/> is available.
/// </summary>
/// <param name="tracerProviderBuilder"><see cref="TracerProviderBuilder"/>.</param>
/// <param name="configure">Configuration callback.</param>
/// <returns>The supplied <see cref="TracerProviderBuilder"/> for chaining.</returns>
public static TracerProviderBuilder ConfigureBuilder(
this TracerProviderBuilder tracerProviderBuilder,
Action<IServiceProvider, TracerProviderBuilder> configure)
{
if (tracerProviderBuilder is IDeferredTracerProviderBuilder deferredTracerProviderBuilder)
{
deferredTracerProviderBuilder.Configure(configure);
}
if (builder is TracerProviderBuilderSdk tracerProviderBuilderSdk)
{
tracerProviderBuilderSdk.AddProcessor(sp.GetRequiredService<T>());
}
});
return tracerProviderBuilder;
}

View File

@ -16,24 +16,199 @@
#nullable enable
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
namespace OpenTelemetry.Trace
{
internal sealed class TracerProviderBuilderSdk : TracerProviderBuilderBase
/// <summary>
/// Stores state used to build a <see cref="TracerProvider"/>.
/// </summary>
internal sealed class TracerProviderBuilderSdk : TracerProviderBuilder, ITracerProviderBuilder
{
public TracerProviderBuilderSdk()
private const string DefaultInstrumentationVersion = "1.0.0.0";
private readonly IServiceProvider serviceProvider;
private TracerProviderSdk? tracerProvider;
public TracerProviderBuilderSdk(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public TracerProviderBuilderSdk(IServiceCollection services)
: base(services)
public List<InstrumentationRegistration> Instrumentation { get; } = new();
public ResourceBuilder? ResourceBuilder { get; private set; }
public TracerProvider? Provider => this.tracerProvider;
public List<BaseProcessor<Activity>> Processors { get; } = new();
public List<string> Sources { get; } = new();
public HashSet<string> LegacyActivityOperationNames { get; } = new(StringComparer.OrdinalIgnoreCase);
public Sampler? Sampler { get; private set; }
public bool ExceptionProcessorEnabled { get; private set; }
public void RegisterProvider(TracerProviderSdk tracerProvider)
{
Debug.Assert(tracerProvider != null, "tracerProvider was null");
if (this.tracerProvider != null)
{
throw new NotSupportedException("TracerProvider cannot be accessed while build is executing.");
}
this.tracerProvider = tracerProvider;
}
public TracerProviderBuilderSdk(TracerProviderBuilderState state)
: base(state)
public override TracerProviderBuilder AddInstrumentation<TInstrumentation>(
Func<TInstrumentation> instrumentationFactory)
{
Debug.Assert(instrumentationFactory != null, "instrumentationFactory was null");
return this.AddInstrumentation(
typeof(TInstrumentation).Name,
typeof(TInstrumentation).Assembly.GetName().Version?.ToString() ?? DefaultInstrumentationVersion,
instrumentationFactory!());
}
public TracerProviderBuilder AddInstrumentation(
string instrumentationName,
string instrumentationVersion,
object instrumentation)
{
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationName), "instrumentationName was null or whitespace");
Debug.Assert(!string.IsNullOrWhiteSpace(instrumentationVersion), "instrumentationVersion was null or whitespace");
Debug.Assert(instrumentation != null, "instrumentation was null");
this.Instrumentation.Add(
new InstrumentationRegistration(
instrumentationName,
instrumentationVersion,
instrumentation!));
return this;
}
public TracerProviderBuilder ConfigureResource(Action<ResourceBuilder> configure)
{
Debug.Assert(configure != null, "configure was null");
var resourceBuilder = this.ResourceBuilder ??= ResourceBuilder.CreateDefault();
configure!(resourceBuilder);
return this;
}
public TracerProviderBuilder SetResourceBuilder(ResourceBuilder resourceBuilder)
{
Debug.Assert(resourceBuilder != null, "resourceBuilder was null");
this.ResourceBuilder = resourceBuilder;
return this;
}
public override TracerProviderBuilder AddLegacySource(string operationName)
{
Debug.Assert(!string.IsNullOrWhiteSpace(operationName), "operationName was null or whitespace");
this.LegacyActivityOperationNames.Add(operationName);
return this;
}
public override TracerProviderBuilder AddSource(params string[] names)
{
Debug.Assert(names != null, "names was null");
foreach (var name in names!)
{
Guard.ThrowIfNullOrWhitespace(name);
// TODO: We need to fix the listening model.
// Today it ignores version.
this.Sources.Add(name);
}
return this;
}
public TracerProviderBuilder AddProcessor(BaseProcessor<Activity> processor)
{
Debug.Assert(processor != null, "processor was null");
this.Processors.Add(processor!);
return this;
}
public TracerProviderBuilder SetSampler(Sampler sampler)
{
Debug.Assert(sampler != null, "sampler was null");
this.Sampler = sampler;
return this;
}
public TracerProviderBuilder SetErrorStatusOnException(bool enabled)
{
this.ExceptionProcessorEnabled = enabled;
return this;
}
public TracerProviderBuilder ConfigureBuilder(Action<IServiceProvider, TracerProviderBuilder> configure)
{
Debug.Assert(configure != null, "configure was null");
configure!(this.serviceProvider, this);
return this;
}
public TracerProviderBuilder ConfigureServices(Action<IServiceCollection> configure)
{
throw new NotSupportedException("Services cannot be configured after ServiceProvider has been created.");
}
public void AddExceptionProcessorIfEnabled()
{
if (this.ExceptionProcessorEnabled)
{
try
{
this.Processors.Insert(0, new ExceptionProcessor());
}
catch (Exception ex)
{
throw new NotSupportedException($"'{nameof(TracerProviderBuilderExtensions.SetErrorStatusOnException)}' is not supported on this platform", ex);
}
}
}
TracerProviderBuilder IDeferredTracerProviderBuilder.Configure(Action<IServiceProvider, TracerProviderBuilder> configure)
=> this.ConfigureBuilder(configure);
internal readonly struct InstrumentationRegistration
{
public readonly string Name;
public readonly string Version;
public readonly object Instance;
internal InstrumentationRegistration(string name, string version, object instance)
{
this.Name = name;
this.Version = version;
this.Instance = instance;
}
}
}
}

View File

@ -1,76 +0,0 @@
// <copyright file="TracerProviderBuilderServiceCollectionExtensions.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#nullable enable
using OpenTelemetry;
using OpenTelemetry.Internal;
using OpenTelemetry.Trace;
namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// Extension methods for setting up OpenTelemetry tracing services in an <see cref="IServiceCollection" />.
/// </summary>
public static class TracerProviderBuilderServiceCollectionExtensions
{
/// <summary>
/// Configures OpenTelemetry tracing services in the supplied <see cref="IServiceCollection" />.
/// </summary>
/// <remarks>
/// Notes:
/// <list type="bullet">
/// <item>A <see cref="TracerProvider"/> will not be created automatically
/// using this method. Either use the
/// <c>IServiceCollection.AddOpenTelemetryTracing</c> extension in the
/// <c>OpenTelemetry.Extensions.Hosting</c> package or access the <see
/// cref="TracerProvider"/> through the application <see
/// cref="IServiceProvider"/> to begin collecting traces.</item>
/// <item>This is safe to be called multiple times and by library authors.
/// Only a single <see cref="TracerProvider"/> will be created for a given
/// <see cref="IServiceCollection"/>.</item>
/// </list>
/// </remarks>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection ConfigureOpenTelemetryTracing(this IServiceCollection services)
=> ConfigureOpenTelemetryTracing(services, (b) => { });
/// <summary>
/// Configures OpenTelemetry tracing services in the supplied <see cref="IServiceCollection" />.
/// </summary>
/// <remarks><inheritdoc cref="ConfigureOpenTelemetryTracing(IServiceCollection)" path="/remarks"/></remarks>
/// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param>
/// <param name="configure">Callback action to configure the <see cref="TracerProviderBuilder"/>.</param>
/// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns>
public static IServiceCollection ConfigureOpenTelemetryTracing(this IServiceCollection services, Action<TracerProviderBuilder> configure)
{
Guard.ThrowIfNull(services);
Guard.ThrowIfNull(configure);
// Accessing Sdk class is just to trigger its static ctor,
// which sets default Propagators and default Activity Id format
_ = Sdk.SuppressInstrumentation;
// Note: We need to create a builder even if there is no configure
// because the builder will register services
var builder = new TracerProviderBuilderSdk(services);
configure(builder);
return services;
}
}

View File

@ -1,96 +0,0 @@
// <copyright file="TracerProviderBuilderState.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
#nullable enable
using System.Diagnostics;
using OpenTelemetry.Internal;
namespace OpenTelemetry.Trace
{
/// <summary>
/// Stores state used to build a <see cref="TracerProvider"/>.
/// </summary>
internal sealed class TracerProviderBuilderState : ProviderBuilderState<TracerProviderBuilderSdk, TracerProviderSdk>
{
private TracerProviderBuilderSdk? builder;
public TracerProviderBuilderState(IServiceProvider serviceProvider)
: base(serviceProvider)
{
}
public override TracerProviderBuilderSdk Builder
=> this.builder ??= new TracerProviderBuilderSdk(this);
public List<BaseProcessor<Activity>> Processors { get; } = new();
public List<string> Sources { get; } = new();
public HashSet<string> LegacyActivityOperationNames { get; } = new(StringComparer.OrdinalIgnoreCase);
public Sampler? Sampler { get; private set; }
public bool SetErrorStatusOnException { get; set; }
public void AddLegacySource(string operationName)
{
Debug.Assert(!string.IsNullOrWhiteSpace(operationName), "operationName was null or whitespace");
this.LegacyActivityOperationNames.Add(operationName);
}
public void AddProcessor(BaseProcessor<Activity> processor)
{
Debug.Assert(processor != null, "processor was null");
this.Processors.Add(processor!);
}
public void AddSource(params string[] names)
{
Debug.Assert(names != null, "names was null");
foreach (var name in names!)
{
Guard.ThrowIfNullOrWhitespace(name);
// TODO: We need to fix the listening model.
// Today it ignores version.
this.Sources.Add(name);
}
}
public void SetSampler(Sampler sampler)
{
Debug.Assert(sampler != null, "sampler was null");
this.Sampler = sampler;
}
internal void EnableErrorStatusOnException()
{
try
{
this.Processors.Insert(0, new ExceptionProcessor());
}
catch (Exception ex)
{
throw new NotSupportedException($"'{nameof(TracerProviderBuilderExtensions.SetErrorStatusOnException)}' is not supported on this platform", ex);
}
}
}
}

View File

@ -21,8 +21,17 @@ using OpenTelemetry.Internal;
namespace OpenTelemetry.Trace
{
/// <summary>
/// Contains extension methods for the <see cref="TracerProvider"/> class.
/// </summary>
public static class TracerProviderExtensions
{
/// <summary>
/// Add a processor to the provider.
/// </summary>
/// <param name="provider"><see cref="TracerProvider"/>.</param>
/// <param name="processor"><see cref="BaseProcessor{T}"/>.</param>
/// <returns>The supplied <see cref="TracerProvider"/> instance for call chaining.</returns>
public static TracerProvider AddProcessor(this TracerProvider provider, BaseProcessor<Activity> processor)
{
Guard.ThrowIfNull(provider);

View File

@ -23,11 +23,6 @@ using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Internal;
using OpenTelemetry.Resources;
using CallbackHelper = OpenTelemetry.ProviderBuilderServiceCollectionCallbackHelper<
OpenTelemetry.Trace.TracerProviderBuilderSdk,
OpenTelemetry.Trace.TracerProviderSdk,
OpenTelemetry.Trace.TracerProviderBuilderState>;
namespace OpenTelemetry.Trace
{
internal sealed class TracerProviderSdk : TracerProvider
@ -50,8 +45,8 @@ namespace OpenTelemetry.Trace
{
Debug.Assert(serviceProvider != null, "serviceProvider was null");
var state = serviceProvider!.GetRequiredService<TracerProviderBuilderState>();
state.RegisterProvider(nameof(TracerProvider), this);
var state = serviceProvider!.GetRequiredService<TracerProviderBuilderSdk>();
state.RegisterProvider(this);
this.ServiceProvider = serviceProvider!;
@ -63,17 +58,16 @@ namespace OpenTelemetry.Trace
OpenTelemetrySdkEventSource.Log.TracerProviderSdkEvent("Building TracerProvider.");
CallbackHelper.InvokeRegisteredConfigureStateCallbacks(
serviceProvider!,
state);
var configureProviderBuilders = serviceProvider!.GetServices<IConfigureTracerProviderBuilder>();
foreach (var configureProviderBuilder in configureProviderBuilders)
{
configureProviderBuilder.ConfigureBuilder(serviceProvider!, state);
}
StringBuilder processorsAdded = new StringBuilder();
StringBuilder instrumentationFactoriesAdded = new StringBuilder();
if (state.SetErrorStatusOnException)
{
state.EnableErrorStatusOnException();
}
state.AddExceptionProcessorIfEnabled();
var resourceBuilder = state.ResourceBuilder ?? ResourceBuilder.CreateDefault();
resourceBuilder.ServiceProvider = serviceProvider;

View File

@ -124,8 +124,8 @@ namespace OpenTelemetry.Exporter.Jaeger.Tests
services.AddHttpClient("JaegerExporter", configureClient: (client) => invocations++);
services.AddOpenTelemetryTracing(builder => builder.AddJaegerExporter(
o => o.Protocol = JaegerExportProtocol.HttpBinaryThrift));
services.AddOpenTelemetry().WithTracing(builder => builder
.AddJaegerExporter(o => o.Protocol = JaegerExportProtocol.HttpBinaryThrift));
using var serviceProvider = services.BuildServiceProvider();

View File

@ -161,8 +161,8 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests
services.AddHttpClient("OtlpMetricExporter", configureClient: (client) => invocations++);
services.AddOpenTelemetryMetrics(builder => builder.AddOtlpExporter(
o => o.Protocol = OtlpExportProtocol.HttpProtobuf));
services.AddOpenTelemetry().WithMetrics(builder => builder
.AddOtlpExporter(o => o.Protocol = OtlpExportProtocol.HttpProtobuf));
using var serviceProvider = services.BuildServiceProvider();

View File

@ -136,8 +136,8 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests
services.AddHttpClient("OtlpTraceExporter", configureClient: (client) => invocations++);
services.AddOpenTelemetryTracing(builder => builder.AddOtlpExporter(
o => o.Protocol = OtlpExportProtocol.HttpProtobuf));
services.AddOpenTelemetry().WithTracing(builder => builder
.AddOtlpExporter(o => o.Protocol = OtlpExportProtocol.HttpProtobuf));
using var serviceProvider = services.BuildServiceProvider();

View File

@ -258,7 +258,7 @@ namespace OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests
{
if (registerMeterProvider)
{
services.AddOpenTelemetryMetrics(builder => builder
services.AddOpenTelemetry().WithMetrics(builder => builder
.AddMeter(MeterName)
.AddPrometheusExporter(o =>
{

View File

@ -283,7 +283,8 @@ namespace OpenTelemetry.Exporter.Zipkin.Tests
services.AddHttpClient("ZipkinExporter", configureClient: (client) => invocations++);
services.AddOpenTelemetryTracing(builder => builder.AddZipkinExporter());
services.AddOpenTelemetry().WithTracing(builder => builder
.AddZipkinExporter());
using var serviceProvider = services.BuildServiceProvider();

View File

@ -0,0 +1,144 @@
// <copyright file="MeterProviderBuilderExtensionsTests.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Metrics;
using Xunit;
namespace OpenTelemetry.Extensions.DependencyInjection.Tests;
public class MeterProviderBuilderExtensionsTests
{
[Fact]
public void AddInstrumentationFromServiceProviderTest()
{
using var builder = new TestMeterProviderBuilder();
builder.AddInstrumentation<TestInstrumentation>();
var serviceProvider = builder.BuildServiceProvider();
var instrumentation = serviceProvider.GetRequiredService<TestInstrumentation>();
Assert.NotNull(instrumentation);
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Instrumentation);
Assert.Equal(instrumentation, builder.Instrumentation[0]);
}
[Fact]
public void AddInstrumentationUsingInstanceTest()
{
using var builder = new TestMeterProviderBuilder();
var instrumentation = new TestInstrumentation();
builder.AddInstrumentation(instrumentation);
var serviceProvider = builder.BuildServiceProvider();
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Instrumentation);
Assert.Equal(instrumentation, builder.Instrumentation[0]);
}
[Fact]
public void AddInstrumentationUsingFactoryTest()
{
using var builder = new TestMeterProviderBuilder();
var instrumentation = new TestInstrumentation();
builder.AddInstrumentation(sp =>
{
Assert.NotNull(sp);
return instrumentation;
});
var serviceProvider = builder.BuildServiceProvider();
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Instrumentation);
Assert.Equal(instrumentation, builder.Instrumentation[0]);
}
[Fact]
public void AddInstrumentationUsingFactoryAndProviderTest()
{
using var builder = new TestMeterProviderBuilder();
var instrumentation = new TestInstrumentation();
builder.AddInstrumentation((sp, provider) =>
{
Assert.NotNull(sp);
Assert.NotNull(provider);
return instrumentation;
});
var serviceProvider = builder.BuildServiceProvider();
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Instrumentation);
Assert.Equal(instrumentation, builder.Instrumentation[0]);
}
[Fact]
public void ConfigureServicesTest()
{
using var builder = new TestMeterProviderBuilder();
builder.ConfigureServices(services => services.TryAddSingleton<TestInstrumentation>());
var serviceProvider = builder.BuildServiceProvider();
serviceProvider.GetRequiredService<TestInstrumentation>();
}
[Fact]
public void ConfigureBuilderTest()
{
using var builder = new TestMeterProviderBuilder();
builder.ConfigureBuilder((sp, builder) =>
{
Assert.NotNull(sp);
Assert.NotNull(builder);
builder.AddMeter("HelloWorld");
});
var serviceProvider = builder.BuildServiceProvider();
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Meters);
Assert.Equal("HelloWorld", builder.Meters[0]);
}
private sealed class TestInstrumentation
{
}
}

View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Unit test project for OpenTelemetry .NET dependency injection extensions</Description>
<!-- OmniSharp/VS Code requires TargetFrameworks to be in descending order for IntelliSense and analysis. -->
<TargetFrameworks>net7.0;net6.0</TargetFrameworks>
<TargetFrameworks Condition="$(OS) == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.DependencyInjection\OpenTelemetry.Extensions.DependencyInjection.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPkgVer)" />
<PackageReference Include="xunit" Version="$(XUnitPkgVer)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XUnitRunnerVisualStudioPkgVer)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionAbstractionsPkgVer)" />
<DotNetCliToolReference Include="dotnet-xunit" Version="$(DotNetXUnitCliVer)" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,81 @@
// <copyright file="ServiceCollectionExtensionsTests.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using Xunit;
namespace OpenTelemetry.Extensions.DependencyInjection.Tests;
public class ServiceCollectionExtensionsTests
{
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(3)]
public void ConfigureOpenTelemetryTracerProvider(int numberOfCalls)
{
var invocations = 0;
var services = new ServiceCollection();
for (int i = 0; i < numberOfCalls; i++)
{
services.ConfigureOpenTelemetryTracerProvider((sp, builder) => invocations++);
}
using var serviceProvider = services.BuildServiceProvider();
var registrations = serviceProvider.GetServices<IConfigureTracerProviderBuilder>();
foreach (var registration in registrations)
{
registration.ConfigureBuilder(serviceProvider, null!);
}
Assert.Equal(invocations, registrations.Count());
Assert.Equal(numberOfCalls, registrations.Count());
}
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(3)]
public void ConfigureOpenTelemetryMeterProvider(int numberOfCalls)
{
var invocations = 0;
var services = new ServiceCollection();
for (int i = 0; i < numberOfCalls; i++)
{
services.ConfigureOpenTelemetryMeterProvider((sp, builder) => invocations++);
}
using var serviceProvider = services.BuildServiceProvider();
var registrations = serviceProvider.GetServices<IConfigureMeterProviderBuilder>();
foreach (var registration in registrations)
{
registration.ConfigureBuilder(serviceProvider, null!);
}
Assert.Equal(invocations, registrations.Count());
Assert.Equal(numberOfCalls, registrations.Count());
}
}

View File

@ -0,0 +1,140 @@
// <copyright file="TestMeterProviderBuilder.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Metrics;
namespace OpenTelemetry.Extensions.DependencyInjection.Tests;
public sealed class TestMeterProviderBuilder : MeterProviderBuilder, IMeterProviderBuilder, IDisposable
{
public TestMeterProviderBuilder()
{
this.Services = new ServiceCollection();
}
public IServiceCollection? Services { get; private set; }
public ServiceProvider? ServiceProvider { get; private set; }
public List<string> Meters { get; } = new();
public List<object> Instrumentation { get; } = new();
public MeterProvider? Provider { get; private set; }
public override MeterProviderBuilder AddInstrumentation<TInstrumentation>(Func<TInstrumentation> instrumentationFactory)
{
if (this.Services != null)
{
this.ConfigureBuilder((sp, builder) => builder.AddInstrumentation(instrumentationFactory));
}
else
{
this.Instrumentation.Add(instrumentationFactory());
}
return this;
}
public override MeterProviderBuilder AddMeter(params string[] names)
{
if (this.Services != null)
{
this.ConfigureBuilder((sp, builder) => builder.AddMeter(names));
}
else
{
foreach (string name in names)
{
this.Meters.Add(name);
}
}
return this;
}
public MeterProviderBuilder ConfigureBuilder(Action<IServiceProvider, MeterProviderBuilder> configure)
{
var services = this.Services;
if (services != null)
{
services.ConfigureOpenTelemetryMeterProvider(configure);
}
else
{
var serviceProvider = this.ServiceProvider ?? throw new InvalidOperationException("Test failure");
configure(serviceProvider, this);
}
return this;
}
public MeterProviderBuilder ConfigureServices(Action<IServiceCollection> configure)
{
var services = this.Services;
if (services != null)
{
configure(services);
}
else
{
throw new NotSupportedException("Services cannot be configured after the ServiceProvider has been created.");
}
return this;
}
public IServiceProvider BuildServiceProvider()
{
var services = this.Services ?? throw new InvalidOperationException();
this.Services = null;
this.Provider = new NoopMeterProvider();
return this.ServiceProvider = services.BuildServiceProvider();
}
public int InvokeRegistrations()
{
var serviceProvider = this.ServiceProvider ?? throw new InvalidOperationException();
var registrations = serviceProvider.GetServices<IConfigureMeterProviderBuilder>();
var count = 0;
foreach (var registration in registrations)
{
registration.ConfigureBuilder(serviceProvider, this);
count++;
}
return count;
}
public void Dispose()
{
this.ServiceProvider?.Dispose();
}
MeterProviderBuilder IDeferredMeterProviderBuilder.Configure(Action<IServiceProvider, MeterProviderBuilder> configure)
=> this.ConfigureBuilder(configure);
private sealed class NoopMeterProvider : MeterProvider
{
}
}

View File

@ -0,0 +1,156 @@
// <copyright file="TestTracerProviderBuilder.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using OpenTelemetry.Trace;
namespace OpenTelemetry.Extensions.DependencyInjection.Tests;
public sealed class TestTracerProviderBuilder : TracerProviderBuilder, ITracerProviderBuilder, IDisposable
{
public TestTracerProviderBuilder()
{
this.Services = new ServiceCollection();
}
public IServiceCollection? Services { get; private set; }
public ServiceProvider? ServiceProvider { get; private set; }
public List<string> Sources { get; } = new();
public List<string> LegacySources { get; } = new();
public List<object> Instrumentation { get; } = new();
public TracerProvider? Provider { get; private set; }
public override TracerProviderBuilder AddInstrumentation<TInstrumentation>(Func<TInstrumentation> instrumentationFactory)
{
if (this.Services != null)
{
this.ConfigureBuilder((sp, builder) => builder.AddInstrumentation(instrumentationFactory));
}
else
{
this.Instrumentation.Add(instrumentationFactory());
}
return this;
}
public override TracerProviderBuilder AddLegacySource(string operationName)
{
if (this.Services != null)
{
this.ConfigureBuilder((sp, builder) => builder.AddLegacySource(operationName));
}
else
{
this.LegacySources.Add(operationName);
}
return this;
}
public override TracerProviderBuilder AddSource(params string[] names)
{
if (this.Services != null)
{
this.ConfigureBuilder((sp, builder) => builder.AddSource(names));
}
else
{
foreach (string name in names)
{
this.Sources.Add(name);
}
}
return this;
}
public TracerProviderBuilder ConfigureBuilder(Action<IServiceProvider, TracerProviderBuilder> configure)
{
var services = this.Services;
if (services != null)
{
services.ConfigureOpenTelemetryTracerProvider(configure);
}
else
{
var serviceProvider = this.ServiceProvider ?? throw new InvalidOperationException("Test failure");
configure(serviceProvider, this);
}
return this;
}
public TracerProviderBuilder ConfigureServices(Action<IServiceCollection> configure)
{
var services = this.Services;
if (services != null)
{
configure(services);
}
else
{
throw new NotSupportedException("Services cannot be configured after the ServiceProvider has been created.");
}
return this;
}
public IServiceProvider BuildServiceProvider()
{
var services = this.Services ?? throw new InvalidOperationException();
this.Services = null;
this.Provider = new NoopTracerProvider();
return this.ServiceProvider = services.BuildServiceProvider();
}
public int InvokeRegistrations()
{
var serviceProvider = this.ServiceProvider ?? throw new InvalidOperationException();
var registrations = serviceProvider.GetServices<IConfigureTracerProviderBuilder>();
var count = 0;
foreach (var registration in registrations)
{
registration.ConfigureBuilder(serviceProvider, this);
count++;
}
return count;
}
public void Dispose()
{
this.ServiceProvider?.Dispose();
}
TracerProviderBuilder IDeferredTracerProviderBuilder.Configure(Action<IServiceProvider, TracerProviderBuilder> configure)
=> this.ConfigureBuilder(configure);
private sealed class NoopTracerProvider : TracerProvider
{
}
}

View File

@ -0,0 +1,144 @@
// <copyright file="TracerProviderBuilderExtensionsTests.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenTelemetry.Trace;
using Xunit;
namespace OpenTelemetry.Extensions.DependencyInjection.Tests;
public class TracerProviderBuilderExtensionsTests
{
[Fact]
public void AddInstrumentationFromServiceProviderTest()
{
using var builder = new TestTracerProviderBuilder();
builder.AddInstrumentation<TestInstrumentation>();
var serviceProvider = builder.BuildServiceProvider();
var instrumentation = serviceProvider.GetRequiredService<TestInstrumentation>();
Assert.NotNull(instrumentation);
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Instrumentation);
Assert.Equal(instrumentation, builder.Instrumentation[0]);
}
[Fact]
public void AddInstrumentationUsingInstanceTest()
{
using var builder = new TestTracerProviderBuilder();
var instrumentation = new TestInstrumentation();
builder.AddInstrumentation(instrumentation);
var serviceProvider = builder.BuildServiceProvider();
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Instrumentation);
Assert.Equal(instrumentation, builder.Instrumentation[0]);
}
[Fact]
public void AddInstrumentationUsingFactoryTest()
{
using var builder = new TestTracerProviderBuilder();
var instrumentation = new TestInstrumentation();
builder.AddInstrumentation(sp =>
{
Assert.NotNull(sp);
return instrumentation;
});
var serviceProvider = builder.BuildServiceProvider();
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Instrumentation);
Assert.Equal(instrumentation, builder.Instrumentation[0]);
}
[Fact]
public void AddInstrumentationUsingFactoryAndProviderTest()
{
using var builder = new TestTracerProviderBuilder();
var instrumentation = new TestInstrumentation();
builder.AddInstrumentation((sp, provider) =>
{
Assert.NotNull(sp);
Assert.NotNull(provider);
return instrumentation;
});
var serviceProvider = builder.BuildServiceProvider();
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Instrumentation);
Assert.Equal(instrumentation, builder.Instrumentation[0]);
}
[Fact]
public void ConfigureServicesTest()
{
using var builder = new TestTracerProviderBuilder();
builder.ConfigureServices(services => services.TryAddSingleton<TestInstrumentation>());
var serviceProvider = builder.BuildServiceProvider();
serviceProvider.GetRequiredService<TestInstrumentation>();
}
[Fact]
public void ConfigureBuilderTest()
{
using var builder = new TestTracerProviderBuilder();
builder.ConfigureBuilder((sp, builder) =>
{
Assert.NotNull(sp);
Assert.NotNull(builder);
builder.AddSource("HelloWorld");
});
var serviceProvider = builder.BuildServiceProvider();
var registrationCount = builder.InvokeRegistrations();
Assert.Equal(1, registrationCount);
Assert.Single(builder.Sources);
Assert.Equal("HelloWorld", builder.Sources[0]);
}
private sealed class TestInstrumentation
{
}
}

View File

@ -14,9 +14,7 @@
// limitations under the License.
// </copyright>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -29,175 +27,41 @@ namespace OpenTelemetry.Extensions.Hosting.Tests
public class HostingMeterExtensionTests
{
[Fact]
public async Task AddOpenTelemetryMeterProviderInstrumentationCreationAndDisposal()
public async Task AddOpenTelemetry_StartWithHost_CreationAndDisposal()
{
var testInstrumentation = new TestInstrumentation();
var callbackRun = false;
var builder = new HostBuilder().ConfigureServices(services =>
{
services.AddOpenTelemetryMetrics(builder =>
{
builder.AddInstrumentation(() =>
{
callbackRun = true;
return testInstrumentation;
});
});
services.AddOpenTelemetry()
.WithMetrics(builder => builder
.AddInstrumentation(() =>
{
callbackRun = true;
return new object();
}))
.StartWithHost();
});
var host = builder.Build();
Assert.False(callbackRun);
Assert.False(testInstrumentation.Disposed);
await host.StartAsync();
Assert.True(callbackRun);
Assert.False(testInstrumentation.Disposed);
await host.StopAsync();
Assert.True(callbackRun);
Assert.False(testInstrumentation.Disposed);
host.Dispose();
Assert.True(callbackRun);
Assert.True(testInstrumentation.Disposed);
}
[Fact]
public void AddOpenTelemetryMeterProvider_HostBuilt_OpenTelemetrySdk_RegisteredAsSingleton()
{
var builder = new HostBuilder().ConfigureServices(services =>
{
services.AddOpenTelemetryMetrics();
});
var host = builder.Build();
var meterProvider1 = host.Services.GetRequiredService<MeterProvider>();
var meterProvider2 = host.Services.GetRequiredService<MeterProvider>();
Assert.Same(meterProvider1, meterProvider2);
}
[Fact]
public void AddOpenTelemetryMeterProvider_ServiceProviderArgument_ServicesRegistered()
{
var testInstrumentation = new TestInstrumentation();
var services = new ServiceCollection();
services.AddSingleton(testInstrumentation);
services.AddOpenTelemetryMetrics(builder =>
{
builder.ConfigureBuilder(
(sp, b) => b.AddInstrumentation(() => sp.GetRequiredService<TestInstrumentation>()));
});
var serviceProvider = services.BuildServiceProvider();
var meterFactory = serviceProvider.GetRequiredService<MeterProvider>();
Assert.NotNull(meterFactory);
Assert.False(testInstrumentation.Disposed);
serviceProvider.Dispose();
Assert.True(testInstrumentation.Disposed);
}
[Fact]
public void AddOpenTelemetryMeterProvider_BadArgs_NullServiceCollection()
{
ServiceCollection services = null;
Assert.Throws<ArgumentNullException>(() => services.AddOpenTelemetryMetrics(null));
Assert.Throws<ArgumentNullException>(() =>
services.AddOpenTelemetryMetrics(builder =>
{
builder.ConfigureBuilder(
(sp, b) => b.AddInstrumentation(() => sp.GetRequiredService<TestInstrumentation>()));
}));
}
[Fact]
public void AddOpenTelemetryMeterProvider_GetServicesExtension()
{
var services = new ServiceCollection();
services.AddOpenTelemetryMetrics(builder => AddMyFeature(builder));
using var serviceProvider = services.BuildServiceProvider();
var meterProvider = (MeterProviderSdk)serviceProvider.GetRequiredService<MeterProvider>();
Assert.True(meterProvider.Reader is TestReader);
}
[Fact]
public void AddOpenTelemetryMeterProvider_NestedConfigureCallbacks()
{
int configureCalls = 0;
var services = new ServiceCollection();
services.AddOpenTelemetryMetrics(builder => builder
.ConfigureBuilder((sp1, builder1) =>
{
configureCalls++;
builder1.ConfigureBuilder((sp2, builder2) =>
{
configureCalls++;
});
}));
using var serviceProvider = services.BuildServiceProvider();
var meterFactory = serviceProvider.GetRequiredService<MeterProvider>();
Assert.Equal(2, configureCalls);
}
[Fact]
public void AddOpenTelemetryMeterProvider_ConfigureCallbacksUsingExtensions()
{
var services = new ServiceCollection();
services.AddSingleton<TestInstrumentation>();
services.AddSingleton<TestReader>();
services.AddOpenTelemetryMetrics(builder => builder
.ConfigureBuilder((sp1, builder1) =>
{
builder1
.AddInstrumentation<TestInstrumentation>()
.AddReader<TestReader>();
}));
using var serviceProvider = services.BuildServiceProvider();
var meterProvider = (MeterProviderSdk)serviceProvider.GetRequiredService<MeterProvider>();
Assert.True(meterProvider.Instrumentations.FirstOrDefault() is TestInstrumentation);
Assert.True(meterProvider.Reader is TestReader);
}
[Fact]
public void AddOpenTelemetryMetrics_MultipleCallsConfigureSingleProvider()
{
var services = new ServiceCollection();
services.AddOpenTelemetryMetrics(builder => builder.AddMeter("TestSourceBuilder1"));
services.AddOpenTelemetryMetrics();
services.AddOpenTelemetryMetrics(builder => builder.AddMeter("TestSourceBuilder2"));
using var serviceProvider = services.BuildServiceProvider();
var providers = serviceProvider.GetServices<MeterProvider>();
Assert.Single(providers);
}
[Fact]
public async Task AddOpenTelemetryMetrics_HostConfigurationHonoredTest()
public async Task AddOpenTelemetry_StartWithHost_HostConfigurationHonoredTest()
{
bool configureBuilderCalled = false;
@ -211,19 +75,19 @@ namespace OpenTelemetry.Extensions.Hosting.Tests
})
.ConfigureServices(services =>
{
services.AddOpenTelemetryMetrics(builder =>
{
builder.ConfigureBuilder((sp, builder) =>
{
configureBuilderCalled = true;
services.AddOpenTelemetry()
.WithMetrics(builder => builder
.ConfigureBuilder((sp, builder) =>
{
configureBuilderCalled = true;
var configuration = sp.GetRequiredService<IConfiguration>();
var configuration = sp.GetRequiredService<IConfiguration>();
var testKeyValue = configuration.GetValue<string>("TEST_KEY", null);
var testKeyValue = configuration.GetValue<string>("TEST_KEY", null);
Assert.Equal("TEST_KEY_VALUE", testKeyValue);
});
});
Assert.Equal("TEST_KEY_VALUE", testKeyValue);
}))
.StartWithHost();
});
var host = builder.Build();
@ -238,26 +102,5 @@ namespace OpenTelemetry.Extensions.Hosting.Tests
host.Dispose();
}
private static MeterProviderBuilder AddMyFeature(MeterProviderBuilder meterProviderBuilder)
{
meterProviderBuilder.ConfigureServices(services => services.AddSingleton<TestReader>());
return meterProviderBuilder.AddReader<TestReader>();
}
internal class TestInstrumentation : IDisposable
{
public bool Disposed { get; private set; }
public void Dispose()
{
this.Disposed = true;
}
}
internal class TestReader : MetricReader
{
}
}
}

View File

@ -14,10 +14,7 @@
// limitations under the License.
// </copyright>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@ -30,178 +27,41 @@ namespace OpenTelemetry.Extensions.Hosting.Tests
public class HostingTracerExtensionTests
{
[Fact]
public async Task AddOpenTelemetryTracerProviderInstrumentationCreationAndDisposal()
public async Task AddOpenTelemetry_StartWithHost_CreationAndDisposal()
{
var testInstrumentation = new TestInstrumentation();
var callbackRun = false;
var builder = new HostBuilder().ConfigureServices(services =>
{
services.AddOpenTelemetryTracing(builder =>
{
builder.AddInstrumentation(() =>
{
callbackRun = true;
return testInstrumentation;
});
});
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddInstrumentation(() =>
{
callbackRun = true;
return new object();
}))
.StartWithHost();
});
var host = builder.Build();
Assert.False(callbackRun);
Assert.False(testInstrumentation.Disposed);
await host.StartAsync();
Assert.True(callbackRun);
Assert.False(testInstrumentation.Disposed);
await host.StopAsync();
Assert.True(callbackRun);
Assert.False(testInstrumentation.Disposed);
host.Dispose();
Assert.True(callbackRun);
Assert.True(testInstrumentation.Disposed);
}
[Fact]
public void AddOpenTelemetryTracerProvider_HostBuilt_OpenTelemetrySdk_RegisteredAsSingleton()
{
var builder = new HostBuilder().ConfigureServices(services =>
{
services.AddOpenTelemetryTracing();
});
var host = builder.Build();
var tracerProvider1 = host.Services.GetRequiredService<TracerProvider>();
var tracerProvider2 = host.Services.GetRequiredService<TracerProvider>();
Assert.Same(tracerProvider1, tracerProvider2);
}
[Fact]
public void AddOpenTelemetryTracerProvider_ServiceProviderArgument_ServicesRegistered()
{
var testInstrumentation = new TestInstrumentation();
var services = new ServiceCollection();
services.AddSingleton(testInstrumentation);
services.AddOpenTelemetryTracing(builder =>
{
builder.ConfigureBuilder(
(sp, b) => b.AddInstrumentation(() => sp.GetRequiredService<TestInstrumentation>()));
});
var serviceProvider = services.BuildServiceProvider();
var tracerFactory = serviceProvider.GetRequiredService<TracerProvider>();
Assert.NotNull(tracerFactory);
Assert.False(testInstrumentation.Disposed);
serviceProvider.Dispose();
Assert.True(testInstrumentation.Disposed);
}
[Fact]
public void AddOpenTelemetryTracerProvider_BadArgs_NullServiceCollection()
{
ServiceCollection services = null;
Assert.Throws<ArgumentNullException>(() => services.AddOpenTelemetryTracing(null));
Assert.Throws<ArgumentNullException>(() =>
services.AddOpenTelemetryTracing(builder =>
{
builder.ConfigureBuilder(
(sp, b) => b.AddInstrumentation(() => sp.GetRequiredService<TestInstrumentation>()));
}));
}
[Fact]
public void AddOpenTelemetryTracerProvider_GetServicesExtension()
{
var services = new ServiceCollection();
services.AddOpenTelemetryTracing(builder => AddMyFeature(builder));
using var serviceProvider = services.BuildServiceProvider();
var tracerProvider = (TracerProviderSdk)serviceProvider.GetRequiredService<TracerProvider>();
Assert.True(tracerProvider.Sampler is TestSampler);
}
[Fact]
public void AddOpenTelemetryTracerProvider_NestedConfigureCallbacks()
{
int configureCalls = 0;
var services = new ServiceCollection();
services.AddOpenTelemetryTracing(builder => builder
.ConfigureBuilder((sp1, builder1) =>
{
configureCalls++;
builder1.ConfigureBuilder((sp2, builder2) =>
{
configureCalls++;
});
}));
using var serviceProvider = services.BuildServiceProvider();
var tracerFactory = serviceProvider.GetRequiredService<TracerProvider>();
Assert.Equal(2, configureCalls);
}
[Fact]
public void AddOpenTelemetryTracerProvider_ConfigureCallbacksUsingExtensions()
{
var services = new ServiceCollection();
services.AddSingleton<TestInstrumentation>();
services.AddSingleton<TestProcessor>();
services.AddSingleton<TestSampler>();
services.AddOpenTelemetryTracing(builder => builder
.ConfigureBuilder((sp1, builder1) =>
{
builder1
.AddInstrumentation<TestInstrumentation>()
.AddProcessor<TestProcessor>()
.SetSampler<TestSampler>();
}));
using var serviceProvider = services.BuildServiceProvider();
var tracerProvider = (TracerProviderSdk)serviceProvider.GetRequiredService<TracerProvider>();
Assert.True(tracerProvider.Instrumentations.FirstOrDefault() is TestInstrumentation);
Assert.True(tracerProvider.Processor is TestProcessor);
Assert.True(tracerProvider.Sampler is TestSampler);
}
[Fact]
public void AddOpenTelemetryTracing_MultipleCallsConfigureSingleProvider()
{
var services = new ServiceCollection();
services.AddOpenTelemetryTracing(builder => builder.AddSource("TestSourceBuilder1"));
services.AddOpenTelemetryTracing();
services.AddOpenTelemetryTracing(builder => builder.AddSource("TestSourceBuilder2"));
using var serviceProvider = services.BuildServiceProvider();
var providers = serviceProvider.GetServices<TracerProvider>();
Assert.Single(providers);
}
[Fact]
public async Task AddOpenTelemetryTracing_HostConfigurationHonoredTest()
public async Task AddOpenTelemetry_StartWithHost_HostConfigurationHonoredTest()
{
bool configureBuilderCalled = false;
@ -215,19 +75,19 @@ namespace OpenTelemetry.Extensions.Hosting.Tests
})
.ConfigureServices(services =>
{
services.AddOpenTelemetryTracing(builder =>
{
builder.ConfigureBuilder((sp, builder) =>
{
configureBuilderCalled = true;
services.AddOpenTelemetry()
.WithTracing(builder => builder
.ConfigureBuilder((sp, builder) =>
{
configureBuilderCalled = true;
var configuration = sp.GetRequiredService<IConfiguration>();
var configuration = sp.GetRequiredService<IConfiguration>();
var testKeyValue = configuration.GetValue<string>("TEST_KEY", null);
var testKeyValue = configuration.GetValue<string>("TEST_KEY", null);
Assert.Equal("TEST_KEY_VALUE", testKeyValue);
});
});
Assert.Equal("TEST_KEY_VALUE", testKeyValue);
}))
.StartWithHost();
});
var host = builder.Build();
@ -242,34 +102,5 @@ namespace OpenTelemetry.Extensions.Hosting.Tests
host.Dispose();
}
private static TracerProviderBuilder AddMyFeature(TracerProviderBuilder tracerProviderBuilder)
{
tracerProviderBuilder.ConfigureServices(services => services.AddSingleton<TestSampler>());
return tracerProviderBuilder.SetSampler<TestSampler>();
}
internal class TestInstrumentation : IDisposable
{
public bool Disposed { get; private set; }
public void Dispose()
{
this.Disposed = true;
}
}
internal class TestProcessor : BaseProcessor<Activity>
{
}
internal class TestSampler : Sampler
{
public override SamplingResult ShouldSample(in SamplingParameters samplingParameters)
{
return new SamplingResult(SamplingDecision.RecordAndSample);
}
}
}
}

View File

@ -89,7 +89,7 @@ namespace OpenTelemetry.Extensions.Hosting.Tests
using var host = await new HostBuilder()
.ConfigureWebHost(webBuilder => webBuilder
.UseTestServer()
.ConfigureServices(services => services.AddOpenTelemetryMetrics(configure))
.ConfigureServices(services => services.AddOpenTelemetry().WithMetrics(configure).StartWithHost())
.Configure(app => app.Run(httpContext =>
{
testAction.Invoke();

View File

@ -655,9 +655,12 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
builder.ConfigureTestServices((IServiceCollection services) =>
{
services.AddSingleton<ActivityMiddleware.ActivityMiddlewareImpl>(new TestNullHostActivityMiddlewareImpl(activitySourceName, activityName));
services.AddOpenTelemetryTracing((builder) => builder.AddAspNetCoreInstrumentation()
.AddSource(activitySourceName)
.AddInMemoryExporter(exportedItems));
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddAspNetCoreInstrumentation()
.AddSource(activitySourceName)
.AddInMemoryExporter(exportedItems))
.StartWithHost();
});
builder.ConfigureLogging(loggingBuilder => loggingBuilder.ClearProviders());
})
@ -692,11 +695,11 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
var exportedItems = new List<Activity>();
void ConfigureTestServices(IServiceCollection services)
{
services.AddOpenTelemetryTracing(options =>
{
options.AddAspNetCoreInstrumentation()
.AddInMemoryExporter(exportedItems);
});
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddAspNetCoreInstrumentation()
.AddInMemoryExporter(exportedItems))
.StartWithHost();
// Register ActivitySource here so that it will be used
// by ASP.NET Core to create activities

View File

@ -44,8 +44,10 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
bool optionsPickedFromDI = false;
void ConfigureTestServices(IServiceCollection services)
{
services.AddOpenTelemetryTracing(
builder => builder.AddAspNetCoreInstrumentation(name, configureAspNetCoreInstrumentationOptions: null));
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddAspNetCoreInstrumentation(name, configureAspNetCoreInstrumentationOptions: null))
.StartWithHost();
services.Configure<AspNetCoreInstrumentationOptions>(name, options =>
{
@ -74,8 +76,10 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
bool optionsPickedFromDI = false;
void ConfigureTestServices(IServiceCollection services)
{
services.AddOpenTelemetryMetrics(
builder => builder.AddAspNetCoreInstrumentation(name, configureAspNetCoreInstrumentationOptions: null));
services.AddOpenTelemetry()
.WithMetrics(builder => builder
.AddAspNetCoreInstrumentation(name, configureAspNetCoreInstrumentationOptions: null))
.StartWithHost();
services.Configure<AspNetCoreMetricsInstrumentationOptions>(name, options =>
{
@ -85,9 +89,9 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
// Arrange
using (var client = this.factory
.WithWebHostBuilder(builder =>
builder.ConfigureTestServices(ConfigureTestServices))
.CreateClient())
.WithWebHostBuilder(builder =>
builder.ConfigureTestServices(ConfigureTestServices))
.CreateClient())
{
}

View File

@ -64,8 +64,11 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
builder.ConfigureTestServices((IServiceCollection services) =>
{
services.AddSingleton<CallbackMiddleware.CallbackMiddlewareImpl>(new TestCallbackMiddlewareImpl(statusCode, reasonPhrase));
services.AddOpenTelemetryTracing((builder) => builder.AddAspNetCoreInstrumentation(options => options.RecordException = recordException)
.AddInMemoryExporter(exportedItems));
services.AddOpenTelemetry()
.WithTracing(builder => builder
.AddAspNetCoreInstrumentation(options => options.RecordException = recordException)
.AddInMemoryExporter(exportedItems))
.StartWithHost();
});
builder.ConfigureLogging(loggingBuilder => loggingBuilder.ClearProviders());
})

View File

@ -32,8 +32,6 @@ namespace OpenTelemetry.Metrics.Tests
{
var builder = Sdk.CreateMeterProviderBuilder();
builder.ConfigureServices(services => services.AddSingleton<MyInstrumentation>());
MyInstrumentation myInstrumentation = null;
RunBuilderServiceLifecycleTest(
@ -71,7 +69,7 @@ namespace OpenTelemetry.Metrics.Tests
ServiceProvider serviceProvider = null;
MeterProviderSdk provider = null;
services.ConfigureOpenTelemetryMetrics(builder =>
services.AddOpenTelemetry().WithMetrics(builder =>
{
testRun = true;
@ -111,12 +109,12 @@ namespace OpenTelemetry.Metrics.Tests
{
var services = new ServiceCollection();
services.ConfigureOpenTelemetryMetrics(builder =>
services.AddOpenTelemetry().WithMetrics(builder =>
{
builder.AddInstrumentation<MyInstrumentation>(() => new());
});
services.ConfigureOpenTelemetryMetrics(builder =>
services.AddOpenTelemetry().WithMetrics(builder =>
{
builder.AddInstrumentation<MyInstrumentation>(() => new());
});
@ -273,7 +271,7 @@ namespace OpenTelemetry.Metrics.Tests
{
if (callNestedConfigure)
{
services.ConfigureOpenTelemetryMetrics();
services.AddOpenTelemetry().WithMetrics(builder => { });
}
})
.ConfigureBuilder((sp, builder) =>
@ -293,9 +291,9 @@ namespace OpenTelemetry.Metrics.Tests
{
bool innerTestExecuted = false;
var serviceCollection = new ServiceCollection();
var services = new ServiceCollection();
serviceCollection.ConfigureOpenTelemetryMetrics(builder =>
services.AddOpenTelemetry().WithMetrics(builder =>
{
builder.ConfigureBuilder((sp, builder) =>
{
@ -304,7 +302,7 @@ namespace OpenTelemetry.Metrics.Tests
});
});
using var serviceProvider = serviceCollection.BuildServiceProvider();
using var serviceProvider = services.BuildServiceProvider();
var resolvedProvider = serviceProvider.GetRequiredService<MeterProvider>();
@ -317,7 +315,6 @@ namespace OpenTelemetry.Metrics.Tests
Action<MeterProviderSdk> postAction)
{
var baseBuilder = builder as MeterProviderBuilderBase;
Assert.Null(baseBuilder.State);
builder.AddMeter("TestSource");
@ -328,12 +325,15 @@ namespace OpenTelemetry.Metrics.Tests
Assert.NotNull(services);
services.TryAddSingleton<MyInstrumentation>();
services.TryAddSingleton<MyReader>();
services.ConfigureOpenTelemetryMetrics(b =>
// Note: This is strange to call ConfigureOpenTelemetryMeterProvider here, but supported
services.ConfigureOpenTelemetryMeterProvider((sp, b) =>
{
// Note: This is strange to call ConfigureOpenTelemetryMetrics here, but supported
b.AddInstrumentation<MyInstrumentation>();
Assert.Throws<NotSupportedException>(() => b.ConfigureServices(services => { }));
b.AddInstrumentation(sp.GetRequiredService<MyInstrumentation>());
});
});
@ -342,13 +342,13 @@ namespace OpenTelemetry.Metrics.Tests
{
configureBuilderInvocations++;
var baseBuilder = builder as MeterProviderBuilderBase;
Assert.NotNull(baseBuilder?.State);
var sdkBuilder = builder as MeterProviderBuilderSdk;
Assert.NotNull(sdkBuilder);
builder.AddMeter("TestSource2");
Assert.Contains(baseBuilder.State.MeterSources, s => s == "TestSource");
Assert.Contains(baseBuilder.State.MeterSources, s => s == "TestSource2");
Assert.Contains(sdkBuilder.MeterSources, s => s == "TestSource");
Assert.Contains(sdkBuilder.MeterSources, s => s == "TestSource2");
// Note: Services can't be configured at this stage
Assert.Throws<NotSupportedException>(

View File

@ -1356,26 +1356,26 @@ namespace OpenTelemetry.Metrics.Tests
// for no tag point!
// This may be changed later.
counterLong.Add(10);
for (int i = 0; i < MeterProviderBuilderState.MaxMetricPointsPerMetricDefault + 1; i++)
for (int i = 0; i < MeterProviderBuilderSdk.MaxMetricPointsPerMetricDefault + 1; i++)
{
counterLong.Add(10, new KeyValuePair<string, object>("key", "value" + i));
}
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(MeterProviderBuilderState.MaxMetricPointsPerMetricDefault, MetricPointCount());
Assert.Equal(MeterProviderBuilderSdk.MaxMetricPointsPerMetricDefault, MetricPointCount());
exportedItems.Clear();
counterLong.Add(10);
for (int i = 0; i < MeterProviderBuilderState.MaxMetricPointsPerMetricDefault + 1; i++)
for (int i = 0; i < MeterProviderBuilderSdk.MaxMetricPointsPerMetricDefault + 1; i++)
{
counterLong.Add(10, new KeyValuePair<string, object>("key", "value" + i));
}
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(MeterProviderBuilderState.MaxMetricPointsPerMetricDefault, MetricPointCount());
Assert.Equal(MeterProviderBuilderSdk.MaxMetricPointsPerMetricDefault, MetricPointCount());
counterLong.Add(10);
for (int i = 0; i < MeterProviderBuilderState.MaxMetricPointsPerMetricDefault + 1; i++)
for (int i = 0; i < MeterProviderBuilderSdk.MaxMetricPointsPerMetricDefault + 1; i++)
{
counterLong.Add(10, new KeyValuePair<string, object>("key", "value" + i));
}
@ -1386,7 +1386,7 @@ namespace OpenTelemetry.Metrics.Tests
counterLong.Add(10, new KeyValuePair<string, object>("key", "valueC"));
exportedItems.Clear();
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
Assert.Equal(MeterProviderBuilderState.MaxMetricPointsPerMetricDefault, MetricPointCount());
Assert.Equal(MeterProviderBuilderSdk.MaxMetricPointsPerMetricDefault, MetricPointCount());
}
[Fact]

View File

@ -118,8 +118,6 @@ namespace OpenTelemetry.Trace.Tests
{
var builder = Sdk.CreateTracerProviderBuilder();
builder.ConfigureServices(services => services.AddSingleton<MyInstrumentation>());
MyInstrumentation myInstrumentation = null;
RunBuilderServiceLifecycleTest(
@ -157,7 +155,7 @@ namespace OpenTelemetry.Trace.Tests
ServiceProvider serviceProvider = null;
TracerProviderSdk provider = null;
services.ConfigureOpenTelemetryTracing(builder =>
services.AddOpenTelemetry().WithTracing(builder =>
{
testRun = true;
@ -197,12 +195,12 @@ namespace OpenTelemetry.Trace.Tests
{
var services = new ServiceCollection();
services.ConfigureOpenTelemetryTracing(builder =>
services.AddOpenTelemetry().WithTracing(builder =>
{
builder.AddInstrumentation<MyInstrumentation>(() => new());
});
services.ConfigureOpenTelemetryTracing(builder =>
services.AddOpenTelemetry().WithTracing(builder =>
{
builder.AddInstrumentation<MyInstrumentation>(() => new());
});
@ -359,7 +357,7 @@ namespace OpenTelemetry.Trace.Tests
{
if (callNestedConfigure)
{
services.ConfigureOpenTelemetryTracing();
services.AddOpenTelemetry().WithTracing(builder => { });
}
})
.ConfigureBuilder((sp, builder) =>
@ -379,9 +377,9 @@ namespace OpenTelemetry.Trace.Tests
{
bool innerTestExecuted = false;
var serviceCollection = new ServiceCollection();
var services = new ServiceCollection();
serviceCollection.ConfigureOpenTelemetryTracing(builder =>
services.AddOpenTelemetry().WithTracing(builder =>
{
builder.ConfigureBuilder((sp, builder) =>
{
@ -390,7 +388,7 @@ namespace OpenTelemetry.Trace.Tests
});
});
using var serviceProvider = serviceCollection.BuildServiceProvider();
using var serviceProvider = services.BuildServiceProvider();
var resolvedProvider = serviceProvider.GetRequiredService<TracerProvider>();
@ -403,7 +401,6 @@ namespace OpenTelemetry.Trace.Tests
Action<TracerProviderSdk> postAction)
{
var baseBuilder = builder as TracerProviderBuilderBase;
Assert.Null(baseBuilder.State);
builder
.AddSource("TestSource")
@ -417,12 +414,15 @@ namespace OpenTelemetry.Trace.Tests
Assert.NotNull(services);
services.TryAddSingleton<MyInstrumentation>();
services.TryAddSingleton<MyProcessor>();
services.ConfigureOpenTelemetryTracing(b =>
// Note: This is strange to call ConfigureOpenTelemetryTracerProvider here, but supported
services.ConfigureOpenTelemetryTracerProvider((sp, b) =>
{
// Note: This is strange to call ConfigureOpenTelemetryTracing here, but supported
b.AddInstrumentation<MyInstrumentation>();
Assert.Throws<NotSupportedException>(() => b.ConfigureServices(services => { }));
b.AddInstrumentation(sp.GetRequiredService<MyInstrumentation>());
});
});
@ -431,17 +431,17 @@ namespace OpenTelemetry.Trace.Tests
{
configureBuilderInvocations++;
var baseBuilder = builder as TracerProviderBuilderBase;
Assert.NotNull(baseBuilder?.State);
var sdkBuilder = builder as TracerProviderBuilderSdk;
Assert.NotNull(sdkBuilder);
builder
.AddSource("TestSource2")
.AddLegacySource("TestLegacySource2");
Assert.Contains(baseBuilder.State.Sources, s => s == "TestSource");
Assert.Contains(baseBuilder.State.Sources, s => s == "TestSource2");
Assert.Contains(baseBuilder.State.LegacyActivityOperationNames, s => s == "TestLegacySource");
Assert.Contains(baseBuilder.State.LegacyActivityOperationNames, s => s == "TestLegacySource2");
Assert.Contains(sdkBuilder.Sources, s => s == "TestSource");
Assert.Contains(sdkBuilder.Sources, s => s == "TestSource2");
Assert.Contains(sdkBuilder.LegacyActivityOperationNames, s => s == "TestLegacySource");
Assert.Contains(sdkBuilder.LegacyActivityOperationNames, s => s == "TestLegacySource2");
// Note: Services can't be configured at this stage
Assert.Throws<NotSupportedException>(