From 63b8c02b753877ea7834cd4572bbaad748ae4143 Mon Sep 17 00:00:00 2001 From: Vishwesh Bankwar Date: Tue, 5 Dec 2023 11:31:26 -0800 Subject: [PATCH 1/4] test app --- .../Controllers/WeatherForecastController.cs | 31 +++++++++++++ .../InstrumentationOptions.cs | 8 ++++ .../MyExporter.cs | 45 +++++++++++++++++++ TestAspNetCoreInstrumentationPerf/Program.cs | 42 +++++++++++++++++ .../TestAspNetCoreInstrumentationPerf.csproj | 16 +++++++ .../TestAspNetCoreInstrumentationPerf.http | 6 +++ .../WeatherForecast.cs | 12 +++++ .../appsettings.Development.json | 8 ++++ .../appsettings.json | 13 ++++++ 9 files changed, 181 insertions(+) create mode 100644 TestAspNetCoreInstrumentationPerf/Controllers/WeatherForecastController.cs create mode 100644 TestAspNetCoreInstrumentationPerf/InstrumentationOptions.cs create mode 100644 TestAspNetCoreInstrumentationPerf/MyExporter.cs create mode 100644 TestAspNetCoreInstrumentationPerf/Program.cs create mode 100644 TestAspNetCoreInstrumentationPerf/TestAspNetCoreInstrumentationPerf.csproj create mode 100644 TestAspNetCoreInstrumentationPerf/TestAspNetCoreInstrumentationPerf.http create mode 100644 TestAspNetCoreInstrumentationPerf/WeatherForecast.cs create mode 100644 TestAspNetCoreInstrumentationPerf/appsettings.Development.json create mode 100644 TestAspNetCoreInstrumentationPerf/appsettings.json diff --git a/TestAspNetCoreInstrumentationPerf/Controllers/WeatherForecastController.cs b/TestAspNetCoreInstrumentationPerf/Controllers/WeatherForecastController.cs new file mode 100644 index 00000000000..6bd2d62b1d9 --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/Controllers/WeatherForecastController.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Mvc; + +namespace TestAspNetCoreInstrumentationPerf.Controllers; +[ApiController] +[Route("[controller]")] +public class WeatherForecastController : ControllerBase +{ + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } +} diff --git a/TestAspNetCoreInstrumentationPerf/InstrumentationOptions.cs b/TestAspNetCoreInstrumentationPerf/InstrumentationOptions.cs new file mode 100644 index 00000000000..e72f4047dd9 --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/InstrumentationOptions.cs @@ -0,0 +1,8 @@ +namespace TestAspNetCoreInstrumentationPerf; + +public class InstrumentationOptions +{ + public bool EnableTraceInstrumentation { get; set; } + + public bool EnableMetricInstrumentation { get; set; } +} diff --git a/TestAspNetCoreInstrumentationPerf/MyExporter.cs b/TestAspNetCoreInstrumentationPerf/MyExporter.cs new file mode 100644 index 00000000000..aa26271e24c --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/MyExporter.cs @@ -0,0 +1,45 @@ +// +// 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. +// + +using System.Text; +using OpenTelemetry; + +internal class MyExporter : BaseExporter + where T : class +{ + private readonly string name; + + public MyExporter(string name = "MyExporter") + { + this.name = name; + } + + public override ExportResult Export(in Batch batch) + { + return ExportResult.Success; + } + + protected override bool OnShutdown(int timeoutMilliseconds) + { + Console.WriteLine($"{this.name}.OnShutdown(timeoutMilliseconds={timeoutMilliseconds})"); + return true; + } + + protected override void Dispose(bool disposing) + { + Console.WriteLine($"{this.name}.Dispose({disposing})"); + } +} diff --git a/TestAspNetCoreInstrumentationPerf/Program.cs b/TestAspNetCoreInstrumentationPerf/Program.cs new file mode 100644 index 00000000000..9b790ce473b --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/Program.cs @@ -0,0 +1,42 @@ +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; +using TestAspNetCoreInstrumentationPerf; + +var builder = WebApplication.CreateBuilder(args); + +var instrumentationOptions = new InstrumentationOptions(); +builder.Configuration.GetSection("InstrumentationOptions").Bind(instrumentationOptions); + +// 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(); + +if (instrumentationOptions.EnableMetricInstrumentation) +{ + builder.Services.AddOpenTelemetry().WithMetrics(builder => builder.AddAspNetCoreInstrumentation().AddReader(new PeriodicExportingMetricReader(new MyExporter("TestExporter")))); +} + +if (instrumentationOptions.EnableTraceInstrumentation) +{ + builder.Services.AddOpenTelemetry().WithTracing(builder => builder.AddAspNetCoreInstrumentation()); +} + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/TestAspNetCoreInstrumentationPerf/TestAspNetCoreInstrumentationPerf.csproj b/TestAspNetCoreInstrumentationPerf/TestAspNetCoreInstrumentationPerf.csproj new file mode 100644 index 00000000000..5ebcd40e9ee --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/TestAspNetCoreInstrumentationPerf.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + diff --git a/TestAspNetCoreInstrumentationPerf/TestAspNetCoreInstrumentationPerf.http b/TestAspNetCoreInstrumentationPerf/TestAspNetCoreInstrumentationPerf.http new file mode 100644 index 00000000000..2f0f3e91e93 --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/TestAspNetCoreInstrumentationPerf.http @@ -0,0 +1,6 @@ +@TestAspNetCoreInstrumentationPerf_HostAddress = http://localhost:5203 + +GET {{TestAspNetCoreInstrumentationPerf_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/TestAspNetCoreInstrumentationPerf/WeatherForecast.cs b/TestAspNetCoreInstrumentationPerf/WeatherForecast.cs new file mode 100644 index 00000000000..3d41e65d0da --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/WeatherForecast.cs @@ -0,0 +1,12 @@ +namespace TestAspNetCoreInstrumentationPerf; + +public class WeatherForecast +{ + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } +} diff --git a/TestAspNetCoreInstrumentationPerf/appsettings.Development.json b/TestAspNetCoreInstrumentationPerf/appsettings.Development.json new file mode 100644 index 00000000000..0c208ae9181 --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/TestAspNetCoreInstrumentationPerf/appsettings.json b/TestAspNetCoreInstrumentationPerf/appsettings.json new file mode 100644 index 00000000000..3bee62ce1d4 --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/appsettings.json @@ -0,0 +1,13 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "InstrumentationOptions": { + "EnableTraceInstrumentation": false, + "EnableMetricInstrumentation": false + }, + "AllowedHosts": "*" +} From 5abc649d75ac50425ed649c90c68451f1f972d60 Mon Sep 17 00:00:00 2001 From: "Vishwesh Bankwar (from Dev Box)" Date: Tue, 5 Dec 2023 14:24:04 -0800 Subject: [PATCH 2/4] print --- TestAspNetCoreInstrumentationPerf/Program.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/TestAspNetCoreInstrumentationPerf/Program.cs b/TestAspNetCoreInstrumentationPerf/Program.cs index 9b790ce473b..1600b7df1de 100644 --- a/TestAspNetCoreInstrumentationPerf/Program.cs +++ b/TestAspNetCoreInstrumentationPerf/Program.cs @@ -14,6 +14,9 @@ builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +Console.WriteLine("EnableMetricInstrumentation: " + instrumentationOptions.EnableMetricInstrumentation); +Console.WriteLine("EnableTraceInstrumentation: " + instrumentationOptions.EnableTraceInstrumentation); + if (instrumentationOptions.EnableMetricInstrumentation) { builder.Services.AddOpenTelemetry().WithMetrics(builder => builder.AddAspNetCoreInstrumentation().AddReader(new PeriodicExportingMetricReader(new MyExporter("TestExporter")))); From 69c1395a7d2e2b60a409032cade5c6c56e3a2d9b Mon Sep 17 00:00:00 2001 From: Vishwesh Bankwar Date: Tue, 5 Dec 2023 14:41:13 -0800 Subject: [PATCH 3/4] diagnosticsource overhead --- .../DiagnosticSourceListener.cs | 18 ++++++++++ .../DiagnosticSourceObserver.cs | 35 +++++++++++++++++++ .../InstrumentationOptions.cs | 2 ++ TestAspNetCoreInstrumentationPerf/Program.cs | 14 ++++++++ .../appsettings.json | 3 +- 5 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 TestAspNetCoreInstrumentationPerf/DiagnosticSourceListener.cs create mode 100644 TestAspNetCoreInstrumentationPerf/DiagnosticSourceObserver.cs diff --git a/TestAspNetCoreInstrumentationPerf/DiagnosticSourceListener.cs b/TestAspNetCoreInstrumentationPerf/DiagnosticSourceListener.cs new file mode 100644 index 00000000000..e4ad839f39c --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/DiagnosticSourceListener.cs @@ -0,0 +1,18 @@ +namespace TestAspNetCoreInstrumentationPerf; + +public class DiagnosticSourceListener : IObserver> +{ + public void OnCompleted() + { + } + + public void OnError(Exception error) + { + } + + public void OnNext(KeyValuePair value) + { + // do nothing + // Measure how much perf is impacted by simply subscribing to diagnostic source. + } +} \ No newline at end of file diff --git a/TestAspNetCoreInstrumentationPerf/DiagnosticSourceObserver.cs b/TestAspNetCoreInstrumentationPerf/DiagnosticSourceObserver.cs new file mode 100644 index 00000000000..e5158010975 --- /dev/null +++ b/TestAspNetCoreInstrumentationPerf/DiagnosticSourceObserver.cs @@ -0,0 +1,35 @@ +using System.Diagnostics; + +namespace TestAspNetCoreInstrumentationPerf +{ + internal sealed class DiagnosticSourceSubscriber : IObserver + { + private static readonly HashSet DiagnosticSourceEvents = new() + { + "Microsoft.AspNetCore.Hosting.HttpRequestIn", + "Microsoft.AspNetCore.Hosting.HttpRequestIn.Start", + "Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop", + "Microsoft.AspNetCore.Diagnostics.UnhandledException", + "Microsoft.AspNetCore.Hosting.UnhandledException", + }; + + private readonly Func isEnabled = (eventName, _, _) + => DiagnosticSourceEvents.Contains(eventName); + + public void OnCompleted() + { + } + + public void OnError(Exception error) + { + } + + public void OnNext(DiagnosticListener value) + { + if (value.Name == "Microsoft.AspNetCore") + { + _ = value.Subscribe(new DiagnosticSourceListener(), isEnabled); + } + } + } +} diff --git a/TestAspNetCoreInstrumentationPerf/InstrumentationOptions.cs b/TestAspNetCoreInstrumentationPerf/InstrumentationOptions.cs index e72f4047dd9..135f3e84e56 100644 --- a/TestAspNetCoreInstrumentationPerf/InstrumentationOptions.cs +++ b/TestAspNetCoreInstrumentationPerf/InstrumentationOptions.cs @@ -5,4 +5,6 @@ public class InstrumentationOptions public bool EnableTraceInstrumentation { get; set; } public bool EnableMetricInstrumentation { get; set; } + + public bool EnableDiagnosticSourceSubscription { get; set; } } diff --git a/TestAspNetCoreInstrumentationPerf/Program.cs b/TestAspNetCoreInstrumentationPerf/Program.cs index 1600b7df1de..58d72d21ccf 100644 --- a/TestAspNetCoreInstrumentationPerf/Program.cs +++ b/TestAspNetCoreInstrumentationPerf/Program.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using OpenTelemetry.Metrics; using OpenTelemetry.Trace; using TestAspNetCoreInstrumentationPerf; @@ -27,6 +28,19 @@ builder.Services.AddOpenTelemetry().WithTracing(builder => builder.AddAspNetCoreInstrumentation()); } +if (instrumentationOptions.EnableDiagnosticSourceSubscription) +{ + ActivitySource.AddActivityListener(new ActivityListener + { + ShouldListenTo = source => source.Name == "Microsoft.AspNetCore", + Sample = (ref ActivityCreationOptions options) => ActivitySamplingResult.AllDataAndRecorded, + ActivityStarted = activity => { }, + ActivityStopped = activity => { }, + }); + + DiagnosticListener.AllListeners.Subscribe(new DiagnosticSourceSubscriber()); +} + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/TestAspNetCoreInstrumentationPerf/appsettings.json b/TestAspNetCoreInstrumentationPerf/appsettings.json index 3bee62ce1d4..1466473c944 100644 --- a/TestAspNetCoreInstrumentationPerf/appsettings.json +++ b/TestAspNetCoreInstrumentationPerf/appsettings.json @@ -7,7 +7,8 @@ }, "InstrumentationOptions": { "EnableTraceInstrumentation": false, - "EnableMetricInstrumentation": false + "EnableMetricInstrumentation": false, + "EnableDiagnosticSourceSubscription" : false }, "AllowedHosts": "*" } From cd0cb2e952662de404333d698715a48a1b9d2584 Mon Sep 17 00:00:00 2001 From: "Vishwesh Bankwar (from Dev Box)" Date: Tue, 5 Dec 2023 14:42:04 -0800 Subject: [PATCH 4/4] print --- TestAspNetCoreInstrumentationPerf/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/TestAspNetCoreInstrumentationPerf/Program.cs b/TestAspNetCoreInstrumentationPerf/Program.cs index 58d72d21ccf..85dade38c8c 100644 --- a/TestAspNetCoreInstrumentationPerf/Program.cs +++ b/TestAspNetCoreInstrumentationPerf/Program.cs @@ -17,6 +17,7 @@ Console.WriteLine("EnableMetricInstrumentation: " + instrumentationOptions.EnableMetricInstrumentation); Console.WriteLine("EnableTraceInstrumentation: " + instrumentationOptions.EnableTraceInstrumentation); +Console.WriteLine("EnableDiagnosticSourceSubscription: " + instrumentationOptions.EnableDiagnosticSourceSubscription); if (instrumentationOptions.EnableMetricInstrumentation) {