Skip to content

websdotcom/marlowe

 
 

Repository files navigation

marlowe

Description

marlowe provides a correlation id header for Rails and Rack applications to correlate logs for a single request across multiple services.

Install

You can install it as a gem:

$ gem install marlowe

or add it into a Gemfile:

gem 'marlowe'

Configuration

To configure the header where Marlowe looks for and puts the correlation id:

  • In Rails, specify the header in your environment configuration:

    config.marlowe_correlation_header = “My-Correlation-Id”

  • If you are adding the middleware to a Rack application directly, pass it as an option:

    use Marlowe::Middleware, correlation_header: “My-Correlation-Id”

(Note that HTTP headers are case insensitive. In the Rack ‘env`, this header name is actually represented as `env`.)

Accesing the Correlation ID

The correlation id can be accessed throughout the application by accessing the RequestStore storage.

RequestStore[:correlation_id]

Logging

For a rails application, you simply need to change the log formatter to one of the provided ones. Correlated versions of both the SimpleFormatter and Formatter are included.

# config/environments/development.rb
Rails.application.configure do
  config.log_formatter = Marlowe::SimpleFormatter.new
end

To create your own formatter, you’ll need to access the RequestStore storage. You can use this pattern if you’ve rolled your own logger/formatter:

# lib/correlated_formatter.rb
require 'request_store'

class CorrelatedSimpleFormatter < ActiveSupport::Logger::SimpleFormatter
  def call(severity, timestamp, progname, msg)
    "[#{RequestStore.store[:correlation_id]}] #{super}"
  end
end

Lograge

As lograge supplies it’s own formatter, you will need to do something a little different:

# config/application.rb

class Application < Rails::Application
  config.before_initialize do
    ...
    # use lograge for all request logs
    config.lograge.enabled = true
    config.lograge.custom_options = lambda do |event|
      { correlation_id: RequestStore[:correlation_id] }
    end
  end
end

Clients

Catching and creating the correlation ID is a great all on its own, but to really take advantage of the correlation in a service based architecture you’ll need to pass the id to the next service in the change.

Here’s an example of a Hurley client:

# lib/correlated_client.rb

require 'hurley'
require 'request_store'

class Hurley::CorrelatedClient < Hurley::Client
  def initialize(*args, &block)
    super
    header['Correlation-Id'] = ::RequestStore.store[:correlation_id]
  end
end

If you have long-lived Hurley clients, it is also possible to use the Hurley callback machanism to add the outgoing headers:

client.before_call do |request|
  request.header['Correlation-Id'] = ::RequestStore.store[:correlation_id]
end

or

class Correlator
  def name
    :correlator
  end

  def call(request)
    request.header['Correlation-Id'] = ::RequestStore.store[:correlation_id]
  end
end

client.before_call(Correlator.new)

About

Marlowe makes it easier to trace a request through all of your application logs

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Ruby 100.0%