# -*- coding: utf-8 -*-
import logging
import sys
import inspect
from datetime import datetime
class OptimizedFormatter( logging .Formatter ) :
def format( self , record) :
try :
# 智能帧捕获(带缓存优化)
if not hasattr ( record, 'module' ) :
frame = self ._cached_caller_frame( )
if frame:
module = inspect .getmodule ( frame)
record.module = module.__name__ if module else 'unknown'
record.lineno = frame.f_lineno
# 参数统一处理
args_str = self ._process_args( record)
if args_str:
record.msg = u"%s ⎸ %s" % ( record.msg , args_str)
return super ( OptimizedFormatter, self ) .format ( record)
except Exception as e:
return u"⚠️ Format Error | Err: %s | Raw: %s" % ( e, record.getMessage ( ) )
def _cached_caller_frame( self ) :
"""带LRU缓存的帧查找"""
stack = inspect .stack ( )
for frame_info in reversed ( stack) :
frame = frame_info[ 0 ]
if inspect .getmodule ( frame) .__name__ != __name__:
return frame
return inspect .currentframe ( )
def _process_args( self , record) :
"""处理所有参数类型"""
parts = [ ]
# 处理位置参数(修改键名避免冲突)
if hasattr ( record, 'positional_args' ) and record.positional_args :
parts.extend ( self ._safe_repr( a) for a in record.positional_args )
# 处理额外参数
if hasattr ( record, 'extra' ) and record.extra :
parts.extend ( u"%s=%s" % ( k, self ._safe_repr( v) )
for k, v in record.extra .iteritems ( ) )
return u" ⎸ " .join ( parts) if parts else u""
def _safe_repr( self , value) :
"""安全类型转换(增强编码处理)"""
try :
if isinstance ( value, dict ) :
return u"{%s}" % u"," .join ( u"%s:%s" % ( self ._safe_repr( k) , self ._safe_repr( v) )
for k, v in value.iteritems ( ) )
elif isinstance ( value, ( list , tuple ) ) :
return u"[%s]" % u"," .join ( self ._safe_repr( x) for x in value)
return self ._safe_str( value)
except :
return u"<Unprintable>"
def _safe_str( obj) :
"""安全字符串转换(解决编码问题)"""
try :
if isinstance ( obj, str ) :
return obj.decode ( 'utf-8' , 'replace' )
return unicode ( obj)
except UnicodeDecodeError :
return u"<非UTF-8字节数据>"
except :
return u"<无法转换对象>"
class SimpleLogger( object ) :
_initialized = False
@ classmethod
def _ensure_init( cls) :
if not cls._initialized:
root = logging .getLogger ( )
root.setLevel ( logging .DEBUG )
if not root.handlers :
handler = logging .StreamHandler ( )
handler.setFormatter ( OptimizedFormatter(
fmt= u'[%(asctime)s] [%(levelname)s] %(module)s:%(lineno)d ➤ %(message)s' ,
datefmt= '%H:%M:%S'
) )
root.addHandler ( handler)
cls._initialized = True
@ classmethod
def _log( cls, level, msg, *args, **kwargs) :
cls._ensure_init( )
try :
# 预处理消息(确保Unicode)
msg = cls._preprocess_message( msg)
# 智能参数处理
formatted_msg = cls._format_message( msg, args)
# 获取调用者信息
frame = inspect .currentframe ( ) .f_back .f_back
logger = logging .getLogger (
inspect .getmodule ( frame) .__name__
if inspect .getmodule ( frame) else 'unknown'
)
# 创建日志记录(修改参数键名)
logger.log (
level,
formatted_msg,
extra= { 'extra' : kwargs, 'positional_args' : args} # 修改键名
)
except Exception as e:
sys .stderr .write ( u"Log Error: %s\n " % unicode ( e) )
@ staticmethod
def _preprocess_message( msg) :
"""消息预处理(强制转Unicode)"""
if isinstance ( msg, str ) :
try :
return msg.decode ( 'utf-8' )
except UnicodeDecodeError :
return msg.decode ( 'latin-1' , 'replace' )
return unicode ( msg)
@ classmethod
def _format_message( cls, msg, args) :
"""混合参数格式化(增强容错)"""
try :
# 尝试传统格式化
if args and '%' in msg:
return msg % args
except ( TypeError , ValueError ) :
pass
# 自动拼接模式
if args:
return u" " .join ( [ msg] + [ cls._safe_str( a) for a in args] )
return msg
@ classmethod
def debug( cls, msg, *args, **kwargs) :
cls._log( logging .DEBUG , msg, *args, **kwargs)
@ classmethod
def info( cls, msg, *args, **kwargs) :
cls._log( logging .INFO , msg, *args, **kwargs)
@ classmethod
def warning( cls, msg, *args, **kwargs) :
cls._log( logging .WARNING , msg, *args, **kwargs)
@ classmethod
def error( cls, msg, *args, **kwargs) :
cls._log( logging .ERROR , msg, *args, **kwargs)
# 测试用例
if __name__ == "__main__" :
# 测试中文日志
SimpleLogger.info ( u"用户登录" , u"张三" , ip= "192.168.1.100" )
# 测试混合参数
SimpleLogger.error ( "错误发生在 %s" , u"配置文件" , code = 500 , detail= { "line" : 42 } )
# 测试二进制数据
bad_data = '\x e6\x 97\x a0' # UTF-8编码的"无"
SimpleLogger.warning ( "无效数据" , bad_data)
IyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KaW1wb3J0IGxvZ2dpbmcKaW1wb3J0IHN5cwppbXBvcnQgaW5zcGVjdApmcm9tIGRhdGV0aW1lIGltcG9ydCBkYXRldGltZQoKY2xhc3MgT3B0aW1pemVkRm9ybWF0dGVyKGxvZ2dpbmcuRm9ybWF0dGVyKToKICAgIGRlZiBmb3JtYXQoc2VsZiwgcmVjb3JkKToKICAgICAgICB0cnk6CiAgICAgICAgICAgICMg5pm66IO95bin5o2V6I6377yI5bim57yT5a2Y5LyY5YyW77yJCiAgICAgICAgICAgIGlmIG5vdCBoYXNhdHRyKHJlY29yZCwgJ21vZHVsZScpOgogICAgICAgICAgICAgICAgZnJhbWUgPSBzZWxmLl9jYWNoZWRfY2FsbGVyX2ZyYW1lKCkKICAgICAgICAgICAgICAgIGlmIGZyYW1lOgogICAgICAgICAgICAgICAgICAgIG1vZHVsZSA9IGluc3BlY3QuZ2V0bW9kdWxlKGZyYW1lKQogICAgICAgICAgICAgICAgICAgIHJlY29yZC5tb2R1bGUgPSBtb2R1bGUuX19uYW1lX18gaWYgbW9kdWxlIGVsc2UgJ3Vua25vd24nCiAgICAgICAgICAgICAgICAgICAgcmVjb3JkLmxpbmVubyA9IGZyYW1lLmZfbGluZW5vCgogICAgICAgICAgICAjIOWPguaVsOe7n+S4gOWkhOeQhgogICAgICAgICAgICBhcmdzX3N0ciA9IHNlbGYuX3Byb2Nlc3NfYXJncyhyZWNvcmQpCiAgICAgICAgICAgIGlmIGFyZ3Nfc3RyOgogICAgICAgICAgICAgICAgcmVjb3JkLm1zZyA9IHUiJXMg4o64ICVzIiAlIChyZWNvcmQubXNnLCBhcmdzX3N0cikKCiAgICAgICAgICAgIHJldHVybiBzdXBlcihPcHRpbWl6ZWRGb3JtYXR0ZXIsIHNlbGYpLmZvcm1hdChyZWNvcmQpCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICByZXR1cm4gdSLimqDvuI8gRm9ybWF0IEVycm9yIHwgRXJyOiAlcyB8IFJhdzogJXMiICUgKGUsIHJlY29yZC5nZXRNZXNzYWdlKCkpCgogICAgZGVmIF9jYWNoZWRfY2FsbGVyX2ZyYW1lKHNlbGYpOgogICAgICAgICIiIuW4pkxSVee8k+WtmOeahOW4p+afpeaJviIiIgogICAgICAgIHN0YWNrID0gaW5zcGVjdC5zdGFjaygpCiAgICAgICAgZm9yIGZyYW1lX2luZm8gaW4gcmV2ZXJzZWQoc3RhY2spOgogICAgICAgICAgICBmcmFtZSA9IGZyYW1lX2luZm9bMF0KICAgICAgICAgICAgaWYgaW5zcGVjdC5nZXRtb2R1bGUoZnJhbWUpLl9fbmFtZV9fICE9IF9fbmFtZV9fOgogICAgICAgICAgICAgICAgcmV0dXJuIGZyYW1lCiAgICAgICAgcmV0dXJuIGluc3BlY3QuY3VycmVudGZyYW1lKCkKCiAgICBkZWYgX3Byb2Nlc3NfYXJncyhzZWxmLCByZWNvcmQpOgogICAgICAgICIiIuWkhOeQhuaJgOacieWPguaVsOexu+WeiyIiIgogICAgICAgIHBhcnRzID0gW10KICAgICAgICAKICAgICAgICAjIOWkhOeQhuS9jee9ruWPguaVsO+8iOS/ruaUuemUruWQjemBv+WFjeWGsueqge+8iQogICAgICAgIGlmIGhhc2F0dHIocmVjb3JkLCAncG9zaXRpb25hbF9hcmdzJykgYW5kIHJlY29yZC5wb3NpdGlvbmFsX2FyZ3M6CiAgICAgICAgICAgIHBhcnRzLmV4dGVuZChzZWxmLl9zYWZlX3JlcHIoYSkgZm9yIGEgaW4gcmVjb3JkLnBvc2l0aW9uYWxfYXJncykKICAgICAgICAKICAgICAgICAjIOWkhOeQhumineWkluWPguaVsAogICAgICAgIGlmIGhhc2F0dHIocmVjb3JkLCAnZXh0cmEnKSBhbmQgcmVjb3JkLmV4dHJhOgogICAgICAgICAgICBwYXJ0cy5leHRlbmQodSIlcz0lcyIgJSAoaywgc2VsZi5fc2FmZV9yZXByKHYpKSAKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIGssIHYgaW4gcmVjb3JkLmV4dHJhLml0ZXJpdGVtcygpKQogICAgICAgIAogICAgICAgIHJldHVybiB1IiDijrggIi5qb2luKHBhcnRzKSBpZiBwYXJ0cyBlbHNlIHUiIgoKICAgIGRlZiBfc2FmZV9yZXByKHNlbGYsIHZhbHVlKToKICAgICAgICAiIiLlronlhajnsbvlnovovazmjaLvvIjlop7lvLrnvJbnoIHlpITnkIbvvIkiIiIKICAgICAgICB0cnk6CiAgICAgICAgICAgIGlmIGlzaW5zdGFuY2UodmFsdWUsIGRpY3QpOgogICAgICAgICAgICAgICAgcmV0dXJuIHUieyVzfSIgJSB1IiwiLmpvaW4odSIlczolcyIgJSAoc2VsZi5fc2FmZV9yZXByKGspLCBzZWxmLl9zYWZlX3JlcHIodikpIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciBrLCB2IGluIHZhbHVlLml0ZXJpdGVtcygpKQogICAgICAgICAgICBlbGlmIGlzaW5zdGFuY2UodmFsdWUsIChsaXN0LCB0dXBsZSkpOgogICAgICAgICAgICAgICAgcmV0dXJuIHUiWyVzXSIgJSB1IiwiLmpvaW4oc2VsZi5fc2FmZV9yZXByKHgpIGZvciB4IGluIHZhbHVlKQogICAgICAgICAgICByZXR1cm4gc2VsZi5fc2FmZV9zdHIodmFsdWUpCiAgICAgICAgZXhjZXB0OgogICAgICAgICAgICByZXR1cm4gdSI8VW5wcmludGFibGU+IgoKICAgIAogICAgZGVmIF9zYWZlX3N0cihvYmopOgogICAgICAgICIiIuWuieWFqOWtl+espuS4sui9rOaNou+8iOino+WGs+e8lueggemXrumimO+8iSIiIgogICAgICAgIHRyeToKICAgICAgICAgICAgaWYgaXNpbnN0YW5jZShvYmosIHN0cik6CiAgICAgICAgICAgICAgICByZXR1cm4gb2JqLmRlY29kZSgndXRmLTgnLCAncmVwbGFjZScpCiAgICAgICAgICAgIHJldHVybiB1bmljb2RlKG9iaikKICAgICAgICBleGNlcHQgVW5pY29kZURlY29kZUVycm9yOgogICAgICAgICAgICByZXR1cm4gdSI86Z2eVVRGLTjlrZfoioLmlbDmja4+IgogICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgcmV0dXJuIHUiPOaXoOazlei9rOaNouWvueixoT4iCgpjbGFzcyBTaW1wbGVMb2dnZXIob2JqZWN0KToKICAgIF9pbml0aWFsaXplZCA9IEZhbHNlCgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgX2Vuc3VyZV9pbml0KGNscyk6CiAgICAgICAgaWYgbm90IGNscy5faW5pdGlhbGl6ZWQ6CiAgICAgICAgICAgIHJvb3QgPSBsb2dnaW5nLmdldExvZ2dlcigpCiAgICAgICAgICAgIHJvb3Quc2V0TGV2ZWwobG9nZ2luZy5ERUJVRykKICAgICAgICAgICAgaWYgbm90IHJvb3QuaGFuZGxlcnM6CiAgICAgICAgICAgICAgICBoYW5kbGVyID0gbG9nZ2luZy5TdHJlYW1IYW5kbGVyKCkKICAgICAgICAgICAgICAgIGhhbmRsZXIuc2V0Rm9ybWF0dGVyKE9wdGltaXplZEZvcm1hdHRlcigKICAgICAgICAgICAgICAgICAgICBmbXQ9dSdbJShhc2N0aW1lKXNdIFslKGxldmVsbmFtZSlzXSAlKG1vZHVsZSlzOiUobGluZW5vKWQg4p6kICUobWVzc2FnZSlzJywKICAgICAgICAgICAgICAgICAgICBkYXRlZm10PSclSDolTTolUycKICAgICAgICAgICAgICAgICkpCiAgICAgICAgICAgICAgICByb290LmFkZEhhbmRsZXIoaGFuZGxlcikKICAgICAgICAgICAgY2xzLl9pbml0aWFsaXplZCA9IFRydWUKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiBfbG9nKGNscywgbGV2ZWwsIG1zZywgKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICBjbHMuX2Vuc3VyZV9pbml0KCkKICAgICAgICB0cnk6CiAgICAgICAgICAgICMg6aKE5aSE55CG5raI5oGv77yI56Gu5L+dVW5pY29kZe+8iQogICAgICAgICAgICBtc2cgPSBjbHMuX3ByZXByb2Nlc3NfbWVzc2FnZShtc2cpCiAgICAgICAgICAgIAogICAgICAgICAgICAjIOaZuuiDveWPguaVsOWkhOeQhgogICAgICAgICAgICBmb3JtYXR0ZWRfbXNnID0gY2xzLl9mb3JtYXRfbWVzc2FnZShtc2csIGFyZ3MpCiAgICAgICAgICAgIAogICAgICAgICAgICAjIOiOt+WPluiwg+eUqOiAheS/oeaBrwogICAgICAgICAgICBmcmFtZSA9IGluc3BlY3QuY3VycmVudGZyYW1lKCkuZl9iYWNrLmZfYmFjawogICAgICAgICAgICBsb2dnZXIgPSBsb2dnaW5nLmdldExvZ2dlcigKICAgICAgICAgICAgICAgIGluc3BlY3QuZ2V0bW9kdWxlKGZyYW1lKS5fX25hbWVfXyAKICAgICAgICAgICAgICAgIGlmIGluc3BlY3QuZ2V0bW9kdWxlKGZyYW1lKSBlbHNlICd1bmtub3duJwogICAgICAgICAgICApCgogICAgICAgICAgICAjIOWIm+W7uuaXpeW/l+iusOW9le+8iOS/ruaUueWPguaVsOmUruWQje+8iQogICAgICAgICAgICBsb2dnZXIubG9nKAogICAgICAgICAgICAgICAgbGV2ZWwsCiAgICAgICAgICAgICAgICBmb3JtYXR0ZWRfbXNnLAogICAgICAgICAgICAgICAgZXh0cmE9eydleHRyYSc6IGt3YXJncywgJ3Bvc2l0aW9uYWxfYXJncyc6IGFyZ3N9ICAjIOS/ruaUuemUruWQjQogICAgICAgICAgICApCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKHUiTG9nIEVycm9yOiAlc1xuIiAlIHVuaWNvZGUoZSkpCgogICAgQHN0YXRpY21ldGhvZAogICAgZGVmIF9wcmVwcm9jZXNzX21lc3NhZ2UobXNnKToKICAgICAgICAiIiLmtojmga/pooTlpITnkIbvvIjlvLrliLbovaxVbmljb2Rl77yJIiIiCiAgICAgICAgaWYgaXNpbnN0YW5jZShtc2csIHN0cik6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIHJldHVybiBtc2cuZGVjb2RlKCd1dGYtOCcpCiAgICAgICAgICAgIGV4Y2VwdCBVbmljb2RlRGVjb2RlRXJyb3I6CiAgICAgICAgICAgICAgICByZXR1cm4gbXNnLmRlY29kZSgnbGF0aW4tMScsICdyZXBsYWNlJykKICAgICAgICByZXR1cm4gdW5pY29kZShtc2cpCgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgX2Zvcm1hdF9tZXNzYWdlKGNscywgbXNnLCBhcmdzKToKICAgICAgICAiIiLmt7flkIjlj4LmlbDmoLzlvI/ljJbvvIjlop7lvLrlrrnplJnvvIkiIiIKICAgICAgICB0cnk6CiAgICAgICAgICAgICMg5bCd6K+V5Lyg57uf5qC85byP5YyWCiAgICAgICAgICAgIGlmIGFyZ3MgYW5kICclJyBpbiBtc2c6CiAgICAgICAgICAgICAgICByZXR1cm4gbXNnICUgYXJncwogICAgICAgIGV4Y2VwdCAoVHlwZUVycm9yLCBWYWx1ZUVycm9yKToKICAgICAgICAgICAgcGFzcwogICAgICAgIAogICAgICAgICMg6Ieq5Yqo5ou85o6l5qih5byPCiAgICAgICAgaWYgYXJnczoKICAgICAgICAgICAgcmV0dXJuIHUiICIuam9pbihbbXNnXSArIFtjbHMuX3NhZmVfc3RyKGEpIGZvciBhIGluIGFyZ3NdKQogICAgICAgIHJldHVybiBtc2cKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiBkZWJ1ZyhjbHMsIG1zZywgKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICBjbHMuX2xvZyhsb2dnaW5nLkRFQlVHLCBtc2csICphcmdzLCAqKmt3YXJncykKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiBpbmZvKGNscywgbXNnLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgIGNscy5fbG9nKGxvZ2dpbmcuSU5GTywgbXNnLCAqYXJncywgKiprd2FyZ3MpCgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgd2FybmluZyhjbHMsIG1zZywgKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICBjbHMuX2xvZyhsb2dnaW5nLldBUk5JTkcsIG1zZywgKmFyZ3MsICoqa3dhcmdzKQoKICAgIEBjbGFzc21ldGhvZAogICAgZGVmIGVycm9yKGNscywgbXNnLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgIGNscy5fbG9nKGxvZ2dpbmcuRVJST1IsIG1zZywgKmFyZ3MsICoqa3dhcmdzKQoKIyDmtYvor5XnlKjkvosKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgICMg5rWL6K+V5Lit5paH5pel5b+XCiAgICBTaW1wbGVMb2dnZXIuaW5mbyh1IueUqOaIt+eZu+W9lSIsIHUi5byg5LiJIiwgaXA9IjE5Mi4xNjguMS4xMDAiKQogICAgCiAgICAjIOa1i+ivlea3t+WQiOWPguaVsAogICAgU2ltcGxlTG9nZ2VyLmVycm9yKCLplJnor6/lj5HnlJ/lnKggJXMiLCB1IumFjee9ruaWh+S7tiIsIGNvZGU9NTAwLCBkZXRhaWw9eyJsaW5lIjogNDJ9KQogICAgCiAgICAjIOa1i+ivleS6jOi/m+WItuaVsOaNrgogICAgYmFkX2RhdGEgPSAnXHhlNlx4OTdceGEwJyAgIyBVVEYtOOe8lueggeeahCLml6AiCiAgICBTaW1wbGVMb2dnZXIud2FybmluZygi5peg5pWI5pWw5o2uIiwgYmFkX2RhdGEp