如何使用rails_semantic_logger记录完整请求与外部API调用详情
用rails_semantic_logger自动记录外部API调用详情
可以通过拦截项目中使用的HTTP客户端请求流程,结合rails_semantic_logger的结构化日志能力实现需求,以下是针对不同场景的具体方案:
方案1:拦截Rails默认的Net::HTTP客户端
Net::HTTP是Ruby标准库的HTTP客户端,Rails内部及多数基础HTTP请求都会依赖它。通过重写其请求方法注入日志逻辑:
# 在config/initializers/net_http_logger.rb中添加 require 'net/http' require 'rails_semantic_logger' module NetHTTPLogging def request(req, body = nil, &block) # 记录请求详情 Rails.logger.tagged('External API') do Rails.logger.info( action: 'api_request', method: req.method, url: "#{self.address}#{req.path}", headers: req.to_hash, params: URI.parse(req.path).query&.then { |q| CGI.parse(q) }, body: body || req.body ) end # 执行原请求并记录响应 response = super Rails.logger.tagged('External API') do Rails.logger.info( action: 'api_response', status: response.code, headers: response.to_hash, body: response.body ) end response end end Net::HTTP.prepend(NetHTTPLogging)
配置后,所有通过Net::HTTP发起的外部请求都会自动记录请求/响应的headers、body、params等信息。
方案2:适配Faraday第三方HTTP客户端
如果项目使用Faraday作为HTTP客户端,可通过自定义中间件实现日志记录:
# 在config/initializers/faraday_logger.rb中添加 require 'faraday' require 'rails_semantic_logger' class FaradaySemanticLogger < Faraday::Middleware def call(env) # 记录请求信息 Rails.logger.tagged('External API') do Rails.logger.info( action: 'api_request', method: env.method, url: env.url.to_s, headers: env.request_headers, params: env.params, body: env.body ) end # 执行请求并记录响应 @app.call(env).on_complete do |response_env| Rails.logger.tagged('External API') do Rails.logger.info( action: 'api_response', status: response_env.status, headers: response_env.response_headers, body: response_env.body ) end end end end # 全局注册中间件,所有Faraday实例自动生效 Faraday::Connection.register_middleware(logger: -> { FaradaySemanticLogger })
方案3:统一结构化日志格式
为了更方便后续日志分析,可在Rails环境配置中设置rails_semantic_logger输出结构化JSON格式:
# 在config/environments/production.rb(或对应环境文件)中添加 Rails.application.configure do config.semantic_logger.add_appender( io: $stdout, formatter: :json, level: :info ) end
关键注意事项
- 敏感信息过滤:禁止直接记录Authorization、Token等敏感字段,需提前做替换处理,示例:
filtered_headers = req.to_hash.transform_values do |value| req.key?('Authorization') && value == req['Authorization'] ? '[FILTERED]' : value end - 性能优化:生产环境中若请求/响应体过大,建议对内容做截断或仅记录关键字段,避免影响系统性能。
- 其他客户端适配:若使用HTTParty、Typhoeus等其他HTTP客户端,可参考上述思路,找到对应请求钩子注入日志逻辑。
内容的提问来源于stack exchange,提问作者Ramachandra Hegde
相关产品推荐
相关产品推荐

