use crate::serde::Serialize;
use crate::tina::data::json::{JsonToString, ToJson};
use crate::tina::util::string::{CharIndex, StringExt};
use serde_json::{Map, Value};
use std::borrow::Cow;
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::mem::swap;
use std::ops::Deref;
use std::sync::atomic::{AtomicBool, AtomicI64, AtomicUsize, Ordering};
use std::sync::{Arc, RwLock};
use tracing::Level;
pub struct RequestLogParam {
level: RwLock<Level>,
contains_sensitive_param: AtomicBool,
user_id: RwLock<String>,
request_uri: RwLock<String>,
remote_ip_address: RwLock<String>,
http_method: RwLock<String>,
handler_name: RwLock<String>,
max_param_len: AtomicUsize,
start_time_millis: AtomicI64,
end_time_millis: AtomicI64,
raw_param: RwLock<Arc<String>>,
param: RwLock<Arc<Value>>,
result: RwLock<Arc<Value>>,
err: RwLock<Option<Arc<Value>>>,
}
impl Default for RequestLogParam {
fn default() -> Self {
Self::new()
}
}
impl RequestLogParam {
pub fn new() -> RequestLogParam {
RequestLogParam {
level: RwLock::new(Level::DEBUG),
contains_sensitive_param: Default::default(),
user_id: RwLock::new("unkown".to_string()),
request_uri: RwLock::new("unkown".to_string()),
remote_ip_address: RwLock::new("unkown".to_string()),
http_method: RwLock::new("unkown".to_string()),
handler_name: Default::default(),
max_param_len: Default::default(),
start_time_millis: Default::default(),
end_time_millis: Default::default(),
raw_param: Default::default(),
param: RwLock::new(Arc::new(Default::default())),
result: RwLock::new(Arc::new(Default::default())),
err: Default::default(),
}
}
pub fn set_log_level(&self, level: Level) {
match self.level.write() {
Ok(mut v) => (*v) = level,
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn get_log_level(&self) -> Level {
match self.level.read() {
Ok(v) => *v,
Err(err) => {
tracing::error!("{}", err);
Level::DEBUG
}
}
}
pub fn set_contains_sensitive_param(&self, contains_sensitive_param: bool) {
self.contains_sensitive_param.store(contains_sensitive_param, Ordering::Relaxed);
}
pub fn set_user_id(&self, user_id: String) {
match self.user_id.write() {
Ok(mut v) => (*v) = user_id,
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn set_request_uri(&self, request_uri: String) {
match self.request_uri.write() {
Ok(mut v) => (*v) = request_uri,
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn set_remote_ip_address(&self, remote_ip_address: String) {
match self.remote_ip_address.write() {
Ok(mut v) => (*v) = remote_ip_address,
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn set_http_method(&self, http_method: String) {
match self.http_method.write() {
Ok(mut v) => (*v) = http_method,
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn set_handler_name(&self, handler_name: String) {
match self.handler_name.write() {
Ok(mut v) => (*v) = handler_name,
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn set_max_param_len(&self, max_param_len: usize) {
self.max_param_len.store(max_param_len, Ordering::Relaxed);
}
pub fn set_start_time_millis(&self, start_time_millis: i64) {
self.start_time_millis.store(start_time_millis, Ordering::Relaxed);
}
pub fn set_end_time_millis(&self, end_time_millis: i64) {
self.end_time_millis.store(end_time_millis, Ordering::Relaxed);
}
pub fn set_param(&self, param: Arc<Value>) {
match self.param.write() {
Ok(mut v) => (*v) = param,
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn set_param_val<T: Serialize>(&self, param: &T) {
let mut value = param.to_json_value();
filter_non_null(&mut value);
self.set_param(Arc::new(value));
}
pub fn get_param(&self) -> Option<Arc<Value>> {
match self.param.read() {
Ok(v) => Some((*v).clone()),
Err(err) => {
tracing::error!("{}", err);
None
}
}
}
pub fn set_raw_param(&self, param: String) {
match self.raw_param.write() {
Ok(mut v) => (*v) = Arc::new(param),
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn set_raw_param_lossy(&self, param: Cow<'_, str>) {
match self.raw_param.write() {
Ok(mut v) => {
(*v) = match param {
Cow::Borrowed(s) => Arc::new(s.to_string()),
Cow::Owned(s) => Arc::new(s),
}
}
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn get_raw_param(&self) -> Option<Arc<String>> {
match self.raw_param.read() {
Ok(v) => Some((*v).clone()),
Err(err) => {
tracing::error!("{}", err);
None
}
}
}
pub fn set_result(&self, result: Arc<Value>) {
match self.result.write() {
Ok(mut v) => (*v) = result,
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn set_result_val<T: Serialize>(&self, result: &T) {
let mut value = result.to_json_value();
filter_non_null(&mut value);
self.set_result(Arc::new(value));
}
pub fn get_result(&self) -> Option<Arc<Value>> {
match self.result.read() {
Ok(v) => Some((*v).clone()),
Err(err) => {
tracing::error!("{}", err);
None
}
}
}
pub fn set_err(&self, err: impl Error) {
match self.err.write() {
Ok(mut v) => (*v) = Some(Arc::new(Value::String(format!("{}", err)))),
Err(err) => {
tracing::error!("{}", err);
}
}
}
pub fn get_err(&self) -> Option<Arc<Value>> {
match self.err.read() {
Ok(v) => (*v).clone(),
Err(err) => {
tracing::error!("{}", err);
None
}
}
}
pub fn get_execution_time_millis(&self) -> i64 {
self.end_time_millis.load(Ordering::Relaxed) - self.start_time_millis.load(Ordering::Relaxed)
}
}
fn filter_non_null(value: &mut Value) {
match value {
Value::Null => {}
Value::Bool(_) => {}
Value::Number(_) => {}
Value::String(_) => {}
Value::Array(v) => {
for item in v.iter_mut() {
filter_non_null(item);
}
}
Value::Object(map) => {
let mut tmp = Map::new();
swap(map, &mut tmp);
for (k, v) in tmp.into_iter() {
match v {
Value::Null => {}
Value::Array(mut arr) => {
for item in arr.iter_mut() {
filter_non_null(item);
}
map.insert(k, Value::Array(arr));
}
Value::Object(item) => {
let mut v = Value::Object(item);
filter_non_null(&mut v);
map.insert(k, v);
}
_ => {
map.insert(k, v);
}
}
}
}
}
}
impl Display for RequestLogParam {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
let contains_sensitive_param = self.contains_sensitive_param.load(Ordering::Relaxed);
let handler_name = match self.handler_name.read() {
Ok(v) => v.deref().to_string(),
Err(err) => {
tracing::error!("{}", err);
"[锁异常]".to_owned()
}
};
let raw_param = match contains_sensitive_param {
true => "[包含敏感信息, 不显示内容]".to_owned(),
false => match self.raw_param.read() {
Ok(param) => param.deref().to_string(),
Err(err) => {
tracing::error!("{}", err);
"[锁异常]".to_owned()
}
},
};
let param = match contains_sensitive_param {
true => "[包含敏感信息, 不显示内容]".to_owned(),
false => match self.param.read() {
Ok(param) => param.deref().to_json_string(),
Err(err) => {
tracing::error!("{}", err);
"[锁异常]".to_owned()
}
},
};
let mut result = match contains_sensitive_param {
true => "[包含敏感信息, 不显示内容]".to_owned(),
false => match self.result.read() {
Ok(result) => result.deref().to_json_string(),
Err(err) => {
tracing::error!("{}", err);
"[锁异常]".to_owned()
}
},
};
let err = self.get_err().map(|v| {
let mut str_val = v.to_string_value();
if str_val.is_empty() {
str_val = v.to_json_string();
}
str_val
});
if let Some(err) = err {
result = err;
}
let max_len = self.max_param_len.load(Ordering::Relaxed);
let raw_param = match raw_param.char_length() > CharIndex::value_of(max_len) {
true => (raw_param.substring(CharIndex::ZERO..CharIndex::value_of(max_len)), Cow::Borrowed(" (参数过长)...")),
false => (Cow::Borrowed(raw_param.as_str()), Cow::Borrowed("")),
};
let param = match param.char_length() > CharIndex::value_of(max_len) {
true => (param.substring(CharIndex::ZERO..CharIndex::value_of(max_len)), Cow::Borrowed(" (参数过长)...")),
false => (Cow::Borrowed(param.as_str()), Cow::Borrowed("")),
};
let result = match result.char_length() > CharIndex::value_of(max_len) {
true => (result.substring(CharIndex::ZERO..CharIndex::value_of(max_len)), Cow::Borrowed(" (参数过长)...")),
false => (Cow::Borrowed(result.as_str()), Cow::Borrowed("")),
};
let execution_time_seconds = (self.get_execution_time_millis() as f64) / 1000f64;
let execution_time_seconds = match execution_time_seconds > 0f64 {
true => execution_time_seconds,
false => 0f64,
};
let user_id = match self.user_id.read() {
Ok(v) => v.deref().to_string(),
Err(err) => {
tracing::error!("{}", err);
"[锁异常]".to_owned()
}
};
let remote_ip_address = match self.remote_ip_address.read() {
Ok(v) => v.deref().to_string(),
Err(err) => {
tracing::error!("{}", err);
"[锁异常]".to_owned()
}
};
let http_method = match self.http_method.read() {
Ok(v) => v.deref().to_string(),
Err(err) => {
tracing::error!("{}", err);
"[锁异常]".to_owned()
}
};
let request_uri = match self.request_uri.read() {
Ok(v) => v.deref().to_string(),
Err(err) => {
tracing::error!("{}", err);
"[锁异常]".to_owned()
}
};
let sep = match cfg!(debug_assertions) {
true => "\r\n",
false => " | ",
};
let msg = format!(
"用户: {} | 来源({}) | 请求{}接口: {} | 方法名: {}{}原始参数: {}{}{}有效参数: {}{}{}返回结果: {}{}{}运行时间: {}秒",
user_id,
remote_ip_address,
http_method,
request_uri,
handler_name,
sep,
raw_param.0,
raw_param.1,
sep,
param.0,
param.1,
sep,
result.0,
result.1,
sep,
execution_time_seconds
);
f.write_str(msg.as_str())
}
}