Skip to content

Commit 956ed91

Browse files
committed
Auto merge of #3988 - Turbo87:sentry-conduit, r=locks
Use `sentry-conduit` middleware for error reporting The implementation of this crate is largely based on the Sentry middleware code in crates.io and the implementation of sentry-actix. It has several advantages over the implementation that we currently use: - Automatic per-request scoping of errors, breadcrumbs and other data - Optional release health tracking - Reporting of error stack traces, if available - `transaction` field support (aka. the route pattern that was used by conduit-router) see https://github.com/Turbo87/sentry-conduit
2 parents e34e3e2 + c6c63f1 commit 956ed91

File tree

5 files changed

+30
-60
lines changed

5 files changed

+30
-60
lines changed

Cargo.lock

Lines changed: 22 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ reqwest = { version = "0.11", features = ["blocking", "gzip", "json"] }
7474
scheduled-thread-pool = "0.2.0"
7575
semver = { version = "1.0.3", features = ["serde"] }
7676
sentry = { version = "0.23.0", features = ["tracing"] }
77+
sentry-conduit = "0.2.0"
7778
serde = { version = "1.0.0", features = ["derive"] }
7879
serde_json = "1.0.0"
7980
sha2 = "0.9"

src/middleware.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use conduit_conditional_get::ConditionalGet;
3232
use conduit_cookie::{Middleware as Cookie, SessionMiddleware};
3333
use conduit_middleware::MiddlewareBuilder;
3434
use conduit_router::RouteBuilder;
35+
use sentry_conduit::SentryMiddleware;
3536

3637
use std::env;
3738
use std::sync::Arc;
@@ -46,6 +47,7 @@ pub fn build_middleware(app: Arc<App>, endpoints: RouteBuilder) -> MiddlewareBui
4647
if env != Env::Test {
4748
m.add(ensure_well_formed_500::EnsureWellFormed500);
4849
m.add(log_request::LogRequests::default());
50+
m.around(SentryMiddleware::default());
4951
}
5052

5153
if env == Env::Development {

src/middleware/log_request.rs

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@
44
use super::prelude::*;
55
use crate::util::request_header;
66

7-
use conduit::{header, Host, RequestExt, Scheme, StatusCode};
7+
use conduit::{header, RequestExt, StatusCode};
88
use conduit_cookie::RequestSession;
9-
use sentry::Level;
109

1110
use std::fmt::{self, Display, Formatter};
1211
use std::time::{SystemTime, UNIX_EPOCH};
1312

1413
const SLOW_REQUEST_THRESHOLD_MS: u64 = 1000;
1514

16-
const FILTERED_HEADERS: &[&str] = &["Authorization", "Cookie", "X-Real-Ip", "X-Forwarded-For"];
17-
1815
#[derive(Default)]
1916
pub(super) struct LogRequests();
2017

@@ -92,28 +89,7 @@ pub fn add_custom_metadata<V: Display>(req: &mut dyn RequestExt, key: &'static s
9289
}
9390

9491
fn report_to_sentry(req: &dyn RequestExt, res: &AfterResult, response_time: u64) {
95-
let (message, level) = match res {
96-
Err(e) => (e.to_string(), Level::Error),
97-
Ok(_) => return,
98-
};
99-
100-
let config = |scope: &mut sentry::Scope| {
101-
let method = Some(req.method().as_str().to_owned());
102-
103-
let scheme = match req.scheme() {
104-
Scheme::Http => "http",
105-
Scheme::Https => "https",
106-
};
107-
108-
let host = match req.host() {
109-
Host::Name(name) => name.to_owned(),
110-
Host::Socket(addr) => addr.to_string(),
111-
};
112-
113-
let path = &req.extensions().find::<OriginalPath>().unwrap().0;
114-
115-
let url = format!("{}://{}{}", scheme, host, path).parse().ok();
116-
92+
sentry::configure_scope(|scope| {
11793
{
11894
let id = req.session().get("user_id").map(|str| str.to_string());
11995

@@ -125,29 +101,6 @@ fn report_to_sentry(req: &dyn RequestExt, res: &AfterResult, response_time: u64)
125101
scope.set_user(Some(user));
126102
}
127103

128-
{
129-
let headers = req
130-
.headers()
131-
.iter()
132-
.filter(|(k, _v)| !FILTERED_HEADERS.iter().any(|name| k == name))
133-
.map(|(k, v)| (k.to_string(), v.to_str().unwrap_or_default().to_string()))
134-
.collect();
135-
136-
let sentry_req = sentry::protocol::Request {
137-
url,
138-
method,
139-
headers,
140-
..Default::default()
141-
};
142-
143-
scope.add_event_processor(Box::new(move |mut event| {
144-
if event.request.is_none() {
145-
event.request = Some(sentry_req.clone());
146-
}
147-
Some(event)
148-
}));
149-
}
150-
151104
if let Some(request_id) = req
152105
.headers()
153106
.get("x-request-id")
@@ -172,9 +125,7 @@ fn report_to_sentry(req: &dyn RequestExt, res: &AfterResult, response_time: u64)
172125
scope.set_extra(key, value.to_string().into());
173126
}
174127
}
175-
};
176-
177-
sentry::with_scope(config, || sentry::capture_message(&message, level));
128+
});
178129
}
179130

180131
#[cfg(test)]

src/sentry.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ pub fn init() -> ClientInitGuard {
2323
let release = dotenv::var("HEROKU_SLUG_COMMIT").ok().map(Into::into);
2424

2525
let opts = ClientOptions {
26+
auto_session_tracking: true,
2627
dsn,
2728
environment,
2829
release,
30+
session_mode: sentry::SessionMode::Request,
2931
..Default::default()
3032
};
3133

0 commit comments

Comments
 (0)