# -*- 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] + [OptimizedFormatter._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 = '\xe6\x97\xa0' # UTF-8编码的"无"
SimpleLogger.warning("无效数据", bad_data)
IyAtKi0gY29kaW5nOiB1dGYtOCAtKi0KaW1wb3J0IGxvZ2dpbmcKaW1wb3J0IHN5cwppbXBvcnQgaW5zcGVjdApmcm9tIGRhdGV0aW1lIGltcG9ydCBkYXRldGltZQoKCmNsYXNzIE9wdGltaXplZEZvcm1hdHRlcihsb2dnaW5nLkZvcm1hdHRlcik6CiAgICBkZWYgZm9ybWF0KHNlbGYsIHJlY29yZCk6CiAgICAgICAgdHJ5OgogICAgICAgICAgICAjIOaZuuiDveW4p+aNleiOt++8iOW4pue8k+WtmOS8mOWMlu+8iQogICAgICAgICAgICBpZiBub3QgaGFzYXR0cihyZWNvcmQsICdtb2R1bGUnKToKICAgICAgICAgICAgICAgIGZyYW1lID0gc2VsZi5fY2FjaGVkX2NhbGxlcl9mcmFtZSgpCiAgICAgICAgICAgICAgICBpZiBmcmFtZToKICAgICAgICAgICAgICAgICAgICBtb2R1bGUgPSBpbnNwZWN0LmdldG1vZHVsZShmcmFtZSkKICAgICAgICAgICAgICAgICAgICByZWNvcmQubW9kdWxlID0gbW9kdWxlLl9fbmFtZV9fIGlmIG1vZHVsZSBlbHNlICd1bmtub3duJwogICAgICAgICAgICAgICAgICAgIHJlY29yZC5saW5lbm8gPSBmcmFtZS5mX2xpbmVubwoKICAgICAgICAgICAgIyDlj4LmlbDnu5/kuIDlpITnkIYKICAgICAgICAgICAgYXJnc19zdHIgPSBzZWxmLl9wcm9jZXNzX2FyZ3MocmVjb3JkKQogICAgICAgICAgICBpZiBhcmdzX3N0cjoKICAgICAgICAgICAgICAgIHJlY29yZC5tc2cgPSB1IiVzIOKOuCAlcyIgJSAocmVjb3JkLm1zZywgYXJnc19zdHIpCgogICAgICAgICAgICByZXR1cm4gc3VwZXIoT3B0aW1pemVkRm9ybWF0dGVyLCBzZWxmKS5mb3JtYXQocmVjb3JkKQogICAgICAgIGV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgICAgICAgICAgcmV0dXJuIHUi4pqg77iPIEZvcm1hdCBFcnJvciB8IEVycjogJXMgfCBSYXc6ICVzIiAlIChlLCByZWNvcmQuZ2V0TWVzc2FnZSgpKQoKICAgIGRlZiBfY2FjaGVkX2NhbGxlcl9mcmFtZShzZWxmKToKICAgICAgICAiIiLluKZMUlXnvJPlrZjnmoTluKfmn6Xmib4iIiIKICAgICAgICBzdGFjayA9IGluc3BlY3Quc3RhY2soKQogICAgICAgIGZvciBmcmFtZV9pbmZvIGluIHJldmVyc2VkKHN0YWNrKToKICAgICAgICAgICAgZnJhbWUgPSBmcmFtZV9pbmZvWzBdCiAgICAgICAgICAgIGlmIGluc3BlY3QuZ2V0bW9kdWxlKGZyYW1lKS5fX25hbWVfXyAhPSBfX25hbWVfXzoKICAgICAgICAgICAgICAgIHJldHVybiBmcmFtZQogICAgICAgIHJldHVybiBpbnNwZWN0LmN1cnJlbnRmcmFtZSgpCgogICAgZGVmIF9wcm9jZXNzX2FyZ3Moc2VsZiwgcmVjb3JkKToKICAgICAgICAiIiLlpITnkIbmiYDmnInlj4LmlbDnsbvlnosiIiIKICAgICAgICBwYXJ0cyA9IFtdCiAgICAgICAgCiAgICAgICAgIyDlpITnkIbkvY3nva7lj4LmlbDvvIjkv67mlLnplK7lkI3pgb/lhY3lhrLnqoHvvIkKICAgICAgICBpZiBoYXNhdHRyKHJlY29yZCwgJ3Bvc2l0aW9uYWxfYXJncycpIGFuZCByZWNvcmQucG9zaXRpb25hbF9hcmdzOgogICAgICAgICAgICBwYXJ0cy5leHRlbmQoc2VsZi5fc2FmZV9yZXByKGEpIGZvciBhIGluIHJlY29yZC5wb3NpdGlvbmFsX2FyZ3MpCiAgICAgICAgCiAgICAgICAgIyDlpITnkIbpop3lpJblj4LmlbAKICAgICAgICBpZiBoYXNhdHRyKHJlY29yZCwgJ2V4dHJhJykgYW5kIHJlY29yZC5leHRyYToKICAgICAgICAgICAgcGFydHMuZXh0ZW5kKHUiJXM9JXMiICUgKGssIHNlbGYuX3NhZmVfcmVwcih2KSkgCiAgICAgICAgICAgICAgICAgICAgICAgIGZvciBrLCB2IGluIHJlY29yZC5leHRyYS5pdGVyaXRlbXMoKSkKICAgICAgICAKICAgICAgICByZXR1cm4gdSIg4o64ICIuam9pbihwYXJ0cykgaWYgcGFydHMgZWxzZSB1IiIKCiAgICBkZWYgX3NhZmVfcmVwcihzZWxmLCB2YWx1ZSk6CiAgICAgICAgIiIi5a6J5YWo57G75Z6L6L2s5o2i77yI5aKe5by657yW56CB5aSE55CG77yJIiIiCiAgICAgICAgdHJ5OgogICAgICAgICAgICBpZiBpc2luc3RhbmNlKHZhbHVlLCBkaWN0KToKICAgICAgICAgICAgICAgIHJldHVybiB1Inslc30iICUgdSIsIi5qb2luKHUiJXM6JXMiICUgKHNlbGYuX3NhZmVfcmVwcihrKSwgc2VsZi5fc2FmZV9yZXByKHYpKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgaywgdiBpbiB2YWx1ZS5pdGVyaXRlbXMoKSkKICAgICAgICAgICAgZWxpZiBpc2luc3RhbmNlKHZhbHVlLCAobGlzdCwgdHVwbGUpKToKICAgICAgICAgICAgICAgIHJldHVybiB1Ilslc10iICUgdSIsIi5qb2luKHNlbGYuX3NhZmVfcmVwcih4KSBmb3IgeCBpbiB2YWx1ZSkKICAgICAgICAgICAgcmV0dXJuIHNlbGYuX3NhZmVfc3RyKHZhbHVlKQogICAgICAgIGV4Y2VwdDoKICAgICAgICAgICAgcmV0dXJuIHUiPFVucHJpbnRhYmxlPiIKCiAgICBAc3RhdGljbWV0aG9kCiAgICBkZWYgX3NhZmVfc3RyKG9iaik6CiAgICAgICAgIiIi5a6J5YWo5a2X56ym5Liy6L2s5o2i77yI6Kej5Yaz57yW56CB6Zeu6aKY77yJIiIiCiAgICAgICAgdHJ5OgogICAgICAgICAgICBpZiBpc2luc3RhbmNlKG9iaiwgc3RyKToKICAgICAgICAgICAgICAgIHJldHVybiBvYmouZGVjb2RlKCd1dGYtOCcsICdyZXBsYWNlJykKICAgICAgICAgICAgcmV0dXJuIHVuaWNvZGUob2JqKQogICAgICAgIGV4Y2VwdCBVbmljb2RlRGVjb2RlRXJyb3I6CiAgICAgICAgICAgIHJldHVybiB1IjzpnZ5VVEYtOOWtl+iKguaVsOaNrj4iCiAgICAgICAgZXhjZXB0OgogICAgICAgICAgICByZXR1cm4gdSI85peg5rOV6L2s5o2i5a+56LGhPiIKCgpjbGFzcyBTaW1wbGVMb2dnZXIob2JqZWN0KToKICAgIF9pbml0aWFsaXplZCA9IEZhbHNlCgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgX2Vuc3VyZV9pbml0KGNscyk6CiAgICAgICAgaWYgbm90IGNscy5faW5pdGlhbGl6ZWQ6CiAgICAgICAgICAgIHJvb3QgPSBsb2dnaW5nLmdldExvZ2dlcigpCiAgICAgICAgICAgIHJvb3Quc2V0TGV2ZWwobG9nZ2luZy5ERUJVRykKICAgICAgICAgICAgaWYgbm90IHJvb3QuaGFuZGxlcnM6CiAgICAgICAgICAgICAgICBoYW5kbGVyID0gbG9nZ2luZy5TdHJlYW1IYW5kbGVyKCkKICAgICAgICAgICAgICAgIGhhbmRsZXIuc2V0Rm9ybWF0dGVyKE9wdGltaXplZEZvcm1hdHRlcigKICAgICAgICAgICAgICAgICAgICBmbXQ9dSdbJShhc2N0aW1lKXNdIFslKGxldmVsbmFtZSlzXSAlKG1vZHVsZSlzOiUobGluZW5vKWQg4p6kICUobWVzc2FnZSlzJywKICAgICAgICAgICAgICAgICAgICBkYXRlZm10PSclSDolTTolUycKICAgICAgICAgICAgICAgICkpCiAgICAgICAgICAgICAgICByb290LmFkZEhhbmRsZXIoaGFuZGxlcikKICAgICAgICAgICAgY2xzLl9pbml0aWFsaXplZCA9IFRydWUKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiBfbG9nKGNscywgbGV2ZWwsIG1zZywgKmFyZ3MsICoqa3dhcmdzKToKICAgICAgICBjbHMuX2Vuc3VyZV9pbml0KCkKICAgICAgICB0cnk6CiAgICAgICAgICAgICMg6aKE5aSE55CG5raI5oGv77yI56Gu5L+dVW5pY29kZe+8iQogICAgICAgICAgICBtc2cgPSBjbHMuX3ByZXByb2Nlc3NfbWVzc2FnZShtc2cpCiAgICAgICAgICAgIAogICAgICAgICAgICAjIOaZuuiDveWPguaVsOWkhOeQhgogICAgICAgICAgICBmb3JtYXR0ZWRfbXNnID0gY2xzLl9mb3JtYXRfbWVzc2FnZShtc2csIGFyZ3MpCiAgICAgICAgICAgIAogICAgICAgICAgICAjIOiOt+WPluiwg+eUqOiAheS/oeaBrwogICAgICAgICAgICBmcmFtZSA9IGluc3BlY3QuY3VycmVudGZyYW1lKCkuZl9iYWNrLmZfYmFjawogICAgICAgICAgICBsb2dnZXIgPSBsb2dnaW5nLmdldExvZ2dlcigKICAgICAgICAgICAgICAgIGluc3BlY3QuZ2V0bW9kdWxlKGZyYW1lKS5fX25hbWVfXyAKICAgICAgICAgICAgICAgIGlmIGluc3BlY3QuZ2V0bW9kdWxlKGZyYW1lKSBlbHNlICd1bmtub3duJwogICAgICAgICAgICApCgogICAgICAgICAgICAjIOWIm+W7uuaXpeW/l+iusOW9le+8iOS/ruaUueWPguaVsOmUruWQje+8iQogICAgICAgICAgICBsb2dnZXIubG9nKAogICAgICAgICAgICAgICAgbGV2ZWwsCiAgICAgICAgICAgICAgICBmb3JtYXR0ZWRfbXNnLAogICAgICAgICAgICAgICAgZXh0cmE9eydleHRyYSc6IGt3YXJncywgJ3Bvc2l0aW9uYWxfYXJncyc6IGFyZ3N9ICAjIOS/ruaUuemUruWQjQogICAgICAgICAgICApCiAgICAgICAgZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgogICAgICAgICAgICBzeXMuc3RkZXJyLndyaXRlKHUiTG9nIEVycm9yOiAlc1xuIiAlIHVuaWNvZGUoZSkpCgogICAgQHN0YXRpY21ldGhvZAogICAgZGVmIF9wcmVwcm9jZXNzX21lc3NhZ2UobXNnKToKICAgICAgICAiIiLmtojmga/pooTlpITnkIbvvIjlvLrliLbovaxVbmljb2Rl77yJIiIiCiAgICAgICAgaWYgaXNpbnN0YW5jZShtc2csIHN0cik6CiAgICAgICAgICAgIHRyeToKICAgICAgICAgICAgICAgIHJldHVybiBtc2cuZGVjb2RlKCd1dGYtOCcpCiAgICAgICAgICAgIGV4Y2VwdCBVbmljb2RlRGVjb2RlRXJyb3I6CiAgICAgICAgICAgICAgICByZXR1cm4gbXNnLmRlY29kZSgnbGF0aW4tMScsICdyZXBsYWNlJykKICAgICAgICByZXR1cm4gdW5pY29kZShtc2cpCgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgX2Zvcm1hdF9tZXNzYWdlKGNscywgbXNnLCBhcmdzKToKICAgICAgICAiIiLmt7flkIjlj4LmlbDmoLzlvI/ljJbvvIjlop7lvLrlrrnplJnvvIkiIiIKICAgICAgICB0cnk6CiAgICAgICAgICAgICMg5bCd6K+V5Lyg57uf5qC85byP5YyWCiAgICAgICAgICAgIGlmIGFyZ3MgYW5kICclJyBpbiBtc2c6CiAgICAgICAgICAgICAgICByZXR1cm4gbXNnICUgYXJncwogICAgICAgIGV4Y2VwdCAoVHlwZUVycm9yLCBWYWx1ZUVycm9yKToKICAgICAgICAgICAgcGFzcwogICAgCiAgICAgICAgIyDoh6rliqjmi7zmjqXmqKHlvI8KICAgICAgICBpZiBhcmdzOgogICAgICAgICAgICByZXR1cm4gdSIgIi5qb2luKFttc2ddICsgW09wdGltaXplZEZvcm1hdHRlci5fc2FmZV9zdHIoYSkgZm9yIGEgaW4gYXJnc10pCiAgICAgICAgcmV0dXJuIG1zZwoKICAgIEBjbGFzc21ldGhvZAogICAgZGVmIGRlYnVnKGNscywgbXNnLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgIGNscy5fbG9nKGxvZ2dpbmcuREVCVUcsIG1zZywgKmFyZ3MsICoqa3dhcmdzKQoKICAgIEBjbGFzc21ldGhvZAogICAgZGVmIGluZm8oY2xzLCBtc2csICphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgY2xzLl9sb2cobG9nZ2luZy5JTkZPLCBtc2csICphcmdzLCAqKmt3YXJncykKCiAgICBAY2xhc3NtZXRob2QKICAgIGRlZiB3YXJuaW5nKGNscywgbXNnLCAqYXJncywgKiprd2FyZ3MpOgogICAgICAgIGNscy5fbG9nKGxvZ2dpbmcuV0FSTklORywgbXNnLCAqYXJncywgKiprd2FyZ3MpCgogICAgQGNsYXNzbWV0aG9kCiAgICBkZWYgZXJyb3IoY2xzLCBtc2csICphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgY2xzLl9sb2cobG9nZ2luZy5FUlJPUiwgbXNnLCAqYXJncywgKiprd2FyZ3MpCgoKIyDmtYvor5XnlKjkvosKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgICMg5rWL6K+V5Lit5paH5pel5b+XCiAgICBTaW1wbGVMb2dnZXIuaW5mbyh1IueUqOaIt+eZu+W9lSIsIHUi5byg5LiJIiwgaXA9IjE5Mi4xNjguMS4xMDAiKQogICAgCiAgICAjIOa1i+ivlea3t+WQiOWPguaVsAogICAgU2ltcGxlTG9nZ2VyLmVycm9yKCLplJnor6/lj5HnlJ/lnKggJXMiLCB1IumFjee9ruaWh+S7tiIsIGNvZGU9NTAwLCBkZXRhaWw9eyJsaW5lIjogNDJ9KQogICAgCiAgICAjIOa1i+ivleS6jOi/m+WItuaVsOaNrgogICAgYmFkX2RhdGEgPSAnXHhlNlx4OTdceGEwJyAgIyBVVEYtOOe8lueggeeahCLml6AiCiAgICBTaW1wbGVMb2dnZXIud2FybmluZygi5peg5pWI5pWw5o2uIiwgYmFkX2RhdGEpCg==