Loga
Description
Loga provides consistent logging across frameworks and environments.
Includes:
- One tagged logger for all environments
- Human readable logs for development
- Structured logs for production (GELF)
- One Rack logger for all Rack based applications
TOC
- Installation
- Rails
- Reduced logs
- Request log tags
- Sinatra
- Rails
- Output example
- GELF Format
- Simple Format
- Road map
- Contributing
- Running tests
- Credits
- License
Installation
Add this line to your application's Gemfile:
gem 'loga'
Rails
Let Loga know what your application name is and Loga will do the rest.
# config/application.rb
class MyApp::Application < Rails::Application
config.loga = { service_name: 'my_app' }
end
Loga hooks into the Rails logger initialization process and defines its own logger for all environments.
The logger configuration is adjusted based on the environment:
Production | Test | Development | Others | |
---|---|---|---|---|
Output | STDOUT | log/test.log | STDOUT | STDOUT |
Format | gelf | simple | simple | simple |
You can customize the configuration to your liking:
# config/application.rb
class MyApp::Application < Rails::Application
config.loga = {
device: File.open("log/application.log", 'a'),
format: :gelf,
service_name: 'my_app',
}
end
Loga leverages existing Rails configuration options:
config.filter_parameters
config.log_level
config.log_tags
Use these options to customize Loga instead of the Loga options hash.
Inside your application use Rails.logger
instead of Loga.logger
, even though
they are equivalent, to prevent lock-in.
Reduced logs
When the format set to gelf
requests logs are reduced to a single log entry, which
could include an exception.
This is made possible by silencing these loggers:
Rack::Request::Logger
ActionDispatch::DebugExceptions
ActionController::LogSubscriber
ActionView::LogSubscriber
ActionMailer::LogSubscriber
Request log tags
To provide consistency between Rails and other Rack frameworks, tags (e.i config.log_tags
)
are computed with a Loga::Rack::Request as
opposed to a ActionDispatch::Request
.
Sinatra
With Sinatra Loga needs to be configured manually:
# config.ru
require 'sinatra/base'
require 'loga'
Loga.configure(
filter_parameters: [:password],
format: :gelf,
service_name: 'my_app',
tags: [:uuid],
)
class MyApp < Sinatra::Base
set :logging, false # suppress Sinatra request logger
get '/' do
Loga.logger.info('Everything is Awesome!')
'Hello World!'
end
end
use Loga::Rack::RequestId
use Loga::Rack::Logger
run MyApp
You can now use Loga.logger
or assign it to your existing logger.
The above configuration also inserts two middleware:
-
Loga::Rack::RequestId
makes the request id available to the request logger -
Loga::Rack::Logger
logs requests
You can easily switch between formats by using the LOGA_FORMAT
environment variable. The format
key in the options takes precedence over the
environment variable therefore it must be removed.
LOGA_FORMAT=simple rackup
Sidekiq
Loga 2.7
provides an out-of-the-box support for Sidekiq ~> 7.0
.
Output Example
GELF Format
Rails request logger: (includes controller/action name):
curl localhost:3000/ok -X GET -H "X-Request-Id: 12345"
{
"_request.status": 200,
"_request.method": "GET",
"_request.path": "/ok",
"_request.params": {},
"_request.request_id": "12345",
"_request.request_ip": "127.0.0.1",
"_request.user_agent": null,
"_request.controller": "ApplicationController#ok",
"_request.duration": 0,
"_type": "request",
"_service.name": "my_app",
"_service.version": "1.0",
"_tags": "12345",
"short_message": "GET /ok 200 in 0ms",
"timestamp": 1450150205.123,
"host": "example.com",
"level": 6,
"version": "1.1"
}
Sinatra request output is identical to Rails but without the _request.controller
key.
Logger output:
# Rails.logger
# or
# Loga.logger
Loga.configure(service_name: 'my_app', format: :gelf)
Loga.logger.info('I love Loga')
Loga.logger.tagged(%w(USER_123 CRM)) do
Loga.logger.info('I love Loga with tags')
end
{
"_service.name": "my_app",
"_service.version": "v1.0.0",
"_tags": "",
"host": "example.com",
"level": 6,
"short_message": "I love Loga",
"timestamp": 1479402679.663,
"version": "1.1"
}
{
"_service.name": "my_app",
"_service.version": "v1.0.0",
"_tags": "USER_123 CRM",
"host": "example.com",
"level": 6,
"short_message": "I love Loga",
"timestamp": 1479402706.102,
"version": "1.1"
}
Simple Format
Request logger:
curl localhost:3000/ok -X GET -H "X-Request-Id: 12345"
Rails
I, [2016-11-15T16:05:03.614081+00:00 #1][12345] Started GET "/ok" for ::1 at 2016-11-15 16:05:03 +0000
I, [2016-11-15T16:05:03.620176+00:00 #1][12345] Processing by ApplicationController#ok as HTML
I, [2016-11-15T16:05:03.624807+00:00 #1][12345] Rendering text template
I, [2016-11-15T16:05:03.624952+00:00 #1][12345] Rendered text template (0.0ms)
I, [2016-11-15T16:05:03.625137+00:00 #1][12345] Completed 200 OK in 5ms (Views: 4.7ms)
Sinatra
I, [2016-11-15T16:10:08.645521+00:00 #1][12345] GET /ok 200 in 0ms type=request data={:request=>{"status"=>200, "method"=>"GET", "path"=>"/ok", "params"=>{}, "request_id"=>"12345", "request_ip"=>"127.0.0.1", "user_agent"=>nil, "duration"=>0}}
Logger output:
Loga.configure(service_name: 'my_app', format: :simple)
Loga.logger.info('I love Loga')
Loga.logger.tagged(%w(USER_123 CRM)) do
Loga.logger.info('I love Loga with tags')
end
I, [2016-11-17T17:07:46.714215+00:00 #595] I love Loga
I, [2016-11-17T17:07:46.725624+00:00 #595][USER_123 CRM] I love Loga with tags
Road map
Consult the milestones.
Contributing
Loga is in active development, feedback and contributions are welcomed.
Running tests
This project uses appraisal
to run tests against different versions of dependencies (e.g. Rails, Sinatra).
Install Loga dependencies with bundle install
and then appraisals
with bundle exec appraisal install
.
Run all tests with bundle exec appraisal rspec
.
You can run tests for one appraisal with bundle exec appraisal appraisal-name rspec
.
Refer to the Appraisals file for a complete lists of appraisals.
Prefix test command with RACK_ENV to switch between environments for Rack based tests
RACK_ENV=production bundle exec appraisal rspec
.
Experiment Guard support introduced to ease running tests locally bundle exec guard
.
CI results are the source of truth.
Credits
License
Copyright (c) 2015 Funding Circle. All rights reserved.
Distributed under the BSD 3-Clause License.