1use std::fmt;
2
3#[derive(Debug)]
4pub struct Error {
5 message: String,
6}
7
8impl Error {
9 pub fn new(msg: impl Into<String>) -> Self {
10 Error {
11 message: msg.into(),
12 }
13 }
14}
15
16impl fmt::Display for Error {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 write!(f, "{}", self.message)
19 }
20}
21
22impl std::error::Error for Error {}
23
24pub type WorkflowError = Error;
25
26pub fn attach_node_span_attribute(node_id: &str) {
27 eprintln!("[etdl.telemetry] span attribute etdl.node.id={}", node_id);
28}
29
30pub fn emit_anomaly_event(
31 node_id: &str,
32 outcome: &str,
33 declared_probability: f64,
34 observed_frequency: f64,
35) {
36 eprintln!(
37 "[etdl.telemetry] SLA ANOMALY | node={} outcome={} declared={:.6} observed={:.6} deviation={:.6}",
38 node_id,
39 outcome,
40 declared_probability,
41 observed_frequency,
42 (observed_frequency - declared_probability).abs()
43 );
44}
45
46pub fn inject_traceparent(message_type: &str) -> String {
47 let trace_id = generate_trace_id();
48 let span_id = generate_span_id();
49 let traceparent = format!("00-{}-{}-01", trace_id, span_id);
50
51 eprintln!(
52 "[etdl.telemetry] inject traceparent into {} message: {}",
53 message_type, traceparent
54 );
55
56 traceparent
57}
58
59fn generate_trace_id() -> String {
60 use std::time::{SystemTime, UNIX_EPOCH};
61 let nanos = SystemTime::now()
62 .duration_since(UNIX_EPOCH)
63 .map(|d| d.as_nanos())
64 .unwrap_or(0);
65 format!("{:032x}", nanos)
66}
67
68fn generate_span_id() -> String {
69 use std::time::{SystemTime, UNIX_EPOCH};
70 let nanos = SystemTime::now()
71 .duration_since(UNIX_EPOCH)
72 .map(|d| d.as_nanos())
73 .unwrap_or(0);
74 format!("{:016x}", nanos.wrapping_mul(17))
75}