use async_trait::async_trait;
use std::collections::BTreeMap;
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorSeverity {
Warning,
Error,
Fatal,
}
#[derive(Debug, Clone, Default)]
pub struct ErrorScope {
pub user_id: Option<String>,
pub org_id: Option<String>,
pub session_id: Option<String>,
pub request_id: Option<String>,
pub route: Option<String>,
pub component: Option<String>,
pub task_id: Option<String>,
pub workflow_id: Option<String>,
pub extra: BTreeMap<String, String>,
}
impl ErrorScope {
pub fn new() -> Self {
Self::default()
}
pub fn with_user(mut self, user_id: impl Into<String>) -> Self {
self.user_id = Some(user_id.into());
self
}
pub fn with_org(mut self, org_id: impl Into<String>) -> Self {
self.org_id = Some(org_id.into());
self
}
pub fn with_session(mut self, session_id: impl Into<String>) -> Self {
self.session_id = Some(session_id.into());
self
}
pub fn with_request(mut self, request_id: impl Into<String>) -> Self {
self.request_id = Some(request_id.into());
self
}
pub fn with_route(mut self, route: impl Into<String>) -> Self {
self.route = Some(route.into());
self
}
pub fn with_component(mut self, component: impl Into<String>) -> Self {
self.component = Some(component.into());
self
}
pub fn with_task(mut self, task_id: impl Into<String>) -> Self {
self.task_id = Some(task_id.into());
self
}
pub fn with_workflow(mut self, workflow_id: impl Into<String>) -> Self {
self.workflow_id = Some(workflow_id.into());
self
}
pub fn with_extra(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.extra.insert(key.into(), value.into());
self
}
}
#[derive(Debug, Clone)]
pub struct ErrorReport {
pub severity: ErrorSeverity,
pub kind: String,
pub message: String,
pub scope: ErrorScope,
}
impl ErrorReport {
pub fn new(
severity: ErrorSeverity,
kind: impl Into<String>,
message: impl Into<String>,
) -> Self {
Self {
severity,
kind: kind.into(),
message: message.into(),
scope: ErrorScope::default(),
}
}
pub fn error(kind: impl Into<String>, message: impl Into<String>) -> Self {
Self::new(ErrorSeverity::Error, kind, message)
}
pub fn warning(kind: impl Into<String>, message: impl Into<String>) -> Self {
Self::new(ErrorSeverity::Warning, kind, message)
}
pub fn fatal(kind: impl Into<String>, message: impl Into<String>) -> Self {
Self::new(ErrorSeverity::Fatal, kind, message)
}
pub fn with_scope(mut self, scope: ErrorScope) -> Self {
self.scope = scope;
self
}
}
#[async_trait]
pub trait ErrorReporter: Send + Sync {
async fn report(&self, report: ErrorReport);
fn name(&self) -> &'static str {
"ErrorReporter"
}
}
pub type SharedErrorReporter = Arc<dyn ErrorReporter>;
#[derive(Debug, Clone, Default)]
pub struct NoopErrorReporter;
#[async_trait]
impl ErrorReporter for NoopErrorReporter {
async fn report(&self, _report: ErrorReport) {}
fn name(&self) -> &'static str {
"NoopErrorReporter"
}
}