From bbf88122c41b25cb4017a7b77544768ed8262382 Mon Sep 17 00:00:00 2001 From: "francesco.belacca" Date: Thu, 25 Jan 2024 18:01:57 +0100 Subject: [PATCH] Not all data seems to be flowing but now this uses otel. --- .../BlazorPong.SignalR.csproj | 9 +- src/BlazorPong.SignalR/Program.cs | 2 + .../WebApplicationBuilderExtensions.cs | 96 ++++++++++++++++++- .../Server/BlazorPong.Web.Server.csproj | 10 +- src/BlazorPong.Web/Server/Program.cs | 5 +- .../Server/WebApplicationBuilderExtensions.cs | 95 ++++++++++++++++++ src/Observability/otel-collector-config.yaml | 7 +- src/Observability/prometheus.yaml | 23 +---- src/docker-compose.override.yml | 15 +-- 9 files changed, 226 insertions(+), 36 deletions(-) create mode 100644 src/BlazorPong.Web/Server/WebApplicationBuilderExtensions.cs diff --git a/src/BlazorPong.SignalR/BlazorPong.SignalR.csproj b/src/BlazorPong.SignalR/BlazorPong.SignalR.csproj index b3e6634..ddd7fc6 100644 --- a/src/BlazorPong.SignalR/BlazorPong.SignalR.csproj +++ b/src/BlazorPong.SignalR/BlazorPong.SignalR.csproj @@ -20,12 +20,13 @@ - - - - + + + + + diff --git a/src/BlazorPong.SignalR/Program.cs b/src/BlazorPong.SignalR/Program.cs index 7f108e8..f69fdac 100644 --- a/src/BlazorPong.SignalR/Program.cs +++ b/src/BlazorPong.SignalR/Program.cs @@ -18,9 +18,11 @@ .AllowAnyMethod(); }); }); +builder.AddServiceDefaults(); var app = builder.Build(); app.UseCors("AllowAnyOriginPolicy"); +app.MapDefaultEndpoints(); app.MapHub("/gamehub"); app.Run(); diff --git a/src/BlazorPong.SignalR/WebApplicationBuilderExtensions.cs b/src/BlazorPong.SignalR/WebApplicationBuilderExtensions.cs index ced1c78..b25ea72 100644 --- a/src/BlazorPong.SignalR/WebApplicationBuilderExtensions.cs +++ b/src/BlazorPong.SignalR/WebApplicationBuilderExtensions.cs @@ -1,4 +1,9 @@ -using BlazorPong.SignalR.Cache; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using OpenTelemetry.Logs; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; +using BlazorPong.SignalR.Cache; using BlazorPong.SignalR.EFCore; using BlazorPong.SignalR.Rooms; using BlazorPong.SignalR.Rooms.Games; @@ -8,6 +13,7 @@ namespace BlazorPong.SignalR; +// THIS FILE IS DUPLICATED ON PURPOSE public static class WebApplicationBuilderExtensions { public static void AddRedis(this WebApplicationBuilder builder) @@ -51,4 +57,92 @@ public static void AddHostedServices(this WebApplicationBuilder builder) builder.Services.AddHostedService(); builder.Services.AddHostedService(); } + + public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder) + { + builder.ConfigureOpenTelemetry(); + + builder.AddDefaultHealthChecks(); + + return builder; + } + + public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder) + { + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + //logging.AddConsoleExporter(); + }); + + builder.Services.AddOpenTelemetry() + .WithMetrics(metrics => + { + metrics.AddRuntimeInstrumentation() + .AddBuiltInMeters(); + //metrics.AddConsoleExporter(); + }) + .WithTracing(tracing => + { + if (builder.Environment.IsDevelopment()) + { + // We want to view all traces in development + tracing.SetSampler(new AlwaysOnSampler()); + } + + tracing.AddAspNetCoreInstrumentation() + .AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation(); + + //tracing.AddConsoleExporter(); + }); + + builder.AddOpenTelemetryExporters(); + + return builder; + } + + private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) + { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + if (useOtlpExporter) + { + builder.Services.Configure(logging => logging.AddOtlpExporter()); + builder.Services.ConfigureOpenTelemetryMeterProvider(metrics => metrics.AddOtlpExporter()); + builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter()); + } + + return builder; + } + + public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder) + { + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + // All health checks must pass for app to be considered ready to accept traffic after starting + app.MapHealthChecks("/health"); + + // Only health checks tagged with the "live" tag must pass for app to be considered alive + app.MapHealthChecks("/alive", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("live") + }); + + return app; + } + + private static MeterProviderBuilder AddBuiltInMeters(this MeterProviderBuilder meterProviderBuilder) => + meterProviderBuilder.AddMeter( + "Microsoft.AspNetCore.Hosting", + "Microsoft.AspNetCore.Server.Kestrel", + "System.Net.Http"); } diff --git a/src/BlazorPong.Web/Server/BlazorPong.Web.Server.csproj b/src/BlazorPong.Web/Server/BlazorPong.Web.Server.csproj index be3764e..5a8bf68 100644 --- a/src/BlazorPong.Web/Server/BlazorPong.Web.Server.csproj +++ b/src/BlazorPong.Web/Server/BlazorPong.Web.Server.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -15,12 +15,12 @@ - - - - + + + + diff --git a/src/BlazorPong.Web/Server/Program.cs b/src/BlazorPong.Web/Server/Program.cs index a712f9a..ae60ea3 100644 --- a/src/BlazorPong.Web/Server/Program.cs +++ b/src/BlazorPong.Web/Server/Program.cs @@ -1,10 +1,12 @@ -using BlazorPong.Web.Shared; +using BlazorPong.Web.Server; +using BlazorPong.Web.Shared; var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); builder.Services.AddLogging(); builder.Services.AddRazorPages(); +builder.AddServiceDefaults(); var app = builder.Build(); @@ -22,6 +24,7 @@ app.UseStaticFiles(); app.UseRouting(); +app.MapDefaultEndpoints(); // Map get for GetBaseClientConfig endpoint that app.MapGet("/api/GetBaseClientConfig", () => new BaseClientConfig(app.Configuration["GameHubEndpoint"] ?? throw new InvalidOperationException("GameHubEndpoint not found in config")) diff --git a/src/BlazorPong.Web/Server/WebApplicationBuilderExtensions.cs b/src/BlazorPong.Web/Server/WebApplicationBuilderExtensions.cs new file mode 100644 index 0000000..ba16d71 --- /dev/null +++ b/src/BlazorPong.Web/Server/WebApplicationBuilderExtensions.cs @@ -0,0 +1,95 @@ +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using OpenTelemetry.Logs; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; + +namespace BlazorPong.Web.Server; + +public static class WebApplicationBuilderExtensions +{ + public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder) + { + builder.ConfigureOpenTelemetry(); + + builder.AddDefaultHealthChecks(); + + return builder; + } + + public static IHostApplicationBuilder ConfigureOpenTelemetry(this IHostApplicationBuilder builder) + { + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + }); + + builder.Services.AddOpenTelemetry() + .WithMetrics(metrics => + { + metrics.AddRuntimeInstrumentation() + .AddBuiltInMeters(); + }) + .WithTracing(tracing => + { + if (builder.Environment.IsDevelopment()) + { + // We want to view all traces in development + tracing.SetSampler(new AlwaysOnSampler()); + } + + tracing.AddAspNetCoreInstrumentation() + .AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation(); + }); + + builder.AddOpenTelemetryExporters(); + + return builder; + } + + private static IHostApplicationBuilder AddOpenTelemetryExporters(this IHostApplicationBuilder builder) + { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + if (useOtlpExporter) + { + builder.Services.Configure(logging => logging.AddOtlpExporter()); + builder.Services.ConfigureOpenTelemetryMeterProvider(metrics => metrics.AddOtlpExporter()); + builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter()); + } + + return builder; + } + + public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder) + { + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + // All health checks must pass for app to be considered ready to accept traffic after starting + app.MapHealthChecks("/health"); + + // Only health checks tagged with the "live" tag must pass for app to be considered alive + app.MapHealthChecks("/alive", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("live") + }); + + return app; + } + + private static MeterProviderBuilder AddBuiltInMeters(this MeterProviderBuilder meterProviderBuilder) => + meterProviderBuilder.AddMeter( + "Microsoft.AspNetCore.Hosting", + "Microsoft.AspNetCore.Server.Kestrel", + "System.Net.Http"); +} diff --git a/src/Observability/otel-collector-config.yaml b/src/Observability/otel-collector-config.yaml index a15cf23..d5a16cc 100644 --- a/src/Observability/otel-collector-config.yaml +++ b/src/Observability/otel-collector-config.yaml @@ -8,13 +8,15 @@ exporters: logging: loglevel: info otlp: - endpoint: tempo:4317 + endpoint: otlp:4317 tls: insecure: true loki: endpoint: "http://loki:3100/loki/api/v1/push" tls: insecure: true + prometheus: + endpoint: "collector:8889" service: pipelines: @@ -24,3 +26,6 @@ service: logs: receivers: [otlp] exporters: [logging, loki] + metrics: + receivers: [otlp] + exporters: [prometheus] diff --git a/src/Observability/prometheus.yaml b/src/Observability/prometheus.yaml index 8474031..64c8cb4 100644 --- a/src/Observability/prometheus.yaml +++ b/src/Observability/prometheus.yaml @@ -4,22 +4,9 @@ global: evaluation_interval: 15s scrape_configs: - - job_name: signalr - honor_timestamps: true - metrics_path: /metrics - scheme: http + # - job_name: tempo + # static_configs: + # - targets: [ 'tempo:3200' ] + - job_name: collector static_configs: - - targets: - - signalr:9090 - - - job_name: webapp - honor_timestamps: true - metrics_path: /metrics - scheme: http - static_configs: - - targets: - - webapp:9090 - - - job_name: tempo - static_configs: - - targets: [ 'tempo:3200' ] \ No newline at end of file + - targets: [ 'collector:8889' ] \ No newline at end of file diff --git a/src/docker-compose.override.yml b/src/docker-compose.override.yml index 9b65289..f94f68f 100644 --- a/src/docker-compose.override.yml +++ b/src/docker-compose.override.yml @@ -17,23 +17,27 @@ services: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_FORWARDEDHEADERS_ENABLED=true - GameHubEndpoint=http://localhost:6351/gamehub + - OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318 ports: - "6350:8080" - "6401:9090" depends_on: - signalr + - collector signalr: environment: - ASPNETCORE_ENVIRONMENT=Development - ConnectionStrings__Redis=redis:6379 - ConnectionStrings__AzureSql=Server=azuresql;Database=Blazorpong.Database.AzureSql;User=sa;Password=yourStrong(!)Password;TrustServerCertificate=True + - OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318 ports: - "6351:8080" - "6402:9090" depends_on: - redis - azuresql + - collector signalr-dapr: command: ["./daprd", @@ -78,7 +82,7 @@ services: prometheus: image: prom/prometheus:latest ports: - - "9090:9090" + - "9090" volumes: - ./Observability/prometheus.yaml:/etc/prometheus/prometheus.yaml @@ -88,13 +92,14 @@ services: command: [ "--config=/etc/collector.yaml" ] ports: - "4317:4317" + - "4318:4318" + - "8889:8889" volumes: - ./Observability/otel-collector-config.yaml:/etc/collector.yaml depends_on: - tempo - prometheus - loki - - signalr tempo: image: grafana/tempo:latest @@ -124,9 +129,9 @@ services: - GF_AUTH_DISABLE_LOGIN_FORM=true - GF_FEATURE_TOGGLES_ENABLE=traceqlEditor depends_on: - - collector - tempo - loki + - prometheus loki: image: grafana/loki:latest @@ -141,6 +146,4 @@ services: ports: - "3100:3100" volumes: - - ./Observability/loki.yaml:/etc/loki.yaml - depends_on: - - collector \ No newline at end of file + - ./Observability/loki.yaml:/etc/loki.yaml \ No newline at end of file