1 // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
2 
3 use std::ffi::CStr;
4 
5 use crate::grpc_sys::{self, gpr_log_func_args, gpr_log_severity};
6 use log::{self, Level, LevelFilter, Record};
7 
8 #[inline]
severity_to_log_level(severity: gpr_log_severity) -> Level9 fn severity_to_log_level(severity: gpr_log_severity) -> Level {
10     match severity {
11         gpr_log_severity::GPR_LOG_SEVERITY_DEBUG => Level::Debug,
12         gpr_log_severity::GPR_LOG_SEVERITY_INFO => Level::Info,
13         gpr_log_severity::GPR_LOG_SEVERITY_ERROR => Level::Error,
14     }
15 }
16 
delegate(c_args: *mut gpr_log_func_args)17 extern "C" fn delegate(c_args: *mut gpr_log_func_args) {
18     let args = unsafe { &*c_args };
19     let level = severity_to_log_level(args.severity);
20     if !log_enabled!(level) {
21         return;
22     }
23 
24     // can't panic.
25     let file_str = unsafe { CStr::from_ptr(args.file).to_str().unwrap() };
26     let line = args.line as u32;
27 
28     let msg = unsafe { CStr::from_ptr(args.message).to_string_lossy() };
29     log::logger().log(
30         &Record::builder()
31             .args(format_args!("{msg}"))
32             .level(level)
33             .file_static(file_str.into())
34             .line(line.into())
35             .module_path_static(module_path!().into())
36             .build(),
37     );
38 }
39 
40 /// Redirect grpc log to rust's log implementation.
redirect_log()41 pub fn redirect_log() {
42     let level = match log::max_level() {
43         LevelFilter::Off => unsafe {
44             // disable log.
45             grpc_sys::gpr_set_log_function(None);
46             return;
47         },
48         LevelFilter::Error | LevelFilter::Warn => gpr_log_severity::GPR_LOG_SEVERITY_ERROR,
49         LevelFilter::Info => gpr_log_severity::GPR_LOG_SEVERITY_INFO,
50         LevelFilter::Debug | LevelFilter::Trace => gpr_log_severity::GPR_LOG_SEVERITY_DEBUG,
51     };
52 
53     unsafe {
54         grpc_sys::gpr_set_log_verbosity(level);
55         grpc_sys::gpr_set_log_function(Some(delegate));
56     }
57 }
58