liminal_server/console/records/
tap_records.rs1use super::RECORD_VERSION;
4use crate::console::{ConsoleError, wall::WallBase};
5use crate::tap::{self, TapIdent, TapOutcome, TapSource};
6use serde::Serialize;
7use std::num::NonZeroU32;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
13#[serde(rename_all = "lowercase")]
14pub enum Outcome {
15 Delivered,
17 Answered,
19 Unanswered,
21 Nobody,
23 Unaccepted,
25 Refused,
27 Unresolved,
29}
30
31impl From<TapOutcome> for Outcome {
32 fn from(outcome: TapOutcome) -> Self {
33 match outcome {
34 TapOutcome::Answered => Self::Answered,
35 TapOutcome::Unanswered => Self::Unanswered,
36 TapOutcome::Delivered => Self::Delivered,
37 TapOutcome::NoSubscriber => Self::Nobody,
38 TapOutcome::NoneAccepted => Self::Unaccepted,
39 TapOutcome::Unresolved => Self::Unresolved,
40 TapOutcome::Refused => Self::Refused,
41 }
42 }
43}
44
45#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
47pub struct Hop {
48 pub node: String,
50 pub at_ms: u64,
52}
53
54#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
56pub struct TapMessage {
57 pub id: String,
60 pub subject: String,
62 pub size: u64,
64 pub outcome: Outcome,
66 pub t: u64,
68 pub from: String,
70 #[serde(skip_serializing_if = "Option::is_none")]
74 pub from_station: Option<String>,
75 pub to: String,
77 #[serde(skip_serializing_if = "Option::is_none")]
87 pub to_stations: Option<Vec<String>>,
88 pub hops: Vec<Hop>,
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub reply_to: Option<String>,
93 pub held: bool,
95 #[serde(skip_serializing_if = "Option::is_none")]
97 pub diverted: Option<String>,
98 #[serde(skip_serializing_if = "Option::is_none")]
100 pub fields: Option<tap::message::CallDetails>,
101}
102
103#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
106pub struct TapBatch {
107 v: u64,
108 #[serde(rename = "type")]
109 record_type: &'static str,
110 pub target: String,
112 pub seq: u64,
114 pub sampled: NonZeroU32,
116 pub dropped: u64,
118 pub messages: Vec<TapMessage>,
120}
121
122impl TapBatch {
123 #[must_use]
125 pub const fn new(
126 target: String,
127 seq: u64,
128 sampled: NonZeroU32,
129 dropped: u64,
130 messages: Vec<TapMessage>,
131 ) -> Self {
132 Self {
133 v: RECORD_VERSION,
134 record_type: "tap.batch",
135 target,
136 seq,
137 sampled,
138 dropped,
139 messages,
140 }
141 }
142}
143
144pub fn tap_batch_record(
154 device: &str,
155 target: &str,
156 batch: &tap::TapBatch,
157 wall: &WallBase,
158) -> Result<TapBatch, ConsoleError> {
159 let messages = batch
160 .messages
161 .iter()
162 .map(|message| tap_message(device, message, wall))
163 .collect::<Result<Vec<_>, _>>()?;
164 Ok(TapBatch::new(
165 target.to_owned(),
166 batch.seq,
167 batch.sampled,
168 batch.dropped,
169 messages,
170 ))
171}
172
173fn tap_message(
174 device: &str,
175 message: &tap::TapMessage,
176 wall: &WallBase,
177) -> Result<TapMessage, ConsoleError> {
178 Ok(TapMessage {
179 id: match message.ident {
180 TapIdent::Call {
181 connection,
182 operation,
183 } => format!("{device}:call:{connection}:{operation}"),
184 TapIdent::Message(id) => format!("{device}:{id}"),
185 TapIdent::Observation(observation) => format!("{device}:x{observation}"),
186 },
187 subject: message.subject.clone(),
188 size: message.size,
189 outcome: message.outcome.into(),
190 t: wall.unix_ms_at(message.seen_at)?,
191 from: match message.source {
192 TapSource::Connection(connection) => connection.to_string(),
193 TapSource::Server => message
194 .station
195 .as_deref()
196 .map_or_else(|| format!("liminal.{device}"), str::to_owned),
197 },
198 from_station: message.station.as_deref().map(str::to_owned),
199 to: device.to_owned(),
200 to_stations: message.to_stations.as_deref().map(|stations| {
201 stations
202 .iter()
203 .map(|reached| reached.station.to_string())
204 .collect()
205 }),
206 hops: message
207 .hops
208 .iter()
209 .map(|hop| Hop {
210 node: hop.node.to_string(),
211 at_ms: hop.at_ms,
212 })
213 .collect(),
214 reply_to: message.reply_to.clone(),
215 held: message.held,
216 diverted: None,
217 fields: message.call.clone(),
218 })
219}