Tornado 日志系统完整指南:tornado.log 模块的三条日志流、格式化器与命令行配置实战
Tornado 日志系统完整指南tornado.log 模块的三条日志流、格式化器与命令行配置实战【免费下载链接】tornadoTornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.项目地址: https://gitcode.com/gh_mirrors/to/tornado导读本文以 Tornado 官方文档 docs/log.rst 为主题系统讲解tornado.log模块的三大日志流tornado.access、tornado.application、tornado.general、内置的LogFormatter格式化器以及通过tornado.options命令行/配置文件自动启用彩色日志、文件输出与日志轮转的完整机制。读完本文你将掌握 Tornado 应用从「开箱即用的日志」到「按需独立配置日志流」的完整实战能力并能从源码层面理解访问日志、应用异常日志与框架内部日志的流向。一、概述Tornado 为什么自带一套日志封装Tornado 是 Python 的 Web 框架与异步网络库最初由 FriendFeed 开发其源码模块 tornado/log.py 位于仓库根目录的tornado/包内。该模块并不另起炉灶实现一套日志框架而是基于 Python 标准库logging之上的一层轻量封装它预定义了三个具名 logger并提供了一个能输出彩色、带时间戳、抗编码问题的格式化器LogFormatter。模块 docstringtornado/log.py明确指出 Tornado 使用三条日志流Logger 名称用途tornado.accessHTTP 服务器的按请求per-request日志未来也可能被其他服务器复用tornado.application应用代码产生的错误日志例如回调中未捕获的异常tornado.general通用日志包括 Tornado 自身的错误与警告三条流可以在标准库logging模块之上独立配置——例如你希望把tornado.access日志单独输出到一份文件用于分析其余日志仍走终端。这正是 Tornado 日志设计的第一原则与 Python 生态完全兼容不引入任何自定义日志语法。在源码中这三个 logger 以模块级单例形式创建tornado/log.pyaccess_log logging.getLogger(tornado.access) app_log logging.getLogger(tornado.application) gen_log logging.getLogger(tornado.general)Tornado 各核心模块正是通过导入这三个 logger 来打日志的例如tornado/autoreload.py 使用gen_log输出文件变更重启、进程退出等框架级信息tornado/ioloop.py、tornado/iostream.py 使用app_log/gen_log记录回调异常、读写错误tornado/process.py 使用gen_log记录多进程 fork 与子进程状态。二、三条日志流在 Web 应用中的真实流向2.1tornado.accessHTTP 访问日志当 HTTP 请求完成时Application.log_request会被调用tornado/web.py。其默认实现tornado/web.py按响应状态码选择不同级别的tornado.access日志if handler.get_status() 400: log_method access_log.info elif handler.get_status() 500: log_method access_log.warning else: log_method access_log.error request_time 1000.0 * handler.request.request_time() log_method( %d %s %.2fms, handler.get_status(), handler._request_summary(), request_time, )即2xx/3xx 记INFO4xx 记WARNING5xx 记ERROR每条日志包含状态码、请求摘要与毫秒级耗时。应用可以通过两种方式定制在Application的 settings 中传入log_function回调传参为RequestHandler对象或继承Application重写log_request。2.2tornado.application应用未捕获异常当 handler 处理过程中抛出未捕获异常时RequestHandler.log_exceptiontornado/web.py负责记录若异常是HTTPError如raise HTTPError(404)则仅以gen_log.warning记录状态码与摘要不带堆栈其他所有异常以app_log.error记录完整堆栈exc_info传入。if isinstance(value, HTTPError): ... gen_log.warning(format, *args) else: app_log.error( Uncaught exception %s\n%r, self._request_summary(), self.request, exc_info(typ, value, tb), )若write_error自身抛出异常同样会走app_log.error(Uncaught exception in write_error, ...)tornado/web.py。此外tornado/gen.py、tornado/concurrent.py 等异步模块在协程/Future 回调异常时也统一使用app_log.error。2.3tornado.general框架内部事件gen_log覆盖 Tornado 自身的事件例如tornado/http1connection.pygen_log.info(Malformed HTTP message from %s: %s, ...)记录畸形 HTTP 报文tornado/http1connection.py记录请求体读取超时tornado/iostream.pygen_log.error(Reached maximum read buffer size)记录读缓冲上限。三、LogFormatter彩色、带时间戳、抗编码的格式化器3.1 三大特性与默认格式LogFormattertornado/log.py是 Tornado 内置的日志格式化器核心特性颜色支持输出到支持颜色的终端时按日志级别着色每条日志带时间戳对 str/bytes 编码问题健壮字节串/非 UTF-8 内容不会导致日志管线崩溃。默认格式与默认颜色映射tornado/log.pyDEFAULT_FORMAT %(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]%(end_color)s %(message)s DEFAULT_DATE_FORMAT %y%m%d %H:%M:%S DEFAULT_COLORS { logging.DEBUG: 4, # Blue logging.INFO: 2, # Green logging.WARNING: 3, # Yellow logging.ERROR: 1, # Red logging.CRITICAL: 5, # Magenta }实际输出形如[I 240101 12:00:00 module:42] Hello, world [E 240101 12:00:01 web:1952] Uncaught exception ...%(color)s与%(end_color)s之间的文本会按级别着色format方法在 tornado/log.py 中注入record.color/record.end_color。3.2 构造参数构造函数签名tornado/log.pyLogFormatter(fmtDEFAULT_FORMAT, datefmtDEFAULT_DATE_FORMAT, style%, colorTrue, colorsDEFAULT_COLORS)参数含义color是否启用颜色支持默认True实际是否着色还取决于终端检测结果fmt日志格式模板应用于 log record 的属性字典%(color)s~%(end_color)s之间部分按级别着色colors日志级别到终端颜色码的映射datefmt时间格式用于格式化(asctime)占位符注意color只是是否允许开关最终是否真正着色取决于_stderr_supports_color()tornado/log.py——它要求stderr是 TTY且要么curses能查到终端颜色数 0要么在 Windows 上使用colorama包装过的stderr。3.3 颜色支持与 WindowscoloramaTornado 4.5 起LogFormatter增加对colorama的支持tornado/log.py用于不支持 ANSI 颜色码的 Windows 版本。应用如需在 Windows 获得颜色必须先调用colorama.init()初始化。当curses不可用典型场景即 Windows colorama代码会回退到硬编码 ANSI 颜色码tornado/log.pyself._colors[levelno] \033[2;3%dm % code self._normal \033[0m自 Tornado 4.5 起构造函数签名同时兼容logging.config.dictConfig因此可直接在字典配置中引用。3.4 抗编码问题的健壮性设计format方法tornado/log.py做了两件关键的事消息统一经_safe_unicode转成 Unicode——正常情况用_unicode遇到UnicodeDecodeError则退化为repr(s)tornado/log.py保证任意字节串都能成功落盘异常堆栈逐行做_safe_unicode后再拼接避免某一行非 UTF-8 字节破坏整个 traceback 的换行结构最终输出中所有换行统一缩进为\n 保证多行日志在文件里层次清晰。四、enable_pretty_logging与命令行日志配置4.1 自动启用机制LogFormatter会在调用tornado.options.parse_command_line或tornado.options.parse_config_file时自动启用除非使用--loggingnone。其背后是两条主线define_logging_options在 options 上注册全部日志相关参数tornado/log.pyoptions.add_parse_callback(lambda: enable_pretty_logging(options))将enable_pretty_logging注册为解析回调命令行/配置文件解析完成后自动执行。enable_pretty_loggingtornado/log.py的完整逻辑if options.logging is None or options.logging.lower() none: return # 显式关闭Tornado 不碰 logging 配置 logger.setLevel(getattr(logging, options.logging.upper())) # 设置根 logger 级别 if options.log_file_prefix: # 配置了文件输出 → 按轮转模式建 Handler if rotate_mode size: channel logging.handlers.RotatingFileHandler( filenameoptions.log_file_prefix, maxBytesoptions.log_file_max_size, backupCountoptions.log_file_num_backups, encodingutf-8, ) elif rotate_mode time: channel logging.handlers.TimedRotatingFileHandler( filenameoptions.log_file_prefix, whenoptions.log_rotate_when, intervaloptions.log_rotate_interval, backupCountoptions.log_file_num_backups, encodingutf-8, ) else: raise ValueError(The value of log_rotate_mode option should be size or time) channel.setFormatter(LogFormatter(colorFalse)) logger.addHandler(channel) if options.log_to_stderr or (options.log_to_stderr is None and not logger.handlers): channel logging.StreamHandler() channel.setFormatter(LogFormatter()) # stderr 可着色 logger.addHandler(channel)注意两个细节文件输出必须禁用颜色LogFormatter(colorFalse)避免日志文件里混入终端转义序列若未设置log_file_prefix且根 logger 没有任何 handler则默认输出到stderrlog_to_stderr显式为False可强制关掉 stderr 输出。4.2 全部日志相关命令行选项define_logging_optionstornado/log.py注册的参数如下均可通过命令行--xxxvalue或配置文件键值对设置选项类型默认值说明--loggingstrinfoPython 日志级别取值debug\|info\|warning\|error\|none为none时 Tornado 不修改 logging 配置--log_to_stderrboolNone是否输出到 stderr可着色。默认未设置log_file_prefix且无其他日志配置时输出到 stderr--log_file_prefixstrNone日志文件路径前缀。多进程运行时每个进程必须使用不同前缀例如包含端口号否则日志互相覆盖--log_file_max_sizeint100 * 1000 * 1000约 100MBsize 模式下日志文件轮转前的大小上限--log_file_num_backupsint10保留的日志文件份数--log_rotate_whenstrmidnightTimedRotatingFileHandler 的时间间隔类型可选S秒、M分、H时、D天、W0-W6星期几--log_rotate_intervalint1时间轮转的间隔数值--log_rotate_modestrsize轮转模式size按大小或time按时间4.3 实战示例以仓库自带示例 demos/helloworld/helloworld.py 为蓝本最简单的方式是直接调用tornado.options.parse_command_line()日志配置即自动生效python demos/helloworld/helloworld.py --logginginfo按大小轮转并写入文件python demos/helloworld/helloworld.py \ --log_file_prefix/var/log/myapp/app.log \ --log_rotate_modesize \ --log_file_max_size104857600 \ --log_file_num_backups10按天轮转每天午夜切割python demos/helloworld/helloworld.py \ --log_file_prefix/var/log/myapp/app.log \ --log_rotate_modetime \ --log_rotate_whenmidnight \ --log_rotate_interval1 \ --log_file_num_backups30关闭 Tornado 的日志接管、完全交给应用自己管理python demos/helloworld/helloworld.py --loggingnone若在代码中希望禁用可在parse_command_line()之前设置options.logging None参考 tornado/options.py 的说明与 tornado/test/log_test.py 的测试用例。多进程注意--log_file_prefix在多进程场景例如 tornado/process.py 的fork_processes下必须每个进程不同官方建议把端口号拼进前缀。五、程序化独立配置摆脱命令行自由掌控如果不想依赖命令行解析也可在代码中直接用标准库logging配置 Tornado 的任意日志流。例如将访问日志单独送入文件、应用日志保留在 stderrimport logging # 独立配置 tornado.access access logging.getLogger(tornado.access) access.setLevel(logging.INFO) fh logging.FileHandler(access.log, encodingutf-8) fh.setFormatter(logging.Formatter(%(asctime)s %(message)s)) access.addHandler(fh) # 其余日志tornado.application / tornado.general / 根 logger保持默认 logging.basicConfig(levellogging.INFO)define_logging_options也可用于自定义的OptionParser实例tornado/log.py 注明默认 options 实例已自动包含这些选项仅当自建OptionParser时才需要显式调用from tornado.options import OptionParser from tornado.log import define_logging_options, enable_pretty_logging parser OptionParser() define_logging_options(parser) enable_pretty_logging(parser) # 或调用 parser.parse_command_line() 自动触发此时LogFormatter亦可直接复用在任何 handler 上from tornado.log import LogFormatter handler logging.StreamHandler() handler.setFormatter(LogFormatter(colorTrue)) logging.getLogger().addHandler(handler)六、从源码与测试看行为保证仓库 tornado/test/log_test.py 是验证上述行为的最佳参考LogFormatterTest.test_basic_logging等用例验证单条日志输出格式与正则[E 240101 12:00:00 log_test:N]完全一致tornado/test/log_test.pytest_bytes_logging/test_utf8_logging/test_bytes_exception_logging验证了字节串消息、非 UTF-8 消息、字节型异常堆栈均不会导致日志崩溃且异常堆栈中的换行不会被转义tornado/test/log_test.pyEnablePrettyLoggingTest.test_log_file验证设置log_file_prefix后文件内容格式为[E ...] hellotest_log_file_with_timed_rotating验证time轮转模式test_wrong_rotate_mode_value验证非法log_rotate_mode会抛ValueErrortornado/test/log_test.pyLoggingOptionTest通过子进程验证默认不解析时不启用日志、调用parse_command_line()后info级日志可见、--loggingnone含大小写None可关闭、命令行参数可覆盖代码中设置的options.loggingtornado/test/log_test.py。七、常见问题与最佳实践小结--loggingnone的含义不是不记日志而是Tornado 不接管 logging 配置此时根 logger 级别与 handler 完全由你掌控。颜色丢失日志重定向到文件/管道时_stderr_supports_color()返回False属预期行为如需在文件中保留颜色必须自行设置。编码崩溃消息可能包含任意 bytes 时优先使用LogFormatter其_safe_unicode/repr回退机制保证日志管线永不因编码异常中断。多进程日志多进程场景务必让每个进程的log_file_prefix唯一如包含端口号否则多个进程写同一文件会互相覆盖。访问日志定制需要自定义访问日志格式时优先在Applicationsettings 传入log_function或在子类中重写log_requesttornado/web.py。异常分级HTTP 4xx 异常HTTPError走gen_log.warning且无堆栈非 HTTP 异常走app_log.error带完整堆栈——监控告警可据此分流。延伸阅读仓库内相关文档tornado.options 命令行解析说明日志选项是如何注册与解析的tornado.web 的 log_function / log_request 说明访问日志钩子的应用层入口异步与协程指南理解tornado.application日志对应的异步回调异常场景【免费下载链接】tornadoTornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.项目地址: https://gitcode.com/gh_mirrors/to/tornado创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →