early_request_diagnostic/
early_request_diagnostic.rs1use saddle_core::{
3 BoundedDiagnosticCause, DiagnosticCategory, DiagnosticCode, DiagnosticOutcomeAxes,
4 DiagnosticStage, OperationOutcome,
5};
6use saddle_observability::{
7 DiagnosticRequestPhase, DiagnosticSubmission, EarlyRequestContext, FrameworkRequestFailure,
8 RequestDiagnosticScope,
9};
10use std::io::{self, Read};
11
12#[allow(clippy::result_large_err)]
14fn read_head(
15 reader: &mut impl Read,
16 scope: &RequestDiagnosticScope<'_>,
17) -> Result<(), FrameworkRequestFailure<io::Error>> {
18 reader.read_exact(&mut [0; 1]).map_err(|error| {
19 let kind = match error.kind() {
20 io::ErrorKind::UnexpectedEof => "io.unexpected_eof",
21 io::ErrorKind::TimedOut => "io.timed_out",
22 _ => "io.other",
23 };
24 let cause = BoundedDiagnosticCause::new(
25 DiagnosticStage::RequestDecode,
26 DiagnosticCode::new("request.read_failed").unwrap(),
27 )
28 .with_system(DiagnosticCode::new(kind).unwrap(), error.raw_os_error());
29 scope.fail(error, DiagnosticCategory::UnexpectedError, cause)
30 })
31}
32fn main() {
33 let scope =
36 RequestDiagnosticScope::early(None, EarlyRequestContext::socket_accepted("example"))
37 .with_phase(DiagnosticRequestPhase::ReadingHead);
38 let failure = match read_head(&mut io::empty(), &scope) {
39 Err(failure) => failure,
40 Ok(()) => panic!("owned empty reader must fail"),
41 };
42 let id = failure.source_diagnostic().id();
43 let (retained, delivery) = failure.finish_boundary_retained(
44 None,
45 &DiagnosticOutcomeAxes {
46 operation: OperationOutcome::Failed,
47 ..Default::default()
48 },
49 );
50 assert_eq!(retained.error().kind(), io::ErrorKind::UnexpectedEof);
51 assert_eq!(retained.source_diagnostic().id(), id);
52 assert_eq!(
53 delivery.source_submission(),
54 DiagnosticSubmission::OutputUnavailable
55 );
56 assert_eq!(
57 delivery.boundary_submission(),
58 DiagnosticSubmission::OutputUnavailable
59 );
60 println!("GO: early source retained without invented identities or output");
62}