Asp6sample (#2989)
This commit is contained in:
parent
97f21802a3
commit
52258f12e3
|
|
@ -42,7 +42,7 @@
|
||||||
<MoqPkgVer>[4.14.5,5.0)</MoqPkgVer>
|
<MoqPkgVer>[4.14.5,5.0)</MoqPkgVer>
|
||||||
<RabbitMQClientPkgVer>[6.1.0,7.0)</RabbitMQClientPkgVer>
|
<RabbitMQClientPkgVer>[6.1.0,7.0)</RabbitMQClientPkgVer>
|
||||||
<StackExchangeRedisPkgVer>[2.1.58,3.0)</StackExchangeRedisPkgVer>
|
<StackExchangeRedisPkgVer>[2.1.58,3.0)</StackExchangeRedisPkgVer>
|
||||||
<SwashbuckleAspNetCorePkgVer>[5.0.0]</SwashbuckleAspNetCorePkgVer>
|
<SwashbuckleAspNetCorePkgVer>[6.2.3]</SwashbuckleAspNetCorePkgVer>
|
||||||
<XUnitRunnerVisualStudioPkgVer>[2.4.3,3.0)</XUnitRunnerVisualStudioPkgVer>
|
<XUnitRunnerVisualStudioPkgVer>[2.4.3,3.0)</XUnitRunnerVisualStudioPkgVer>
|
||||||
<XUnitPkgVer>[2.4.1,3.0)</XUnitPkgVer>
|
<XUnitPkgVer>[2.4.1,3.0)</XUnitPkgVer>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ in `Application_Start`, and disposed in `Application_End` (both methods part of
|
||||||
Global.asax.cs file) as shown [here](../../../examples/AspNet/Global.asax.cs). In
|
Global.asax.cs file) as shown [here](../../../examples/AspNet/Global.asax.cs). In
|
||||||
a typical ASP.NET Core application, `MeterProvider` lifetime is managed by
|
a typical ASP.NET Core application, `MeterProvider` lifetime is managed by
|
||||||
leveraging the built-in Dependency Injection container as shown
|
leveraging the built-in Dependency Injection container as shown
|
||||||
[here](../../../examples/AspNetCore/Startup.cs).
|
[here](../../../examples/AspNetCore/Program.cs).
|
||||||
|
|
||||||
## MeterProvider configuration
|
## MeterProvider configuration
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ in `Application_Start`, and disposed in `Application_End` (both methods part of
|
||||||
Global.asax.cs file) as shown [here](../../../examples/AspNet/Global.asax.cs). In
|
Global.asax.cs file) as shown [here](../../../examples/AspNet/Global.asax.cs). In
|
||||||
a typical ASP.NET Core application, `TracerProvider` lifetime is managed by
|
a typical ASP.NET Core application, `TracerProvider` lifetime is managed by
|
||||||
leveraging the built-in Dependency Injection container as shown
|
leveraging the built-in Dependency Injection container as shown
|
||||||
[here](../../../examples/AspNetCore/Startup.cs).
|
[here](../../../examples/AspNetCore/Program.cs).
|
||||||
|
|
||||||
## TracerProvider configuration
|
## TracerProvider configuration
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,58 +14,51 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
using System;
|
namespace Examples.AspNetCore.Controllers;
|
||||||
using System.Collections.Generic;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using Examples.AspNetCore.Models;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Examples.AspNetCore.Controllers
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class WeatherForecastController : ControllerBase
|
||||||
{
|
{
|
||||||
[ApiController]
|
private static readonly string[] Summaries = new[]
|
||||||
[Route("[controller]")]
|
|
||||||
public class WeatherForecastController : ControllerBase
|
|
||||||
{
|
{
|
||||||
private static readonly string[] Summaries = new[]
|
|
||||||
{
|
|
||||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching",
|
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching",
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly HttpClient HttpClient = new();
|
private static readonly HttpClient HttpClient = new HttpClient();
|
||||||
|
|
||||||
private readonly ILogger<WeatherForecastController> logger;
|
private readonly ILogger<WeatherForecastController> logger;
|
||||||
|
|
||||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
||||||
|
{
|
||||||
|
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IEnumerable<WeatherForecast> Get()
|
||||||
|
{
|
||||||
|
using var scope = this.logger.BeginScope("{Id}", Guid.NewGuid().ToString("N"));
|
||||||
|
|
||||||
|
// Making an http call here to serve as an example of
|
||||||
|
// how dependency calls will be captured and treated
|
||||||
|
// automatically as child of incoming request.
|
||||||
|
var res = HttpClient.GetStringAsync("http://google.com").Result;
|
||||||
|
var rng = new Random();
|
||||||
|
var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||||
{
|
{
|
||||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
Date = DateTime.Now.AddDays(index),
|
||||||
}
|
TemperatureC = rng.Next(-20, 55),
|
||||||
|
Summary = Summaries[rng.Next(Summaries.Length)],
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
[HttpGet]
|
this.logger.LogInformation(
|
||||||
public IEnumerable<WeatherForecast> Get()
|
"WeatherForecasts generated {count}: {forecasts}",
|
||||||
{
|
forecast.Length,
|
||||||
using var scope = this.logger.BeginScope("{Id}", Guid.NewGuid().ToString("N"));
|
forecast);
|
||||||
|
|
||||||
// Making an http call here to serve as an example of
|
return forecast;
|
||||||
// how dependency calls will be captured and treated
|
|
||||||
// automatically as child of incoming request.
|
|
||||||
var res = HttpClient.GetStringAsync("http://google.com").Result;
|
|
||||||
var rng = new Random();
|
|
||||||
var forecast = Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
|
||||||
{
|
|
||||||
Date = DateTime.Now.AddDays(index),
|
|
||||||
TemperatureC = rng.Next(-20, 55),
|
|
||||||
Summary = Summaries[rng.Next(Summaries.Length)],
|
|
||||||
})
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
this.logger.LogInformation(
|
|
||||||
"WeatherForecasts generated {count}: {forecasts}",
|
|
||||||
forecast.Length,
|
|
||||||
forecast);
|
|
||||||
|
|
||||||
return forecast;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,24 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<Nullable>enable</Nullable>
|
||||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.20" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(SwashbuckleAspNetCorePkgVer)" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(SwashbuckleAspNetCorePkgVer)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Hosting\OpenTelemetry.Extensions.Hosting.csproj" />
|
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Extensions.Hosting\OpenTelemetry.Extensions.Hosting.csproj" />
|
||||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
|
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Console\OpenTelemetry.Exporter.Console.csproj" />
|
||||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" />
|
|
||||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" />
|
|
||||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj" />
|
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.OpenTelemetryProtocol\OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj" />
|
||||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs\OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs.csproj" />
|
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs\OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs.csproj" />
|
||||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" />
|
|
||||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.AspNetCore\OpenTelemetry.Instrumentation.AspNetCore.csproj" />
|
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.AspNetCore\OpenTelemetry.Instrumentation.AspNetCore.csproj" />
|
||||||
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.Http\OpenTelemetry.Instrumentation.Http.csproj" />
|
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Instrumentation.Http\OpenTelemetry.Instrumentation.Http.csproj" />
|
||||||
|
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Jaeger\OpenTelemetry.Exporter.Jaeger.csproj" />
|
||||||
|
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Prometheus\OpenTelemetry.Exporter.Prometheus.csproj" />
|
||||||
|
<ProjectReference Include="$(RepoRoot)\src\OpenTelemetry.Exporter.Zipkin\OpenTelemetry.Exporter.Zipkin.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
using System;
|
namespace Examples.AspNetCore
|
||||||
|
|
||||||
namespace Examples.AspNetCore.Models
|
|
||||||
{
|
{
|
||||||
public class WeatherForecast
|
public class WeatherForecast
|
||||||
{
|
{
|
||||||
|
|
@ -26,6 +24,6 @@ namespace Examples.AspNetCore.Models
|
||||||
|
|
||||||
public int TemperatureF => 32 + (int)(this.TemperatureC / 0.5556);
|
public int TemperatureF => 32 + (int)(this.TemperatureC / 0.5556);
|
||||||
|
|
||||||
public string Summary { get; set; }
|
public string? Summary { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,67 +14,163 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
// </copyright>
|
// </copyright>
|
||||||
|
|
||||||
using System;
|
using System.Reflection;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using OpenTelemetry.Exporter;
|
||||||
using Microsoft.Extensions.Configuration;
|
using OpenTelemetry.Instrumentation.AspNetCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using OpenTelemetry.Logs;
|
using OpenTelemetry.Logs;
|
||||||
|
using OpenTelemetry.Metrics;
|
||||||
using OpenTelemetry.Resources;
|
using OpenTelemetry.Resources;
|
||||||
|
using OpenTelemetry.Trace;
|
||||||
|
|
||||||
namespace Examples.AspNetCore
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
var serviceName = "AspNetCoreExampleService";
|
||||||
|
|
||||||
|
// OpenTelemetry
|
||||||
|
var assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown";
|
||||||
|
|
||||||
|
// Switch between Zipkin/Jaeger/OTLP by setting UseExporter in appsettings.json.
|
||||||
|
var tracingExporter = builder.Configuration.GetValue<string>("UseTracingExporter").ToLowerInvariant();
|
||||||
|
|
||||||
|
var resourceBuilder = tracingExporter switch
|
||||||
{
|
{
|
||||||
public class Program
|
"jaeger" => ResourceBuilder.CreateDefault().AddService(builder.Configuration.GetValue<string>("Jaeger:ServiceName"), serviceVersion: assemblyVersion, serviceInstanceId: Environment.MachineName),
|
||||||
|
"zipkin" => ResourceBuilder.CreateDefault().AddService(builder.Configuration.GetValue<string>("Zipkin:ServiceName"), serviceVersion: assemblyVersion, serviceInstanceId: Environment.MachineName),
|
||||||
|
"otlp" => ResourceBuilder.CreateDefault().AddService(builder.Configuration.GetValue<string>("Otlp:ServiceName"), serviceVersion: assemblyVersion, serviceInstanceId: Environment.MachineName),
|
||||||
|
_ => ResourceBuilder.CreateDefault().AddService(serviceName, serviceVersion: assemblyVersion, serviceInstanceId: Environment.MachineName),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Traces
|
||||||
|
builder.Services.AddOpenTelemetryTracing(options =>
|
||||||
|
{
|
||||||
|
options
|
||||||
|
.SetResourceBuilder(resourceBuilder)
|
||||||
|
.SetSampler(new AlwaysOnSampler())
|
||||||
|
.AddHttpClientInstrumentation()
|
||||||
|
.AddAspNetCoreInstrumentation();
|
||||||
|
|
||||||
|
switch (tracingExporter)
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
case "jaeger":
|
||||||
{
|
options.AddJaegerExporter();
|
||||||
CreateHostBuilder(args).Build().Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
builder.Services.Configure<JaegerExporterOptions>(builder.Configuration.GetSection("Jaeger"));
|
||||||
Host.CreateDefaultBuilder(args)
|
|
||||||
.ConfigureWebHostDefaults(webBuilder =>
|
// 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;
|
||||||
|
|
||||||
|
case "zipkin":
|
||||||
|
options.AddZipkinExporter();
|
||||||
|
|
||||||
|
builder.Services.Configure<ZipkinExporterOptions>(builder.Configuration.GetSection("Zipkin"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "otlp":
|
||||||
|
options.AddOtlpExporter(otlpOptions =>
|
||||||
{
|
{
|
||||||
webBuilder.UseStartup<Startup>();
|
otlpOptions.Endpoint = new Uri(builder.Configuration.GetValue<string>("Otlp:Endpoint"));
|
||||||
})
|
|
||||||
.ConfigureLogging((context, builder) =>
|
|
||||||
{
|
|
||||||
builder.ClearProviders();
|
|
||||||
builder.AddConsole();
|
|
||||||
|
|
||||||
var logExporter = context.Configuration.GetValue<string>("UseLogExporter").ToLowerInvariant();
|
|
||||||
switch (logExporter)
|
|
||||||
{
|
|
||||||
case "otlp":
|
|
||||||
// Adding the OtlpExporter creates a GrpcChannel.
|
|
||||||
// This switch must be set before creating a GrpcChannel when calling an insecure gRPC service.
|
|
||||||
// See: https://docs.microsoft.com/aspnet/core/grpc/troubleshoot#call-insecure-grpc-services-with-net-core-client
|
|
||||||
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
|
||||||
builder.AddOpenTelemetry(options =>
|
|
||||||
{
|
|
||||||
options.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(context.Configuration.GetValue<string>("Otlp:ServiceName")));
|
|
||||||
options.AddOtlpExporter(otlpOptions =>
|
|
||||||
{
|
|
||||||
otlpOptions.Endpoint = new Uri(context.Configuration.GetValue<string>("Otlp:Endpoint"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
builder.AddOpenTelemetry(options =>
|
|
||||||
{
|
|
||||||
options.AddConsoleExporter();
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Services.Configure<OpenTelemetryLoggerOptions>(opt =>
|
|
||||||
{
|
|
||||||
opt.IncludeScopes = true;
|
|
||||||
opt.ParseStateValues = true;
|
|
||||||
opt.IncludeFormattedMessage = true;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
options.AddConsoleExporter();
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// For options which can be bound from IConfiguration.
|
||||||
|
builder.Services.Configure<AspNetCoreInstrumentationOptions>(builder.Configuration.GetSection("AspNetCoreInstrumentation"));
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
builder.Logging.ClearProviders();
|
||||||
|
|
||||||
|
builder.Logging.AddOpenTelemetry(options =>
|
||||||
|
{
|
||||||
|
options.SetResourceBuilder(resourceBuilder);
|
||||||
|
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"));
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
options.AddConsoleExporter();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.Configure<OpenTelemetryLoggerOptions>(opt =>
|
||||||
|
{
|
||||||
|
opt.IncludeScopes = true;
|
||||||
|
opt.ParseStateValues = true;
|
||||||
|
opt.IncludeFormattedMessage = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Metrics
|
||||||
|
builder.Services.AddOpenTelemetryMetrics(options =>
|
||||||
|
{
|
||||||
|
options.SetResourceBuilder(resourceBuilder)
|
||||||
|
.AddHttpClientInstrumentation();
|
||||||
|
|
||||||
|
var metricsExporter = builder.Configuration.GetValue<string>("UseMetricsExporter").ToLowerInvariant();
|
||||||
|
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((exporterOptions, metricReaderOptions) =>
|
||||||
|
{
|
||||||
|
exporterOptions.Targets = ConsoleExporterOutputTargets.Console;
|
||||||
|
|
||||||
|
// The ConsoleMetricExporter defaults to a manual collect cycle.
|
||||||
|
// This configuration causes metrics to be exported to stdout on a 10s interval.
|
||||||
|
metricReaderOptions.MetricReaderType = MetricReaderType.Periodic;
|
||||||
|
metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 10000;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
app.UseSwaggerUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
var metricsExporter = builder.Configuration.GetValue<string>("UseMetricsExporter").ToLowerInvariant();
|
||||||
|
|
||||||
|
if (metricsExporter == "prometheus")
|
||||||
|
{
|
||||||
|
app.UseOpenTelemetryPrometheusScrapingEndpoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Run();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
# OpenTelemetry ASP.Net Core 6 Web API Example
|
||||||
|
|
||||||
|
This example uses the new WebApplication host that ships with .Net 6
|
||||||
|
and shows how to setup
|
||||||
|
|
||||||
|
1. OpenTelemetry logging
|
||||||
|
2. OpenTelemetry metrics
|
||||||
|
3. OpenTelemetry tracing
|
||||||
|
|
||||||
|
`ResourceBuilder` is associated with OpenTelemetry to associate the
|
||||||
|
service name, version and the machine on which this program is running.
|
||||||
|
|
||||||
|
The sample rate is set to emit all the traces using `AlwaysOnSampler`.
|
||||||
|
You can try out different samplers like `TraceIdRatioBasedSampler`.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
* [ASP.NET Core 3.1 Example](https://github.com/open-telemetry/opentelemetry-dotnet/tree/98cb28974af43fc893ab80a8cead6e2d4163e144/examples/AspNetCore)
|
||||||
|
* [OpenTelemetry Project](https://opentelemetry.io/)
|
||||||
|
|
@ -1,184 +0,0 @@
|
||||||
// <copyright file="Startup.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;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.OpenApi.Models;
|
|
||||||
using OpenTelemetry.Exporter;
|
|
||||||
using OpenTelemetry.Instrumentation.AspNetCore;
|
|
||||||
using OpenTelemetry.Metrics;
|
|
||||||
using OpenTelemetry.Resources;
|
|
||||||
using OpenTelemetry.Trace;
|
|
||||||
|
|
||||||
namespace Examples.AspNetCore
|
|
||||||
{
|
|
||||||
public class Startup
|
|
||||||
{
|
|
||||||
public Startup(IConfiguration configuration)
|
|
||||||
{
|
|
||||||
this.Configuration = configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IConfiguration Configuration { get; }
|
|
||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.AddControllers();
|
|
||||||
|
|
||||||
// Enable HttpClientFactory integration for customization of the HttpClient used for export calls.
|
|
||||||
services.AddHttpClient();
|
|
||||||
|
|
||||||
services.AddSwaggerGen(c =>
|
|
||||||
{
|
|
||||||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
|
|
||||||
|
|
||||||
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
|
||||||
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
|
||||||
if (File.Exists(xmlPath))
|
|
||||||
{
|
|
||||||
c.IncludeXmlComments(xmlPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Switch between Zipkin/Jaeger/OTLP by setting UseExporter in appsettings.json.
|
|
||||||
var tracingExporter = this.Configuration.GetValue<string>("UseTracingExporter").ToLowerInvariant();
|
|
||||||
switch (tracingExporter)
|
|
||||||
{
|
|
||||||
case "jaeger":
|
|
||||||
services.AddOpenTelemetryTracing((builder) => builder
|
|
||||||
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(this.Configuration.GetValue<string>("Jaeger:ServiceName")))
|
|
||||||
.AddAspNetCoreInstrumentation()
|
|
||||||
.AddHttpClientInstrumentation()
|
|
||||||
.AddJaegerExporter());
|
|
||||||
|
|
||||||
services.Configure<JaegerExporterOptions>(this.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;
|
|
||||||
case "zipkin":
|
|
||||||
services.AddOpenTelemetryTracing((builder) => builder
|
|
||||||
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(this.Configuration.GetValue<string>("Zipkin:ServiceName")))
|
|
||||||
.AddAspNetCoreInstrumentation()
|
|
||||||
.AddHttpClientInstrumentation()
|
|
||||||
.AddZipkinExporter());
|
|
||||||
|
|
||||||
services.Configure<ZipkinExporterOptions>(this.Configuration.GetSection("Zipkin"));
|
|
||||||
break;
|
|
||||||
case "otlp":
|
|
||||||
// Adding the OtlpExporter creates a GrpcChannel.
|
|
||||||
// This switch must be set before creating a GrpcChannel when calling an insecure gRPC service.
|
|
||||||
// See: https://docs.microsoft.com/aspnet/core/grpc/troubleshoot#call-insecure-grpc-services-with-net-core-client
|
|
||||||
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
|
||||||
|
|
||||||
services.AddOpenTelemetryTracing((builder) => builder
|
|
||||||
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(this.Configuration.GetValue<string>("Otlp:ServiceName")))
|
|
||||||
.AddAspNetCoreInstrumentation()
|
|
||||||
.AddHttpClientInstrumentation()
|
|
||||||
.AddOtlpExporter(otlpOptions =>
|
|
||||||
{
|
|
||||||
otlpOptions.Endpoint = new Uri(this.Configuration.GetValue<string>("Otlp:Endpoint"));
|
|
||||||
}));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
services.AddOpenTelemetryTracing((builder) => builder
|
|
||||||
.AddAspNetCoreInstrumentation()
|
|
||||||
.AddHttpClientInstrumentation()
|
|
||||||
.AddConsoleExporter());
|
|
||||||
|
|
||||||
// For options which can be bound from IConfiguration.
|
|
||||||
services.Configure<AspNetCoreInstrumentationOptions>(this.Configuration.GetSection("AspNetCoreInstrumentation"));
|
|
||||||
|
|
||||||
// For options which can be configured from code only.
|
|
||||||
services.Configure<AspNetCoreInstrumentationOptions>(options =>
|
|
||||||
{
|
|
||||||
options.Filter = (req) =>
|
|
||||||
{
|
|
||||||
return req.Request.Host != null;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var metricsExporter = this.Configuration.GetValue<string>("UseMetricsExporter").ToLowerInvariant();
|
|
||||||
services.AddOpenTelemetryMetrics(builder =>
|
|
||||||
{
|
|
||||||
builder.AddAspNetCoreInstrumentation();
|
|
||||||
builder.AddHttpClientInstrumentation();
|
|
||||||
|
|
||||||
switch (metricsExporter)
|
|
||||||
{
|
|
||||||
case "prometheus":
|
|
||||||
builder.AddPrometheusExporter();
|
|
||||||
break;
|
|
||||||
case "otlp":
|
|
||||||
builder.AddOtlpExporter();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
builder.AddConsoleExporter((exporterOptions, metricReaderOptions) =>
|
|
||||||
{
|
|
||||||
exporterOptions.Targets = ConsoleExporterOutputTargets.Console;
|
|
||||||
|
|
||||||
// The ConsoleMetricExporter defaults to a manual collect cycle.
|
|
||||||
// This configuration causes metrics to be exported to stdout on a 10s interval.
|
|
||||||
metricReaderOptions.MetricReaderType = MetricReaderType.Periodic;
|
|
||||||
metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = 10000;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
services.Configure<PrometheusExporterOptions>(this.Configuration.GetSection("Prometheus"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
|
||||||
{
|
|
||||||
if (env.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseDeveloperExceptionPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
|
||||||
|
|
||||||
app.UseSwagger();
|
|
||||||
|
|
||||||
app.UseSwaggerUI(c =>
|
|
||||||
{
|
|
||||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseRouting();
|
|
||||||
|
|
||||||
var metricsExporter = this.Configuration.GetValue<string>("UseMetricsExporter").ToLowerInvariant();
|
|
||||||
if (metricsExporter == "prometheus")
|
|
||||||
{
|
|
||||||
app.UseOpenTelemetryPrometheusScrapingEndpoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
|
||||||
{
|
|
||||||
endpoints.MapControllers();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -60,7 +60,7 @@ This exporter allows easy configuration of `ZipkinExporterOptions` from
|
||||||
dependency injection container, when used in conjunction with
|
dependency injection container, when used in conjunction with
|
||||||
[`OpenTelemetry.Extensions.Hosting`](../OpenTelemetry.Extensions.Hosting/README.md).
|
[`OpenTelemetry.Extensions.Hosting`](../OpenTelemetry.Extensions.Hosting/README.md).
|
||||||
|
|
||||||
See the [Startup](../../examples/AspNetCore/Startup.cs) class of the ASP.NET
|
See the [Startup](../../examples/AspNetCore/Program.cs) class of the ASP.NET
|
||||||
Core application for example use.
|
Core application for example use.
|
||||||
|
|
||||||
### Configuration using Environment Variables
|
### Configuration using Environment Variables
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue