#[cfg(test)]
mod tests;
use super::*;
use saddle_core::{BoundedDiagnostic, Diagnostic, DiagnosticCode};
use saddle_observability::root_diagnostic::RootActiveStage;
use saddle_observability::{DiagnosticSubmission, Observer};
#[derive(Clone, Copy)]
pub enum ReservedObservationStage {
Ingress,
Admission,
Handler,
Database,
Outbound,
Response,
}
impl ReservedObservationStage {
fn event(self) -> RootRequestEvent {
match self {
Self::Ingress => RootRequestEvent::Ingress,
Self::Admission => RootRequestEvent::Admission,
Self::Handler => RootRequestEvent::Handler,
Self::Database => RootRequestEvent::Database,
Self::Outbound => RootRequestEvent::Outbound,
Self::Response => RootRequestEvent::Response,
}
}
}
impl ReservedRequestView {
pub fn source_error_with_facts(
&self,
error: &(dyn std::error::Error + 'static),
facts: BoundedDiagnostic,
classification: DiagnosticCode,
output: Option<&EmergencyDiagnosticHandle>,
event: RootRequestEvent,
outcome: RootOutcomeFacts,
) -> ReservedRequestFailure {
ReservedRequestFailure {
failure: RootDiagnosticScope::new(&self.0.view, output).source_error_with_facts(
error,
facts,
classification,
event,
outcome,
),
source: self.clone(),
}
}
pub fn source_description<D: std::fmt::Display + std::fmt::Debug>(
&self,
description: &D,
facts: BoundedDiagnostic,
classification: DiagnosticCode,
output: Option<&EmergencyDiagnosticHandle>,
event: RootRequestEvent,
outcome: RootOutcomeFacts,
) -> ReservedRequestFailure {
ReservedRequestFailure {
failure: RootDiagnosticScope::new(&self.0.view, output).source_description(
description,
facts,
classification,
event,
outcome,
),
source: self.clone(),
}
}
pub fn source_existing_error(
&self,
error: &(dyn std::error::Error + 'static),
facts: Diagnostic,
classification: DiagnosticCode,
output: Option<&EmergencyDiagnosticHandle>,
event: RootRequestEvent,
outcome: RootOutcomeFacts,
) -> ReservedRequestFailure {
ReservedRequestFailure {
failure: RootDiagnosticScope::new(&self.0.view, output).source_existing_error(
error,
facts,
classification,
event,
outcome,
),
source: self.clone(),
}
}
pub fn source_existing_description<D: std::fmt::Display + std::fmt::Debug>(
&self,
description: &D,
facts: Diagnostic,
classification: DiagnosticCode,
output: Option<&EmergencyDiagnosticHandle>,
event: RootRequestEvent,
outcome: RootOutcomeFacts,
) -> ReservedRequestFailure {
ReservedRequestFailure {
failure: RootDiagnosticScope::new(&self.0.view, output).source_existing_description(
description,
facts,
classification,
event,
outcome,
),
source: self.clone(),
}
}
pub fn start_stage<'a>(
&'a self,
observer: &'a Observer,
output: Option<&'a EmergencyDiagnosticHandle>,
stage: ReservedObservationStage,
) -> ReservedActiveStage<'a> {
ReservedActiveStage {
inner: RootDiagnosticScope::new(&self.0.view, output)
.start_stage(observer, stage.event()),
guard: self,
}
}
}
#[must_use = "finish this observation interval, or Drop records observation cancellation"]
pub struct ReservedActiveStage<'a> {
inner: RootActiveStage<'a>,
guard: &'a ReservedRequestView,
}
impl ReservedActiveStage<'_> {
pub fn finish_failure_retained(
self,
failure: ReservedRequestFailure,
facts: RootOutcomeFacts,
) -> Result<(ReservedRequestFailure, DiagnosticSubmission), (Self, ReservedRequestFailure)> {
let Self { inner, guard } = self;
let ReservedRequestFailure { failure, source } = failure;
match inner.finish_failure_retained(failure, facts) {
Ok((failure, submission)) => Ok((ReservedRequestFailure { failure, source }, submission)),
Err((inner, failure)) => Err((Self { inner, guard }, ReservedRequestFailure { failure, source })),
}
}
pub fn finish_failure_public(
self,
failure: ReservedRequestFailure,
facts: RootOutcomeFacts,
) -> Result<
saddle_observability::root_diagnostic::PublicRequestFailure,
(Self, ReservedRequestFailure),
> {
let Self { inner, guard } = self;
let ReservedRequestFailure { failure, source } = failure;
inner
.finish_failure_public(failure, facts)
.map_err(|(inner, failure)| {
(
Self { inner, guard },
ReservedRequestFailure { failure, source },
)
})
}
pub fn finish_nonfailure(self, facts: RootOutcomeFacts) -> Result<DiagnosticSubmission, Self> {
let Self { inner, guard } = self;
inner
.finish_nonfailure(facts)
.map_err(|inner| Self { inner, guard })
}
pub fn finish_failure(
self,
failure: ReservedRequestFailure,
facts: RootOutcomeFacts,
) -> Result<(ReservedRequestFailure, DiagnosticSubmission), (Self, ReservedRequestFailure)>
{
let Self { inner, guard } = self;
let ReservedRequestFailure { failure, source } = failure;
match inner.finish_failure(failure, facts) {
Ok((failure, submission)) => {
Ok((ReservedRequestFailure { failure, source }, submission))
}
Err((inner, failure)) => Err((
Self { inner, guard },
ReservedRequestFailure { failure, source },
)),
}
}
}