如何在Rails中生成唯一的请求ID?

时间:2022-08-22 20:31:48

I need a unique request ID for my logger, so I can track each request in the log file.

我的记录器需要一个唯一的请求ID,因此我可以跟踪日志文件中的每个请求。

So far I got this

到目前为止我得到了这个

REQUEST_ID = Digest::MD5.hexdigest(Time.now.to_f.to_s + $PID.to_s)

The problem is that I don't know where to put this. I tried placing it inside my custom logger file, outside the class. But it must be being cached or something because I'm always getting the same hash.

问题是我不知道在哪里放这个。我尝试将它放在我的自定义记录器文件中,在类外面。但它必须被缓存或其他东西,因为我总是得到相同的哈希。

Any ideas?

有任何想法吗?

note. I'm using Rails 3 and Passenger standalone

注意。我正在使用Rails 3和Passenger独立版

UPDATE:

更新:

Rails 3.2 :uuid tag won't work. Look how badly formatted the logs are:

Rails 3.2:uuid标签不起作用。看看日志的格式是多么糟糕:

[0909413851b79676cb06e0842d21c466] [127.0.0.1] 

Started HEAD "/" for 127.0.0.1 at Tue Feb 21 14:08:25 -0300 2012
[0909413851b79676cb06e0842d21c466] [127.0.0.1] Processing by PagesController#home as HTML
[0909413851b79676cb06e0842d21c466] [127.0.0.1] bla
[0909413851b79676cb06e0842d21c466] [127.0.0.1]   Rendered pages/home.html.erb within layouts/application (2.0ms)

In production this will be a mess. Notice the newlines after the first line? Now imagine how the logs would look like in a server handling many requests per second. It will be hard to associate a request with a URI

在生产中,这将是一个烂摊子。请注意第一行之后的换行符?现在想象一下在每秒处理许多请求的服务器中日志的样子。将请求与URI关联起来很困难

3 个解决方案

#1


4  

If you want to insert the request UUID at the log line Started GET "/" for 127.0.0.1 at Tue Feb 21 14:00:00 -0300 2012, you can patch or subclass Rails::Rack::Logger to modify the call_app method:

如果要在2012年2月21日星期二14:00:00 -0300的日志行开始GET“/”为127.0.0.1插入请求UUID,您可以修补或子类Rails :: Rack :: Logger来修改call_app方法:

def call_app(env)
  request = ActionDispatch::Request.new(env)
  path = request.filtered_path
  Rails.logger.info "\n\nStarted #{request.request_method} \"#{path}\" for #{request.ip} at #{Time.now.to_default_s}"
  @app.call(env)
ensure
  ActiveSupport::LogSubscriber.flush_all!
end

The request object is created right before the logging statement, so you can change the logging statement to include request.uuid.

请求对象在日志记录语句之前创建,因此您可以更改logging语句以包含request.uuid。

#2


34  

Rails core team took care of it for you!

Rails核心团队为您服务!

Rails 3.2 introduces request.uuid method, which returns, um, unique request identifier, which looks like this: ab939dfca5d57843ea4c695cab6f721d.

Rails 3.2引入了request.uuid方法,该方法返回唯一的请求标识符,如下所示:ab939dfca5d57843ea4c695cab6f721d。

See release notes here.

请参阅此处的发行说明

Also take a look at this awesome screencast to know how to use this new method with logging.

另外,请看一下这个精彩的截屏视频,了解如何在记录时使用这种新方法。

# config/environments/development.rb 
config.log_tags = [:uuid, :remote_ip]


# log file
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1] 

Started GET "/" for 127.0.0.1 at 2012-01-27 21:52:58 +0000
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1] Processing by ProductsController#index as HTML
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1]   Product Load (0.3ms)  SELECT "products".* FROM "products" 
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1]   Rendered products/index.html.erb within layouts/application (22.0ms)
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1] Completed 200 OK in 81ms (Views: 73.1ms | ActiveRecord: 0.3ms)
[98eec5f8976586c1165b981797086b6a] [127.0.0.1] 

#3


5  

Follow-up to the answer using log_tags, since :uuid is only unique among a request, it is difficult to use it with session tracking.

使用log_tags对答案进行后续跟踪,因为:uuid在请求中仅是唯一的,因此很难将其与会话跟踪一起使用。

I found log_tags accept a Proc, and pass a request object as an parameter. So, following code will stamp all of log entry with session_id (assuming you're using ActiveRecord based session store)

我发现log_tags接受Proc,并将请求对象作为参数传递。因此,以下代码将使用session_id标记所有日志条目(假设您正在使用基于ActiveRecord的会话存储)

config.log_tags = [ lambda {|req| "#{req.cookie_jar["_session_id"]}" }, :remote_ip, :uuid  ]

#1


4  

If you want to insert the request UUID at the log line Started GET "/" for 127.0.0.1 at Tue Feb 21 14:00:00 -0300 2012, you can patch or subclass Rails::Rack::Logger to modify the call_app method:

如果要在2012年2月21日星期二14:00:00 -0300的日志行开始GET“/”为127.0.0.1插入请求UUID,您可以修补或子类Rails :: Rack :: Logger来修改call_app方法:

def call_app(env)
  request = ActionDispatch::Request.new(env)
  path = request.filtered_path
  Rails.logger.info "\n\nStarted #{request.request_method} \"#{path}\" for #{request.ip} at #{Time.now.to_default_s}"
  @app.call(env)
ensure
  ActiveSupport::LogSubscriber.flush_all!
end

The request object is created right before the logging statement, so you can change the logging statement to include request.uuid.

请求对象在日志记录语句之前创建,因此您可以更改logging语句以包含request.uuid。

#2


34  

Rails core team took care of it for you!

Rails核心团队为您服务!

Rails 3.2 introduces request.uuid method, which returns, um, unique request identifier, which looks like this: ab939dfca5d57843ea4c695cab6f721d.

Rails 3.2引入了request.uuid方法,该方法返回唯一的请求标识符,如下所示:ab939dfca5d57843ea4c695cab6f721d。

See release notes here.

请参阅此处的发行说明

Also take a look at this awesome screencast to know how to use this new method with logging.

另外,请看一下这个精彩的截屏视频,了解如何在记录时使用这种新方法。

# config/environments/development.rb 
config.log_tags = [:uuid, :remote_ip]


# log file
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1] 

Started GET "/" for 127.0.0.1 at 2012-01-27 21:52:58 +0000
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1] Processing by ProductsController#index as HTML
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1]   Product Load (0.3ms)  SELECT "products".* FROM "products" 
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1]   Rendered products/index.html.erb within layouts/application (22.0ms)
[ab939dfca5d57843ea4c695cab6f721d] [127.0.0.1] Completed 200 OK in 81ms (Views: 73.1ms | ActiveRecord: 0.3ms)
[98eec5f8976586c1165b981797086b6a] [127.0.0.1] 

#3


5  

Follow-up to the answer using log_tags, since :uuid is only unique among a request, it is difficult to use it with session tracking.

使用log_tags对答案进行后续跟踪,因为:uuid在请求中仅是唯一的,因此很难将其与会话跟踪一起使用。

I found log_tags accept a Proc, and pass a request object as an parameter. So, following code will stamp all of log entry with session_id (assuming you're using ActiveRecord based session store)

我发现log_tags接受Proc,并将请求对象作为参数传递。因此,以下代码将使用session_id标记所有日志条目(假设您正在使用基于ActiveRecord的会话存储)

config.log_tags = [ lambda {|req| "#{req.cookie_jar["_session_id"]}" }, :remote_ip, :uuid  ]