1use saddle_core::*;
3use saddle_observability::{
4 root_diagnostic::{request_child_view, request_identity_group},
5 *,
6};
7
8fn call(rpc: &str, span: u64, module: &str, service: &str, operation: &str) -> CallContext {
9 CallContext::new(
10 "saddle".into(),
11 module.into(),
12 service.into(),
13 operation.into(),
14 TraceId::from_u128(1),
15 SpanId::from_u64(span),
16 )
17 .with_trace_correlation_id(TraceCorrelationId::new("opaque-gateway-trace").unwrap())
18 .with_rpc_correlation_id(RpcCorrelationId::new(rpc))
19}
20
21fn database_source(
24 view: &RequestExecutionView,
25 request: &DbPhysicalRequestHalf,
26 execution: &DbPhysicalExecutionHalf,
27 output: Option<&EmergencyDiagnosticHandle>,
28 original: &(dyn std::error::Error + 'static),
29) -> RootRequestFailure {
30 let checked = request
31 .project_diagnostic_context(execution, view.clone())
32 .ok()
33 .unwrap();
34 let db = view
35 .in_db_scope(&checked)
36 .unwrap()
37 .with_db_operation(RegisteredContextOperation::checked("mapping.checks.A").unwrap());
38 let diagnostic = BoundedDiagnostic::capture(
39 DiagnosticCategory::UnexpectedError,
40 CaptureSite::Origin,
41 BoundedDiagnosticCause::new(
42 DiagnosticStage::RequestDb,
43 DiagnosticCode::new("db.decode.type").unwrap(),
44 )
45 .with_column(Some(0), Some(2)),
46 );
47 RootDiagnosticScope::new(&db, output).source_error_with_facts(
48 original,
49 diagnostic,
50 DiagnosticCode::new("db.decode").unwrap(),
51 RootRequestEvent::Database,
52 RootOutcomeFacts {
53 axes: DiagnosticOutcomeAxes {
54 operation: OperationOutcome::Failed,
55 ..Default::default()
56 },
57 transaction: ContextFact::Present(RequestTransactionFact::Unknown),
58 },
59 )
60}
61
62fn main() {
63 let mut publisher = RequestRootPublisher::create(
66 ContextLabel::checked("saddle").unwrap(),
67 ContextFact::NotEstablished,
68 )
69 .unwrap();
70 let root = publisher.reference();
71 let early = root.view(
72 RequestLocalFacts::new(RequestViewPhase::Reading).with_task(ContextFact::Present(17)),
73 );
74 let read_error = std::io::Error::from(std::io::ErrorKind::UnexpectedEof);
75 let early_failure = RootDiagnosticScope::new(&early, None).source_error(
76 &read_error,
77 DiagnosticStage::RequestDecode,
78 RootRequestEvent::Ingress,
79 RootOutcomeFacts::default(),
80 );
81 let event = EventContext::new(
82 RequestIdentity::new("request-a").unwrap(),
83 RouteIdentity::new("example.live").unwrap(),
84 1,
85 )
86 .unwrap();
87 assert!(
88 publisher
89 .publish(
90 request_identity_group(
91 &call("0", 1, "entry", "app", "example.live"),
92 &event,
93 ContextFact::Present(ContextLabel::checked("local").unwrap())
94 )
95 .unwrap()
96 )
97 .is_ok()
98 );
99 let active = early
100 .refresh(&root)
101 .unwrap()
102 .with_phase(RequestViewPhase::Handler);
103 let child_event = EventContext::new(
106 RequestIdentity::new("request-a").unwrap(),
107 RouteIdentity::new("receipt.invoke").unwrap(),
108 1,
109 )
110 .unwrap();
111 let child = request_child_view(
112 &active,
113 &call("0.1", 2, "local", "profusecontract", "invoke"),
114 &child_event,
115 )
116 .unwrap();
117 assert!(active.same_request(&child));
118 let (_, issuer) = DbPhysicalDispositionIssuer::issue().into_startup_and_request_issuer();
119 let (request, execution) = issuer.issue_request().unwrap();
120 let raw_error = std::io::Error::new(
123 std::io::ErrorKind::PermissionDenied,
124 "original driver description",
125 );
126 let db_failure = database_source(&active, &request, &execution, None, &raw_error);
127 drop(raw_error);
128 let supervised = RootSupervisionReturn::<()>::failed(
129 db_failure.map_classification(DiagnosticCode::new("handler.failed").unwrap()),
130 );
131 let failure = supervised.consume().err().unwrap();
132 let public = failure
135 .finish(&active, None, RootOutcomeFacts::default())
136 .ok()
137 .unwrap();
138 let early_public = early_failure
139 .finish(&active, None, RootOutcomeFacts::default())
140 .ok()
141 .unwrap();
142 let observer = Observer::with_writer(ObserverConfig::default(), std::io::sink()).unwrap();
143 let completed = RootDiagnosticScope::new(&active, None)
144 .start_stage(&observer, RootRequestEvent::Response)
145 .finish_nonfailure(RootOutcomeFacts {
146 axes: DiagnosticOutcomeAxes {
147 operation: OperationOutcome::Succeeded,
148 ..Default::default()
149 },
150 ..Default::default()
151 })
152 .ok()
153 .unwrap();
154 assert_eq!(completed, DiagnosticSubmission::OutputUnavailable);
155 assert_eq!(
156 RootDiagnosticScope::new(&active, None).ordinary(
157 &observer,
158 RootRequestEvent::Handler,
159 RootOutcomeFacts::default()
160 ),
161 DiagnosticSubmission::Enqueued
162 );
163 drop((publisher, root, early, active, child));
164 assert_eq!(
165 public.source_submission(),
166 DiagnosticSubmission::OutputUnavailable
167 );
168 assert_eq!(
169 early_public.terminal_submission(),
170 DiagnosticSubmission::OutputUnavailable
171 );
172 for (name, (payload, shared)) in ["root", "view", "child"]
173 .into_iter()
174 .zip(saddle_core::request_context::request_context_layouts())
175 {
176 println!(
177 "layout {name}: payload={} align={} arc_allocation={} arc_align={}",
178 payload.size(),
179 payload.align(),
180 shared.size(),
181 shared.align()
182 );
183 }
184 println!(
185 "layout receipt={} public={} root_ref={} view_ref={} identity_input={} bounded_detail={} borrowed_stage={}",
186 size_of::<RootRequestFailure>(),
187 size_of::<PublicRequestFailure>(),
188 size_of::<RequestRootRef>(),
189 size_of::<RequestExecutionView>(),
190 size_of::<RequestIdentityGroup>(),
191 size_of::<BoundedDiagnostic>(),
192 size_of::<RootActiveStage<'static>>()
193 );
194 println!("C consumer contract GO; production reservation/lifecycle NOT_RUN");
195 let layout = saddle_observability::root_diagnostic::request_logging_layouts();
196 let (stream, cycle, payload) = saddle_observability::root_diagnostic::original_capture_layout();
197 println!(
198 "layout original_stream={} align={} cycle_detector={} align={} payload_limit={} total_content_limit=none",
199 stream.size(),
200 stream.align(),
201 cycle.size(),
202 cycle.align(),
203 payload
204 );
205 println!(
206 "layout source_frame={} source_record={} emergency_packet={} emergency_slots={} ordinary_command={} ordinary_payload_max={}",
207 layout.source_frame.size(),
208 layout.source_record.size(),
209 layout.emergency_packet.size(),
210 layout.emergency_slots,
211 layout.ordinary_command.size(),
212 layout.ordinary_encoded_bytes_max
213 );
214}