How to use Rails Current Attributes to track nginx (web server) and unicorn (app server) logs with X-Request-ID

Rails version confirmed to work

6.0.3.4

As a common story

In order to search the log of the web server such as Nginx and the log of the application server such as unicorn and puma with the same ID, X-Request-ID is put in the log of the application server. It is easy to do it with the config setting prepared in Rails in advance, but there are the following problems.

Tagged Logging issues

If you are using Tagged Logging, X-Request-ID will be assigned to the log if you uncomment the following settings in the config file. config.log_tags = [ :request_id ]

If the X-Request-ID is 123456789, the log will look like ↓.

[2020-11-XXT09:37:34+09:00] [123456789] some message 

However, Tagged Logging does not output the backtrace to the log when there is the following processing, for example.

def XXX
rescue StandardError => e  
  logger.error e
end

In that case, you can achieve the same thing by using CurrentAttributes implemented from Rails 5.2. Current Attributes There is a word request_id in Documentation, and you can imagine that such a use case is assumed.

Code example in the documentation

# app/models/current.rb
class Current < ActiveSupport::CurrentAttributes
  attribute :account, :user
  attribute :request_id, :user_agent, :ip_address

  resets { Time.zone = nil }

  def user=(user)
    super
    self.account = user.account
    Time.zone    = user.time_zone
  end
end

Implementation method

All you have to do is set the X-Request-ID to CurrentAttributes in middleware and output it in formatter.

Create a class that inherits ActiveSupport :: CurrentAttributes

app/models/current.rb

# frozen_string_literal: true

class Current < ActiveSupport::CurrentAttributes
  attribute :x_request_id
end

Set the value to the class created using middleware,

config/initializers/x_request_id.rb


require 'current_x_request_id'

Rails.application.config.middleware.insert_after ActionDispatch::RequestId, CurrentXRequestId

ActionDispatch :: RequestId sets X-Request-ID to env ['action_dispatch.request_id']

lib/current_x_request_id.rb


# frozen_string_literal: true

class CurrentXRequestId
  def initialize(app)
    @app = app
  end

  def call(env)
    Current.x_request_id = env['action_dispatch.request_id']
    @app.call(env)
  end
end

Then output it with formatter

lib/formatter.rb


    def call(severity, time, progname, msg)
        msg = msg2str(msg) #Parent class (Logger) to output backtrace::Formatter) method (msg2str) is used
        ~~~
        "request_id: #{Current.x_request_id} #{msg}"
        ~~~
    end

As a caveat

CurrentAttributes is a very powerful mechanism, but it seems that you need to carefully consider it when using it. Here is an example of a note.

A word of caution: It's easy to overdo a global singleton like Current and tangle your model as a result.
Current should only be used for a few, top-level globals, like account, user, and request details.
The attributes stuck in Current should be used by more or less all actions on all requests. If you start
sticking controller-specific attributes in there, you're going to create a mess.

deepl translator

Overdoing a global singleton like Current can result in model entanglement.
Current should only be used globally for a few top-level globals such as account, user, request details, etc.
Attributes fixed to Current should be used more or less in every action in every request. if
Pasting controller-specific attributes can be confusing.

Recommended Posts

How to use Rails Current Attributes to track nginx (web server) and unicorn (app server) logs with X-Request-ID
[Rails] How to use rails console with docker
How to build API with GraphQL and Rails
How to push an app developed with Rails to Github
How to use RealSense with ubuntu 20.04 and ROS Noetic
How to get started with creating a Rails app
[Docker + Rails] How to deal with Rails server startup failure
How to specify db when creating an app with rails
How to run React and Rails on the same server
[Rails] How to use enum
[Rails] How to use enum
How to use rails join
How to terminate rails server
[Rails] How to use validation
[Rails] How to use authenticate_user!
[Rails] How to use "kaminari"
Rails web server and application server
[Rails] How to use Scope
[Rails] How to introduce kaminari with Slim and change the design
[Rails] How to use gem "devise"
How to use StringBurrer and Arrays.toString.
[Rails] How to use flash messages
How to use EventBus3 and ThreadMode
How to use Ruby on Rails
How to use mssql-tools with alpine
[Rails] How to use Active Storage
Track Rails app errors with Sentry
Connect to Rails server with iPhone
[Introduction to Rails] How to use render
How to interact with a server that does not crash the app
Use Timecop in Rails web app to travel time on your browser
[Swift] How to connect TabBar with Storyboard Reference and also use NavigationController
How to use args :, environment :, env_file: and .env files with docker-compose command
How to create a server executable JAR and WAR with Spring gradle
[Rails] How to apply the CSS used in the main app with Administrate
How to make an app with a plugin mechanism [C # and Java]
How to change app name in rails
How to use OrientJS and OrientDB together
How to use custom helpers in rails
[Ruby on Rails] How to use CarrierWave
[Rails] How to use ActiveRecord :: Bitemporal (BiTemporalDataModel)
[Rails] How to use the map method
How to use MySQL in Rails tutorial
[Ruby on Rails] How to use redirect_to
[Note] How to use Rails 6 Devise + cancancan
[Ruby on Rails] How to use kaminari
[AWS] Publish rails app with nginx + puma
How to use substring and substr methods
[Rails] How to use video_tag to display videos
[Rails] How to use helper method, confimartion
How to use credentials.yml.enc introduced in Rails 5.2
How to use @Builder and @NoArgsConstructor together
How to build Rails 6 environment with Docker
How to connect to lcalhost from your smartphone and use the app under development
How to use ToolBar with super margin Part1 Set characters and change colors
I'm making an Android app and I'm stuck with errors and how to solve it
How to use Eclipse on my PC with 32bit and 2GB of memory