mirror of
https://github.com/samsonjs/grape_logging.git
synced 2026-04-27 14:57:40 +00:00
Add GrapeLogging::Formatters::RailsFormatter.new. Updates to README (#47)
This commit is contained in:
parent
83117bc7e1
commit
7ae51d30d8
7 changed files with 219 additions and 5 deletions
80
README.md
80
README.md
|
|
@ -33,11 +33,83 @@ use GrapeLogging::Middleware::RequestLogger, { logger: logger }
|
||||||
|
|
||||||
### Log Format
|
### Log Format
|
||||||
|
|
||||||
With the default configuration you will get nice log message
|
There are formatters provided for you, or you can provide your own.
|
||||||
|
|
||||||
[2015-04-16 12:52:12 +0200] INFO -- 200 -- total=2.06 db=0.36 -- PATCH /your_app/endpoint params={"some_param"=>{"value_1"=>"123", "value_2"=>"456"}}
|
#### `GrapeLogging::Formatters::Default`
|
||||||
|
|
||||||
If you prefer some other format I strongly encourage you to do pull request with new formatter class ;)
|
[2015-04-16 12:52:12 +0200] INFO -- 200 -- total=2.06 db=0.36 -- PATCH /api/endpoint params={"some_param"=>{"value_1"=>"123", "value_2"=>"456"}}
|
||||||
|
|
||||||
|
#### `GrapeLogging::Formatters::Json`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"date": "2015-04-16 12:52:12+0200",
|
||||||
|
"severity": "INFO",
|
||||||
|
"data": {
|
||||||
|
"status": 200,
|
||||||
|
"time": {
|
||||||
|
"total": 2.06,
|
||||||
|
"db": 0.36,
|
||||||
|
"view": 1.70
|
||||||
|
},
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/endpoint",
|
||||||
|
"params": {
|
||||||
|
"value_1": "123",
|
||||||
|
"value_2": "456"
|
||||||
|
},
|
||||||
|
"host": "localhost"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `GrapeLogging::Formatters::Lograge`
|
||||||
|
|
||||||
|
severity="INFO", duration=2.06, db=0.36, view=1.70, datetime="2015-04-16 12:52:12+0200", status=200, method="PATCH", path="/api/endpoint", params={}, host="localhost"
|
||||||
|
|
||||||
|
#### `GrapeLogging::Formatters::Logstash`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"@timestamp": "2015-04-16 12:52:12+0200",
|
||||||
|
"severity": "INFO",
|
||||||
|
"status": 200,
|
||||||
|
"time": {
|
||||||
|
"total": 2.06,
|
||||||
|
"db": 0.36,
|
||||||
|
"view": 1.70
|
||||||
|
},
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/endpoint",
|
||||||
|
"params": {
|
||||||
|
"value_1": "123",
|
||||||
|
"value_2": "456"
|
||||||
|
},
|
||||||
|
"host": "localhost"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `GrapeLogging::Formatters::Rails`
|
||||||
|
|
||||||
|
Rails will print the "Started..." line:
|
||||||
|
|
||||||
|
Started GET "/api/endpoint" for ::1 at 2015-04-16 12:52:12 +0200
|
||||||
|
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1
|
||||||
|
...
|
||||||
|
|
||||||
|
The `Rails` formatter adds the last line of the request, like a standard Rails request:
|
||||||
|
|
||||||
|
Completed 200 OK in 349ms (Views: 250.1ms | DB: 98.63ms)
|
||||||
|
|
||||||
|
#### Custom
|
||||||
|
|
||||||
|
You can provide your own class that implements the `call` method returning a `String`:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def call(severity, datetime, _, data)
|
||||||
|
...
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
You can change the formatter like so
|
You can change the formatter like so
|
||||||
```ruby
|
```ruby
|
||||||
|
|
@ -46,6 +118,8 @@ class MyAPI < Grape::API
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you prefer some other format I strongly encourage you to do pull request with new formatter class ;)
|
||||||
|
|
||||||
### Customising What Is Logged
|
### Customising What Is Logged
|
||||||
|
|
||||||
You can include logging of other parts of the request / response cycle by including subclasses of `GrapeLogging::Loggers::Base`
|
You can include logging of other parts of the request / response cycle by including subclasses of `GrapeLogging::Loggers::Base`
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
|
||||||
spec.require_paths = ['lib']
|
spec.require_paths = ['lib']
|
||||||
|
|
||||||
spec.add_dependency 'grape'
|
spec.add_dependency 'grape'
|
||||||
|
spec.add_dependency 'rack'
|
||||||
|
|
||||||
spec.add_development_dependency 'bundler', '~> 1.8'
|
spec.add_development_dependency 'bundler', '~> 1.8'
|
||||||
spec.add_development_dependency 'rake', '~> 10.0'
|
spec.add_development_dependency 'rake', '~> 10.0'
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ require 'grape_logging/formatters/default'
|
||||||
require 'grape_logging/formatters/json'
|
require 'grape_logging/formatters/json'
|
||||||
require 'grape_logging/formatters/lograge'
|
require 'grape_logging/formatters/lograge'
|
||||||
require 'grape_logging/formatters/logstash'
|
require 'grape_logging/formatters/logstash'
|
||||||
|
require 'grape_logging/formatters/rails'
|
||||||
require 'grape_logging/loggers/base'
|
require 'grape_logging/loggers/base'
|
||||||
require 'grape_logging/loggers/response'
|
require 'grape_logging/loggers/response'
|
||||||
require 'grape_logging/loggers/filter_parameters'
|
require 'grape_logging/loggers/filter_parameters'
|
||||||
|
|
|
||||||
59
lib/grape_logging/formatters/rails.rb
Normal file
59
lib/grape_logging/formatters/rails.rb
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
require 'rack/utils'
|
||||||
|
|
||||||
|
module GrapeLogging
|
||||||
|
module Formatters
|
||||||
|
class Rails
|
||||||
|
|
||||||
|
def call(severity, datetime, _, data)
|
||||||
|
if data.is_a?(String)
|
||||||
|
"#{severity[0..0]} [#{datetime}] #{severity} -- : #{data}\n"
|
||||||
|
elsif data.is_a?(Exception)
|
||||||
|
"#{severity[0..0]} [#{datetime}] #{severity} -- : #{format_exception(data)}\n"
|
||||||
|
elsif data.is_a?(Hash)
|
||||||
|
format_hash(data)
|
||||||
|
else
|
||||||
|
"#{data.inspect}\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def format_exception(exception)
|
||||||
|
backtrace_array = (exception.backtrace || []).map { |line| "\t#{line}" }
|
||||||
|
|
||||||
|
[
|
||||||
|
"#{exception.message} (#{exception.class})",
|
||||||
|
backtrace_array.join("\n")
|
||||||
|
].reject{|line| line == ""}.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_hash(hash)
|
||||||
|
# Create Rails' single summary line at the end of every request, formatted like:
|
||||||
|
# Completed 200 OK in 958ms (Views: 951.1ms | ActiveRecord: 3.8ms)
|
||||||
|
# See: actionpack/lib/action_controller/log_subscriber.rb
|
||||||
|
|
||||||
|
message = ""
|
||||||
|
additions = []
|
||||||
|
status = hash.delete(:status)
|
||||||
|
params = hash.delete(:params)
|
||||||
|
|
||||||
|
total_time = hash[:time] && hash[:time][:total] && hash[:time][:total].round(2)
|
||||||
|
view_time = hash[:time] && hash[:time][:view] && hash[:time][:view].round(2)
|
||||||
|
db_time = hash[:time] && hash[:time][:db] && hash[:time][:db].round(2)
|
||||||
|
|
||||||
|
additions << "Views: #{view_time}ms" if view_time
|
||||||
|
additions << "DB: #{db_time}ms" if db_time
|
||||||
|
|
||||||
|
message << " Parameters: #{params.inspect}\n" if params
|
||||||
|
|
||||||
|
message << "Completed #{status} #{::Rack::Utils::HTTP_STATUS_CODES[status]} in #{total_time}ms"
|
||||||
|
message << " (#{additions.join(" | ".freeze)})" if additions.size > 0
|
||||||
|
message << "\n"
|
||||||
|
message << "\n" if defined?(::Rails.env) && ::Rails.env.development?
|
||||||
|
|
||||||
|
message
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -4,7 +4,7 @@ module GrapeLogging
|
||||||
AD_PARAMS = 'action_dispatch.request.parameters'.freeze
|
AD_PARAMS = 'action_dispatch.request.parameters'.freeze
|
||||||
|
|
||||||
def initialize(filter_parameters = nil, replacement = nil, exceptions = %w(controller action format))
|
def initialize(filter_parameters = nil, replacement = nil, exceptions = %w(controller action format))
|
||||||
@filter_parameters = filter_parameters || (defined?(Rails.application) ? Rails.application.config.filter_parameters : [])
|
@filter_parameters = filter_parameters || (defined?(::Rails.application) ? ::Rails.application.config.filter_parameters : [])
|
||||||
@replacement = replacement || '[FILTERED]'
|
@replacement = replacement || '[FILTERED]'
|
||||||
@exceptions = exceptions
|
@exceptions = exceptions
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
if defined?(Rails.application)
|
if defined?(::Rails.application)
|
||||||
class ParameterFilter < ActionDispatch::Http::ParameterFilter
|
class ParameterFilter < ActionDispatch::Http::ParameterFilter
|
||||||
def initialize(_replacement, filter_parameters)
|
def initialize(_replacement, filter_parameters)
|
||||||
super(filter_parameters)
|
super(filter_parameters)
|
||||||
|
|
|
||||||
79
spec/lib/grape_logging/formatters/rails_spec.rb
Normal file
79
spec/lib/grape_logging/formatters/rails_spec.rb
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe GrapeLogging::Formatters::Rails do
|
||||||
|
let(:formatter) { described_class.new }
|
||||||
|
let(:severity) { "INFO" }
|
||||||
|
let(:datetime) { Time.new('2018', '03', '02', '10', '35', '04', '+13:00') }
|
||||||
|
|
||||||
|
let(:exception_data) { ArgumentError.new('Message') }
|
||||||
|
let(:hash_data) {
|
||||||
|
{
|
||||||
|
status: 200,
|
||||||
|
time: {
|
||||||
|
total: 272.4,
|
||||||
|
db: 40.63,
|
||||||
|
view: 231.76999999999998
|
||||||
|
},
|
||||||
|
method: "GET",
|
||||||
|
path: "/api/endpoint",
|
||||||
|
host: "localhost"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe '#call' do
|
||||||
|
context 'string data' do
|
||||||
|
it 'returns a formatted string' do
|
||||||
|
message = formatter.call(severity, datetime, nil, 'value')
|
||||||
|
|
||||||
|
expect(message).to eq "I [2018-03-02 10:35:04 +1300] INFO -- : value\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'exception data' do
|
||||||
|
it 'returns a string with a backtrace' do
|
||||||
|
exception_data.set_backtrace(caller)
|
||||||
|
|
||||||
|
message = formatter.call(severity, datetime, nil, exception_data)
|
||||||
|
lines = message.split("\n")
|
||||||
|
|
||||||
|
expect(lines[0]).to eq "I [2018-03-02 10:35:04 +1300] INFO -- : Message (ArgumentError)"
|
||||||
|
expect(lines[1]).to include 'grape_logging'
|
||||||
|
expect(lines.size).to be > 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'hash data' do
|
||||||
|
it 'returns a formatted string' do
|
||||||
|
message = formatter.call(severity, datetime, nil, hash_data)
|
||||||
|
|
||||||
|
expect(message).to eq "Completed 200 OK in 272.4ms (Views: 231.77ms | DB: 40.63ms)\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes params if included (from GrapeLogging::Loggers::FilterParameters)' do
|
||||||
|
hash_data.merge!(
|
||||||
|
params: {
|
||||||
|
"some_param" => {
|
||||||
|
value_1: "123",
|
||||||
|
value_2: "456"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
message = formatter.call(severity, datetime, nil, hash_data)
|
||||||
|
lines = message.split("\n")
|
||||||
|
|
||||||
|
expect(lines.first).to eq ' Parameters: {"some_param"=>{:value_1=>"123", :value_2=>"456"}}'
|
||||||
|
expect(lines.last).to eq "Completed 200 OK in 272.4ms (Views: 231.77ms | DB: 40.63ms)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "unhandled data" do
|
||||||
|
it 'returns the #inspect string representation' do
|
||||||
|
message = formatter.call(severity, datetime, nil, [1, 2, 3])
|
||||||
|
|
||||||
|
expect(message).to eq "[1, 2, 3]\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
Loading…
Reference in a new issue