kmp_application/
observability.rs1use std::future::Future;
2use std::pin::Pin;
3
4use kmp_domain::PortError;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct ObservabilityQuery {
10 pub about: Option<String>,
11 pub from_millis: u64,
12 pub to_millis: u64,
13 pub series: Vec<String>,
14 pub max_points: usize,
15}
16
17pub trait ObservabilityQueryPort: Send + Sync {
20 fn available_series(&self) -> Vec<String> {
24 Vec::new()
25 }
26
27 fn query<'a>(
28 &'a self,
29 query: ObservabilityQuery,
30 ) -> Pin<Box<dyn Future<Output = Result<ObservabilityProjection, PortError>> + Send + 'a>>;
31}
32
33#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
34pub struct ObservabilityProjection {
35 pub contract: String,
36 pub from_millis: u64,
37 pub to_millis: u64,
38 pub series: Vec<ObservabilitySeries>,
39 pub exemplars: Vec<ObservabilityExemplar>,
40 pub missing: Vec<String>,
41 pub truncated: bool,
42}
43
44impl ObservabilityProjection {
45 pub fn empty(query: &ObservabilityQuery) -> Self {
46 Self {
47 contract: "kmp.observability.projection.v1".to_string(),
48 from_millis: query.from_millis,
49 to_millis: query.to_millis,
50 series: Vec::new(),
51 exemplars: Vec::new(),
52 missing: query.series.clone(),
53 truncated: false,
54 }
55 }
56}
57
58#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
59pub struct ObservabilitySeries {
60 pub name: String,
61 pub unit: String,
62 pub scope: String,
63 pub points: Vec<ObservabilityMetricPoint>,
64}
65
66#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
67pub struct ObservabilityMetricPoint {
68 pub at_millis: u64,
69 pub value: f64,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub exemplar_id: Option<String>,
72}
73
74#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
77pub struct ObservabilityExemplar {
78 pub id: String,
79 pub at_millis: u64,
80 pub operation: String,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub about: Option<String>,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub bundle_ref: Option<String>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub revision: Option<u64>,
87 pub attributes: std::collections::BTreeMap<String, String>,
88}