bss_oss_utils/
observability.rs1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct TraceContext {
10 pub trace_id: Uuid,
11 pub span_id: Uuid,
12 pub parent_span_id: Option<Uuid>,
13 pub timestamp: DateTime<Utc>,
14}
15
16impl TraceContext {
17 pub fn new() -> Self {
19 Self {
20 trace_id: Uuid::new_v4(),
21 span_id: Uuid::new_v4(),
22 parent_span_id: None,
23 timestamp: Utc::now(),
24 }
25 }
26
27 pub fn child_span(&self) -> Self {
29 Self {
30 trace_id: self.trace_id,
31 span_id: Uuid::new_v4(),
32 parent_span_id: Some(self.span_id),
33 timestamp: Utc::now(),
34 }
35 }
36}
37
38impl Default for TraceContext {
39 fn default() -> Self {
40 Self::new()
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct ApiMetrics {
47 pub endpoint: String,
48 pub method: String,
49 pub status_code: u16,
50 pub duration_ms: u64,
51 pub timestamp: DateTime<Utc>,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct HealthCheck {
57 pub status: HealthStatus,
58 pub version: String,
59 pub timestamp: DateTime<Utc>,
60 #[serde(skip_serializing_if = "Option::is_none")]
61 pub checks: Option<Vec<ComponentCheck>>,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
66#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
67pub enum HealthStatus {
68 Healthy,
69 Degraded,
70 Unhealthy,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct ComponentCheck {
76 pub name: String,
77 pub status: HealthStatus,
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub message: Option<String>,
80}
81
82impl HealthCheck {
83 pub fn healthy(version: String) -> Self {
85 Self {
86 status: HealthStatus::Healthy,
87 version,
88 timestamp: Utc::now(),
89 checks: None,
90 }
91 }
92}