fix sentry logging (#982)

This commit is contained in:
Gabriel Gordon-Hall
2025-10-09 11:45:23 +01:00
committed by GitHub
parent f2cc538a8f
commit e52ced99e0
12 changed files with 86 additions and 75 deletions

View File

@@ -30,13 +30,12 @@ use services::services::{
git::{GitService, GitServiceError},
image::{ImageError, ImageService},
pr_monitor::PrMonitorService,
sentry::SentryService,
worktree_manager::WorktreeError,
};
use sqlx::{Error as SqlxError, types::Uuid};
use thiserror::Error;
use tokio::sync::RwLock;
use utils::msg_store::MsgStore;
use utils::{msg_store::MsgStore, sentry as sentry_utils};
#[derive(Debug, Error)]
pub enum DeploymentError {
@@ -82,8 +81,6 @@ pub trait Deployment: Clone + Send + Sync + 'static {
fn config(&self) -> &Arc<RwLock<Config>>;
fn sentry(&self) -> &SentryService;
fn db(&self) -> &DBService;
fn analytics(&self) -> &Option<AnalyticsService>;
@@ -113,8 +110,7 @@ pub trait Deployment: Clone + Send + Sync + 'static {
let config = self.config().read().await;
let username = config.github.username.as_deref();
let email = config.github.primary_email.as_deref();
self.sentry().update_scope(user_id, username, email).await;
sentry_utils::configure_user_scope(user_id, username, email);
Ok(())
}

View File

@@ -31,8 +31,6 @@ regex = "1.11.1"
notify-rust = "4.11"
notify = "8.2.0"
notify-debouncer-full = "0.5.0"
sentry = { version = "0.41.0", features = ["anyhow", "backtrace", "panic", "debug-images"] }
sentry-tracing = { version = "0.41.0", features = ["backtrace"] }
reqwest = { version = "0.12", features = ["json"] }
futures = "0.3"
async-stream = "0.3"

View File

@@ -16,21 +16,18 @@ use services::services::{
filesystem::FilesystemService,
git::GitService,
image::ImageService,
sentry::SentryService,
};
use tokio::sync::RwLock;
use utils::{assets::config_path, msg_store::MsgStore};
use uuid::Uuid;
use crate::container::LocalContainerService;
mod command;
pub mod container;
#[derive(Clone)]
pub struct LocalDeployment {
config: Arc<RwLock<Config>>,
sentry: SentryService,
user_id: String,
db: DBService,
analytics: Option<AnalyticsService>,
@@ -74,7 +71,6 @@ impl Deployment for LocalDeployment {
save_config_to_file(&raw_config, &config_path()).await?;
let config = Arc::new(RwLock::new(raw_config));
let sentry = SentryService::new();
let user_id = generate_user_id();
let analytics = AnalyticsConfig::new().map(AnalyticsService::new);
let git = GitService::new();
@@ -131,7 +127,6 @@ impl Deployment for LocalDeployment {
Ok(Self {
config,
sentry,
user_id,
db,
analytics,
@@ -160,10 +155,6 @@ impl Deployment for LocalDeployment {
&self.config
}
fn sentry(&self) -> &SentryService {
&self.sentry
}
fn db(&self) -> &DBService {
&self.db
}

View File

@@ -34,8 +34,6 @@ rmcp = { version = "0.5.0", features = ["server", "transport-io"] }
schemars = { workspace = true }
regex = "1.11.1"
toml = "0.8"
sentry = { version = "0.41.0", features = ["anyhow", "backtrace", "panic", "debug-images"] }
sentry-tracing = { version = "0.41.0", features = ["backtrace"] }
reqwest = { version = "0.12", features = ["json"] }
strip-ansi-escapes = "0.2.1"
thiserror = { workspace = true }

View File

@@ -1,25 +1,13 @@
use rmcp::{ServiceExt, transport::stdio};
use server::mcp::task_server::TaskServer;
use tracing_subscriber::{EnvFilter, prelude::*};
use utils::{port_file::read_port_file, sentry::sentry_layer};
use utils::{
port_file::read_port_file,
sentry::{self as sentry_utils, SentrySource, sentry_layer},
};
fn main() -> anyhow::Result<()> {
let environment = if cfg!(debug_assertions) {
"dev"
} else {
"production"
};
let _guard = sentry::init((
"https://1065a1d276a581316999a07d5dffee26@o4509603705192449.ingest.de.sentry.io/4509605576441937",
sentry::ClientOptions {
release: sentry::release_name!(),
environment: Some(environment.into()),
..Default::default()
},
));
sentry::configure_scope(|scope| {
scope.set_tag("source", "mcp");
});
sentry_utils::init_once(SentrySource::Mcp);
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
@@ -67,9 +55,9 @@ fn main() -> anyhow::Result<()> {
let service = TaskServer::new(&base_url)
.serve(stdio())
.await
.inspect_err(|e| {
.map_err(|e| {
tracing::error!("serving error: {:?}", e);
sentry::capture_error(e);
e
})?;
service.waiting().await?;

View File

@@ -6,7 +6,10 @@ use strip_ansi_escapes::strip;
use thiserror::Error;
use tracing_subscriber::{EnvFilter, prelude::*};
use utils::{
assets::asset_dir, browser::open_browser, port_file::write_port_file, sentry::sentry_layer,
assets::asset_dir,
browser::open_browser,
port_file::write_port_file,
sentry::{self as sentry_utils, SentrySource, sentry_layer},
};
#[derive(Debug, Error)]
@@ -23,6 +26,8 @@ pub enum VibeKanbanError {
#[tokio::main]
async fn main() -> Result<(), VibeKanbanError> {
sentry_utils::init_once(SentrySource::Backend);
let log_level = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string());
let filter_string = format!(
"warn,server={level},services={level},db={level},executors={level},deployment={level},local_deployment={level},utils={level}",

View File

@@ -1,5 +1,6 @@
use axum::{
Router,
middleware::from_fn_with_state,
routing::{IntoMakeService, get},
};
@@ -39,6 +40,10 @@ pub fn router(deployment: DeploymentImpl) -> IntoMakeService<Router> {
.merge(events::router(&deployment))
.merge(approvals::router())
.nest("/images", images::routes())
.layer(from_fn_with_state(
deployment.clone(),
auth::sentry_user_context_middleware,
))
.with_state(deployment);
Router::new()

View File

@@ -39,8 +39,6 @@ regex = "1.11.1"
notify-rust = "4.11"
octocrab = "0.44"
os_info = "3.12.0"
sentry = { version = "0.41.0", features = ["anyhow", "backtrace", "panic", "debug-images"] }
sentry-tracing = { version = "0.41.0", features = ["backtrace"] }
reqwest = { version = "0.12", features = ["json"] }
lazy_static = "1.4"
futures-util = "0.3"

View File

@@ -16,5 +16,4 @@ pub mod github_service;
pub mod image;
pub mod notification;
pub mod pr_monitor;
pub mod sentry;
pub mod worktree_manager;

View File

@@ -1,33 +0,0 @@
#[derive(Clone)]
pub struct SentryService {}
impl Default for SentryService {
fn default() -> Self {
Self::new()
}
}
impl SentryService {
pub fn new() -> Self {
SentryService {}
}
pub async fn update_scope(&self, user_id: &str, username: Option<&str>, email: Option<&str>) {
let sentry_user = match (username, email) {
(Some(user), Some(email)) => sentry::User {
id: Some(user_id.to_string()),
username: Some(user.to_string()),
email: Some(email.to_string()),
..Default::default()
},
_ => sentry::User {
id: Some(user_id.to_string()),
..Default::default()
},
};
sentry::configure_scope(|scope| {
scope.set_user(Some(sentry_user));
});
}
}

View File

@@ -19,6 +19,7 @@ rust-embed = "8.2"
directories = "6.0.0"
open = "5.3.2"
regex = "1.11.1"
sentry = { version = "0.41.0", features = ["anyhow", "backtrace", "panic", "debug-images"] }
sentry-tracing = { version = "0.41.0", features = ["backtrace"] }
lazy_static = "1.4"
futures-util = "0.3"

View File

@@ -1,6 +1,71 @@
use std::sync::OnceLock;
use sentry_tracing::{EventFilter, SentryLayer};
use tracing::Level;
const SENTRY_DSN: &str = "https://1065a1d276a581316999a07d5dffee26@o4509603705192449.ingest.de.sentry.io/4509605576441937";
static INIT_GUARD: OnceLock<sentry::ClientInitGuard> = OnceLock::new();
#[derive(Clone, Copy, Debug)]
pub enum SentrySource {
Backend,
Mcp,
}
impl SentrySource {
fn tag(self) -> &'static str {
match self {
SentrySource::Backend => "backend",
SentrySource::Mcp => "mcp",
}
}
}
fn environment() -> &'static str {
if cfg!(debug_assertions) {
"dev"
} else {
"production"
}
}
pub fn init_once(source: SentrySource) {
INIT_GUARD.get_or_init(|| {
sentry::init((
SENTRY_DSN,
sentry::ClientOptions {
release: sentry::release_name!(),
environment: Some(environment().into()),
..Default::default()
},
))
});
sentry::configure_scope(|scope| {
scope.set_tag("source", source.tag());
});
}
pub fn configure_user_scope(user_id: &str, username: Option<&str>, email: Option<&str>) {
let mut sentry_user = sentry::User {
id: Some(user_id.to_string()),
..Default::default()
};
if let Some(username) = username {
sentry_user.username = Some(username.to_string());
}
if let Some(email) = email {
sentry_user.email = Some(email.to_string());
}
sentry::configure_scope(|scope| {
scope.set_user(Some(sentry_user));
});
}
pub fn sentry_layer<S>() -> SentryLayer<S>
where
S: tracing::Subscriber,