From 63777bf810275817111fe218c423f25918c8f52e Mon Sep 17 00:00:00 2001 From: alyssa Date: Sun, 23 Feb 2025 18:49:31 +0000 Subject: [PATCH] feat: add sentry error logging to dotnet-api and rust crates --- Cargo.lock | 60 +++++++++++++++--------------- Cargo.toml | 4 +- PluralKit.API/PluralKit.API.csproj | 1 + PluralKit.API/Program.cs | 10 +++++ PluralKit.API/Startup.cs | 5 +++ PluralKit.API/packages.lock.json | 6 +++ crates/libpk/Cargo.toml | 1 + crates/libpk/src/lib.rs | 37 +++++++++++++++--- 8 files changed, 86 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc949bbe..63502687 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1490,7 +1490,7 @@ dependencies = [ "http 1.1.0", "hyper 1.5.0", "hyper-util", - "rustls 0.23.10", + "rustls 0.23.23", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -1698,6 +1698,7 @@ dependencies = [ "metrics", "metrics-exporter-prometheus", "sentry", + "sentry-tracing", "serde", "serde_json", "sqlx", @@ -2349,7 +2350,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.10", + "rustls 0.23.23", "socket2 0.5.7", "thiserror", "tokio", @@ -2366,7 +2367,7 @@ dependencies = [ "rand", "ring 0.17.8", "rustc-hash", - "rustls 0.23.10", + "rustls 0.23.23", "slab", "thiserror", "tinyvec", @@ -2599,7 +2600,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.10", + "rustls 0.23.23", "rustls-pemfile 2.1.2", "rustls-pki-types", "serde", @@ -2809,25 +2810,24 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ - "log", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.4", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.10" +version = "0.23.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" dependencies = [ "log", "once_cell", "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.4", + "rustls-webpki 0.102.8", "subtle", "zeroize", ] @@ -2882,9 +2882,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring 0.17.8", "rustls-pki-types", @@ -3002,13 +3002,13 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "sentry" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5484316556650182f03b43d4c746ce0e3e48074a21e2f51244b648b6542e1066" +checksum = "3a7332159e544e34db06b251b1eda5e546bd90285c3f58d9c8ff8450b484e0da" dependencies = [ "httpdate", "reqwest 0.12.8", - "rustls 0.22.4", + "rustls 0.23.23", "sentry-backtrace", "sentry-contexts", "sentry-core", @@ -3022,9 +3022,9 @@ dependencies = [ [[package]] name = "sentry-backtrace" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40aa225bb41e2ec9d7c90886834367f560efc1af028f1c5478a6cce6a59c463a" +checksum = "565ec31ad37bab8e6d9f289f34913ed8768347b133706192f10606dabd5c6bc4" dependencies = [ "backtrace", "once_cell", @@ -3034,9 +3034,9 @@ dependencies = [ [[package]] name = "sentry-contexts" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a8dd746da3d16cb8c39751619cefd4fcdbd6df9610f3310fd646b55f6e39910" +checksum = "e860275f25f27e8c0c7726ce116c7d5c928c5bba2ee73306e52b20a752298ea6" dependencies = [ "hostname", "libc", @@ -3048,9 +3048,9 @@ dependencies = [ [[package]] name = "sentry-core" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161283cfe8e99c8f6f236a402b9ccf726b201f365988b5bb637ebca0abbd4a30" +checksum = "653942e6141f16651273159f4b8b1eaeedf37a7554c00cd798953e64b8a9bf72" dependencies = [ "once_cell", "rand", @@ -3061,9 +3061,9 @@ dependencies = [ [[package]] name = "sentry-debug-images" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc6b25e945fcaa5e97c43faee0267eebda9f18d4b09a251775d8fef1086238a" +checksum = "2a60bc2154e6df59beed0ac13d58f8dfaf5ad20a88548a53e29e4d92e8e835c2" dependencies = [ "findshlibs", "once_cell", @@ -3072,9 +3072,9 @@ dependencies = [ [[package]] name = "sentry-panic" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc74f229c7186dd971a9491ffcbe7883544aa064d1589bd30b83fb856cd22d63" +checksum = "105e3a956c8aa9dab1e4087b1657b03271bfc49d838c6ae9bfc7c58c802fd0ef" dependencies = [ "sentry-backtrace", "sentry-core", @@ -3082,9 +3082,9 @@ dependencies = [ [[package]] name = "sentry-tracing" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c5faf2103cd01eeda779ea439b68c4ee15adcdb16600836e97feafab362ec" +checksum = "64e75c831b4d8b34a5aec1f65f67c5d46a26c7c5d3c7abd8b5ef430796900cf8" dependencies = [ "sentry-backtrace", "sentry-core", @@ -3094,9 +3094,9 @@ dependencies = [ [[package]] name = "sentry-types" -version = "0.34.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d68cdf6bc41b8ff3ae2a9c4671e97426dcdd154cc1d4b6b72813f285d6b163f" +checksum = "2d4203359e60724aa05cf2385aaf5d4f147e837185d7dd2b9ccf1ee77f4420c8" dependencies = [ "debugid", "hex", @@ -3819,7 +3819,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.10", + "rustls 0.23.23", "rustls-pki-types", "tokio", ] @@ -4233,7 +4233,7 @@ dependencies = [ "base64 0.22.1", "log", "once_cell", - "rustls 0.23.10", + "rustls 0.23.23", "rustls-pki-types", "url", "webpki-roots 0.26.6", diff --git a/Cargo.toml b/Cargo.toml index af0f6674..c605303a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,13 +15,13 @@ futures = "0.3.30" lazy_static = "1.4.0" metrics = "0.23.0" reqwest = { version = "0.12.7" , default-features = false, features = ["rustls-tls", "trust-dns"]} -sentry = { version = "0.34.0", default-features = false, features = ["backtrace", "contexts", "panic", "debug-images", "reqwest", "rustls"] } # replace native-tls with rustls +sentry = { version = "0.36.0", default-features = false, features = ["backtrace", "contexts", "panic", "debug-images", "reqwest", "rustls"] } # replace native-tls with rustls serde = { version = "1.0.196", features = ["derive"] } serde_json = "1.0.117" signal-hook = "0.3.17" sqlx = { version = "0.8.2", features = ["runtime-tokio", "postgres", "time", "macros", "uuid"] } tokio = { version = "1.36.0", features = ["full"] } -tracing = "0.1.40" +tracing = "0.1" tracing-subscriber = { version = "0.3.16", features = ["env-filter", "json"] } uuid = { version = "1.7.0", features = ["serde"] } diff --git a/PluralKit.API/PluralKit.API.csproj b/PluralKit.API/PluralKit.API.csproj index ea792b98..e35518dd 100644 --- a/PluralKit.API/PluralKit.API.csproj +++ b/PluralKit.API/PluralKit.API.csproj @@ -31,6 +31,7 @@ + diff --git a/PluralKit.API/Program.cs b/PluralKit.API/Program.cs index d3466d4f..4f746b57 100644 --- a/PluralKit.API/Program.cs +++ b/PluralKit.API/Program.cs @@ -14,6 +14,16 @@ public class Program await BuildInfoService.LoadVersion(); var host = CreateHostBuilder(args).Build(); var config = host.Services.GetRequiredService(); + + // Initialize Sentry SDK, and make sure it gets dropped at the end + using var _ = SentrySdk.Init(opts => + { + opts.Dsn = config.SentryUrl ?? ""; + opts.Release = BuildInfoService.FullVersion; + opts.AutoSessionTracking = true; + // opts.DisableTaskUnobservedTaskExceptionCapture(); + }); + await host.Services.GetRequiredService().InitAsync(config); await host.RunAsync(); } diff --git a/PluralKit.API/Startup.cs b/PluralKit.API/Startup.cs index a564cbdc..ecb91710 100644 --- a/PluralKit.API/Startup.cs +++ b/PluralKit.API/Startup.cs @@ -62,8 +62,13 @@ public class Startup await ctx.Response.WriteJSON(400, "{\"message\":\"400: Bad Request\",\"code\":0}"); else if (exc.Error is not PKError) + { await ctx.Response.WriteJSON(500, "{\"message\":\"500: Internal Server Error\",\"code\":0}"); + var sentryEvent = new SentryEvent(exc.Error); + SentrySdk.CaptureEvent(sentryEvent); + } + // for some reason, if we don't specifically cast to ModelParseError, it uses the base's ToJson method else if (exc.Error is ModelParseError fe) await ctx.Response.WriteJSON(fe.ResponseCode, JsonConvert.SerializeObject(fe.ToJson())); diff --git a/PluralKit.API/packages.lock.json b/PluralKit.API/packages.lock.json index 8c8be7c4..adc4279b 100644 --- a/PluralKit.API/packages.lock.json +++ b/PluralKit.API/packages.lock.json @@ -28,6 +28,12 @@ "Microsoft.AspNetCore.Mvc.Versioning": "5.1.0" } }, + "Sentry": { + "type": "Direct", + "requested": "[4.13.0, )", + "resolved": "4.13.0", + "contentHash": "Wfw3M1WpFcrYaGzPm7QyUTfIOYkVXQ1ry6p4WYjhbLz9fPwV23SGQZTFDpdox67NHM0V0g1aoQ4YKLm4ANtEEg==" + }, "Serilog.AspNetCore": { "type": "Direct", "requested": "[9.0.0, )", diff --git a/crates/libpk/Cargo.toml b/crates/libpk/Cargo.toml index 4b084038..40d430c8 100644 --- a/crates/libpk/Cargo.toml +++ b/crates/libpk/Cargo.toml @@ -21,3 +21,4 @@ uuid = { workspace = true } config = "0.14.0" json-subscriber = { version = "0.2.2", features = ["env-filter"] } metrics-exporter-prometheus = { version = "0.15.3", default-features = false, features = ["tokio", "http-listener", "tracing"] } +sentry-tracing = "0.36.0" diff --git a/crates/libpk/src/lib.rs b/crates/libpk/src/lib.rs index ee7a6536..39643fb6 100644 --- a/crates/libpk/src/lib.rs +++ b/crates/libpk/src/lib.rs @@ -5,6 +5,8 @@ use metrics_exporter_prometheus::PrometheusBuilder; use sentry::IntoDsn; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; +use sentry_tracing::event_from_event; + pub mod db; pub mod state; pub mod util; @@ -14,8 +16,20 @@ pub use crate::_config::CONFIG as config; // functions in this file are only used by the main function below -pub fn init_logging(component: &str) -> anyhow::Result<()> { +pub fn init_logging(component: &str) { + // todo: clean up the sentry duplication if config.json_log { + let sentry_layer = + sentry_tracing::layer().event_mapper(|md, ctx| match md.metadata().level() { + &tracing::Level::ERROR => { + // for some reason this works, but letting the library handle it doesn't + let event = event_from_event(md, ctx); + sentry::capture_event(event); + sentry_tracing::EventMapping::Ignore + } + _ => sentry_tracing::EventMapping::Ignore, + }); + let mut layer = json_subscriber::layer(); layer.inner_layer_mut().add_static_field( "component", @@ -23,15 +37,26 @@ pub fn init_logging(component: &str) -> anyhow::Result<()> { ); tracing_subscriber::registry() .with(layer) + .with(sentry_layer) .with(EnvFilter::from_default_env()) .init(); } else { - tracing_subscriber::fmt() - .with_env_filter(EnvFilter::from_default_env()) + let sentry_layer = + sentry_tracing::layer().event_mapper(|md, ctx| match md.metadata().level() { + &tracing::Level::ERROR => { + // for some reason this works, but letting the library handle it doesn't + let event = event_from_event(md, ctx); + sentry::capture_event(event); + sentry_tracing::EventMapping::Ignore + } + _ => sentry_tracing::EventMapping::Ignore, + }); + + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer()) + .with(sentry_layer) .init(); } - - Ok(()) } pub fn init_metrics() -> anyhow::Result<()> { @@ -61,7 +86,7 @@ macro_rules! main { fn main() -> anyhow::Result<()> { let _sentry_guard = libpk::init_sentry(); // we might also be able to use env!("CARGO_CRATE_NAME") here - libpk::init_logging($component)?; + libpk::init_logging($component); tokio::runtime::Builder::new_multi_thread() .enable_all() .build()