Added Feature Telemetry (Prometheus + OTLP using OTLP_Endpoint_Url config key)

This commit is contained in:
Mia Rose Winter 2024-04-10 23:43:03 +02:00
parent 7f89b5a196
commit a83fdbbe7a
Signed by: miawinter
GPG key ID: 4B6F6A83178F595E
7 changed files with 73 additions and 3 deletions

View file

@ -4,4 +4,5 @@ public class Features {
public bool Rss { get; set; } = true; public bool Rss { get; set; } = true;
public bool EmailSubscriptions { get; set; } = false; public bool EmailSubscriptions { get; set; } = false;
public bool NativeSignup { get; set; } = true; public bool NativeSignup { get; set; } = true;
public bool Telemetry {get; set; } = false;
} }

View file

@ -19,6 +19,10 @@
using Wave.Services; using Wave.Services;
using Wave.Utilities; using Wave.Utilities;
using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Serilog; using Serilog;
using Serilog.Events; using Serilog.Events;
using Serilog.Sinks.Grafana.Loki; using Serilog.Sinks.Grafana.Loki;
@ -48,6 +52,8 @@
.AddXmlFile( Path.Combine(FileSystemService.ConfigurationDirectory, "config.xml"), true, false) .AddXmlFile( Path.Combine(FileSystemService.ConfigurationDirectory, "config.xml"), true, false)
.AddEnvironmentVariables("WAVE_"); .AddEnvironmentVariables("WAVE_");
var customizations = builder.Configuration.GetSection(nameof(Customization)).Get<Customization>();
#region Logging #region Logging
builder.Services.AddSerilog((services, configuration) => { builder.Services.AddSerilog((services, configuration) => {
@ -56,8 +62,7 @@
.ReadFrom.Services(services) .ReadFrom.Services(services)
.Enrich.WithProperty("Application", "Wave") .Enrich.WithProperty("Application", "Wave")
.Enrich.WithProperty("WaveVersion", humanReadableVersion) .Enrich.WithProperty("WaveVersion", humanReadableVersion)
.Enrich.WithProperty("AppName", .Enrich.WithProperty("AppName", customizations?.AppName)
builder.Configuration.GetSection(nameof(Customization))[nameof(Customization.AppName)])
.Enrich.FromLogContext(); .Enrich.FromLogContext();
if (builder.Configuration["loki"] is {} lokiConfiguration) { if (builder.Configuration["loki"] is {} lokiConfiguration) {
configuration.WriteTo.GrafanaLoki(lokiConfiguration, null, [ configuration.WriteTo.GrafanaLoki(lokiConfiguration, null, [
@ -270,6 +275,38 @@
#endregion #endregion
#region Open Telemetry
var features = builder.Configuration.GetSection(nameof(Features)).Get<Features>();
if (features?.Telemetry is true) {
var otel = builder.Services.AddOpenTelemetry();
otel.ConfigureResource(resource => resource.AddService(serviceName:customization?.AppName ?? "Wave"));
// Prometheus
otel.WithMetrics(metrics => metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddMeter("Microsoft.AspNetCore.Hosting")
.AddMeter("Microsoft.AspNetCore.Server.Kestrel")
.AddMeter("Microsoft.AspNetCore.Http.Connections")
.AddMeter("Microsoft.AspNetCore.Http.Routing")
.AddMeter("Microsoft.AspNetCore.Diagnostics")
.AddPrometheusExporter());
// Jaeger etc.
if (builder.Configuration["OTLP_ENDPOINT_URL"] is {} otlpUrl) {
otel.WithTracing(tracing => {
tracing.AddAspNetCoreInstrumentation();
tracing.AddHttpClientInstrumentation();
tracing.AddOtlpExporter(options => options.Endpoint = new Uri(otlpUrl));
});
}
}
#endregion
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@ -279,6 +316,10 @@
app.UseExceptionHandler("/Error", createScopeForErrors: true); app.UseExceptionHandler("/Error", createScopeForErrors: true);
} }
if (features?.Telemetry is true) {
app.UseOpenTelemetryPrometheusScrapingEndpoint();
}
app.UseSerilogRequestLogging(); app.UseSerilogRequestLogging();
app.UseStaticFiles(new StaticFileOptions { app.UseStaticFiles(new StaticFileOptions {

View file

@ -32,6 +32,11 @@
<PackageReference Include="Mjml.Net" Version="3.8.0" /> <PackageReference Include="Mjml.Net" Version="3.8.0" />
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="3.1.0" /> <PackageReference Include="NetEscapades.Configuration.Yaml" Version="3.1.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.7.0" />
<PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.7.0-rc.1" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.7.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.7.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.7.0" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.Sinks.Grafana.Loki" Version="8.3.0" /> <PackageReference Include="Serilog.Sinks.Grafana.Loki" Version="8.3.0" />
<PackageReference Include="System.ServiceModel.Syndication" Version="8.0.0" /> <PackageReference Include="System.ServiceModel.Syndication" Version="8.0.0" />

View file

@ -15,6 +15,7 @@
</None> </None>
<None Include="docker-compose.yml" /> <None Include="docker-compose.yml" />
<None Include=".dockerignore" /> <None Include=".dockerignore" />
<None Include="prometheus\prometheus.yml" />
<None Include="provisioning\datasources\auomatic.yml" /> <None Include="provisioning\datasources\auomatic.yml" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -17,6 +17,7 @@ services:
- "WAVE_ConnectionStrings__DefaultConnection=Host=db; Username=wave; Password=development; Include Error Detail=true" - "WAVE_ConnectionStrings__DefaultConnection=Host=db; Username=wave; Password=development; Include Error Detail=true"
- "WAVE_ConnectionStrings__Redis=redis,password=development" - "WAVE_ConnectionStrings__Redis=redis,password=development"
- "WAVE_Loki=http://loki:3100" - "WAVE_Loki=http://loki:3100"
- "WAVE_Features__Telemetry=true"
volumes: volumes:
- wave-files:/app/files - wave-files:/app/files
- wave-config:/configuration - wave-config:/configuration
@ -64,6 +65,13 @@ services:
depends_on: depends_on:
loki: loki:
condition: service_healthy condition: service_healthy
prometheus:
image: prom/prometheus:v2.45.0
restart: unless-stopped
ports:
- 9090:9090
volumes:
- ./prometheus:/etc/prometheus
mailhog: mailhog:
image: mailhog/mailhog:latest image: mailhog/mailhog:latest

View file

@ -0,0 +1,8 @@
global:
scrape_interval: 5s
scrape_configs:
- job_name: wave
scrape_interval: 1s
static_configs:
- targets: ["wave:8080"]

View file

@ -5,7 +5,7 @@ deleteDatasources:
orgId: 1 orgId: 1
datasources: datasources:
- name: Wave - name: Wave Logs
type: loki type: loki
isDefault: true isDefault: true
orgId: 1 orgId: 1
@ -15,3 +15,9 @@ datasources:
jsonData: jsonData:
timeout: 60 timeout: 60
maxLines: 1000 maxLines: 1000
- name: Wave Metrics
type: prometheus
ordId: 1
access: proxy
url: http://prometheus:9090
editable: true