使用 Rails 4.2 和 lograge,如何在每个记录的行之前启用日期/时间?

Posted

技术标签:

【中文标题】使用 Rails 4.2 和 lograge,如何在每个记录的行之前启用日期/时间?【英文标题】:With Rails 4.2 and lograge, how do I enable date/times before each logged line? 【发布时间】:2021-12-25 06:25:08 【问题描述】:

我使用 gem “Lograge” 0.3.6 和 Rails 4.2。我在我的 config/environments/development.rb 文件中配置了这个

  config.lograge.enabled = true
  config.lograge.formatter = CustomLogstash.new

但是,我注意到我的 log/development.log 文件中的输出不包含每一行前面的日期/时间。如何配置 lograge(或者只是我的 Rails 记录器?)为该文件中的每一行加上日期和时间的前缀?

【问题讨论】:

【参考方案1】:

如果有帮助,您可以在配置中添加以下内容吗?

config.lograge.formatter = ->(data)  data.reverse_merge(time: Time.now) # data is a ruby hash.

它会给你如下输出

:time=>2021-11-16 12:26:24.65362 +0000, :method=>"GET", :path=>"/", :format=>:html, :controller=>"Controller", :action=>"index", :status=>200, :duration=>393.41, :view=>85.55, :db=>1.38

【讨论】:

试一试,但没有骰子。重新启动服务器后,我的 log/development.log 文件中仍然没有添加日期。 每个环境有不同的 lograge 配置吗? 配置相同,但有三个单独的文件——config/environments/development.rb、config/environments/staging.rb和config/environments/production.rb。 您在配置中使用了哪个自定义记录器格式化程序?就像您在上面的示例中提到的那样 config.lograge.formatter = CustomLogstash.new 如果您可以分享您的开发配置的外观,是否有可能?【参考方案2】:

你能粘贴 CustomLogstash 类的内容吗?从文档来看,这个类应该响应 call 方法并返回 Hash

这对我有用:

class CustomLogstash
  def call(data)
     time: Time.now, controller: data[:controller]  # this can be anything as long it is Hash, eg. data.merge(time: Time.now)

  end
end

上面的示例输出:

:time=>"2021-11-18T20:31:41.486+01:00", :controller=>"calendar_events"

【讨论】:

你是说我应该创建这个类吗?我的项目中没有一个名为 this 的类。 我指的是你粘贴的代码,所以我假设你已经有了这个类。如果没有,请创建它并确保在调用 config.lograge.formatter = CustomLogstash.new 之前加载它。 明白了。因此,当调用控制器方法并在它们前面加上时间戳时,包括该行似乎确实将行添加到 log/development.log 文件中,例如':time=>"2021-11-21T03:46:53.525+00:00", :controller=>"api/products"'。有什么办法让这个通用吗?将时间戳添加到所有内容(例如记录的 SQL 查询)【参考方案3】:

根据official documentationlograge,你可以使用custom_options

EDIT 1:custom_options 使用time: Time.nowtime:event.time


Rails.application.configure do
  config.lograge.enabled = true
  config.lograge.formatter = Lograge::Formatters::Logstash.new

  # add time to lograge
  config.lograge.custom_options = lambda do |event|
     time: Time.now  #or use time:event.time 
  end
end

注意:使用 logstash 输出时,需要添加额外的 gem logstash-event。您可以像这样简单地将它添加到您的 Gemfile 中

      gem "logstash-event"

编辑 2: 基于 cmets custom_options 使用 :time => event.time

进行更新

#config/environments/production.rb
MyApp::Application.configure do
  config.lograge.enabled = true

  # add time to lograge
  config.lograge.custom_options = lambda do |event|
    :time => event.time
  end
end

OR 以下自定义选项修复了使用 time: event.time.to_s(:db)

记录的lograge issue to ensure both 日期和时间

config.lograge.custom_options = lambda do |event|
      unwanted_keys = %w[format action controller utf8]
      params = event.payload[:params].reject  |key,_| unwanted_keys.include? key 
      time: event.time.to_s(:db), user: event.payload[:user], params: params
    end

或者你可以使用这个Custom logger


# Define a setter to pass in a custom log formatter

class ActiveSupport::BufferedLogger

  def formatter=(formatter)

    @log.formatter = formatter

  end

end



# Defines a custom log format (time, severity, message, PID, backtrace)... all with color!

class Formatter

  SEVERITY_TO_TAG   = 'DEBUG'=>'meh', 'INFO'=>'fyi', 'WARN'=>'hmm', 'ERROR'=>'wtf', 'FATAL'=>'omg', 'UNKNOWN'=>'???'

  SEVERITY_TO_COLOR = 'DEBUG'=>'37',  'INFO'=>'32',  'WARN'=>'33',  'ERROR'=>'31',  'FATAL'=>'31',  'UNKNOWN'=>'37'

  HUMOR_FOR_ENV     = development: true, test: true, production: false

  DEPTH_FOR_ENV     = development: 3,    test: 3,    production: 1

  EXCLUSION_REGEX   = /log|active_support|active_record/



  def humorous?

    return @is_humorous if defined? @is_humorous

    @is_humorous = HUMOR_FOR_ENV[ Rails.env.to_sym ]

  end



  def depth

    @depth ||= DEPTH_FOR_ENV[ Rails.env.to_sym ]

  end



  def call(severity, time, progname, msg)

    t     = time.strftime("%Y-%m-%d %H:%M:%S.") << time.usec.to_s[0..2].rjust(3)

    color = SEVERITY_TO_COLOR[severity]

    sev   = humorous? ? "%-3s" % SEVERITY_TO_TAG[severity] # pad to at least 3 characters

                      : "%-5s" % severity                  # pad to at least 5 characters



    # 2013-05-01 19:16:00.785 [omg] oh noes! (pid:30976) (admin/user.rb:45:in `block (4 levels) in <top (required)>') <- `call' <- `content_for' <- `block (2 levels) in row' <- `block in build_tag'

    "\033[0;37m#t\033[0m [\033[#colorm#sev\033[0m] #msg.strip (pid:#$$) #whodunit\033[0m\n"

  end



  def whodunit

    latest, *others = caller.select |a| a !~ EXCLUSION_REGEX [0, depth]

    latest = latest[/(lib|app)\/(.*)/,-1] || latest

    string = ""

    string << "\033[36m(#latest)"

    string << "\033[35m <- " + others.map |s| s[/`.*/] .join(' <- ') if others.any?

    string

  end



end



Rails.logger.formatter = Formatter.new



对于 Rails 4.2,不要忘记添加 ActiveSupport::TaggedLogging 以便能够像默认的 Rails 记录器一样调用自定义记录器

ActiveSupport::TaggedLogging 用于包装任何标准记录器实例以将“标签”添加到日志语句中。在这种情况下,“标签”通常描述一个子域,默认 Rails.logger 使用它来允许您在多用户、多实例生产应用程序中使用子域、请求 ID 等标记日志语句。


include 
ActiveSupport::TaggedLogging::Formatter

Formatter 类。

【讨论】:

不幸的是,它们都不会在 log/development.log 文件中生成前缀时间条目。 @Dave 检查custom_options 的新更新代码 当您说“将 ActiveSupport::TaggedLogging::Formatter 包含到 Formatter 类中”时,那是什么?我的项目中没有名为 Formatter 的类,至少没有我创建的类。 创建自定义记录器时理想情况下需要它,我添加了自定义记录器,这似乎在我之前的编辑中被遗漏了 你添加的自定义记录器,ActiveSupport::BufferedLogger 类,应该放在什么目录下?【参考方案4】:

根据document,lograge gem 提供以下日志格式化程序。

Lograge::Formatters::Lines.new  # need to install "lines" gem
Lograge::Formatters::Cee.new
Lograge::Formatters::Graylog2.new
Lograge::Formatters::KeyValue.new  # default lograge format
Lograge::Formatters::Json.new
Lograge::Formatters::Logstash.new  # need to install "logstash-event" gem 
Lograge::Formatters::LTSV.new
Lograge::Formatters::Raw.new       # Returns a ruby hash object

默认情况下,lograge gem 使用Lograge::Formatters::KeyValue.new 格式的日志。

您可以通过使用 CustomLogStash 类进行一些更改来自定义它并使其通用。

class CustomLogStash < Lograge::Formatters::KeyValue
  def call(data)
    # I'm using timestamp key here, you can choose whatever you want.
    data_hash =  timestamp: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%3N").merge!(data)
    super(data_hash)
  end
end

您可以使用任何Lograge::Formatters 类并将自定义格式应用于日志。

现在将以下代码添加到您的 config/initializers/lograge.rb 文件中。

Rails.application.configure do
  config.lograge.enabled = true
  config.lograge.formatter = CustomLogStash.new
end

现在重新启动服务器并在浏览器中加载页面。您将看到类似以下的日志:

timestamp=2021-11-21T17:14:10.726 method=GET path=/categories format=html controller=categories action=index status=200 duration=259.11 view=244.91 db=2.60

已编辑

如果您正在寻找类似的日志

那么你不需要任何宝石。您可以通过在首选环境开发/生产/测试中添加以下几行来实现此目的

config.log_level = :debug
config.log_formatter = ::Logger::Formatter.new

如果您想在所有环境中应用此功能,请将以上行添加到 config/application.rb 文件中。

如果有帮助,请告诉我。

【讨论】:

我确认您在上面报告的内容 - 对控制器方法的请求以该时间戳为前缀。这真的很好。我注意到我的 log/development.log 文件中的另一个输出,例如从数据库加载对象不以时间戳为前缀(它们显示为“Product Load (2.3ms) SELECT products.* ...”)。有什么方法可以调整上述以使时间戳前缀通用? @Dave - 你想要这样的东西吗ibb.co/MyzLbJP

以上是关于使用 Rails 4.2 和 lograge,如何在每个记录的行之前启用日期/时间?的主要内容,如果未能解决你的问题,请参考以下文章

Rails 4.2 / Devise - 如果禁用cookie,则向用户显示特定消息

如何在 Rails 4.2 中为多对多关联创建表单

使用 #send_data 从数据库发送图像与 Rails 4.2 冲突

Sidekiq Rails 4.2使用活动作业还是工作者?有什么不同

Rails 4.2 从活动作业中获取延迟的作业 ID

Rails 4.2 不创建非消化资产