Rails 日志实战:配置、请求标记与 Lograge 结构化输出
Rails 日志中文实战:Rails.logger 与 config.log_level、ActiveSupport::TaggedLogging 请求标记、log_tags 注入 request_id、Lograge 单行 JSON 请求日志、生产环境日志配置清单,以及观测云 DataKit 采集与告警落地方案。
Rails 自带完整的日志体系:Rails.logger、按环境的配置文件、请求级标记。但默认的 Rails 请求日志是多行纯文本——开发友好,生产灾难。本文讲解 Rails 日志的配置要点、log_tags 请求关联、Lograge 结构化改造,以及观测云平台落地方案。
核心要点速览
- Rails.logger 开箱即用:默认写到
log/<environment>.log,级别由config.log_level控制。 - 默认请求日志不适合生产:一次请求几十行多行日志,解析与聚合都困难,Lograge 把它压缩成一行结构化日志。
- log_tags + TaggedLogging:给日志自动打上 request_id 等标记,是请求级排障的基础。
- 生产落地:JSON 输出 stdout,观测云 DataKit 采集,监控器告警,APM trace_id 关联。
Rails 日志的默认行为
Rails 应用里随处可用 Rails.logger:
Rails.logger.info("订单创建成功 order_id=#{order.id}")
Rails.logger.error("支付回调验签失败")
默认行为:
- 输出到
log/production.log(随环境变化); - 级别由环境配置控制:开发
debug,生产传统上是info(新版本 Rails 默认从RAILS_LOG_LEVEL环境变量读取); - 每次 HTTP 请求会产生一大坨多行日志:Started、Processing、SQL、Rendered、Completed……
在控制器里还可以用 logger(ActionController 已注入)。自定义子系统日志建议 ActiveSupport::Logger.new 或直接用 Rails.logger.tagged 派生。
调整级别与输出目的地
# config/environments/production.rb
config.log_level = :info
# 输出到 stdout(容器部署推荐)
config.logger = ActiveSupport::Logger.new($stdout)
临时排障不想重启?Rails 控制台里 Rails.logger.level = :debug 即时生效(仅当前进程)。
用 log_tags 给每个请求打标记
config.log_tags = [:request_id, :remote_ip]
之后该请求生命周期内的所有日志都会带上 [7f3a9c...] [10.0.0.8] 前缀。配合 grep request_id 或在观测云中按字段过滤,即可还原单次请求的全部日志。
类内使用:logger.tagged("OrderService") { logger.info("...") } 手动追加标记。
Lograge:把请求日志压缩成一行
默认 Rails 请求日志又长又散。Lograge 把一次请求的所有信息汇总为单行结构化日志:
# Gemfile
gem "lograge"
# config/environments/production.rb
config.lograge.enabled = true
config.lograge.formatter = Lograge::Formatters::Json.new
config.lograge.custom_options = lambda do |event|
{ user_id: event.payload[:current_user_id] }
end
输出从几十行变成一行 JSON:
{"method":"GET","path":"/api/orders","format":"json","controller":"Api::OrdersController","action":"index","status":200,"duration":45.2,"view":12.3,"db":8.9,"timestamp":"2026-08-25T14:42:10.123+08:00","user_id":42}
method、path、status、duration、db/view 耗时一应俱全——访问日志、慢请求分析、5xx 告警全部建立在这一行之上。custom_options 里按需注入业务字段(用户 ID、租户 ID)。
生产配置清单
一份稳妥的 production.rb 日志配置:
config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info")
config.logger = ActiveSupport::Logger.new($stdout) # 容器:stdout
config.log_tags = [:request_id]
config.lograge.enabled = true
config.lograge.formatter = Lograge::Formatters::Json.new
# 业务 logger 用 JSON formatter(见 Ruby 篇自定义 formatter)
要点:stdout 输出(十二要素)、JSON 格式、request_id 标记、级别走环境变量。文件轮转交给容器运行时或系统 logrotate,Rails 自身不用管。
观测云落地:Rails 日志采集与分析
- 应用侧:stdout + JSON(Lograge 管请求日志,业务日志自定义 JSON formatter)。
- DataKit 采集:容器 stdout 自动采集;主机部署在
conf.d/log/logging.conf配置logfiles指向log/production.log,source: rails-app、service标识服务。JSON 自动解析。 - Pipeline 标准化:Lograge 的
status(HTTP 状态码)与业务日志的级别统一映射为观测云标准status字段(5xx/error →error),timestamp解析为time。 - 检索分析:日志查看器按
status、controller、action过滤;图表模式统计各接口耗时与错误率;聚类分析发现新增错误模式。 - 告警:监控器对"5xx 请求 5 分钟超阈值""duration P99 超 2s"等规则告警,通知对象发钉钉/企业微信/飞书。
- 链路关联:接入观测云 APM Ruby 探针后,trace_id 自动出现在日志与链路中,双向跳转定位慢请求。
- 成本控制:请求日志量大走低频索引,错误日志走标准索引长保留,历史数据归档对象存储。
常见问题(FAQ)
Rails 7/8 默认日志有什么变化?
新版本 Rails 生产环境默认 RAILS_LOG_LEVEL 环境变量控制级别(默认 info),并鼓励 stdout 输出(RAILS_LOG_TO_STDOUT)。容器化部署下无需再手动覆盖 config.logger。
开发环境也想用 Lograge 吗?
不建议。开发环境默认的多行详细日志(含 SQL、渲染细节)正是排障所需;Lograge 是给生产环境的机器可读格式。按环境开关即可。
Sidekiq 等后台任务的日志怎么统一?
Sidekiq 自带 logger,可设置 Sidekiq.logger = Rails.logger 统一出口;任务日志建议 tagged(job_id) 标记,平台侧按 job_id 过滤还原任务执行过程。
日志里出现敏感参数怎么办?
Rails 的 config.filter_parameters(如 :password, :token)会在参数日志中打码;Lograge 的 custom_options 也要注意别注入敏感字段。平台侧再启用观测云敏感数据扫描做第二道防线。
系列阅读
- 上一篇:Ruby 日志实战
- 下一篇:Ruby 日志库六款对比
- 相关阅读:Semantic Logger 实战 | 微服务日志最佳实践