Как создать уникальный идентификатор запроса в Rails?

Мне нужен уникальный идентификатор запроса для моего регистратора, поэтому я могу отслеживать каждый запрос в файле журнала.

До сих пор я получил это

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

Проблема в том, что я не знаю, куда ее поместить. Я попытался помещать его в свой собственный файл журнала, вне класса. Но это должно быть кэширование или что-то, потому что я всегда получаю тот же хеш.

Любые идеи?

примечание. Я использую Rails 3 и автономный пассажирский

UPDATE:

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)

В производстве это будет беспорядок. Обратите внимание на строки новой строки после первой строки? Теперь представьте, как журналы будут выглядеть на сервере, обрабатывая много запросов в секунду. Будет сложно связать запрос с URI

Ответ 1

Если вы хотите вставить UUID запроса в строку журнала Started GET "/" for 127.0.0.1 at Tue Feb 21 14:00:00 -0300 2012, вы можете изменить или подклассом 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

Объект запроса создается непосредственно перед оператором ведения журнала, поэтому вы можете изменить оператор регистрации, включив request.uuid.

Ответ 2

Основная команда Rails позаботилась об этом для вас!

Rails 3.2 вводит метод request.uuid, который возвращает, um, уникальный идентификатор запроса, который выглядит следующим образом: ab939dfca5d57843ea4c695cab6f721d.

Смотрите примечания к выпуску здесь.

Также посмотрите на этом потрясающем скринкасте, чтобы узнать, как использовать этот новый метод при регистрации.

# 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

Выполнение ответа с использованием log_tags, поскольку: uuid является уникальным только для запроса, его трудно использовать с отслеживанием сеанса.

Я обнаружил, что log_tags принимают Proc и передают объект запроса в качестве параметра. Таким образом, следующий код будет отмечать все записи в журнале с помощью session_id (при условии, что вы используете хранилище сеансов на основе ActiveRecord)

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