1/* 2 * Copyright (C) 2023 Huawei Device Co., Ltd. 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 16//! Interface definition for rust APIs of hitracechain. 17 18#[macro_use] 19pub mod macros; 20 21use std::ffi::{CString, c_char, c_int, c_ulonglong}; 22use std::ops::BitOr; 23 24/// Enumerate trace flag 25#[non_exhaustive] 26pub enum HiTraceFlag { 27 /// DEFAULT: default value. 28 Default = 0, 29 30 /// trace sync and async call. default: trace sync call only. 31 IncludeAsync = 1 << 0, 32 33 /// do not create child span. default: create child span. 34 DoNotCreateSpan = 1 << 1, 35 36 /// output tracepoint info in span. default: do not output tracepoint info. 37 TpInfo = 1 << 2, 38 39 /// do not output begin and end info. default: output begin and end info. 40 NoBeInfo = 1 << 3, 41 42 /// do not add id to log. default: add id to log. 43 DoNotEnableLog = 1 << 4, 44 45 /// the trace is triggered by fault. 46 FaultTigger = 1 << 5, 47 48 /// output device-to-device tracepoint info in span only. default: do not output device-to-device tracepoint info. 49 D2dTpInfo = 1 << 6, 50} 51 52/// Add support for bitor operating for HiTraceFlag 53impl BitOr for HiTraceFlag { 54 type Output = i32; 55 56 fn bitor(self, rhs: Self) -> Self::Output { 57 (self as i32) | (rhs as i32) 58 } 59} 60 61/// Enumerate trace point type 62#[non_exhaustive] 63pub enum HiTraceTracepointType { 64 65 /// client send 66 Cs = 0, 67 68 /// client receive 69 Cr = 1, 70 71 /// server send 72 Ss = 2, 73 74 /// server receive 75 Sr = 3, 76 77 /// general info 78 General = 4, 79} 80 81/// Enumerate trace communication mode 82#[non_exhaustive] 83pub enum HiTraceCommunicationMode { 84 /// unspecified communication mode 85 Default = 0, 86 87 /// thread-to-thread communication mode 88 Thread = 1, 89 90 /// process-to-process communication mode 91 Process = 2, 92 93 /// device-to-device communication mode 94 Device = 3, 95} 96 97/// This type represent to HiTraceIdStruct defined in C. 98#[repr(C)] 99pub struct HiTraceIdStruct { 100 trace_details: [u64;2], 101} 102 103/// Alias for HiTraceIdStruct 104pub type HiTraceId = HiTraceIdStruct; 105 106impl HiTraceId { 107 /// Judge whether the trace id is valid or not. 108 pub fn is_valid(&self) -> bool { 109 // Safty: call C ffi border function, all risks are under control. 110 unsafe { 111 HiTraceChainIsValidWrapper(self as *const HiTraceId) 112 } 113 } 114 115 /// Judge whether the trace id has enabled a trace flag or not. 116 pub fn is_flag_enabled(&self, flag: HiTraceFlag) -> bool { 117 // Safty: call C ffi border function, all risks are under control. 118 unsafe { 119 HiTraceChainIsFlagEnabledWrapper(self as *const HiTraceId, flag as i32) 120 } 121 } 122 123 /// Enable the designative trace flag for the trace id. 124 pub fn enable_flag(&mut self, flag: HiTraceFlag) { 125 // Safty: call C ffi border function, all risks are under control. 126 unsafe { 127 HiTraceChainEnableFlagWrapper(self as *mut HiTraceId, flag as i32); 128 } 129 } 130 131 /// Set trace flags for the trace id. 132 pub fn set_flags(&mut self, flags: i32) { 133 // Safty: call C ffi border function, all risks are under control. 134 unsafe { 135 HiTraceChainSetFlagsWrapper(self as *mut HiTraceId, flags); 136 } 137 } 138 139 /// Get trace flags of the trace id. 140 pub fn get_flags(&self) -> i32 { 141 // Safty: call C ffi border function, all risks are under control. 142 unsafe { 143 HiTraceChainGetFlagsWrapper(self as *const HiTraceId) 144 } 145 } 146 147 /// Set chain id of the trace id. 148 pub fn set_chain_id(&mut self, chain_id: u64) { 149 // Safty: call C ffi border function, all risks are under control. 150 unsafe { 151 HiTraceChainSetChainIdWrapper(self as *mut HiTraceId, chain_id); 152 } 153 } 154 155 /// Get chain id of the trace id. 156 pub fn get_chain_id(&self) -> u64 { 157 // Safty: call C ffi border function, all risks are under control. 158 unsafe { 159 HiTraceChainGetChainIdWrapper(self as *const HiTraceId) 160 } 161 } 162 163 /// Set span id of the trace id. 164 pub fn set_span_id(&mut self, span_id: u64) { 165 // Safty: call C ffi border function, all risks are under control. 166 unsafe { 167 HiTraceChainSetSpanIdWrapper(self as *mut HiTraceId, span_id); 168 } 169 } 170 171 /// Get span id of the trace id. 172 pub fn get_span_id(&self)-> u64 { 173 // Safty: call C ffi border function, all risks are under control. 174 unsafe { 175 HiTraceChainGetSpanIdWrapper(self as *const HiTraceId) 176 } 177 } 178 179 /// Set parent span id of the trace id. 180 pub fn set_parent_span_id(&mut self, parent_span_id: u64) { 181 // Safty: call C ffi border function, all risks are under control. 182 unsafe { 183 HiTraceChainSetParentSpanIdWrapper(self as *mut HiTraceId, parent_span_id); 184 } 185 } 186 187 /// Get parent span id of the trace id. 188 pub fn get_parent_span_id(&self) -> u64 { 189 // Safty: call C ffi border function, all risks are under control. 190 unsafe { 191 HiTraceChainGetParentSpanIdWrapper(self as *const HiTraceId) 192 } 193 } 194} 195 196/// Start tracing a process impl. 197pub fn begin(name: &str, flags: i32) -> HiTraceId { 198 // Safty: call C ffi border function, all risks are under control. 199 unsafe { 200 let name = CString::new(name).unwrap(); 201 HiTraceChainBegin(name.as_ptr() as *const c_char, flags) 202 } 203} 204 205/// Stop process tracing and clear trace id of current thread if the given trace 206/// id is valid, otherwise do nothing. 207pub fn end(id: &HiTraceId) { 208 // Safty: call C ffi border function, all risks are under control. 209 unsafe { 210 HiTraceChainEnd(id as *const HiTraceId); 211 } 212} 213 214/// Get trace id of current thread, and return a invalid trace id if no 215/// trace id belong to current thread 216pub fn get_id() -> HiTraceId { 217 // Safty: call C ffi border function, all risks are under control. 218 unsafe { 219 HiTraceChainGetId() 220 } 221} 222 223/// Set id as trace id of current thread. Do nothing if id is invalid. 224pub fn set_id(id: &HiTraceId) { 225 // Safty: call C ffi border function, all risks are under control. 226 unsafe { 227 HiTraceChainSetId(id as *const HiTraceId); 228 } 229} 230 231/// Clear trace id of current thread and set it invalid. 232pub fn clear_id() { 233 // Safty: call C ffi border function, all risks are under control. 234 unsafe { 235 HiTraceChainClearId(); 236 } 237} 238 239/// Create a new span id according to the trace id of current thread. 240pub fn create_span() -> HiTraceId { 241 // Safty: call C ffi border function, all risks are under control. 242 unsafe { 243 HiTraceChainCreateSpan() 244 } 245} 246 247/// Persist a trace id into a uint8_t array 248pub fn id_to_bytes(p_id: &HiTraceId, p_id_array: &mut [u8]) -> i32 { 249 let arr_len = p_id_array.len(); 250 let mut id_array_wrapper: Vec<u8> = vec![]; 251 for &item in p_id_array.iter().take(arr_len) { 252 id_array_wrapper.push(item); 253 } 254 // Safty: call C ffi border function, all risks are under control. 255 unsafe { 256 let ret = HiTraceChainIdToBytesWrapper(p_id as *const HiTraceId, 257 id_array_wrapper.as_mut_ptr(), 258 arr_len as c_int); 259 p_id_array[..arr_len].copy_from_slice(&id_array_wrapper[..arr_len]); 260 ret 261 } 262} 263 264/// Build a trace id form a uint8_t array 265pub fn bytes_to_id(p_id_array: &[u8]) -> HiTraceId { 266 let mut id_array_wrapper: Vec<u8> = vec![]; 267 for &item in p_id_array { 268 id_array_wrapper.push(item); 269 } 270 // Safty: call C ffi border function, all risks are under control. 271 unsafe { 272 HiTraceChainBytesToIdWrapper(id_array_wrapper.as_mut_ptr(), p_id_array.len() as c_int) 273 } 274} 275 276extern "C" { 277 /// ffi border function 278 fn HiTraceChainBegin(name: *const c_char, _flags: c_int) -> HiTraceId; 279 280 /// ffi border function 281 fn HiTraceChainEnd(id: *const HiTraceId); 282 283 /// ffi border function 284 fn HiTraceChainGetId() -> HiTraceId; 285 286 /// ffi border function 287 fn HiTraceChainSetId(id: *const HiTraceId); 288 289 /// ffi border function 290 fn HiTraceChainClearId(); 291 292 /// ffi border function 293 fn HiTraceChainCreateSpan() -> HiTraceId; 294 295 /// ffi border function 296 fn HiTraceChainIdToBytesWrapper(id: *const HiTraceId, p_id_array: *const u8, len: c_int) -> c_int; 297 298 /// ffi border function 299 fn HiTraceChainBytesToIdWrapper(p_id_array: *const u8, len: c_int) -> HiTraceId; 300 301 /// ffi border function 302 #[allow(dead_code)] 303 pub fn HiTraceChainTracepointExWrapper(communication_mode: c_int, trace_type: c_int, 304 p_id: *const HiTraceId, fmt: *const c_char, ...); 305 306 /// ffi border function 307 fn HiTraceChainIsValidWrapper(p_id: *const HiTraceId) -> bool; 308 309 /// ffi border function 310 fn HiTraceChainIsFlagEnabledWrapper(p_id: *const HiTraceId, flag: c_int) -> bool; 311 312 /// ffi border function 313 fn HiTraceChainEnableFlagWrapper(p_id: *mut HiTraceId, flag: c_int); 314 315 /// ffi border function 316 fn HiTraceChainSetFlagsWrapper(p_id: *mut HiTraceId, flags: c_int); 317 318 /// ffi border function 319 fn HiTraceChainGetFlagsWrapper(p_id: *const HiTraceId) -> c_int; 320 321 /// ffi border function 322 fn HiTraceChainSetChainIdWrapper(p_id: *mut HiTraceId, chain_id: c_ulonglong); 323 324 /// ffi border function 325 fn HiTraceChainGetChainIdWrapper(p_id: *const HiTraceId) -> c_ulonglong; 326 327 /// ffi border function 328 fn HiTraceChainSetSpanIdWrapper(p_id: *mut HiTraceId, span_id: c_ulonglong); 329 330 /// ffi border function 331 fn HiTraceChainGetSpanIdWrapper(p_id: *const HiTraceId) -> c_ulonglong; 332 333 /// ffi border function 334 fn HiTraceChainSetParentSpanIdWrapper(p_id: *mut HiTraceId, 335 parent_span_id: c_ulonglong); 336 337 /// ffi border function 338 fn HiTraceChainGetParentSpanIdWrapper(p_id: *const HiTraceId) -> c_ulonglong; 339} 340