1pub mod legacy;
2pub mod loglevel;
3pub mod quic;
4pub mod telemetry;
5
6#[doc(hidden)]
7pub mod macro_support;
8mod macros;
9pub mod packet;
10
11use std::{collections::HashMap, fmt::Display, net::SocketAddr};
12
13use bytes::Bytes;
14use derive_builder::Builder;
15use derive_more::{Display, From, Into};
16use qbase::{cid::ConnectionId, role::Role, util::ContinuousData};
17use quic::ConnectionID;
18use serde::{Deserialize, Serialize};
19
20#[serde_with::skip_serializing_none]
21#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
22#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
23pub struct LogFile {
24 file_schema: String,
25 serialization_format: String,
26 #[builder(default)]
27 title: Option<String>,
28 #[builder(default)]
29 description: Option<String>,
30 #[builder(default)]
31 event_schemas: Vec<String>,
32}
33
34#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
35#[builder(setter(into), build_fn(private, name = "fallible_build"))]
36pub struct QlogFile {
37 #[serde(flatten)]
38 log_file: LogFile,
39 traces: Vec<Traces>,
40}
41
42#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
49#[builder(setter(into), build_fn(private, name = "fallible_build"))]
50pub struct QlogFileSeq {
51 #[serde(flatten)]
52 log_file: LogFile,
53 trace_seq: TraceSeq,
54}
55
56impl QlogFileSeq {
57 pub const SCHEMA: &'static str = "urn:ietf:params:qlog:file:sequential";
58}
59
60#[allow(clippy::large_enum_variant)]
61#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
62#[serde(untagged)]
63pub enum Traces {
64 Trace(Trace),
65 TraceError(TraceError),
66}
67
68#[serde_with::skip_serializing_none]
77#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
78#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
79pub struct Trace {
80 #[builder(default)]
82 title: Option<String>,
83 #[builder(default)]
85 description: Option<String>,
86 #[builder(default)]
87 common_fields: Option<CommonFields>,
88 #[builder(default)]
89 vantage_point: Option<VantagePoint>,
90 events: Vec<Event>,
91}
92
93#[serde_with::skip_serializing_none]
97#[derive(Builder, Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
98#[builder(
99 default,
100 setter(into, strip_option),
101 build_fn(private, name = "fallible_build")
102)]
103pub struct TraceSeq {
104 title: Option<String>,
106 description: Option<String>,
108 common_fields: Option<CommonFields>,
109 vantage_point: Option<VantagePoint>,
110}
111
112#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
113#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
114pub struct CommonFields {
115 path: PathID,
116 time_format: TimeFormat,
117 reference_time: ReferenceTime,
118 protocol_types: ProtocolTypeList,
119 group_id: GroupID,
120 #[builder(default)]
121 #[serde(flatten)]
122 #[serde(skip_serializing_if = "HashMap::is_empty")]
123 custom_fields: HashMap<String, serde_json::Value>,
125}
126
127#[serde_with::skip_serializing_none]
129#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
130#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
131pub struct VantagePoint {
132 #[builder(default)]
133 name: Option<String>,
134 r#type: VantagePointType,
135 #[builder(default)]
136 flow: Option<VantagePointType>,
137}
138
139#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
140#[serde(rename_all = "snake_case")]
141pub enum VantagePointType {
142 Client,
144 Server,
146 Network,
148 #[default]
149 Unknow,
150}
151
152impl From<Role> for VantagePointType {
153 fn from(role: Role) -> Self {
154 match role {
155 Role::Client => VantagePointType::Client,
156 Role::Server => VantagePointType::Server,
157 }
158 }
159}
160
161impl Display for VantagePointType {
162 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163 match self {
164 VantagePointType::Client => write!(f, "client"),
165 VantagePointType::Server => write!(f, "server"),
166 VantagePointType::Network => write!(f, "network"),
167 VantagePointType::Unknow => write!(f, "unknow"),
168 }
169 }
170}
171
172#[serde_with::skip_serializing_none]
173#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
174#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
175pub struct TraceError {
176 error_description: String,
177 #[builder(default)]
178 uri: Option<String>,
179 #[builder(default)]
180 vantage_point: Option<VantagePoint>,
181}
182
183#[serde_with::skip_serializing_none]
187#[derive(Builder, Debug, Clone, Serialize, Deserialize, PartialEq)]
188#[builder(setter(into, strip_option), build_fn(private, name = "fallible_build"))]
189pub struct Event {
190 time: f64,
191 #[serde(flatten)]
192 data: EvnetData,
193 #[builder(default)]
198 path: Option<PathID>,
199 #[builder(default)]
200 time_format: Option<TimeFormat>,
201 #[builder(default)]
202 protocol_types: Option<ProtocolTypeList>,
203 #[builder(default)]
204 group_id: Option<GroupID>,
205 #[builder(default)]
206 system_info: Option<SystemInformation>,
207 #[builder(default)]
209 #[serde(flatten)]
210 #[serde(skip_serializing_if = "HashMap::is_empty")]
211 custom_fields: HashMap<String, serde_json::Value>,
213}
214
215#[derive(Debug, Clone, From, Into, Serialize, Deserialize, PartialEq, Eq)]
216#[serde(transparent)]
217pub struct PathID(String);
218
219#[serde_with::skip_serializing_none]
220#[derive(Builder, Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
221#[builder(
222 default,
223 setter(into, strip_option),
224 build_fn(private, name = "fallible_build")
225)]
226#[serde(try_from = "UncheckedReferenceTime")]
227pub struct ReferenceTime {
228 clock_type: TimeClockType,
233 #[serde(default)]
239 epoch: TimeEpoch,
240 #[builder(default)]
246 wall_clock_time: Option<RFC3339DateTime>,
247}
248
249#[derive(Deserialize)]
251struct UncheckedReferenceTime {
252 clock_type: TimeClockType,
253 #[serde(default)]
254 epoch: TimeEpoch,
255 wall_clock_time: Option<RFC3339DateTime>,
256}
257
258impl TryFrom<UncheckedReferenceTime> for ReferenceTime {
259 type Error = &'static str;
260 fn try_from(value: UncheckedReferenceTime) -> Result<Self, Self::Error> {
261 if value.clock_type == TimeClockType::Monotaonic && value.epoch != TimeEpoch::Unknow {
262 return Err(
263 r#"When using the "monotonic" clock type, the epoch field MUST have the value "unknown"."#,
264 );
265 }
266
267 Ok(ReferenceTime {
268 clock_type: value.clock_type,
269 epoch: value.epoch,
270 wall_clock_time: value.wall_clock_time,
271 })
272 }
273}
274
275#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
276#[serde(rename_all = "snake_case")]
277pub enum TimeClockType {
278 #[default]
281 System,
282 Monotaonic,
287 #[serde(untagged)]
288 Custom(String),
289}
290
291#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
292pub enum TimeEpoch {
293 Unknow,
294 #[serde(untagged)]
295 RFC3339DateTime(RFC3339DateTime),
296}
297
298impl Default for TimeEpoch {
299 fn default() -> Self {
300 Self::RFC3339DateTime(Default::default())
301 }
302}
303
304#[derive(Debug, Clone, From, Into, Serialize, Deserialize, PartialEq, Eq)]
305#[serde(transparent)]
306pub struct RFC3339DateTime(String);
307
308impl Default for RFC3339DateTime {
309 fn default() -> Self {
310 Self("1970-01-01T00:00:00.000Z".to_owned())
311 }
312}
313
314#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
315#[serde(rename_all = "snake_case")]
316pub enum TimeFormat {
317 #[default]
320 RelativeToEpoch,
321 RelativeToPreviousEvent,
324}
325
326#[derive(Debug, Clone, From, Into, Serialize, Deserialize, PartialEq, Eq)]
327#[serde(transparent)]
328pub struct ProtocolTypeList(Vec<ProtocolType>);
329
330#[derive(Debug, Clone, From, Into, Serialize, Deserialize, PartialEq, Eq)]
331#[serde(transparent)]
332pub struct ProtocolType(String);
333
334impl ProtocolType {
335 pub fn quic() -> ProtocolType {
336 ProtocolType("QUIC".to_owned())
337 }
338
339 pub fn http3() -> ProtocolType {
340 ProtocolType("HTTP/3".to_owned())
341 }
342}
343
344#[derive(Debug, Display, Clone, From, Into, Serialize, Deserialize, PartialEq, Eq)]
345#[serde(transparent)]
346pub struct GroupID(String);
347
348impl From<ConnectionId> for GroupID {
349 fn from(value: ConnectionId) -> Self {
350 Self(format!("{value:x}"))
351 }
352}
353
354impl From<ConnectionID> for GroupID {
355 fn from(value: ConnectionID) -> Self {
356 Self(format!("{value:x}"))
357 }
358}
359
360impl From<(SocketAddr, SocketAddr)> for GroupID {
361 fn from(_value: (SocketAddr, SocketAddr)) -> Self {
362 todo!()
363 }
364}
365
366#[derive(Builder, Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
370#[serde_with::skip_serializing_none]
371#[builder(
372 default,
373 setter(into, strip_option),
374 build_fn(private, name = "fallible_build")
375)]
376pub struct SystemInformation {
377 processor_id: Option<u32>,
378 process_id: Option<u32>,
379 thread_id: Option<u32>,
380}
381
382#[derive(Debug, Clone, Copy, PartialEq, Eq)]
383pub enum EventImportance {
384 Core = 1,
385 Base = 2,
386 Extra = 3,
387}
388
389#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
390#[serde(tag = "name", content = "data")]
391#[enum_dispatch::enum_dispatch(BeEventData)]
392pub enum EvnetData {
393 #[serde(rename = "quic:server_listening")]
394 ServerListening(quic::connectivity::ServerListening),
395 #[serde(rename = "quic:connection_started")]
396 ConnectionStarted(quic::connectivity::ConnectionStarted),
397 #[serde(rename = "quic:connection_closed")]
398 ConnectionClosed(quic::connectivity::ConnectionClosed),
399 #[serde(rename = "quic:connection_id_updated")]
400 ConnectionIdUpdated(quic::connectivity::ConnectionIdUpdated),
401 #[serde(rename = "quic:spin_bit_updated")]
402 SpinBitUpdated(quic::connectivity::SpinBitUpdated),
403 #[serde(rename = "quic:connection_state_updated")]
404 ConnectionStateUpdated(quic::connectivity::ConnectionStateUpdated),
405 #[serde(rename = "quic:path_assigned")]
406 PathAssigned(quic::connectivity::PathAssigned),
407 #[serde(rename = "quic:mtu_updated")]
408 MtuUpdated(quic::connectivity::MtuUpdated),
409 #[serde(rename = "quic:version_information")]
410 VersionInformation(quic::transport::VersionInformation),
411 #[serde(rename = "quic:alpn_information")]
412 ALPNInformation(quic::transport::ALPNInformation),
413 #[serde(rename = "quic:parameters_set")]
414 ParametersSet(quic::transport::ParametersSet),
415 #[serde(rename = "quic:parameters_restored")]
416 ParametersRestored(quic::transport::ParametersRestored),
417 #[serde(rename = "quic:packet_sent")]
418 PacketSent(quic::transport::PacketSent),
419 #[serde(rename = "quic:packet_received")]
420 PacketReceived(quic::transport::PacketReceived),
421 #[serde(rename = "quic:packet_dropped")]
422 PacketDropped(quic::transport::PacketDropped),
423 #[serde(rename = "quic:packet_buffered")]
424 PacketBuffered(quic::transport::PacketBuffered),
425 #[serde(rename = "quic:packets_acked")]
426 PacketsAcked(quic::transport::PacketsAcked),
427 #[serde(rename = "quic:udp_datagrams_sent")]
428 UdpDatagramSent(quic::transport::UdpDatagramsSent),
429 #[serde(rename = "quic:udp_datagrams_received")]
430 UdpDatagramReceived(quic::transport::UdpDatagramsReceived),
431 #[serde(rename = "quic:udp_datagram_dropped")]
432 UdpDatagramDropped(quic::transport::UdpDatagramDropped),
433 #[serde(rename = "quic:stream_state_updated")]
434 StreamStateUpdated(quic::transport::StreamStateUpdated),
435 #[serde(rename = "quic:frames_processed")]
436 FramesProcessed(quic::transport::FramesProcessed),
437 #[serde(rename = "quic:stream_data_moved")]
438 StreamDataMoved(quic::transport::StreamDataMoved),
439 #[serde(rename = "quic:datagram_data_moved")]
440 DatagramDataMoved(quic::transport::DatagramDataMoved),
441 #[serde(rename = "quic:migration_state_updated")]
442 MigrationStateUpdated(quic::transport::MigrationStateUpdated),
443 #[serde(rename = "quic:key_updated")]
444 KeyUpdated(quic::security::KeyUpdated),
445 #[serde(rename = "quic:key_discarded")]
446 KeyDiscarded(quic::security::KeyDiscarded),
447 #[serde(rename = "quic:recovery_parameters_set")]
448 RecoveryParametersSet(quic::recovery::RecoveryParametersSet),
449 #[serde(rename = "quic:recovery_metrics_updated")]
450 RecoveryMetricsUpdated(quic::recovery::RecoveryMetricsUpdated),
451 #[serde(rename = "quic:congestion_state_updated")]
452 CongestionStateUpdated(quic::recovery::CongestionStateUpdated),
453 #[serde(rename = "quic:loss_timer_updated")]
454 LossTimerUpdated(quic::recovery::LossTimerUpdated),
455 #[serde(rename = "quic:packet_lost")]
456 PacketLost(quic::recovery::PacketLost),
457 #[serde(rename = "quic:marked_for_retransmit")]
458 MarkedForRetransmit(quic::recovery::MarkedForRetransmit),
459 #[serde(rename = "quic:ecn_state_updated")]
460 ECNStateUpdated(quic::recovery::ECNStateUpdated),
461 #[serde(rename = "loglevel:error")]
462 Error(loglevel::Error),
463 #[serde(rename = "loglevel:warning")]
464 Warning(loglevel::Warning),
465 #[serde(rename = "loglevel:info")]
466 Info(loglevel::Info),
467 #[serde(rename = "loglevel:debug")]
468 Debug(loglevel::Debug),
469 #[serde(rename = "loglevel:verbose")]
470 Verbose(loglevel::Verbose),
471}
472
473pub trait BeSpecificEventData {
474 fn scheme() -> &'static str;
475
476 fn importance() -> EventImportance;
477}
478
479#[enum_dispatch::enum_dispatch]
480pub trait BeEventData {
481 fn scheme(&self) -> &'static str;
482
483 fn importance(&self) -> EventImportance;
484}
485
486impl<S: BeSpecificEventData> BeEventData for S {
487 #[inline]
488 fn scheme(&self) -> &'static str {
489 S::scheme()
490 }
491
492 #[inline]
493 fn importance(&self) -> EventImportance {
494 S::importance()
495 }
496}
497
498macro_rules! imp_be_events {
499 ( $($importance:ident $event:ty => $prefix:ident $schme:literal ;)* ) => {
500 $( imp_be_events!{@impl_one $importance $event => $prefix $schme ; } )*
501 };
502 (@impl_one $importance:ident $event:ty => urn $schme:literal ; ) => {
503 impl BeSpecificEventData for $event {
504 fn scheme() -> &'static str {
505 concat!["urn:ietf:params:qlog:events:",$schme]
506 }
507
508 fn importance() -> EventImportance {
509 EventImportance::$importance
510 }
511 }
512 };
513}
514
515imp_be_events! {
516 Extra quic::connectivity::ServerListening => urn "quic:server_listening";
517 Base quic::connectivity::ConnectionStarted => urn "quic:connection_started";
518 Base quic::connectivity::ConnectionClosed => urn "quic:connection_closed";
519 Base quic::connectivity::ConnectionIdUpdated => urn "quic:connection_id_updated";
520 Base quic::connectivity::SpinBitUpdated => urn "quic:spin_bit_updated";
521 Base quic::connectivity::ConnectionStateUpdated => urn "quic:connection_state_updated";
522 Base quic::connectivity::PathAssigned => urn "quic:path_assigned";
523 Extra quic::connectivity::MtuUpdated => urn "quic:mtu_updated";
524 Core quic::transport::VersionInformation => urn "quic:version_information";
525 Core quic::transport::ALPNInformation => urn "quic:alpn_information";
526 Core quic::transport::ParametersSet => urn "quic:parameters_set";
527 Base quic::transport::ParametersRestored => urn "quic:parameters_restored";
528 Core quic::transport::PacketSent => urn "quic:packet_sent";
529 Core quic::transport::PacketReceived => urn "quic:packet_received";
530 Base quic::transport::PacketDropped => urn "quic:packet_dropped";
531 Base quic::transport::PacketBuffered => urn "quic:packet_buffered";
532 Extra quic::transport::PacketsAcked => urn "quic:packets_acked";
533 Extra quic::transport::UdpDatagramsSent => urn "quic:udp_datagrams_sent";
534 Extra quic::transport::UdpDatagramsReceived => urn "quic:udp_datagrams_received";
535 Extra quic::transport::UdpDatagramDropped => urn "quic:udp_datagram_dropped";
536 Base quic::transport::StreamStateUpdated => urn "quic:stream_state_updated";
537 Extra quic::transport::FramesProcessed => urn "quic:frames_processed";
538 Base quic::transport::StreamDataMoved => urn "quic:stream_data_moved";
539 Base quic::transport::DatagramDataMoved => urn "quic:datagram_data_moved";
540 Extra quic::transport::MigrationStateUpdated => urn "quic:migration_state_updated";
541 Base quic::security::KeyUpdated => urn "quic:key_updated";
542 Base quic::security::KeyDiscarded => urn "quic:key_discarded";
543 Base quic::recovery::RecoveryParametersSet => urn "quic:recovery_parameters_set";
544 Core quic::recovery::RecoveryMetricsUpdated => urn "quic:recovery_metrics_updated";
545 Base quic::recovery::CongestionStateUpdated => urn "quic:congestion_state_updated";
546 Extra quic::recovery::LossTimerUpdated => urn "quic:loss_timer_updated";
547 Core quic::recovery::PacketLost => urn "quic:packet_lost";
548 Extra quic::recovery::MarkedForRetransmit => urn "quic:marked_for_retransmit";
549 Extra quic::recovery::ECNStateUpdated => urn "quic:ecn_state_updated";
550 Core loglevel::Error => urn "loglevel:error";
551 Base loglevel::Warning => urn "loglevel:warning";
552 Extra loglevel::Info => urn "loglevel:info";
553 Extra loglevel::Debug => urn "loglevel:debug";
554 Extra loglevel::Verbose => urn "loglevel:verbose";
555}
556
557#[serde_with::serde_as]
559#[derive(Debug, Clone, From, Into, Serialize, Deserialize, PartialEq, Eq)]
560#[serde(transparent)]
561pub struct HexString(#[serde_as(as = "serde_with::hex::Hex")] Bytes);
562
563impl Display for HexString {
564 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
565 write!(f, "{:x}", self.0)
566 }
567}
568
569#[serde_with::skip_serializing_none]
570#[derive(Builder, Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
571#[builder(
572 default,
573 setter(into, strip_option),
574 build_fn(private, name = "fallible_build")
575)]
576pub struct RawInfo {
577 length: Option<u64>,
580 payload_length: Option<u64>,
583 #[builder(setter(custom))]
586 data: Option<HexString>,
587}
588
589impl RawInfoBuilder {
590 pub fn data<D: ContinuousData>(&mut self, data: D) -> &mut Self {
593 self.data = telemetry::filter::raw_data().then(|| Some(data.to_bytes().into()));
594 self
595 }
596}
597
598impl<D: ContinuousData> From<D> for RawInfo {
599 fn from(data: D) -> Self {
600 build!(RawInfo {
601 length: data.len() as u64,
602 data: data
603 })
604 }
605}
606
607#[doc(hidden)]
614#[macro_export] macro_rules! gen_builder_method {
616 ( $($builder:ty => $event:ty;)* ) => {
617 $( $crate::gen_builder_method!{@impl_one $event => $builder ;} )*
618 };
619 (@impl_one $event:ty => $builder:ty ; ) => {
620 impl $event {
621 pub fn builder() -> $builder {
622 Default::default()
623 }
624 }
625
626 impl $builder {
627 pub fn build(&mut self) -> $event {
628 self.fallible_build().expect("Failed to build event")
629 }
630 }
631 };
632}
633
634gen_builder_method! {
635 LogFileBuilder => LogFile;
636 QlogFileBuilder => QlogFile;
637 QlogFileSeqBuilder => QlogFileSeq;
638 TraceBuilder => Trace;
639 TraceSeqBuilder => TraceSeq;
640 TraceErrorBuilder => TraceError;
641 CommonFieldsBuilder => CommonFields;
642 VantagePointBuilder => VantagePoint;
643 EventBuilder => Event;
644 ReferenceTimeBuilder => ReferenceTime;
645 RawInfoBuilder => RawInfo;
646}
647
648mod rollback {
649
650 use super::*;
651 use crate::{build, legacy};
652
653 impl TryFrom<EvnetData> for legacy::EventData {
654 type Error = ();
655 #[rustfmt::skip]
656 fn try_from(value: EvnetData) -> Result<Self, Self::Error> {
657 match value {
658 EvnetData::ServerListening(data) => Ok(legacy::EventData::ServerListening(data.into())),
659 EvnetData::ConnectionStarted(data) => Ok(legacy::EventData::ConnectionStarted(data.into())),
660 EvnetData::ConnectionClosed(data) => Ok(legacy::EventData::ConnectionClosed(data.into())),
661 EvnetData::ConnectionIdUpdated(data) => Ok(legacy::EventData::ConnectionIdUpdated(data.into())),
662 EvnetData::SpinBitUpdated(data) => Ok(legacy::EventData::SpinBitUpdated(data.into())),
663 EvnetData::ConnectionStateUpdated(data) => Ok(legacy::EventData::ConnectionStateUpdated(data.into())),
664 EvnetData::PathAssigned(_data) => Err(()),
665 EvnetData::MtuUpdated(_data) => Err(()),
666 EvnetData::VersionInformation(data) => Ok(legacy::EventData::VersionInformation(data.into())),
667 EvnetData::ALPNInformation(data) => Ok(legacy::EventData::AlpnInformation(data.into())),
668 EvnetData::ParametersSet(data) => Ok(legacy::EventData::TransportParametersSet(data.into())),
669 EvnetData::ParametersRestored(data) => Ok(legacy::EventData::TransportParametersRestored(data.into())),
670 EvnetData::PacketSent(data) => Ok(legacy::EventData::PacketSent(data.into())),
671 EvnetData::PacketReceived(data) => Ok(legacy::EventData::PacketReceived(data.into())),
672 EvnetData::PacketDropped(data) => Ok(legacy::EventData::PacketDropped(data.into())),
673 EvnetData::PacketBuffered(data) => Ok(legacy::EventData::PacketBuffered(data.into())),
674 EvnetData::PacketsAcked(data) => Ok(legacy::EventData::PacketsAcked(data.into())),
675 EvnetData::UdpDatagramSent(data) => Ok(legacy::EventData::DatagramsSent(data.into())),
676 EvnetData::UdpDatagramReceived(data) => Ok(legacy::EventData::DatagramsReceived(data.into())),
677 EvnetData::UdpDatagramDropped(data) => Ok(legacy::EventData::DatagramDropped(data.into())),
678 EvnetData::StreamStateUpdated(data) => Ok(legacy::EventData::StreamStateUpdated(data.into())),
679 EvnetData::FramesProcessed(data) => Ok(legacy::EventData::FramesProcessed(data.into())),
680 EvnetData::StreamDataMoved(data) => Ok(legacy::EventData::DataMoved(data.into())),
681 EvnetData::DatagramDataMoved(_data) => Err(()),
682 EvnetData::MigrationStateUpdated(_data) => Err(()),
683 EvnetData::KeyUpdated(data) => Ok(legacy::EventData::KeyUpdated(data.into())),
684 EvnetData::KeyDiscarded(data) => Ok(legacy::EventData::KeyDiscarded(data.into())),
685 EvnetData::RecoveryParametersSet(data) => Ok(legacy::EventData::RecoveryParametersSet(data.into())),
686 EvnetData::RecoveryMetricsUpdated(data) => Ok(legacy::EventData::MetricsUpdated(data.into())),
687 EvnetData::CongestionStateUpdated(data) => Ok(legacy::EventData::CongestionStateUpdated(data.into())),
688 EvnetData::LossTimerUpdated(data) => Ok(legacy::EventData::LossTimerUpdated(data.into())),
689 EvnetData::PacketLost(data) => Ok(legacy::EventData::PacketLost(data.into())),
690 EvnetData::MarkedForRetransmit(data) => Ok(legacy::EventData::MarkedForRetransmit(data.into())),
691 EvnetData::ECNStateUpdated(_data) => Err(()),
692 EvnetData::Error(data) => Ok(legacy::EventData::GenericError(data.into())),
693 EvnetData::Warning(data) => Ok(legacy::EventData::GenericWarning(data.into())),
694 EvnetData::Info(data) => Ok(legacy::EventData::GenericInfo(data.into())),
695 EvnetData::Debug(data) => Ok(legacy::EventData::GenericDebug(data.into())),
696 EvnetData::Verbose(data) => Ok(legacy::EventData::GenericVerbose(data.into())),
697 }
698 }
699 }
700
701 impl From<TimeFormat> for legacy::TimeFormat {
702 fn from(value: TimeFormat) -> Self {
703 match value {
704 TimeFormat::RelativeToEpoch => legacy::TimeFormat::Absolute,
707 TimeFormat::RelativeToPreviousEvent => legacy::TimeFormat::Delta,
708 }
709 }
710 }
711
712 impl From<ProtocolTypeList> for legacy::ProtocolType {
713 fn from(value: ProtocolTypeList) -> Self {
714 value
715 .0
716 .into_iter()
717 .map(|x| x.into())
718 .collect::<Vec<_>>()
719 .into()
720 }
721 }
722
723 impl TryFrom<Event> for legacy::Event {
724 type Error = ();
725 fn try_from(mut event: Event) -> Result<Self, Self::Error> {
726 if let Some(system_info) = event.system_info {
727 let value = serde_json::to_value(system_info).unwrap();
728 event.custom_fields.insert("system_info".to_owned(), value);
729 }
730 if let Some(path) = event.path {
731 let value = serde_json::to_value(path).unwrap();
732 event.custom_fields.insert("path".to_owned(), value);
733 }
734 Ok(build!(legacy::Event {
735 time: event.time,
736 data: { legacy::EventData::try_from(event.data)? },
737 ?time_format: event.time_format,
738 ?protocol_type: event.protocol_types,
739 ?group_id: event.group_id,
740 custom_fields: event.custom_fields
741 }))
742 }
743 }
744}
745
746#[cfg(test)]
747mod tests {
748 use std::sync::Arc;
749
750 use qbase::cid::ConnectionId;
751
752 use super::*;
753 use crate::{loglevel::Warning, quic::connectivity::ConnectionStarted, telemetry::ExportEvent};
754
755 #[test]
756 fn custom_fields() {
757 let odcid = ConnectionID::from(ConnectionId::from_slice(&[
758 0x61, 0xb6, 0x91, 0x78, 0x80, 0xf7, 0x95, 0xee,
759 ]));
760 let common_fields = build!(CommonFields {
761 path: "".to_owned(),
762 time_format: TimeFormat::default(),
763 reference_time: ReferenceTime::default(),
764 protocol_types: ProtocolTypeList::from(vec![ProtocolType::quic()]),
765 group_id: GroupID::from(odcid),
766 });
767 let expect = r#"{
768 "path": "",
769 "time_format": "relative_to_epoch",
770 "reference_time": {
771 "clock_type": "system",
772 "epoch": "1970-01-01T00:00:00.000Z"
773 },
774 "protocol_types": [
775 "QUIC"
776 ],
777 "group_id": "61b6917880f795ee"
778}"#;
779 assert_eq!(
780 serde_json::to_string_pretty(&common_fields).unwrap(),
781 expect
782 );
783 let with_custom_fields = r#"{
784 "path": "",
785 "time_format": "relative_to_epoch",
786 "reference_time": {
787 "clock_type": "system",
788 "epoch": "1970-01-01T00:00:00.000Z"
789 },
790 "protocol_types": [
791 "QUIC"
792 ],
793 "group_id": "61b6917880f795ee",
794 "pathway": "from A to relay",
795 "customB": "some other extensions"
796}"#;
797 let des = serde_json::from_str::<CommonFields>(with_custom_fields).unwrap();
798 let filed_string = serde_json::to_string_pretty(&des).unwrap();
799 let des2 = serde_json::from_str::<CommonFields>(&filed_string).unwrap();
800 assert_eq!(des, des2);
801 }
802
803 #[test]
804 fn evnet_data() {
805 let data = EvnetData::from(build!(Warning {
806 message: "deepseek(已深度思考(用时0秒)):服务器繁忙,请稍后再试。",
807 code: 255u64,
808 }));
809 let event = build!(Event {
810 time: 1.0,
811 data: data.clone(),
812 });
813 let expect = r#"{
814 "time": 1.0,
815 "name": "loglevel:warning",
816 "data": {
817 "code": 255,
818 "message": "deepseek(已深度思考(用时0秒)):服务器繁忙,请稍后再试。"
819 }
820}"#;
821 assert_eq!(serde_json::to_string_pretty(&event).unwrap(), expect);
822 assert_eq!(data.importance(), EventImportance::Base);
823 }
824
825 #[test]
826 fn rollback() {
827 fn group_id() -> GroupID {
828 GroupID::from(ConnectionID::from(ConnectionId::from_slice(&[
829 0xfe, 0xdc, 0xba, 0x09, 0x87, 0x65, 0x43, 0x32,
830 ])))
831 }
832
833 fn protocol_types() -> Vec<String> {
834 vec!["QUIC".to_owned(), "UNKNOW".to_owned()]
835 }
836
837 struct TestBroker;
838
839 impl ExportEvent for TestBroker {
840 fn emit(&self, event: Event) {
841 let legacy = legacy::Event::try_from(event).unwrap();
842 let event = serde_json::to_value(legacy).unwrap();
843
844 let data = serde_json::json!({
845 "ip_version": "v4",
846 "src_ip": "127.0.0.1",
847 "dst_ip": "192.168.31.1",
848 "protocol": "QUIC",
849 "src_port": 23456,
850 "dst_port": 21
851 });
852 let protocol_type = serde_json::json!(["QUIC", "UNKNOW"]);
854
855 assert_eq!(event["data"], data);
856 assert_eq!(event["protocol_types"], serde_json::Value::Null);
857 assert_eq!(event["protocol_type"], protocol_type);
858 assert_eq!(event["to_router"], true);
859 }
860 }
861
862 span!(
863 Arc::new(TestBroker),
864 group_id = group_id(),
865 protocol_types = protocol_types()
866 )
867 .in_scope(|| {
868 let src = "127.0.0.1:23456".parse().unwrap();
869 let dst = "192.168.31.1:21".parse().unwrap();
870 event!(ConnectionStarted { socket: (src, dst) }, to_router = true)
871 })
872 }
873}