mirror of https://github.com/buster-so/buster.git
removed sentry and set it up better
This commit is contained in:
parent
2649fb7656
commit
67932cfe39
|
@ -74,7 +74,8 @@ redis = { version = "0.27.5", features = [
|
||||||
"tls-rustls-webpki-roots",
|
"tls-rustls-webpki-roots",
|
||||||
] }
|
] }
|
||||||
resend-rs = "0.10.0"
|
resend-rs = "0.10.0"
|
||||||
sentry = { version = "0.35.0", features = ["tokio", "sentry-tracing"] }
|
sentry = { version = "0.37.0", features = ["tokio", "sentry-tracing"] }
|
||||||
|
sentry-tower = { version = "0.37.0", features = ["axum", "http"] }
|
||||||
serde_urlencoded = "0.7.1"
|
serde_urlencoded = "0.7.1"
|
||||||
snowflake-api = "0.11.0"
|
snowflake-api = "0.11.0"
|
||||||
tempfile = "3.10.1"
|
tempfile = "3.10.1"
|
||||||
|
@ -89,6 +90,7 @@ tiberius = { version = "0.12.2", default-features = false, features = [
|
||||||
tiktoken-rs = "0.6.0"
|
tiktoken-rs = "0.6.0"
|
||||||
tokio-stream = "0.1.15"
|
tokio-stream = "0.1.15"
|
||||||
tokio-util = { version = "0.7.11", features = ["compat"] }
|
tokio-util = { version = "0.7.11", features = ["compat"] }
|
||||||
|
tower = { version = "0.5.2" }
|
||||||
tower-http = { version = "0.6.2", features = [
|
tower-http = { version = "0.6.2", features = [
|
||||||
"cors",
|
"cors",
|
||||||
"trace",
|
"trace",
|
||||||
|
@ -106,5 +108,5 @@ incremental = true
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
incremental = true
|
incremental = true
|
||||||
opt-level = 0 # Ensure this is 0 for faster debug builds
|
opt-level = 0 # Ensure this is 0 for faster debug builds
|
||||||
debug = 1 # Reduce debug info slightly while keeping enough for backtraces
|
debug = 1 # Reduce debug info slightly while keeping enough for backtraces
|
||||||
|
|
|
@ -39,6 +39,7 @@ resend-rs = { workspace = true }
|
||||||
rustls = { workspace = true }
|
rustls = { workspace = true }
|
||||||
rustls-native-certs = { workspace = true }
|
rustls-native-certs = { workspace = true }
|
||||||
sentry = { workspace = true }
|
sentry = { workspace = true }
|
||||||
|
sentry-tower = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
serde_urlencoded = { workspace = true }
|
serde_urlencoded = { workspace = true }
|
||||||
|
@ -53,6 +54,7 @@ tokio-postgres = { workspace = true }
|
||||||
tokio-postgres-rustls = { workspace = true }
|
tokio-postgres-rustls = { workspace = true }
|
||||||
tokio-stream = { workspace = true }
|
tokio-stream = { workspace = true }
|
||||||
tokio-util = { workspace = true }
|
tokio-util = { workspace = true }
|
||||||
|
tower = { workspace = true }
|
||||||
tower-http = { workspace = true }
|
tower-http = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-subscriber = { workspace = true }
|
tracing-subscriber = { workspace = true }
|
||||||
|
|
|
@ -4,7 +4,7 @@ pub mod utils;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use axum::{Extension, Router};
|
use axum::{Extension, Router, extract::Request};
|
||||||
use middleware::cors::cors;
|
use middleware::cors::cors;
|
||||||
use database::{self, pool::init_pools};
|
use database::{self, pool::init_pools};
|
||||||
use diesel::{Connection, PgConnection};
|
use diesel::{Connection, PgConnection};
|
||||||
|
@ -12,6 +12,7 @@ use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use rustls::crypto::ring;
|
use rustls::crypto::ring;
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
|
use tower::ServiceBuilder;
|
||||||
use tower_http::{compression::CompressionLayer, trace::TraceLayer};
|
use tower_http::{compression::CompressionLayer, trace::TraceLayer};
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
|
||||||
|
|
||||||
|
@ -23,16 +24,26 @@ async fn main() {
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
|
|
||||||
let environment = env::var("ENVIRONMENT").unwrap_or_else(|_| "development".to_string());
|
let environment = env::var("ENVIRONMENT").unwrap_or_else(|_| "development".to_string());
|
||||||
|
let is_development = environment == "development";
|
||||||
|
|
||||||
ring::default_provider()
|
ring::default_provider()
|
||||||
.install_default()
|
.install_default()
|
||||||
.expect("Failed to install default crypto provider");
|
.expect("Failed to install default crypto provider");
|
||||||
|
|
||||||
let _guard = sentry::init(("https://a417fbed1de30d2714a8afbe38d5bc1b@o4505360096428032.ingest.us.sentry.io/4507360721043456", sentry::ClientOptions {
|
// Only initialize Sentry if not in development environment
|
||||||
release: sentry::release_name!(),
|
let _guard = if !is_development {
|
||||||
environment: Some(environment.into()),
|
Some(sentry::init((
|
||||||
..Default::default()
|
"https://a417fbed1de30d2714a8afbe38d5bc1b@o4505360096428032.ingest.us.sentry.io/4507360721043456",
|
||||||
}));
|
sentry::ClientOptions {
|
||||||
|
release: sentry::release_name!(),
|
||||||
|
environment: Some(environment.clone().into()),
|
||||||
|
traces_sample_rate: 1.0,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
.with(
|
.with(
|
||||||
|
@ -67,6 +78,7 @@ async fn main() {
|
||||||
let (shutdown_tx, _) = broadcast::channel::<()>(1);
|
let (shutdown_tx, _) = broadcast::channel::<()>(1);
|
||||||
let shutdown_tx = Arc::new(shutdown_tx);
|
let shutdown_tx = Arc::new(shutdown_tx);
|
||||||
|
|
||||||
|
// Build the router with or without Sentry layers based on environment
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.merge(protected_router)
|
.merge(protected_router)
|
||||||
.merge(public_router)
|
.merge(public_router)
|
||||||
|
@ -75,6 +87,17 @@ async fn main() {
|
||||||
.layer(CompressionLayer::new())
|
.layer(CompressionLayer::new())
|
||||||
.layer(Extension(shutdown_tx.clone()));
|
.layer(Extension(shutdown_tx.clone()));
|
||||||
|
|
||||||
|
// Add Sentry layers if not in development
|
||||||
|
let app = if !is_development {
|
||||||
|
app.layer(
|
||||||
|
ServiceBuilder::new()
|
||||||
|
.layer(sentry_tower::NewSentryLayer::<Request>::new_from_top())
|
||||||
|
.layer(sentry_tower::SentryHttpLayer::with_transaction())
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
app
|
||||||
|
};
|
||||||
|
|
||||||
let port_number: u16 = env::var("PORT")
|
let port_number: u16 = env::var("PORT")
|
||||||
.unwrap_or_else(|_| "3001".to_string())
|
.unwrap_or_else(|_| "3001".to_string())
|
||||||
.parse()
|
.parse()
|
||||||
|
|
|
@ -7,7 +7,7 @@ use handlers::organizations::{
|
||||||
update_organization_handler,
|
update_organization_handler,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{routes::rest::ApiResponse, utils::clients::sentry_utils::send_sentry_error};
|
use crate::routes::rest::ApiResponse;
|
||||||
use middleware::AuthenticatedUser;
|
use middleware::AuthenticatedUser;
|
||||||
|
|
||||||
pub async fn update_organization(
|
pub async fn update_organization(
|
||||||
|
@ -27,7 +27,6 @@ pub async fn update_organization(
|
||||||
Ok(organization) => organization,
|
Ok(organization) => organization,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Error updating organization: {:?}", e);
|
tracing::error!("Error updating organization: {:?}", e);
|
||||||
send_sentry_error(&e.to_string(), Some(&user.id));
|
|
||||||
|
|
||||||
if e.to_string().contains("not a workspace admin") {
|
if e.to_string().contains("not a workspace admin") {
|
||||||
return Err((StatusCode::FORBIDDEN, "User is not a workspace admin"));
|
return Err((StatusCode::FORBIDDEN, "User is not a workspace admin"));
|
||||||
|
|
|
@ -11,7 +11,7 @@ use database::{
|
||||||
schema::{users, users_to_organizations},
|
schema::{users, users_to_organizations},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{routes::rest::ApiResponse, utils::clients::sentry_utils::send_sentry_error};
|
use crate::routes::rest::ApiResponse;
|
||||||
use middleware::AuthenticatedUser;
|
use middleware::AuthenticatedUser;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
|
@ -31,7 +31,6 @@ pub async fn list_organization_users(
|
||||||
Ok(users) => users,
|
Ok(users) => users,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Error listing organization users: {:?}", e);
|
tracing::error!("Error listing organization users: {:?}", e);
|
||||||
send_sentry_error(&e.to_string(), Some(&user.id));
|
|
||||||
return Err((
|
return Err((
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
"Error listing organization users",
|
"Error listing organization users",
|
||||||
|
|
|
@ -9,7 +9,6 @@ use database::schema::{
|
||||||
organizations, teams, teams_to_users, users, users_to_organizations,
|
organizations, teams, teams_to_users, users, users_to_organizations,
|
||||||
};
|
};
|
||||||
use crate::routes::rest::ApiResponse;
|
use crate::routes::rest::ApiResponse;
|
||||||
use crate::utils::clients::sentry_utils::send_sentry_error;
|
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use diesel::{
|
use diesel::{
|
||||||
BoolExpressionMethods, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl,
|
BoolExpressionMethods, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl,
|
||||||
|
@ -25,7 +24,6 @@ pub async fn get_user(
|
||||||
Ok(user_info_object) => user_info_object,
|
Ok(user_info_object) => user_info_object,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Error getting user information: {:?}", e);
|
tracing::error!("Error getting user information: {:?}", e);
|
||||||
send_sentry_error(&e.to_string(), Some(&user.id));
|
|
||||||
return Err((
|
return Err((
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
"Error getting user information",
|
"Error getting user information",
|
||||||
|
|
|
@ -13,7 +13,7 @@ use database::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{routes::rest::ApiResponse, utils::clients::sentry_utils::send_sentry_error};
|
use crate::routes::rest::ApiResponse;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use diesel::{
|
use diesel::{
|
||||||
BoolExpressionMethods, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl,
|
BoolExpressionMethods, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl,
|
||||||
|
@ -54,7 +54,6 @@ pub async fn get_user_by_id(
|
||||||
Ok(user_info) => user_info,
|
Ok(user_info) => user_info,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Error getting user information: {:?}", e);
|
tracing::error!("Error getting user information: {:?}", e);
|
||||||
send_sentry_error(&e.to_string(), Some(&user.id));
|
|
||||||
return Err((
|
return Err((
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
"Error getting user information",
|
"Error getting user information",
|
||||||
|
|
|
@ -2,19 +2,18 @@ use anyhow::Result;
|
||||||
use axum::extract::Path;
|
use axum::extract::Path;
|
||||||
use axum::{Extension, Json};
|
use axum::{Extension, Json};
|
||||||
|
|
||||||
|
use crate::routes::rest::ApiResponse;
|
||||||
|
use crate::utils::security::checks::is_user_workspace_admin_or_data_admin;
|
||||||
|
use axum::http::StatusCode;
|
||||||
use database::enums::UserOrganizationStatus;
|
use database::enums::UserOrganizationStatus;
|
||||||
|
use database::organization::get_user_organization_id;
|
||||||
use database::schema::{users, users_to_organizations};
|
use database::schema::{users, users_to_organizations};
|
||||||
use database::{enums::UserOrganizationRole, pool::get_pg_pool};
|
use database::{enums::UserOrganizationRole, pool::get_pg_pool};
|
||||||
use crate::routes::rest::ApiResponse;
|
|
||||||
use crate::utils::clients::sentry_utils::send_sentry_error;
|
|
||||||
use crate::utils::security::checks::is_user_workspace_admin_or_data_admin;
|
|
||||||
use database::organization::get_user_organization_id;
|
|
||||||
use axum::http::StatusCode;
|
|
||||||
use diesel::{update, ExpressionMethods};
|
use diesel::{update, ExpressionMethods};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
|
use middleware::AuthenticatedUser;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use middleware::AuthenticatedUser;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct UserResponse {
|
pub struct UserResponse {
|
||||||
|
@ -40,7 +39,6 @@ pub async fn update_user(
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Error getting user information: {:?}", e);
|
tracing::error!("Error getting user information: {:?}", e);
|
||||||
send_sentry_error(&e.to_string(), Some(&user.id));
|
|
||||||
return Err((
|
return Err((
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
"Error getting user information",
|
"Error getting user information",
|
||||||
|
@ -120,7 +118,7 @@ pub async fn update_user_handler(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
Ok(false) => return Err(anyhow::anyhow!("Insufficient permissions to update role")),
|
Ok(false) => return Err(anyhow::anyhow!("Insufficient permissions to update role")),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Error checking user permissions for role update: {:?}", e);
|
tracing::error!("Error checking user permissions for role update: {:?}", e);
|
||||||
|
|
|
@ -5,8 +5,6 @@ use html_escape::encode_text as escape_html;
|
||||||
|
|
||||||
use resend_rs::{types::CreateEmailBaseOptions, Resend};
|
use resend_rs::{types::CreateEmailBaseOptions, Resend};
|
||||||
|
|
||||||
use crate::utils::clients::sentry_utils::send_sentry_error;
|
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref RESEND_API_KEY: String = env::var("RESEND_API_KEY").expect("RESEND_API_KEY must be set");
|
static ref RESEND_API_KEY: String = env::var("RESEND_API_KEY").expect("RESEND_API_KEY must be set");
|
||||||
static ref RESEND_CLIENT: Resend = Resend::new(&RESEND_API_KEY);
|
static ref RESEND_CLIENT: Resend = Resend::new(&RESEND_API_KEY);
|
||||||
|
@ -86,7 +84,6 @@ pub async fn send_email(to_addresses: HashSet<String>, email_type: EmailType) ->
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("Error sending email: {e}");
|
tracing::error!("Error sending email: {e}");
|
||||||
send_sentry_error(&format!("Error sending email: {e}"), None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
pub mod email;
|
pub mod email;
|
||||||
pub mod sentry_utils;
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
use std::time::SystemTime;
|
|
||||||
|
|
||||||
use sentry::{capture_event, protocol::Event, User};
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
pub fn send_sentry_error(message: &String, user_id: Option<&Uuid>) {
|
|
||||||
let user: Option<User> = match user_id {
|
|
||||||
Some(id) => Some(User {
|
|
||||||
id: Some(id.to_string()),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let event = Event {
|
|
||||||
message: Some(message.to_string()),
|
|
||||||
level: sentry::Level::Error,
|
|
||||||
event_id: Uuid::new_v4(),
|
|
||||||
timestamp: SystemTime::now(),
|
|
||||||
user,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
capture_event(event);
|
|
||||||
}
|
|
Loading…
Reference in New Issue