// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. use std::ffi::CStr; use crate::grpc_sys::{self, gpr_log_func_args, gpr_log_severity}; use log::{self, Level, LevelFilter, Record}; #[inline] fn severity_to_log_level(severity: gpr_log_severity) -> Level { match severity { gpr_log_severity::GPR_LOG_SEVERITY_DEBUG => Level::Debug, gpr_log_severity::GPR_LOG_SEVERITY_INFO => Level::Info, gpr_log_severity::GPR_LOG_SEVERITY_ERROR => Level::Error, } } extern "C" fn delegate(c_args: *mut gpr_log_func_args) { let args = unsafe { &*c_args }; let level = severity_to_log_level(args.severity); if !log_enabled!(level) { return; } // can't panic. let file_str = unsafe { CStr::from_ptr(args.file).to_str().unwrap() }; let line = args.line as u32; let msg = unsafe { CStr::from_ptr(args.message).to_string_lossy() }; log::logger().log( &Record::builder() .args(format_args!("{msg}")) .level(level) .file_static(file_str.into()) .line(line.into()) .module_path_static(module_path!().into()) .build(), ); } /// Redirect grpc log to rust's log implementation. pub fn redirect_log() { let level = match log::max_level() { LevelFilter::Off => unsafe { // disable log. grpc_sys::gpr_set_log_function(None); return; }, LevelFilter::Error | LevelFilter::Warn => gpr_log_severity::GPR_LOG_SEVERITY_ERROR, LevelFilter::Info => gpr_log_severity::GPR_LOG_SEVERITY_INFO, LevelFilter::Debug | LevelFilter::Trace => gpr_log_severity::GPR_LOG_SEVERITY_DEBUG, }; unsafe { grpc_sys::gpr_set_log_verbosity(level); grpc_sys::gpr_set_log_function(Some(delegate)); } }