1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
7pub struct ServiceDescriptor {
8 pub name: String,
9 pub commands: Vec<MessageEndpointDescriptor>,
10 pub events: Vec<MessageEndpointDescriptor>,
11 pub transports: Vec<TransportDescriptor>,
12 #[serde(default, skip_serializing_if = "Option::is_none")]
13 pub observability: Option<ServiceObservabilityDescriptor>,
14}
15
16impl ServiceDescriptor {
17 pub fn new(name: impl Into<String>) -> Self {
18 Self {
19 name: name.into(),
20 commands: Vec::new(),
21 events: Vec::new(),
22 transports: Vec::new(),
23 observability: None,
24 }
25 }
26
27 pub fn command(mut self, name: impl Into<String>) -> Self {
28 self.commands.push(MessageEndpointDescriptor::new(name));
29 self
30 }
31
32 pub fn event(mut self, name: impl Into<String>) -> Self {
33 self.events.push(MessageEndpointDescriptor::new(name));
34 self
35 }
36
37 pub fn transport(mut self, kind: impl Into<String>) -> Self {
38 self.transports.push(TransportDescriptor::new(kind));
39 self
40 }
41
42 pub fn observability(mut self, observability: ServiceObservabilityDescriptor) -> Self {
43 self.observability = Some(observability);
44 self
45 }
46
47 pub fn metrics(mut self, metrics: MetricsEndpointDescriptor) -> Self {
48 let mut observability = self.observability.unwrap_or_default();
49 observability.metrics = Some(metrics);
50 self.observability = Some(observability);
51 self
52 }
53
54 pub fn tracing(mut self, tracing: TracingDescriptor) -> Self {
55 let mut observability = self.observability.unwrap_or_default();
56 observability.tracing = Some(tracing);
57 self.observability = Some(observability);
58 self
59 }
60}
61
62#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
63pub struct ServiceObservabilityDescriptor {
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub metrics: Option<MetricsEndpointDescriptor>,
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 pub tracing: Option<TracingDescriptor>,
68}
69
70impl ServiceObservabilityDescriptor {
71 pub fn new() -> Self {
72 Self::default()
73 }
74
75 pub fn metrics(mut self, metrics: MetricsEndpointDescriptor) -> Self {
76 self.metrics = Some(metrics);
77 self
78 }
79
80 pub fn tracing(mut self, tracing: TracingDescriptor) -> Self {
81 self.tracing = Some(tracing);
82 self
83 }
84}
85
86#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
87pub struct MetricsEndpointDescriptor {
88 pub path: String,
89 pub port_name: String,
90 #[serde(default, skip_serializing_if = "Option::is_none")]
91 pub interval: Option<String>,
92}
93
94impl MetricsEndpointDescriptor {
95 pub fn new(path: impl Into<String>, port_name: impl Into<String>) -> Self {
96 Self {
97 path: path.into(),
98 port_name: port_name.into(),
99 interval: None,
100 }
101 }
102
103 pub fn prometheus_default() -> Self {
104 Self::new("/metrics", "http").interval("30s")
105 }
106
107 pub fn interval(mut self, interval: impl Into<String>) -> Self {
108 self.interval = Some(interval.into());
109 self
110 }
111}
112
113#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
114pub struct TracingDescriptor {
115 pub propagation: TracePropagationMode,
116 pub export: TraceExportMode,
117}
118
119impl TracingDescriptor {
120 pub fn otlp() -> Self {
121 Self {
122 propagation: TracePropagationMode::W3cTraceContext,
123 export: TraceExportMode::Otlp,
124 }
125 }
126
127 pub fn disabled() -> Self {
128 Self {
129 propagation: TracePropagationMode::Disabled,
130 export: TraceExportMode::Disabled,
131 }
132 }
133}
134
135#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
136#[serde(rename_all = "snake_case")]
137pub enum TracePropagationMode {
138 #[default]
139 W3cTraceContext,
140 Disabled,
141}
142
143#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
144#[serde(rename_all = "snake_case")]
145pub enum TraceExportMode {
146 #[default]
147 Otlp,
148 Disabled,
149}
150
151#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
152pub struct MessageEndpointDescriptor {
153 pub name: String,
154}
155
156impl MessageEndpointDescriptor {
157 pub fn new(name: impl Into<String>) -> Self {
158 Self { name: name.into() }
159 }
160}
161
162#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
163pub struct TransportDescriptor {
164 pub kind: String,
165}
166
167impl TransportDescriptor {
168 pub fn new(kind: impl Into<String>) -> Self {
169 Self { kind: kind.into() }
170 }
171
172 pub fn http() -> Self {
173 Self::new("http")
174 }
175}