mod client;
mod config;
mod dispatcher;
mod sys;
use std::{panic::PanicHookInfo, sync::Arc, time::Duration};
pub use client::AptabaseClient;
use config::Config;
use serde_json::json;
#[derive(Default, Debug, Clone)]
pub struct InitOptions {
pub host: Option<String>,
pub flush_interval: Option<Duration>,
}
pub struct Builder {
app_key: String,
app_version: String,
enable_polling: bool,
panic_hook: Option<PanicHook>,
options: InitOptions,
}
pub type PanicHook =
Box<dyn Fn(&AptabaseClient, &PanicHookInfo<'_>, String) + 'static + Sync + Send>;
fn get_panic_message(info: &PanicHookInfo) -> String {
let payload = info.payload();
if let Some(s) = payload.downcast_ref::<&str>() {
return s.to_string();
} else if let Some(s) = payload.downcast_ref::<String>() {
return s.to_string();
}
format!("{:?}", payload)
}
impl Builder {
pub fn new(app_key: &str, app_version: &str) -> Self {
Self {
app_key: app_key.into(),
app_version: app_version.into(),
enable_polling: false,
panic_hook: None,
options: Default::default(),
}
}
pub fn with_options(mut self, opts: InitOptions) -> Self {
self.options = opts;
self
}
pub fn with_polling(mut self, enable: bool) -> Self {
self.enable_polling = enable;
self
}
pub fn with_panic_hook(mut self, hook: PanicHook) -> Self {
self.panic_hook = Some(hook);
self
}
pub fn with_default_panic_hook(self) -> Self {
self.with_panic_hook(Box::new(|client, info, message| {
let location = info
.location()
.map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column()))
.unwrap_or_default();
let _ = client.track_event(
"panic",
Some(json!({
"info": format!("{} ({})", message, location),
})),
);
}))
}
pub fn build(self) -> Arc<AptabaseClient> {
let cfg = Config::new(self.app_key, self.options);
let client = Arc::new(AptabaseClient::new(&cfg, self.app_version));
if self.enable_polling {
client.start_polling(cfg.flush_interval);
}
if let Some(hook) = self.panic_hook {
let default_panic = std::panic::take_hook();
let hook_client = client.clone();
std::panic::set_hook(Box::new(move |info| {
let msg = get_panic_message(info);
hook(&hook_client, info, msg);
hook_client.flush_blocking();
default_panic(info);
}));
}
client
}
}