first pass at request scoped tracing
This commit is contained in:
parent
0e8a523145
commit
804292379f
|
@ -88,8 +88,8 @@ pub enum Error {
|
||||||
#[error("invalid webmention: {0}")]
|
#[error("invalid webmention: {0}")]
|
||||||
InvalidWebMention(String),
|
InvalidWebMention(String),
|
||||||
|
|
||||||
#[error("can't switch to the same fronter")]
|
#[error("can't switch to the same fronter {0}")]
|
||||||
SameFronter,
|
SameFronter(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T = ()> = std::result::Result<T, Error>;
|
pub type Result<T = ()> = std::result::Result<T, Error>;
|
||||||
|
@ -99,7 +99,7 @@ impl<'a> Responder<'a> for Error {
|
||||||
error!("{}", self);
|
error!("{}", self);
|
||||||
match self {
|
match self {
|
||||||
Error::NotFound => Err(Status::NotFound),
|
Error::NotFound => Err(Status::NotFound),
|
||||||
Error::InvalidWebMention(_) | Error::SameFronter => Err(Status::BadRequest),
|
Error::InvalidWebMention(_) | Error::SameFronter(_) => Err(Status::BadRequest),
|
||||||
_ => Err(Status::InternalServerError),
|
_ => Err(Status::InternalServerError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ pub fn switch(
|
||||||
.ok_or_else(|| Error::NotFound)?;
|
.ok_or_else(|| Error::NotFound)?;
|
||||||
|
|
||||||
if member.cmene == to.cmene {
|
if member.cmene == to.cmene {
|
||||||
return Err(Error::SameFronter);
|
return Err(Error::SameFronter(member.cmene));
|
||||||
}
|
}
|
||||||
|
|
||||||
let now = Utc::now().naive_utc();
|
let now = Utc::now().naive_utc();
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub const APPLICATION_NAME: &str = concat!(
|
||||||
pub mod api;
|
pub mod api;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod paseto;
|
pub mod paseto;
|
||||||
|
pub mod rocket_trace;
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
pub mod web;
|
pub mod web;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rocket_contrib::helmet::SpaceHelmet;
|
||||||
use rocket_cors::{AllowedHeaders, AllowedOrigins};
|
use rocket_cors::{AllowedHeaders, AllowedOrigins};
|
||||||
use rocket_prometheus::PrometheusMetrics;
|
use rocket_prometheus::PrometheusMetrics;
|
||||||
|
|
||||||
use ::mi::{api, paseto, web::*, MainDatabase, APPLICATION_NAME};
|
use ::mi::{api, paseto, rocket_trace::*, web::*, MainDatabase, APPLICATION_NAME};
|
||||||
|
|
||||||
#[get("/.within/botinfo")]
|
#[get("/.within/botinfo")]
|
||||||
fn botinfo() -> &'static str {
|
fn botinfo() -> &'static str {
|
||||||
|
@ -60,6 +60,7 @@ fn main() -> Result<()> {
|
||||||
.attach(cors)
|
.attach(cors)
|
||||||
.attach(MainDatabase::fairing())
|
.attach(MainDatabase::fairing())
|
||||||
.attach(SpaceHelmet::default())
|
.attach(SpaceHelmet::default())
|
||||||
|
.attach(TraceRequest {})
|
||||||
.attach(paseto::ed25519_keypair())
|
.attach(paseto::ed25519_keypair())
|
||||||
.attach(DiscordWebhook::fairing())
|
.attach(DiscordWebhook::fairing())
|
||||||
.attach(Mastodon::fairing())
|
.attach(Mastodon::fairing())
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
use rocket::fairing::{Fairing, Info, Kind};
|
||||||
|
use rocket::http::{ContentType, Header, Method, Status};
|
||||||
|
use rocket::{Data, Request, Response};
|
||||||
|
use rusty_ulid::generate_ulid_string;
|
||||||
|
use std::mem;
|
||||||
|
use tracing::{span, span::Entered, Level, Span};
|
||||||
|
|
||||||
|
struct SpanWrapper<'a> {
|
||||||
|
span: Box<Span>,
|
||||||
|
entered: Entered<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TraceRequest;
|
||||||
|
|
||||||
|
impl Fairing for TraceRequest {
|
||||||
|
fn info(&self) -> Info {
|
||||||
|
Info {
|
||||||
|
name: "Tracing spans per request",
|
||||||
|
kind: Kind::Request | Kind::Response,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_request(&self, request: &mut Request, _: &Data) {
|
||||||
|
let reqid: String = match request.headers().get_one("X-Request-Id") {
|
||||||
|
Some(reqid) => reqid.to_string(),
|
||||||
|
None => {
|
||||||
|
let reqid = generate_ulid_string();
|
||||||
|
request.add_header(Header::new("X-Request-Id", reqid.clone()));
|
||||||
|
reqid
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.local_cache(|| {
|
||||||
|
let span = span!(
|
||||||
|
Level::INFO,
|
||||||
|
"request",
|
||||||
|
method = &request.method().to_string()[..],
|
||||||
|
uri = &request.uri().to_string()[..],
|
||||||
|
addr = &request
|
||||||
|
.client_ip()
|
||||||
|
.map(|ip| ip.to_string())
|
||||||
|
.unwrap_or("unknown".to_string())[..],
|
||||||
|
request_id = &reqid[..],
|
||||||
|
);
|
||||||
|
let span = Box::new(span);
|
||||||
|
let entered = span.enter();
|
||||||
|
let entered_lt = unsafe { mem::transmute::<_, Entered<'static>>(entered) };
|
||||||
|
|
||||||
|
Box::new(SpanWrapper {
|
||||||
|
entered: entered_lt,
|
||||||
|
span: span,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_response(&self, request: &Request, response: &mut Response) {
|
||||||
|
let span: &Box<SpanWrapper> = request.local_cache(|| {
|
||||||
|
Box::new({
|
||||||
|
let span = error_span!(
|
||||||
|
"somehow the span wasn't put into the request, neat",
|
||||||
|
method = &request.method().to_string()[..],
|
||||||
|
uri = &request.uri().to_string()[..],
|
||||||
|
address = &request
|
||||||
|
.real_ip()
|
||||||
|
.map(|ip| ip.to_string())
|
||||||
|
.unwrap_or("unknown".to_string())[..],
|
||||||
|
);
|
||||||
|
|
||||||
|
let span = Box::new(span);
|
||||||
|
let entered = span.enter();
|
||||||
|
let entered_lt = unsafe { mem::transmute::<_, Entered<'static>>(entered) };
|
||||||
|
|
||||||
|
SpanWrapper {
|
||||||
|
entered: entered_lt,
|
||||||
|
span: span,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
match request.headers().get_one("X-Request-Id") {
|
||||||
|
Some(reqid) => {
|
||||||
|
response.set_header(Header::new("X-Request-Id", format!("{}", reqid)));
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
};
|
||||||
|
info!(
|
||||||
|
status_code = &response.status().code,
|
||||||
|
status_reason = response.status().reason
|
||||||
|
);
|
||||||
|
drop(span);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue