1
2use sentry::ClientInitGuard;
3use std::panic;
4use tokio::task;
5
6pub struct Config {
8 pub public_key: String,
9 pub project_id: String,
10}
11
12pub fn init(config: Config) -> ClientInitGuard {
22 let dsn = format!(
23 "https://{}@pulse.drcode.ai:443/{}",
24 config.public_key, config.project_id
25 );
26
27 let guard = sentry::init((
28 dsn,
29 sentry::ClientOptions {
30 release: sentry::release_name!(),
31 attach_stacktrace: true,
32 ..Default::default()
33 },
34 ));
35
36 let default_panic = panic::take_hook();
38 panic::set_hook(Box::new(move |panic_info| {
39 let payload = panic_info.payload().downcast_ref::<String>();
40 let message = payload.map(|s| s.as_str()).unwrap_or("Unknown panic");
41
42 sentry::capture_message(message, sentry::Level::Fatal);
43
44 default_panic(panic_info);
45 }));
46
47 guard
48}
49
50pub fn report_error<E: std::error::Error + Send + Sync + 'static>(error: E) {
56 sentry::capture_error(&error);
57}
58
59pub async fn run_with_error_reporting<F, T, E>(future: F) -> Result<T, E>
69where
70 F: std::future::Future<Output = Result<T, E>> + Send + 'static,
71 T: Send + 'static,
72 E: std::error::Error + Send + Sync + 'static,
73{
74 task::spawn(async move {
75 match future.await {
76 Ok(result) => Ok(result),
77 Err(e) => {
78 sentry::capture_error(&e);
79 Err(e)
80 }
81 }
82 }).await.unwrap_or_else(|e| {
83 sentry::capture_error(&e);
84 panic!("Task panicked: {:?}", e);
85 })
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_init() {
94 let config = Config {
95 public_key: "test_key".to_string(),
96 project_id: "test_project".to_string(),
97 };
98 let _guard = init(config);
99 }
100
101 #[tokio::test]
102 async fn test_run_with_error_reporting() {
103 let config = Config {
104 public_key: "test_key".to_string(),
105 project_id: "test_project".to_string(),
106 };
107 let _guard = init(config);
108
109 let result = run_with_error_reporting(async {
110 Ok::<_, std::io::Error>(())
111 }).await;
112 assert!(result.is_ok());
113
114 let error_result = run_with_error_reporting(async {
115 Err::<(), _>(std::io::Error::new(std::io::ErrorKind::Other, "Test error"))
116 }).await;
117 assert!(error_result.is_err());
118 }
119}