# your code goes here
# -*- 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>"
@ staticmethod
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)
IyB5b3VyIGNvZGUgZ29lcyBoZXJlCiMgLSotIGNvZGluZzogdXRmLTggLSotCmltcG9ydCBsb2dnaW5nCmltcG9ydCBzeXMKaW1wb3J0IGluc3BlY3QKZnJvbSBkYXRldGltZSBpbXBvcnQgZGF0ZXRpbWUKCmNsYXNzIE9wdGltaXplZEZvcm1hdHRlcihsb2dnaW5nLkZvcm1hdHRlcik6CiAgICBkZWYgZm9ybWF0KHNlbGYsIHJlY29yZCk6CiAgICAgICAgdHJ5OgogICAgICAgICAgICAjIOaZuuiDveW4p+aNleiOt++8iOW4pue8k+WtmOS8mOWMlu+8iQogICAgICAgICAgICBpZiBub3QgaGFzYXR0cihyZWNvcmQsICdtb2R1bGUnKToKICAgICAgICAgICAgICAgIGZyYW1lID0gc2VsZi5fY2FjaGVkX2NhbGxlcl9mcmFtZSgpCiAgICAgICAgICAgICAgICBpZiBmcmFtZToKICAgICAgICAgICAgICAgICAgICBtb2R1bGUgPSBpbnNwZWN0LmdldG1vZHVsZShmcmFtZSkKICAgICAgICAgICAgICAgICAgICByZWNvcmQubW9kdWxlID0gbW9kdWxlLl9fbmFtZV9fIGlmIG1vZHVsZSBlbHNlICd1bmtub3duJwogICAgICAgICAgICAgICAgICAgIHJlY29yZC5saW5lbm8gPSBmcmFtZS5mX2xpbmVubwoKICAgICAgICAgICAgIyDlj4LmlbDnu5/kuIDlpITnkIYKICAgICAgICAgICAgYXJnc19zdHIgPSBzZWxmLl9wcm9jZXNzX2FyZ3MocmVjb3JkKQogICAgICAgICAgICBpZiBhcmdzX3N0cjoKICAgICAgICAgICAgICAgIHJlY29yZC5tc2cgPSB1IiVzIOKOuCAlcyIgJSAocmVjb3JkLm1zZywgYXJnc19zdHIpCgogICAgICAgICAgICByZXR1cm4gc3VwZXIoT3B0aW1pemVkRm9ybWF0dGVyLCBzZWxmKS5mb3JtYXQocmVjb3JkKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgcmV0dXJuIHUi4pqg77iPIEZvcm1hdCBFcnJvciB8IEVycjogJXMgfCBSYXc6ICVzIiAlIChlLCByZWNvcmQuZ2V0TWVzc2FnZSgpKQoKICAgIGRlZiBfY2FjaGVkX2NhbGxlcl9mcmFtZShzZWxmKToKICAgICAgICAiIiLluKZMUlXnvJPlrZjnmoTluKfmn6Xmib4iIiIKICAgICAgICBzdGFjayA9IGluc3BlY3Quc3RhY2soKQogICAgICAgIGZvciBmcmFtZV9pbmZvIGluIHJldmVyc2VkKHN0YWNrKToKICAgICAgICAgICAgZnJhbWUgPSBmcmFtZV9pbmZvWzBdCiAgICAgICAgICAgIGlmIGluc3BlY3QuZ2V0bW9kdWxlKGZyYW1lKS5fX25hbWVfXyAhPSBfX25hbWVfXzoKICAgICAgICAgICAgICAgIHJldHVybiBmcmFtZQogICAgICAgIHJldHVybiBpbnNwZWN0LmN1cnJlbnRmcmFtZSgpCgogICAgZGVmIF9wcm9jZXNzX2FyZ3Moc2VsZiwgcmVjb3JkKToKICAgICAgICAiIiLlpITnkIbmiYDmnInlj4LmlbDnsbvlnosiIiIKICAgICAgICBwYXJ0cyA9IFtdCiAgICAgICAgCiAgICAgICAgIyDlpITnkIbkvY3nva7lj4LmlbDvvIjkv67mlLnplK7lkI3pgb/lhY3lhrLnqoHvvIkKICAgICAgICBpZiBoYXNhdHRyKHJlY29yZCwgJ3Bvc2l0aW9uYWxfYXJncycpIGFuZCByZWNvcmQucG9zaXRpb25hbF9hcmdzOgogICAgICAgICAgICBwYXJ0cy5leHRlbmQoc2VsZi5fc2FmZV9yZXByKGEpIGZvciBhIGluIHJlY29yZC5wb3NpdGlvbmFsX2FyZ3MpCiAgICAgICAgCiAgICAgICAgIyDlpITnkIbpop3lpJblj4LmlbAKICAgICAgICBpZiBoYXNhdHRyKHJlY29yZCwgJ2V4dHJhJykgYW5kIHJlY29yZC5leHRyYToKICAgICAgICAgICAgcGFydHMuZXh0ZW5kKHUiJXM9JXMiICUgKGssIHNlbGYuX3NhZmVfcmVwcih2KSkgCiAgICAgICAgICAgICAgICAgICAgICAgIGZvciBrLCB2IGluIHJlY29yZC5leHRyYS5pdGVyaXRlbXMoKSkKICAgICAgICAKICAgICAgICByZXR1cm4gdSIg4o64ICIuam9pbihwYXJ0cykgaWYgcGFydHMgZWxzZSB1IiIKCiAgICBkZWYgX3NhZmVfcmVwcihzZWxmLCB2YWx1ZSk6CiAgICAgICAgIiIi5a6J5YWo57G75Z6L6L2s5o2i77yI5aKe5by657yW56CB5aSE55CG77yJIiIiCiAgICAgICAgdHJ5OgogICAgICAgICAgICBpZiBpc2luc3RhbmNlKHZhbHVlLCBkaWN0KToKICAgICAgICAgICAgICAgIHJldHVybiB1Inslc30iICUgdSIsIi5qb2luKHUiJXM6JXMiICUgKHNlbGYuX3NhZmVfcmVwcihrKSwgc2VsZi5fc2FmZV9yZXByKHYpKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgaywgdiBpbiB2YWx1ZS5pdGVyaXRlbXMoKSkKICAgICAgICAgICAgZWxpZiBpc2luc3RhbmNlKHZhbHVlLCAobGlzdCwgdHVwbGUpKToKICAgICAgICAgICAgICAgIHJldHVybiB1Ilslc10iICUgdSIsIi5qb2luKHNlbGYuX3NhZmVfcmVwcih4KSBmb3IgeCBpbiB2YWx1ZSkKICAgICAgICAgICAgcmV0dXJuIHNlbGYuX3NhZmVfc3RyKHZhbHVlKQogICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgcmV0dXJuIHUiPFVucHJpbnRhYmxlPiIKCiAgICBAc3RhdGljbWV0aG9kCiAgICBkZWYgX3NhZmVfc3RyKG9iaik6CiAgICAgICAgIiIi5a6J5YWo5a2X56ym5Liy6L2s5o2i77yI6Kej5Yaz57yW56CB6Zeu6aKY77yJIiIiCiAgICAgICAgdHJ5OgogICAgICAgICAgICBpZiBpc2luc3RhbmNlKG9iaiwgc3RyKToKICAgICAgICAgICAgICAgIHJldHVybiBvYmouZGVjb2RlKCd1dGYtOCcsICdyZXBsYWNlJykKICAgICAgICAgICAgcmV0dXJuIHVuaWNvZGUob2JqKQogICAgICAgIGV4Y2VwdCBVbmljb2RlRGVjb2RlRXJyb3I6CiAgICAgICAgICAgIHJldHVybiB1IjzpnZ5VVEYtOOWtl+iKguaVsOaNrj4iCiAgICAgICAgZXhjZXB0OgogICAgICAgICAgICByZXR1cm4gdSI85peg5rOV6L2s5o2i5a+56LGhPiIKCmNsYXNzIFNpbXBsZUxvZ2dlcihvYmplY3QpOgogICAgX2luaXRpYWxpemVkID0gRmFsc2UKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiBfZW5zdXJlX2luaXQoY2xzKToKICAgICAgICBpZiBub3QgY2xzLl9pbml0aWFsaXplZDoKICAgICAgICAgICAgcm9vdCA9IGxvZ2dpbmcuZ2V0TG9nZ2VyKCkKICAgICAgICAgICAgcm9vdC5zZXRMZXZlbChsb2dnaW5nLkRFQlVHKQogICAgICAgICAgICBpZiBub3Qgcm9vdC5oYW5kbGVyczoKICAgICAgICAgICAgICAgIGhhbmRsZXIgPSBsb2dnaW5nLlN0cmVhbUhhbmRsZXIoKQogICAgICAgICAgICAgICAgaGFuZGxlci5zZXRGb3JtYXR0ZXIoT3B0aW1pemVkRm9ybWF0dGVyKAogICAgICAgICAgICAgICAgICAgIGZtdD11J1slKGFzY3RpbWUpc10gWyUobGV2ZWxuYW1lKXNdICUobW9kdWxlKXM6JShsaW5lbm8pZCDinqQgJShtZXNzYWdlKXMnLAogICAgICAgICAgICAgICAgICAgIGRhdGVmbXQ9JyVIOiVNOiVTJwogICAgICAgICAgICAgICAgKSkKICAgICAgICAgICAgICAgIHJvb3QuYWRkSGFuZGxlcihoYW5kbGVyKQogICAgICAgICAgICBjbHMuX2luaXRpYWxpemVkID0gVHJ1ZQoKICAgIEBjbGFzc21ldGhvZAogICAgZGVmIF9sb2coY2xzLCBsZXZlbCwgbXNnLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgIGNscy5fZW5zdXJlX2luaXQoKQogICAgICAgIHRyeToKICAgICAgICAgICAgIyDpooTlpITnkIbmtojmga/vvIjnoa7kv51Vbmljb2Rl77yJCiAgICAgICAgICAgIG1zZyA9IGNscy5fcHJlcHJvY2Vzc19tZXNzYWdlKG1zZykKICAgICAgICAgICAgCiAgICAgICAgICAgICMg5pm66IO95Y+C5pWw5aSE55CGCiAgICAgICAgICAgIGZvcm1hdHRlZF9tc2cgPSBjbHMuX2Zvcm1hdF9tZXNzYWdlKG1zZywgYXJncykKICAgICAgICAgICAgCiAgICAgICAgICAgICMg6I635Y+W6LCD55So6ICF5L+h5oGvCiAgICAgICAgICAgIGZyYW1lID0gaW5zcGVjdC5jdXJyZW50ZnJhbWUoKS5mX2JhY2suZl9iYWNrCiAgICAgICAgICAgIGxvZ2dlciA9IGxvZ2dpbmcuZ2V0TG9nZ2VyKAogICAgICAgICAgICAgICAgaW5zcGVjdC5nZXRtb2R1bGUoZnJhbWUpLl9fbmFtZV9fIAogICAgICAgICAgICAgICAgaWYgaW5zcGVjdC5nZXRtb2R1bGUoZnJhbWUpIGVsc2UgJ3Vua25vd24nCiAgICAgICAgICAgICkKCiAgICAgICAgICAgICMg5Yib5bu65pel5b+X6K6w5b2V77yI5L+u5pS55Y+C5pWw6ZSu5ZCN77yJCiAgICAgICAgICAgIGxvZ2dlci5sb2coCiAgICAgICAgICAgICAgICBsZXZlbCwKICAgICAgICAgICAgICAgIGZvcm1hdHRlZF9tc2csCiAgICAgICAgICAgICAgICBleHRyYT17J2V4dHJhJzoga3dhcmdzLCAncG9zaXRpb25hbF9hcmdzJzogYXJnc30gICMg5L+u5pS56ZSu5ZCNCiAgICAgICAgICAgICkKICAgICAgICBleGNlcHQgRXhjZXB0aW9uIGFzIGU6CiAgICAgICAgICAgIHN5cy5zdGRlcnIud3JpdGUodSJMb2cgRXJyb3I6ICVzXG4iICUgdW5pY29kZShlKSkKCiAgICBAc3RhdGljbWV0aG9kCiAgICBkZWYgX3ByZXByb2Nlc3NfbWVzc2FnZShtc2cpOgogICAgICAgICIiIua2iOaBr+mihOWkhOeQhu+8iOW8uuWItui9rFVuaWNvZGXvvIkiIiIKICAgICAgICBpZiBpc2luc3RhbmNlKG1zZywgc3RyKToKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgcmV0dXJuIG1zZy5kZWNvZGUoJ3V0Zi04JykKICAgICAgICAgICAgZXhjZXB0IFVuaWNvZGVEZWNvZGVFcnJvcjoKICAgICAgICAgICAgICAgIHJldHVybiBtc2cuZGVjb2RlKCdsYXRpbi0xJywgJ3JlcGxhY2UnKQogICAgICAgIHJldHVybiB1bmljb2RlKG1zZykKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiBfZm9ybWF0X21lc3NhZ2UoY2xzLCBtc2csIGFyZ3MpOgogICAgICAgICIiIua3t+WQiOWPguaVsOagvOW8j+WMlu+8iOWinuW8uuWuuemUme+8iSIiIgogICAgICAgIHRyeToKICAgICAgICAgICAgIyDlsJ3or5XkvKDnu5/moLzlvI/ljJYKICAgICAgICAgICAgaWYgYXJncyBhbmQgJyUnIGluIG1zZzoKICAgICAgICAgICAgICAgIHJldHVybiBtc2cgJSBhcmdzCiAgICAgICAgZXhjZXB0IChUeXBlRXJyb3IsIFZhbHVlRXJyb3IpOgogICAgICAgICAgICBwYXNzCiAgICAgICAgCiAgICAgICAgIyDoh6rliqjmi7zmjqXmqKHlvI8KICAgICAgICBpZiBhcmdzOgogICAgICAgICAgICByZXR1cm4gdSIgIi5qb2luKFttc2ddICsgW2Nscy5fc2FmZV9zdHIoYSkgZm9yIGEgaW4gYXJnc10pCiAgICAgICAgcmV0dXJuIG1zZwoKICAgIEBjbGFzc21ldGhvZAogICAgZGVmIGRlYnVnKGNscywgbXNnLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgIGNscy5fbG9nKGxvZ2dpbmcuREVCVUcsIG1zZywgKmFyZ3MsICoqa3dhcmdzKQoKICAgIEBjbGFzc21ldGhvZAogICAgZGVmIGluZm8oY2xzLCBtc2csICphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgY2xzLl9sb2cobG9nZ2luZy5JTkZPLCBtc2csICphcmdzLCAqKmt3YXJncykKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiB3YXJuaW5nKGNscywgbXNnLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgIGNscy5fbG9nKGxvZ2dpbmcuV0FSTklORywgbXNnLCAqYXJncywgKiprd2FyZ3MpCgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgZXJyb3IoY2xzLCBtc2csICphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgY2xzLl9sb2cobG9nZ2luZy5FUlJPUiwgbXNnLCAqYXJncywgKiprd2FyZ3MpCgojIOa1i+ivleeUqOS+iwppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgIyDmtYvor5XkuK3mlofml6Xlv5cKICAgIFNpbXBsZUxvZ2dlci5pbmZvKHUi55So5oi355m75b2VIiwgdSLlvKDkuIkiLCBpcD0iMTkyLjE2OC4xLjEwMCIpCiAgICAKICAgICMg5rWL6K+V5re35ZCI5Y+C5pWwCiAgICBTaW1wbGVMb2dnZXIuZXJyb3IoIumUmeivr+WPkeeUn+WcqCAlcyIsIHUi6YWN572u5paH5Lu2IiwgY29kZT01MDAsIGRldGFpbD17ImxpbmUiOiA0Mn0pCiAgICAKICAgICMg5rWL6K+V5LqM6L+b5Yi25pWw5o2uCiAgICBiYWRfZGF0YSA9ICdceGU2XHg5N1x4YTAnICAjIFVURi0457yW56CB55qEIuaXoCIKICAgIFNpbXBsZUxvZ2dlci53YXJuaW5nKCLml6DmlYjmlbDmja4iLCBiYWRfZGF0YSk=