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