@@ -39,6 +39,30 @@ pub enum ClientDisconnectCause {
3939 ClientMessageError ,
4040 /// The websocket receive stream returned an error.
4141 WebsocketReceiveError ,
42+ /// The websocket receive stream reported that the connection was already closed.
43+ WebsocketReceiveConnectionClosed ,
44+ /// The websocket receive stream was polled after it had already closed.
45+ WebsocketReceiveAlreadyClosed ,
46+ /// The websocket receive stream returned an IO error.
47+ WebsocketReceiveIo ,
48+ /// The websocket receive stream returned a TLS error.
49+ WebsocketReceiveTls ,
50+ /// The websocket receive stream returned a capacity error.
51+ WebsocketReceiveCapacity ,
52+ /// The websocket receive stream returned a protocol error.
53+ WebsocketReceiveProtocol ,
54+ /// The websocket receive stream reported a full write buffer while receiving.
55+ WebsocketReceiveWriteBufferFull ,
56+ /// The websocket receive stream returned a UTF-8 error.
57+ WebsocketReceiveUtf8 ,
58+ /// The websocket receive stream detected an attack attempt.
59+ WebsocketReceiveAttackAttempt ,
60+ /// The websocket receive stream returned a URL error.
61+ WebsocketReceiveUrl ,
62+ /// The websocket receive stream returned an HTTP error.
63+ WebsocketReceiveHttp ,
64+ /// The websocket receive stream returned an HTTP format error.
65+ WebsocketReceiveHttpFormat ,
4266 /// The server failed while sending or flushing websocket data.
4367 WebsocketSendError ,
4468 /// The websocket receive stream ended without a more specific cause.
@@ -48,14 +72,26 @@ pub enum ClientDisconnectCause {
4872}
4973
5074impl ClientDisconnectCause {
51- pub const ALL : [ Self ; 10 ] = [
75+ pub const ALL : [ Self ; 22 ] = [
5276 Self :: ClientClose ,
5377 Self :: IdleTimeout ,
5478 Self :: IncomingQueueFull ,
5579 Self :: OutgoingQueueFull ,
5680 Self :: ModuleExited ,
5781 Self :: ClientMessageError ,
5882 Self :: WebsocketReceiveError ,
83+ Self :: WebsocketReceiveConnectionClosed ,
84+ Self :: WebsocketReceiveAlreadyClosed ,
85+ Self :: WebsocketReceiveIo ,
86+ Self :: WebsocketReceiveTls ,
87+ Self :: WebsocketReceiveCapacity ,
88+ Self :: WebsocketReceiveProtocol ,
89+ Self :: WebsocketReceiveWriteBufferFull ,
90+ Self :: WebsocketReceiveUtf8 ,
91+ Self :: WebsocketReceiveAttackAttempt ,
92+ Self :: WebsocketReceiveUrl ,
93+ Self :: WebsocketReceiveHttp ,
94+ Self :: WebsocketReceiveHttpFormat ,
5995 Self :: WebsocketSendError ,
6096 Self :: WebsocketStreamEnded ,
6197 Self :: Unknown ,
@@ -70,6 +106,18 @@ impl ClientDisconnectCause {
70106 Self :: ModuleExited => "module_exited" ,
71107 Self :: ClientMessageError => "client_message_error" ,
72108 Self :: WebsocketReceiveError => "websocket_receive_error" ,
109+ Self :: WebsocketReceiveConnectionClosed => "websocket_receive_connection_closed" ,
110+ Self :: WebsocketReceiveAlreadyClosed => "websocket_receive_already_closed" ,
111+ Self :: WebsocketReceiveIo => "websocket_receive_io" ,
112+ Self :: WebsocketReceiveTls => "websocket_receive_tls" ,
113+ Self :: WebsocketReceiveCapacity => "websocket_receive_capacity" ,
114+ Self :: WebsocketReceiveProtocol => "websocket_receive_protocol" ,
115+ Self :: WebsocketReceiveWriteBufferFull => "websocket_receive_write_buffer_full" ,
116+ Self :: WebsocketReceiveUtf8 => "websocket_receive_utf8" ,
117+ Self :: WebsocketReceiveAttackAttempt => "websocket_receive_attack_attempt" ,
118+ Self :: WebsocketReceiveUrl => "websocket_receive_url" ,
119+ Self :: WebsocketReceiveHttp => "websocket_receive_http" ,
120+ Self :: WebsocketReceiveHttpFormat => "websocket_receive_http_format" ,
73121 Self :: WebsocketSendError => "websocket_send_error" ,
74122 Self :: WebsocketStreamEnded => "websocket_stream_ended" ,
75123 Self :: Unknown => "unknown" ,
@@ -196,7 +244,13 @@ metrics_group!(
196244 // Accepted-client disconnection `cause` label values are:
197245 // client_close, idle_timeout, incoming_queue_full, outgoing_queue_full,
198246 // module_exited, client_message_error, websocket_receive_error,
199- // websocket_send_error, websocket_stream_ended, unknown.
247+ // websocket_receive_connection_closed, websocket_receive_already_closed,
248+ // websocket_receive_io, websocket_receive_tls, websocket_receive_capacity,
249+ // websocket_receive_protocol, websocket_receive_write_buffer_full,
250+ // websocket_receive_utf8, websocket_receive_attack_attempt,
251+ // websocket_receive_url, websocket_receive_http,
252+ // websocket_receive_http_format, websocket_send_error,
253+ // websocket_stream_ended, unknown.
200254 #[ name = spacetime_worker_ws_client_disconnections_total]
201255 #[ help = "The cumulative number of accepted websocket client disconnections by cause. Cause values are documented by ClientDisconnectCause::ALL." ]
202256 #[ labels( database_identity: Identity , cause: str ) ]
@@ -805,6 +859,15 @@ pub fn spawn_tokio_stats(node_id: String, rt_id: String, rt: tokio::runtime::Han
805859#[ cfg( test) ]
806860mod tests {
807861 use super :: * ;
862+ use std:: collections:: HashSet ;
863+
864+ #[ test]
865+ fn client_disconnect_cause_labels_are_unique ( ) {
866+ let mut labels = HashSet :: new ( ) ;
867+ for cause in ClientDisconnectCause :: ALL {
868+ assert ! ( labels. insert( cause. as_str( ) ) , "duplicate label for {cause:?}" ) ;
869+ }
870+ }
808871
809872 #[ test]
810873 fn client_disconnect_recorder_records_only_first_cause ( ) {
0 commit comments