1use std::sync::Arc;
2use std::time::Duration;
3
4use crate::{ChannelDirection, ChannelId, ConnectionId, MethodId, RequestId};
5
6pub type VoxObserverHandle = Arc<dyn VoxObserver>;
7
8pub trait VoxObserver: Send + Sync + 'static {
10 fn rpc_event(&self, _event: RpcEvent) {}
11 fn channel_event(&self, _event: ChannelEvent) {}
12 fn transport_event(&self, _event: TransportEvent) {}
13 fn driver_event(&self, _event: DriverEvent) {}
14}
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub enum RpcSide {
18 Client,
19 Server,
20}
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum RpcOutcome {
24 Ok,
25 Error,
26 Cancelled,
27 Dropped,
28 Closed,
29 SendFailed,
30 Indeterminate,
31}
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq)]
34pub enum RpcEvent {
35 Started {
36 side: RpcSide,
37 service: Option<&'static str>,
38 method: Option<&'static str>,
39 method_id: MethodId,
40 },
41 Finished {
42 side: RpcSide,
43 service: Option<&'static str>,
44 method: Option<&'static str>,
45 method_id: MethodId,
46 outcome: RpcOutcome,
47 elapsed: Duration,
48 },
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq)]
52pub enum ChannelTrySendOutcome {
53 Sent,
54 FullCredit,
55 FullRuntimeQueue,
56 Unbound,
57 Closed,
58}
59
60#[derive(Clone, Copy, Debug, PartialEq, Eq)]
61pub enum ChannelSendOutcome {
62 Sent,
63 Closed,
64 TransportError,
65}
66
67#[derive(Clone, Copy, Debug, PartialEq, Eq)]
68pub enum ChannelCloseReason {
69 Local,
70 Remote,
71 Dropped,
72 ConnectionClosed,
73 ReceiverDropped,
74 Unknown,
75}
76
77#[derive(Clone, Copy, Debug, PartialEq, Eq)]
78pub enum ChannelResetReason {
79 Local,
80 Remote,
81 ReceiverDropped,
82 Protocol,
83 ConnectionClosed,
84 Unknown,
85}
86
87#[derive(Clone, Copy, Debug, PartialEq, Eq)]
88pub struct SourceLocation {
89 pub file: &'static str,
90 pub line: u32,
91 pub column: u32,
92}
93
94#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
95pub struct ChannelDebugContext {
96 pub label: Option<&'static str>,
97 pub type_name: Option<&'static str>,
98 pub source_location: Option<SourceLocation>,
99 pub service: Option<&'static str>,
100 pub method: Option<&'static str>,
101}
102
103impl ChannelDebugContext {
104 pub const fn is_empty(&self) -> bool {
105 self.label.is_none()
106 && self.type_name.is_none()
107 && self.source_location.is_none()
108 && self.service.is_none()
109 && self.method.is_none()
110 }
111
112 pub const fn into_option(self) -> Option<Self> {
113 if self.is_empty() { None } else { Some(self) }
114 }
115}
116
117#[derive(Clone, Copy, Debug, PartialEq, Eq)]
118pub struct ChannelEventContext {
119 pub connection_id: Option<ConnectionId>,
120 pub channel_id: ChannelId,
121 pub debug: Option<ChannelDebugContext>,
122}
123
124impl ChannelEventContext {
125 pub const fn new(channel_id: ChannelId) -> Self {
126 Self {
127 connection_id: None,
128 channel_id,
129 debug: None,
130 }
131 }
132}
133
134#[derive(Clone, Copy, Debug, PartialEq, Eq)]
137pub enum ChannelEvent {
138 Opened {
139 channel: ChannelEventContext,
140 direction: ChannelDirection,
141 initial_credit: u32,
142 },
143 SendStarted {
144 channel: ChannelEventContext,
145 },
146 SendWaitingForCredit {
147 channel: ChannelEventContext,
148 },
149 SendFinished {
150 channel: ChannelEventContext,
151 outcome: ChannelSendOutcome,
152 elapsed: Duration,
153 },
154 TrySend {
155 channel: ChannelEventContext,
156 outcome: ChannelTrySendOutcome,
157 },
158 CreditGranted {
159 channel: ChannelEventContext,
160 amount: u32,
161 },
162 ItemReceived {
163 channel: ChannelEventContext,
164 },
165 ItemConsumed {
166 channel: ChannelEventContext,
167 },
168 Closed {
169 channel: ChannelEventContext,
170 reason: ChannelCloseReason,
171 },
172 Reset {
173 channel: ChannelEventContext,
174 reason: ChannelResetReason,
175 },
176}
177
178#[derive(Clone, Copy, Debug, PartialEq, Eq)]
179pub enum ConnectionCloseReason {
180 Local,
181 Remote,
182 Protocol,
183 Transport,
184 SessionShutdown,
185 CallerDropped,
186 Unknown,
187}
188
189#[derive(Clone, Copy, Debug, PartialEq, Eq)]
190pub enum DecodeErrorKind {
191 Schema,
192 Payload,
193 Protocol,
194 Unknown,
195}
196
197#[derive(Clone, Copy, Debug, PartialEq, Eq)]
198pub enum EncodeErrorKind {
199 Schema,
200 Payload,
201 Transport,
202 Unknown,
203}
204
205#[derive(Clone, Copy, Debug, PartialEq, Eq)]
206pub enum ProtocolErrorKind {
207 InvalidConnection,
208 InvalidRequest,
209 InvalidChannel,
210 Schema,
211 FlowControl,
212 Unknown,
213}
214
215#[derive(Clone, Copy, Debug, PartialEq, Eq)]
217pub enum DriverEvent {
218 ConnectionOpened {
219 connection_id: ConnectionId,
220 },
221 ConnectionClosed {
222 connection_id: ConnectionId,
223 reason: ConnectionCloseReason,
224 },
225 RequestStarted {
226 connection_id: ConnectionId,
227 request_id: RequestId,
228 method_id: MethodId,
229 },
230 RequestFinished {
231 connection_id: ConnectionId,
232 request_id: RequestId,
233 outcome: RpcOutcome,
234 elapsed: Duration,
235 },
236 OutboundQueueFull {
237 connection_id: ConnectionId,
238 },
239 OutboundQueueClosed {
240 connection_id: ConnectionId,
241 },
242 FrameRead {
243 connection_id: ConnectionId,
244 bytes: usize,
245 },
246 FrameWritten {
247 connection_id: ConnectionId,
248 bytes: usize,
249 },
250 DecodeError {
251 connection_id: ConnectionId,
252 kind: DecodeErrorKind,
253 },
254 EncodeError {
255 connection_id: ConnectionId,
256 kind: EncodeErrorKind,
257 },
258 ProtocolError {
259 connection_id: ConnectionId,
260 kind: ProtocolErrorKind,
261 },
262}
263
264#[derive(Clone, Copy, Debug, PartialEq, Eq)]
265pub enum TransportEvent {
266 FrameRead {
267 connection_id: Option<ConnectionId>,
268 bytes: usize,
269 },
270 FrameWritten {
271 connection_id: Option<ConnectionId>,
272 bytes: usize,
273 },
274 Closed {
275 connection_id: Option<ConnectionId>,
276 reason: ConnectionCloseReason,
277 },
278}