fix sentry logging (#982)
This commit is contained in:
committed by
GitHub
parent
f2cc538a8f
commit
e52ced99e0
@@ -30,13 +30,12 @@ use services::services::{
|
|||||||
git::{GitService, GitServiceError},
|
git::{GitService, GitServiceError},
|
||||||
image::{ImageError, ImageService},
|
image::{ImageError, ImageService},
|
||||||
pr_monitor::PrMonitorService,
|
pr_monitor::PrMonitorService,
|
||||||
sentry::SentryService,
|
|
||||||
worktree_manager::WorktreeError,
|
worktree_manager::WorktreeError,
|
||||||
};
|
};
|
||||||
use sqlx::{Error as SqlxError, types::Uuid};
|
use sqlx::{Error as SqlxError, types::Uuid};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use utils::msg_store::MsgStore;
|
use utils::{msg_store::MsgStore, sentry as sentry_utils};
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum DeploymentError {
|
pub enum DeploymentError {
|
||||||
@@ -82,8 +81,6 @@ pub trait Deployment: Clone + Send + Sync + 'static {
|
|||||||
|
|
||||||
fn config(&self) -> &Arc<RwLock<Config>>;
|
fn config(&self) -> &Arc<RwLock<Config>>;
|
||||||
|
|
||||||
fn sentry(&self) -> &SentryService;
|
|
||||||
|
|
||||||
fn db(&self) -> &DBService;
|
fn db(&self) -> &DBService;
|
||||||
|
|
||||||
fn analytics(&self) -> &Option<AnalyticsService>;
|
fn analytics(&self) -> &Option<AnalyticsService>;
|
||||||
@@ -113,8 +110,7 @@ pub trait Deployment: Clone + Send + Sync + 'static {
|
|||||||
let config = self.config().read().await;
|
let config = self.config().read().await;
|
||||||
let username = config.github.username.as_deref();
|
let username = config.github.username.as_deref();
|
||||||
let email = config.github.primary_email.as_deref();
|
let email = config.github.primary_email.as_deref();
|
||||||
|
sentry_utils::configure_user_scope(user_id, username, email);
|
||||||
self.sentry().update_scope(user_id, username, email).await;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ regex = "1.11.1"
|
|||||||
notify-rust = "4.11"
|
notify-rust = "4.11"
|
||||||
notify = "8.2.0"
|
notify = "8.2.0"
|
||||||
notify-debouncer-full = "0.5.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"] }
|
reqwest = { version = "0.12", features = ["json"] }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
async-stream = "0.3"
|
async-stream = "0.3"
|
||||||
|
|||||||
@@ -16,21 +16,18 @@ use services::services::{
|
|||||||
filesystem::FilesystemService,
|
filesystem::FilesystemService,
|
||||||
git::GitService,
|
git::GitService,
|
||||||
image::ImageService,
|
image::ImageService,
|
||||||
sentry::SentryService,
|
|
||||||
};
|
};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use utils::{assets::config_path, msg_store::MsgStore};
|
use utils::{assets::config_path, msg_store::MsgStore};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::container::LocalContainerService;
|
use crate::container::LocalContainerService;
|
||||||
|
|
||||||
mod command;
|
mod command;
|
||||||
pub mod container;
|
pub mod container;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LocalDeployment {
|
pub struct LocalDeployment {
|
||||||
config: Arc<RwLock<Config>>,
|
config: Arc<RwLock<Config>>,
|
||||||
sentry: SentryService,
|
|
||||||
user_id: String,
|
user_id: String,
|
||||||
db: DBService,
|
db: DBService,
|
||||||
analytics: Option<AnalyticsService>,
|
analytics: Option<AnalyticsService>,
|
||||||
@@ -74,7 +71,6 @@ impl Deployment for LocalDeployment {
|
|||||||
save_config_to_file(&raw_config, &config_path()).await?;
|
save_config_to_file(&raw_config, &config_path()).await?;
|
||||||
|
|
||||||
let config = Arc::new(RwLock::new(raw_config));
|
let config = Arc::new(RwLock::new(raw_config));
|
||||||
let sentry = SentryService::new();
|
|
||||||
let user_id = generate_user_id();
|
let user_id = generate_user_id();
|
||||||
let analytics = AnalyticsConfig::new().map(AnalyticsService::new);
|
let analytics = AnalyticsConfig::new().map(AnalyticsService::new);
|
||||||
let git = GitService::new();
|
let git = GitService::new();
|
||||||
@@ -131,7 +127,6 @@ impl Deployment for LocalDeployment {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
config,
|
config,
|
||||||
sentry,
|
|
||||||
user_id,
|
user_id,
|
||||||
db,
|
db,
|
||||||
analytics,
|
analytics,
|
||||||
@@ -160,10 +155,6 @@ impl Deployment for LocalDeployment {
|
|||||||
&self.config
|
&self.config
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sentry(&self) -> &SentryService {
|
|
||||||
&self.sentry
|
|
||||||
}
|
|
||||||
|
|
||||||
fn db(&self) -> &DBService {
|
fn db(&self) -> &DBService {
|
||||||
&self.db
|
&self.db
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ rmcp = { version = "0.5.0", features = ["server", "transport-io"] }
|
|||||||
schemars = { workspace = true }
|
schemars = { workspace = true }
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
toml = "0.8"
|
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"] }
|
reqwest = { version = "0.12", features = ["json"] }
|
||||||
strip-ansi-escapes = "0.2.1"
|
strip-ansi-escapes = "0.2.1"
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
|
|||||||
@@ -1,25 +1,13 @@
|
|||||||
use rmcp::{ServiceExt, transport::stdio};
|
use rmcp::{ServiceExt, transport::stdio};
|
||||||
use server::mcp::task_server::TaskServer;
|
use server::mcp::task_server::TaskServer;
|
||||||
use tracing_subscriber::{EnvFilter, prelude::*};
|
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<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let environment = if cfg!(debug_assertions) {
|
sentry_utils::init_once(SentrySource::Mcp);
|
||||||
"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");
|
|
||||||
});
|
|
||||||
tokio::runtime::Builder::new_multi_thread()
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
.build()
|
.build()
|
||||||
@@ -67,9 +55,9 @@ fn main() -> anyhow::Result<()> {
|
|||||||
let service = TaskServer::new(&base_url)
|
let service = TaskServer::new(&base_url)
|
||||||
.serve(stdio())
|
.serve(stdio())
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| {
|
.map_err(|e| {
|
||||||
tracing::error!("serving error: {:?}", e);
|
tracing::error!("serving error: {:?}", e);
|
||||||
sentry::capture_error(e);
|
e
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
service.waiting().await?;
|
service.waiting().await?;
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ use strip_ansi_escapes::strip;
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tracing_subscriber::{EnvFilter, prelude::*};
|
use tracing_subscriber::{EnvFilter, prelude::*};
|
||||||
use utils::{
|
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)]
|
#[derive(Debug, Error)]
|
||||||
@@ -23,6 +26,8 @@ pub enum VibeKanbanError {
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), VibeKanbanError> {
|
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 log_level = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string());
|
||||||
let filter_string = format!(
|
let filter_string = format!(
|
||||||
"warn,server={level},services={level},db={level},executors={level},deployment={level},local_deployment={level},utils={level}",
|
"warn,server={level},services={level},db={level},executors={level},deployment={level},local_deployment={level},utils={level}",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use axum::{
|
use axum::{
|
||||||
Router,
|
Router,
|
||||||
|
middleware::from_fn_with_state,
|
||||||
routing::{IntoMakeService, get},
|
routing::{IntoMakeService, get},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,6 +40,10 @@ pub fn router(deployment: DeploymentImpl) -> IntoMakeService<Router> {
|
|||||||
.merge(events::router(&deployment))
|
.merge(events::router(&deployment))
|
||||||
.merge(approvals::router())
|
.merge(approvals::router())
|
||||||
.nest("/images", images::routes())
|
.nest("/images", images::routes())
|
||||||
|
.layer(from_fn_with_state(
|
||||||
|
deployment.clone(),
|
||||||
|
auth::sentry_user_context_middleware,
|
||||||
|
))
|
||||||
.with_state(deployment);
|
.with_state(deployment);
|
||||||
|
|
||||||
Router::new()
|
Router::new()
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ regex = "1.11.1"
|
|||||||
notify-rust = "4.11"
|
notify-rust = "4.11"
|
||||||
octocrab = "0.44"
|
octocrab = "0.44"
|
||||||
os_info = "3.12.0"
|
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"] }
|
reqwest = { version = "0.12", features = ["json"] }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
|
|||||||
@@ -16,5 +16,4 @@ pub mod github_service;
|
|||||||
pub mod image;
|
pub mod image;
|
||||||
pub mod notification;
|
pub mod notification;
|
||||||
pub mod pr_monitor;
|
pub mod pr_monitor;
|
||||||
pub mod sentry;
|
|
||||||
pub mod worktree_manager;
|
pub mod worktree_manager;
|
||||||
|
|||||||
@@ -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));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,6 +19,7 @@ rust-embed = "8.2"
|
|||||||
directories = "6.0.0"
|
directories = "6.0.0"
|
||||||
open = "5.3.2"
|
open = "5.3.2"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
|
sentry = { version = "0.41.0", features = ["anyhow", "backtrace", "panic", "debug-images"] }
|
||||||
sentry-tracing = { version = "0.41.0", features = ["backtrace"] }
|
sentry-tracing = { version = "0.41.0", features = ["backtrace"] }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
|
|||||||
@@ -1,6 +1,71 @@
|
|||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use sentry_tracing::{EventFilter, SentryLayer};
|
use sentry_tracing::{EventFilter, SentryLayer};
|
||||||
use tracing::Level;
|
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>
|
pub fn sentry_layer<S>() -> SentryLayer<S>
|
||||||
where
|
where
|
||||||
S: tracing::Subscriber,
|
S: tracing::Subscriber,
|
||||||
|
|||||||
Reference in New Issue
Block a user