1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! This module provides convenience functions for doh logging.
16
17 use crate::connection::driver::Cause;
18 use crate::connection::driver::HandshakeInfo;
19 use crate::connection::driver::HandshakeResult;
20 use statslog_rust::network_dns_handshake_reported::{
21 Cause as StatsdCause, NetworkDnsHandshakeReported, NetworkType as StatsdNetworkType,
22 PrivateDnsMode as StatsdPrivateDnsMode, Protocol as StatsdProtocol, Result as StatsdResult,
23 };
24
25 const CELLULAR: u32 = 1;
26 const WIFI: u32 = 2;
27 const BLUETOOTH: u32 = 3;
28 const ETHERNET: u32 = 4;
29 const VPN: u32 = 5;
30 const WIFI_AWARE: u32 = 6;
31 const LOWPAN: u32 = 7;
32 const CELLULAR_VPN: u32 = 8;
33 const WIFI_VPN: u32 = 9;
34 const BLUETOOTH_VPN: u32 = 10;
35 const ETHERNET_VPN: u32 = 11;
36 const WIFI_CELLULAR_VPN: u32 = 12;
37
38 const OFF: u32 = 1;
39 const OPPORTUNISTIC: u32 = 2;
40 const STRICT: u32 = 3;
41
42 const TLS1_3_VERSION: u32 = 3;
43
create_default_handshake_atom() -> NetworkDnsHandshakeReported44 fn create_default_handshake_atom() -> NetworkDnsHandshakeReported {
45 NetworkDnsHandshakeReported {
46 protocol: StatsdProtocol::ProtoUnknown,
47 result: StatsdResult::HrUnknown,
48 cause: StatsdCause::HcUnknown,
49 network_type: StatsdNetworkType::NtUnknown,
50 private_dns_mode: StatsdPrivateDnsMode::PdmUnknown,
51 latency_micros: -1,
52 bytes_sent: -1,
53 bytes_received: -1,
54 round_trips: -1,
55 tls_session_cache_hit: false,
56 tls_version: -1,
57 hostname_verification: false,
58 quic_version: -1,
59 server_index: -1,
60 sampling_rate_denom: -1,
61 }
62 }
63
construct_handshake_event_stats( result: HandshakeResult, handshake_info: HandshakeInfo, ) -> NetworkDnsHandshakeReported64 fn construct_handshake_event_stats(
65 result: HandshakeResult,
66 handshake_info: HandshakeInfo,
67 ) -> NetworkDnsHandshakeReported {
68 let mut handshake_event_atom = create_default_handshake_atom();
69 handshake_event_atom.protocol = StatsdProtocol::ProtoDoh;
70 handshake_event_atom.result = match result {
71 HandshakeResult::Success => StatsdResult::HrSuccess,
72 HandshakeResult::Timeout => StatsdResult::HrTimeout,
73 _ => StatsdResult::HrUnknown,
74 };
75 handshake_event_atom.cause = match handshake_info.cause {
76 Cause::Probe => StatsdCause::HcServerProbe,
77 Cause::Reconnect => StatsdCause::HcReconnectAfterIdle,
78 Cause::Retry => StatsdCause::HcRetryAfterError,
79 };
80 handshake_event_atom.network_type = match handshake_info.network_type {
81 CELLULAR => StatsdNetworkType::NtCellular,
82 WIFI => StatsdNetworkType::NtWifi,
83 BLUETOOTH => StatsdNetworkType::NtBluetooth,
84 ETHERNET => StatsdNetworkType::NtEthernet,
85 VPN => StatsdNetworkType::NtVpn,
86 WIFI_AWARE => StatsdNetworkType::NtWifiAware,
87 LOWPAN => StatsdNetworkType::NtLowpan,
88 CELLULAR_VPN => StatsdNetworkType::NtCellularVpn,
89 WIFI_VPN => StatsdNetworkType::NtWifiVpn,
90 BLUETOOTH_VPN => StatsdNetworkType::NtBluetoothVpn,
91 ETHERNET_VPN => StatsdNetworkType::NtEthernetVpn,
92 WIFI_CELLULAR_VPN => StatsdNetworkType::NtWifiCellularVpn,
93 _ => StatsdNetworkType::NtUnknown,
94 };
95 handshake_event_atom.private_dns_mode = match handshake_info.private_dns_mode {
96 OFF => StatsdPrivateDnsMode::PdmOff,
97 OPPORTUNISTIC => StatsdPrivateDnsMode::PdmOpportunistic,
98 STRICT => StatsdPrivateDnsMode::PdmStrict,
99 _ => StatsdPrivateDnsMode::PdmUnknown,
100 };
101 handshake_event_atom.latency_micros = handshake_info.elapsed as i32;
102 handshake_event_atom.bytes_sent = handshake_info.sent_bytes as i32;
103 handshake_event_atom.bytes_received = handshake_info.recv_bytes as i32;
104 handshake_event_atom.tls_session_cache_hit = handshake_info.session_hit_checker;
105 handshake_event_atom.tls_version = TLS1_3_VERSION as i32;
106 handshake_event_atom.hostname_verification = matches!(handshake_info.private_dns_mode, STRICT);
107 handshake_event_atom.quic_version = handshake_info.quic_version as i32;
108 handshake_event_atom
109 }
110
111 /// Log hankshake events via statsd API.
log_handshake_event_stats(result: HandshakeResult, handshake_info: HandshakeInfo)112 pub fn log_handshake_event_stats(result: HandshakeResult, handshake_info: HandshakeInfo) {
113 let handshake_event_stats = construct_handshake_event_stats(result, handshake_info);
114
115 let logging_result = handshake_event_stats.stats_write();
116 if let Err(e) = logging_result {
117 log::error!("Error in logging handshake event. {:?}", e);
118 }
119 }
120
121 #[cfg(test)]
122 mod tests {
123 use super::*;
124
125 #[test]
test_metrics_write()126 fn test_metrics_write() {
127 let handshake_info = HandshakeInfo {
128 cause: Cause::Retry,
129 network_type: WIFI,
130 private_dns_mode: STRICT,
131 elapsed: 42596,
132 sent_bytes: 761,
133 recv_bytes: 6420,
134 session_hit_checker: false,
135 quic_version: 1,
136 };
137 let result = HandshakeResult::Timeout;
138 let handshake_event_stats = construct_handshake_event_stats(result, handshake_info);
139 assert_eq!(handshake_event_stats.protocol as i32, StatsdProtocol::ProtoDoh as i32);
140 assert_eq!(handshake_event_stats.result as i32, HandshakeResult::Timeout as i32);
141 assert_eq!(handshake_event_stats.cause as i32, StatsdCause::HcRetryAfterError as i32);
142 assert_eq!(handshake_event_stats.network_type as i32, StatsdNetworkType::NtWifi as i32);
143 assert_eq!(
144 handshake_event_stats.private_dns_mode as i32,
145 StatsdPrivateDnsMode::PdmStrict as i32
146 );
147 assert_eq!(handshake_event_stats.latency_micros, 42596);
148 assert_eq!(handshake_event_stats.bytes_sent, 761);
149 assert_eq!(handshake_event_stats.bytes_received, 6420);
150 assert_eq!(handshake_event_stats.round_trips, -1);
151 assert!(!handshake_event_stats.tls_session_cache_hit);
152 assert!(handshake_event_stats.hostname_verification);
153 assert_eq!(handshake_event_stats.quic_version, 1);
154 assert_eq!(handshake_event_stats.server_index, -1);
155 assert_eq!(handshake_event_stats.sampling_rate_denom, -1);
156 }
157 }
158