lograge 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +1 -1
- data/Gemfile +1 -1
- data/README.md +52 -4
- data/lib/lograge.rb +59 -11
- data/lib/lograge/formatters/cee.rb +9 -0
- data/lib/lograge/formatters/graylog2.rb +19 -0
- data/lib/lograge/formatters/key_value.rb +29 -0
- data/lib/lograge/formatters/logstash.rb +19 -0
- data/lib/lograge/formatters/raw.rb +9 -0
- data/lib/lograge/log_subscriber.rb +10 -43
- data/lib/lograge/rails_ext/rack/logger.rb +1 -0
- data/lib/lograge/version.rb +1 -1
- data/lograge.gemspec +3 -2
- data/spec/formatters/cee_spec.rb +7 -0
- data/spec/formatters/graylog2_spec.rb +18 -0
- data/spec/formatters/key_value_spec.rb +23 -0
- data/spec/formatters/logstash_spec.rb +25 -0
- data/spec/formatters/raw_spec.rb +6 -0
- data/spec/lograge_logsubscriber_spec.rb +85 -195
- data/spec/lograge_spec.rb +44 -0
- metadata +37 -6
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -70,19 +70,47 @@ MyApp::Application.configure do
|
|
70
70
|
# if it's a lambda then it must return a hash
|
71
71
|
config.lograge.custom_options = lambda do |event|
|
72
72
|
# capture some specific timing values you are interested in
|
73
|
-
{:name => "value", :timing => some_float.round(2)}
|
73
|
+
{:name => "value", :timing => some_float.round(2), :host => event.payload[:host]}
|
74
|
+
end
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
You can then add custom variables to the event to be used in custom_options
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
# app/controllers/application_controller.rb
|
82
|
+
class ApplicationController < ActionController::Base
|
83
|
+
def append_info_to_payload(payload)
|
84
|
+
super
|
85
|
+
payload[:host] = request.host
|
86
|
+
end
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
To further clean up your logging, you can also tell Lograge to skip log messages
|
91
|
+
meeting given criteria. You can skip log messages generated from certain controller
|
92
|
+
actions, or you can write a custom handler to skip messages based on data in the log event:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
# config/environments/production.rb
|
96
|
+
MyApp::Application.configure do
|
97
|
+
config.lograge.enabled = true
|
98
|
+
|
99
|
+
config.lograge.ignore_actions = ['home#index', 'aController#anAction']
|
100
|
+
config.lograge.ignore_custom = lambda do |event|
|
101
|
+
# return true here if you want to ignore based on the event
|
74
102
|
end
|
75
103
|
end
|
76
104
|
```
|
77
105
|
|
78
106
|
Lograge supports multiple output formats. The most common is the default
|
79
|
-
lograge format described above. Alternatively, you can also generate
|
80
|
-
logs in the json_event format used by [Logstash](http://logstash.net/).
|
107
|
+
lograge key-value format described above. Alternatively, you can also generate
|
108
|
+
JSON logs in the json_event format used by [Logstash](http://logstash.net/).
|
81
109
|
|
82
110
|
```ruby
|
83
111
|
# config/environments/production.rb
|
84
112
|
MyApp::Application.configure do
|
85
|
-
config.lograge.
|
113
|
+
config.lograge.formatter = Lograge::Formatters::Logstash.new
|
86
114
|
end
|
87
115
|
```
|
88
116
|
|
@@ -95,6 +123,26 @@ gem "logstash-event"
|
|
95
123
|
|
96
124
|
Done.
|
97
125
|
|
126
|
+
The available formatters are:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
Lograge::Formatters::Cee.new
|
130
|
+
Lograge::Formatters::Graylog2.new
|
131
|
+
Lograge::Formatters::KeyValue.new # default lograge format
|
132
|
+
Lograge::Formatters::Logstash.new
|
133
|
+
Lograge::Formatters::Raw.new # Returns a ruby hash object
|
134
|
+
```
|
135
|
+
|
136
|
+
In addition to the formatters, you can manipulate the data your self by passing
|
137
|
+
an object which responds to #call:
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
# config/environments/production.rb
|
141
|
+
MyApp::Application.configure do
|
142
|
+
config.lograge.formatter = ->(data) { "Called #{data[:controller]}" } # data is a ruby hash
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
98
146
|
**Internals**
|
99
147
|
|
100
148
|
Thanks to the notification system that was introduced in Rails 3, replacing the
|
data/lib/lograge.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
require 'lograge/version'
|
2
|
+
require 'lograge/formatters/cee'
|
3
|
+
require 'lograge/formatters/graylog2'
|
4
|
+
require 'lograge/formatters/key_value'
|
5
|
+
require 'lograge/formatters/logstash'
|
6
|
+
require 'lograge/formatters/raw'
|
2
7
|
require 'lograge/log_subscriber'
|
3
8
|
require 'active_support/core_ext/module/attribute_accessors'
|
4
9
|
require 'active_support/core_ext/string/inflections'
|
5
10
|
require 'active_support/ordered_options'
|
6
11
|
|
12
|
+
|
7
13
|
module Lograge
|
8
14
|
mattr_accessor :logger
|
9
15
|
|
@@ -24,13 +30,51 @@ module Lograge
|
|
24
30
|
end
|
25
31
|
end
|
26
32
|
|
33
|
+
# Set conditions for events that should be ignored
|
34
|
+
#
|
35
|
+
# Currently supported formats are:
|
36
|
+
# - A single string representing a controller action, e.g. 'users#sign_in'
|
37
|
+
# - An array of strings representing controller actions
|
38
|
+
# - An object that responds to call with an event argument and returns
|
39
|
+
# true iff the event should be ignored.
|
40
|
+
#
|
41
|
+
# The action ignores are given to 'ignore_actions'. The callable ignores
|
42
|
+
# are given to 'ignore'. Both methods can be called multiple times, which
|
43
|
+
# just adds more ignore conditions to a list that is checked before logging.
|
44
|
+
|
45
|
+
def self.ignore_actions(actions)
|
46
|
+
ignore(lambda do |event|
|
47
|
+
params = event.payload[:params]
|
48
|
+
Array(actions).include?("#{params['controller']}##{params['action']}")
|
49
|
+
end)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.ignore_tests
|
53
|
+
@@ignore_tests ||= []
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.ignore(test)
|
57
|
+
ignore_tests.push(test) if test
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.ignore_nothing
|
61
|
+
@@ignore_tests = []
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.ignore?(event)
|
65
|
+
ignore_tests.any?{|ignore_test| ignore_test.call(event)}
|
66
|
+
end
|
67
|
+
|
68
|
+
# Loglines are emitted with this log level
|
69
|
+
mattr_accessor :log_level
|
70
|
+
self.log_level = :info
|
71
|
+
|
27
72
|
# The emitted log format
|
28
73
|
#
|
29
74
|
# Currently supported formats are>
|
30
75
|
# - :lograge - The custom tense lograge format
|
31
76
|
# - :logstash - JSON formatted as a Logstash Event.
|
32
|
-
mattr_accessor :
|
33
|
-
self.log_format = :lograge
|
77
|
+
mattr_accessor :formatter
|
34
78
|
|
35
79
|
def self.remove_existing_log_subscriptions
|
36
80
|
ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
|
@@ -60,15 +104,19 @@ module Lograge
|
|
60
104
|
Lograge.remove_existing_log_subscriptions
|
61
105
|
Lograge::RequestLogSubscriber.attach_to :action_controller
|
62
106
|
Lograge.custom_options = app.config.lograge.custom_options
|
63
|
-
Lograge.
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
107
|
+
Lograge.log_level = app.config.lograge.log_level || :info
|
108
|
+
self.support_deprecated_config(app) # TODO: Remove with version 1.0
|
109
|
+
Lograge.formatter = app.config.lograge.formatter || Lograge::Formatters::KeyValue.new
|
110
|
+
Lograge.ignore_actions(app.config.lograge.ignore_actions)
|
111
|
+
Lograge.ignore(app.config.lograge.ignore_custom)
|
112
|
+
end
|
113
|
+
|
114
|
+
# TODO: Remove with version 1.0
|
115
|
+
def self.support_deprecated_config(app)
|
116
|
+
if legacy_log_format = app.config.lograge.log_format
|
117
|
+
ActiveSupport::Deprecation.warn 'config.lograge.log_format is deprecated. Use config.lograge.formatter instead.', caller
|
118
|
+
legacy_log_format = :key_value if legacy_log_format == :lograge
|
119
|
+
app.config.lograge.formatter = "Lograge::Formatters::#{legacy_log_format.to_s.classify}".constantize.new
|
72
120
|
end
|
73
121
|
end
|
74
122
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Lograge
|
2
|
+
module Formatters
|
3
|
+
class Graylog2
|
4
|
+
def call(data)
|
5
|
+
# Cloning because we don't want to mess with the original when mutating keys.
|
6
|
+
my = data.clone
|
7
|
+
|
8
|
+
base = {
|
9
|
+
:short_message => "[#{my[:status]}] #{my[:method]} #{my[:path]} (#{my[:controller]}##{my[:action]})"
|
10
|
+
}
|
11
|
+
|
12
|
+
# Add underscore to every key to follow GELF additional field syntax.
|
13
|
+
my.keys.each { |k| my["_#{k}".to_sym] = my[k]; my.delete(k) }
|
14
|
+
|
15
|
+
my.merge(base)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Lograge
|
2
|
+
module Formatters
|
3
|
+
class KeyValue
|
4
|
+
LOGRAGE_FIELDS = [
|
5
|
+
:method, :path, :format, :controller, :action, :status, :error,
|
6
|
+
:duration, :view, :db, :location
|
7
|
+
]
|
8
|
+
|
9
|
+
def call(data)
|
10
|
+
fields = LOGRAGE_FIELDS
|
11
|
+
fields += (data.keys - LOGRAGE_FIELDS)
|
12
|
+
|
13
|
+
event = fields.inject([]) do |message, key|
|
14
|
+
next message unless data.has_key?(key)
|
15
|
+
# Exactly preserve the previous output
|
16
|
+
# Parsing this can be ambigious if the error messages contains
|
17
|
+
# a single quote
|
18
|
+
data[key] = "'#{data[key]}'" if key == :error
|
19
|
+
# Ensure that we always have exactly two decimals
|
20
|
+
data[key] = "%.2f" % data[key] if data[key].is_a? Float
|
21
|
+
|
22
|
+
message << "#{key}=#{data[key]}"
|
23
|
+
message
|
24
|
+
end
|
25
|
+
event.join(" ")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Lograge
|
2
|
+
module Formatters
|
3
|
+
class Logstash
|
4
|
+
def call(data)
|
5
|
+
load_dependencies
|
6
|
+
event = LogStash::Event.new("@fields" => data)
|
7
|
+
event.message = "[#{data[:status]}] #{data[:method]} #{data[:path]} (#{data[:controller]}##{data[:action]})"
|
8
|
+
event.to_json
|
9
|
+
end
|
10
|
+
|
11
|
+
def load_dependencies
|
12
|
+
require "logstash-event"
|
13
|
+
rescue LoadError
|
14
|
+
puts "You need to install the logstash-event gem to use the logstash output."
|
15
|
+
raise
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,9 +1,13 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
1
3
|
require 'active_support/core_ext/class/attribute'
|
2
4
|
require 'active_support/log_subscriber'
|
3
5
|
|
4
6
|
module Lograge
|
5
7
|
class RequestLogSubscriber < ActiveSupport::LogSubscriber
|
6
8
|
def process_action(event)
|
9
|
+
return if Lograge.ignore?(event)
|
10
|
+
|
7
11
|
payload = event.payload
|
8
12
|
|
9
13
|
data = extract_request(payload)
|
@@ -12,49 +16,8 @@ module Lograge
|
|
12
16
|
data.merge! location(event)
|
13
17
|
data.merge! custom_options(event)
|
14
18
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
LOGRAGE_FIELDS = [
|
19
|
-
:method, :path, :format, :controller, :action, :status, :error,
|
20
|
-
:duration, :view, :db, :location
|
21
|
-
]
|
22
|
-
def process_action_lograge(data)
|
23
|
-
fields = LOGRAGE_FIELDS
|
24
|
-
fields += (data.keys - LOGRAGE_FIELDS)
|
25
|
-
|
26
|
-
event = fields.inject([]) do |message, key|
|
27
|
-
next message unless data.has_key?(key)
|
28
|
-
# Exactly preserve the previous output
|
29
|
-
# Parsing this can be ambigious if the error messages contains
|
30
|
-
# a single quote
|
31
|
-
data[key] = "'#{data[key]}'" if key == :error
|
32
|
-
# Ensure that we always have exactly two decimals
|
33
|
-
data[key] = "%.2f" % data[key] if data[key].is_a? Float
|
34
|
-
|
35
|
-
message << "#{key}=#{data[key]}"
|
36
|
-
message
|
37
|
-
end
|
38
|
-
event.join(" ")
|
39
|
-
end
|
40
|
-
|
41
|
-
def process_action_logstash(data)
|
42
|
-
event = LogStash::Event.new("@fields" => data)
|
43
|
-
event.to_json
|
44
|
-
end
|
45
|
-
|
46
|
-
def process_action_graylog2(data)
|
47
|
-
# Cloning because we don't want to mess with the original when mutating keys.
|
48
|
-
my = data.clone
|
49
|
-
|
50
|
-
base = {
|
51
|
-
:short_message => "[#{my[:status]}] #{my[:method]} #{my[:path]} (#{my[:controller]}##{my[:action]})"
|
52
|
-
}
|
53
|
-
|
54
|
-
# Add underscore to every key to follow GELF additional field syntax.
|
55
|
-
my.keys.each { |k| my["_#{k}".to_sym] = my[k]; my.delete(k) }
|
56
|
-
|
57
|
-
my.merge(base)
|
19
|
+
formatted_message = Lograge.formatter.call(data)
|
20
|
+
logger.send(Lograge.log_level, formatted_message)
|
58
21
|
end
|
59
22
|
|
60
23
|
def redirect_to(event)
|
@@ -63,6 +26,10 @@ module Lograge
|
|
63
26
|
|
64
27
|
private
|
65
28
|
|
29
|
+
def logger
|
30
|
+
Lograge.logger.presence or super
|
31
|
+
end
|
32
|
+
|
66
33
|
def extract_request(payload)
|
67
34
|
{
|
68
35
|
:method => payload[:method],
|
data/lib/lograge/version.rb
CHANGED
data/lograge.gemspec
CHANGED
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
# specify any dependencies here; for example:
|
22
22
|
s.add_development_dependency "rspec"
|
23
23
|
s.add_development_dependency "guard-rspec"
|
24
|
-
s.add_runtime_dependency "activesupport"
|
25
|
-
s.add_runtime_dependency "actionpack"
|
24
|
+
s.add_runtime_dependency "activesupport", '>= 3'
|
25
|
+
s.add_runtime_dependency "actionpack", '>= 3'
|
26
|
+
s.add_runtime_dependency "railties", '>= 3'
|
26
27
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lograge'
|
3
|
+
|
4
|
+
describe Lograge::Formatters::Graylog2 do
|
5
|
+
let(:payload) do
|
6
|
+
{
|
7
|
+
custom: 'data',
|
8
|
+
status: 200,
|
9
|
+
method: 'GET',
|
10
|
+
path: '/',
|
11
|
+
controller: 'welcome',
|
12
|
+
action: 'index'
|
13
|
+
}
|
14
|
+
end
|
15
|
+
subject { described_class.new.call(payload) }
|
16
|
+
it { expect(subject[:_custom]).to eq('data') }
|
17
|
+
it { expect(subject[:short_message]).to eq('[200] GET / (welcome#index)') }
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lograge'
|
3
|
+
|
4
|
+
describe Lograge::Formatters::KeyValue do
|
5
|
+
let(:payload) do
|
6
|
+
{
|
7
|
+
custom: 'data',
|
8
|
+
status: 200,
|
9
|
+
method: 'GET',
|
10
|
+
path: '/',
|
11
|
+
controller: 'welcome',
|
12
|
+
action: 'index'
|
13
|
+
}
|
14
|
+
end
|
15
|
+
subject { described_class.new.call(payload) }
|
16
|
+
|
17
|
+
it { should include('method=GET') }
|
18
|
+
it { should include('path=/') }
|
19
|
+
it { should include('controller=welcome') }
|
20
|
+
it { should include('action=index') }
|
21
|
+
it { should include('status=200') }
|
22
|
+
it { should include('custom=data') }
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lograge'
|
3
|
+
|
4
|
+
describe Lograge::Formatters::Logstash do
|
5
|
+
let(:payload) do
|
6
|
+
{
|
7
|
+
custom: 'data',
|
8
|
+
status: 200,
|
9
|
+
method: 'GET',
|
10
|
+
path: '/',
|
11
|
+
controller: 'welcome',
|
12
|
+
action: 'index'
|
13
|
+
}
|
14
|
+
end
|
15
|
+
subject { described_class.new.call(payload) }
|
16
|
+
it { should match(/"@source":"unknown"/) }
|
17
|
+
it { should match(/"@tags":\[\]/) }
|
18
|
+
it { should match(/"@fields":{/) }
|
19
|
+
it { should match(/"custom":"data"/) }
|
20
|
+
it { should match(/"status":200/) }
|
21
|
+
it { should match(/"method":"GET"/) }
|
22
|
+
it { should match(/"path":"\/"/) }
|
23
|
+
it { should match(/"controller":"welcome"/) }
|
24
|
+
it { should match(/"action":"index"/) }
|
25
|
+
end
|
@@ -8,15 +8,8 @@ require 'logger'
|
|
8
8
|
describe Lograge::RequestLogSubscriber do
|
9
9
|
let(:log_output) {StringIO.new}
|
10
10
|
let(:logger) {
|
11
|
-
|
12
|
-
logger.formatter = ->(_, _, _, msg) {
|
13
|
-
msg
|
14
|
-
}
|
15
|
-
logger
|
11
|
+
Logger.new(log_output).tap {|logger| logger.formatter = ->(_, _, _, msg) { msg } }
|
16
12
|
}
|
17
|
-
before do
|
18
|
-
Lograge::RequestLogSubscriber.logger = logger
|
19
|
-
end
|
20
13
|
|
21
14
|
let(:subscriber) {Lograge::RequestLogSubscriber.new}
|
22
15
|
let(:event) {
|
@@ -28,16 +21,46 @@ describe Lograge::RequestLogSubscriber do
|
|
28
21
|
}
|
29
22
|
)
|
30
23
|
}
|
31
|
-
|
32
24
|
let(:redirect) {
|
33
25
|
ActiveSupport::Notifications::Event.new(
|
34
26
|
'redirect_to.action_controller', Time.now, Time.now, 1, location: 'http://example.com', status: 302
|
35
27
|
)
|
36
28
|
}
|
37
29
|
|
30
|
+
before { Lograge.logger = logger }
|
31
|
+
|
32
|
+
describe "with custom_options configured for cee output" do
|
33
|
+
before do
|
34
|
+
Lograge::formatter = ->(data) { "My test: #{data}" }
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should combine the hash properly for the output" do
|
38
|
+
Lograge.custom_options = {:data => "value"}
|
39
|
+
subscriber.process_action(event)
|
40
|
+
log_output.string.should =~ /^My test: {.*:data=>"value"/
|
41
|
+
end
|
42
|
+
it "should combine the output of a lambda properly" do
|
43
|
+
Lograge.custom_options = lambda {|event| {:data => "value"}}
|
44
|
+
subscriber.process_action(event)
|
45
|
+
log_output.string.should =~ /^My test: {.*:data=>"value"/
|
46
|
+
end
|
47
|
+
it "should work if the method returns nil" do
|
48
|
+
Lograge.custom_options = lambda {|event| nil}
|
49
|
+
subscriber.process_action(event)
|
50
|
+
log_output.string.should be_present
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "when processing a redirect" do
|
55
|
+
it "should store the location in a thread local variable" do
|
56
|
+
subscriber.redirect_to(redirect)
|
57
|
+
Thread.current[:lograge_location].should == "http://example.com"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
38
61
|
describe "when processing an action with lograge output" do
|
39
62
|
before do
|
40
|
-
Lograge
|
63
|
+
Lograge.formatter = Lograge::Formatters::KeyValue.new
|
41
64
|
end
|
42
65
|
|
43
66
|
it "should include the URL in the log output" do
|
@@ -117,234 +140,101 @@ describe Lograge::RequestLogSubscriber do
|
|
117
140
|
end
|
118
141
|
end
|
119
142
|
|
120
|
-
describe "
|
143
|
+
describe "with custom_options configured for lograge output" do
|
121
144
|
before do
|
122
|
-
|
123
|
-
Lograge::log_format = :logstash
|
145
|
+
Lograge.formatter = Lograge::Formatters::KeyValue.new
|
124
146
|
end
|
125
147
|
|
126
|
-
it "should
|
127
|
-
|
128
|
-
log_output.string.should include('/home')
|
129
|
-
end
|
130
|
-
|
131
|
-
it "should start include the HTTP method" do
|
132
|
-
subscriber.process_action(event)
|
133
|
-
log_output.string.should include('"method":"GET"')
|
134
|
-
end
|
135
|
-
|
136
|
-
it "should include the status code" do
|
137
|
-
subscriber.process_action(event)
|
138
|
-
log_output.string.should include('"status":200')
|
139
|
-
end
|
140
|
-
|
141
|
-
it "should include the controller and action" do
|
142
|
-
subscriber.process_action(event)
|
143
|
-
log_output.string.should include('"controller":"home"')
|
144
|
-
log_output.string.should include('"action":"index"')
|
145
|
-
end
|
146
|
-
|
147
|
-
it "should include the duration" do
|
148
|
-
subscriber.process_action(event)
|
149
|
-
log_output.string.should =~ /"duration":\d+\.\d{0,2}/
|
150
|
-
end
|
151
|
-
|
152
|
-
it "should include the view rendering time" do
|
153
|
-
subscriber.process_action(event)
|
154
|
-
log_output.string.should =~ /"view":0.01/
|
155
|
-
end
|
156
|
-
|
157
|
-
it "should include the database rendering time" do
|
158
|
-
subscriber.process_action(event)
|
159
|
-
log_output.string.should =~ /"db":0.02/
|
160
|
-
end
|
161
|
-
|
162
|
-
it "should add a 500 status when an exception occurred" do
|
163
|
-
event.payload[:status] = nil
|
164
|
-
event.payload[:exception] = ['AbstractController::ActionNotFound', 'Route not found']
|
148
|
+
it "should combine the hash properly for the output" do
|
149
|
+
Lograge.custom_options = {:data => "value"}
|
165
150
|
subscriber.process_action(event)
|
166
|
-
log_output.string.should =~ /
|
167
|
-
log_output.string.should =~ /"error":"AbstractController::ActionNotFound:Route not found"/
|
151
|
+
log_output.string.should =~ / data=value/
|
168
152
|
end
|
169
|
-
|
170
|
-
|
171
|
-
event.payload[:status] = nil
|
172
|
-
event.payload[:exception] = nil
|
153
|
+
it "should combine the output of a lambda properly" do
|
154
|
+
Lograge.custom_options = lambda {|event| {:data => "value"}}
|
173
155
|
subscriber.process_action(event)
|
174
|
-
log_output.string.should =~ /
|
175
|
-
end
|
176
|
-
|
177
|
-
describe "with a redirect" do
|
178
|
-
before do
|
179
|
-
Thread.current[:lograge_location] = "http://www.example.com"
|
180
|
-
end
|
181
|
-
|
182
|
-
it "should add the location to the log line" do
|
183
|
-
subscriber.process_action(event)
|
184
|
-
log_output.string.should =~ %r{"location":"http://www.example.com"}
|
185
|
-
end
|
186
|
-
|
187
|
-
it "should remove the thread local variable" do
|
188
|
-
subscriber.process_action(event)
|
189
|
-
Thread.current[:lograge_location].should == nil
|
190
|
-
end
|
156
|
+
log_output.string.should =~ / data=value/
|
191
157
|
end
|
192
|
-
|
193
|
-
|
158
|
+
it "should work if the method returns nil" do
|
159
|
+
Lograge.custom_options = lambda {|event| nil}
|
194
160
|
subscriber.process_action(event)
|
195
|
-
log_output.string.
|
161
|
+
log_output.string.should be_present
|
196
162
|
end
|
197
163
|
end
|
198
164
|
|
199
|
-
describe "
|
165
|
+
describe "with ignore configured" do
|
200
166
|
before do
|
201
|
-
Lograge::log_format = :
|
202
|
-
|
203
|
-
|
204
|
-
it "should include the URL in the log output" do
|
205
|
-
subscriber.process_action(event)
|
206
|
-
log_output.string.should include(':_path=>"/home"')
|
167
|
+
# Lograge::log_format = :lograge
|
168
|
+
Lograge::ignore_nothing # clear the old ignores before each test
|
207
169
|
end
|
208
170
|
|
209
|
-
it "should
|
171
|
+
it "should not log ignored controller actions given a single ignored action" do
|
172
|
+
Lograge.ignore_actions 'home#index'
|
210
173
|
subscriber.process_action(event)
|
211
|
-
log_output.string.should
|
174
|
+
log_output.string.should be_blank
|
212
175
|
end
|
213
176
|
|
214
|
-
it "should
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
it "should include the controller and action" do
|
177
|
+
it "should not log ignored controller actions given a single ignored action after a custom ignore" do
|
178
|
+
Lograge.ignore(lambda {|event| false})
|
179
|
+
Lograge.ignore_actions 'home#index'
|
219
180
|
subscriber.process_action(event)
|
220
|
-
log_output.string.should
|
221
|
-
log_output.string.should include(':_action=>"index"')
|
181
|
+
log_output.string.should be_blank
|
222
182
|
end
|
223
183
|
|
224
|
-
it "should
|
184
|
+
it "should log non-ignored controller actions given a single ignored action" do
|
185
|
+
Lograge.ignore_actions 'foo#bar'
|
225
186
|
subscriber.process_action(event)
|
226
|
-
log_output.string.
|
187
|
+
log_output.string.should_not be_blank
|
227
188
|
end
|
228
189
|
|
229
|
-
it "should
|
190
|
+
it "should not log ignored controller actions given multiple ignored actions" do
|
191
|
+
Lograge.ignore_actions ['foo#bar', 'home#index', 'bar#foo']
|
230
192
|
subscriber.process_action(event)
|
231
|
-
log_output.string.should
|
193
|
+
log_output.string.should be_blank
|
232
194
|
end
|
233
195
|
|
234
|
-
it "should
|
196
|
+
it "should log non-ignored controller actions given multiple ignored actions" do
|
197
|
+
Lograge.ignore_actions ['foo#bar', 'bar#foo']
|
235
198
|
subscriber.process_action(event)
|
236
|
-
log_output.string.
|
199
|
+
log_output.string.should_not be_blank
|
237
200
|
end
|
238
201
|
|
239
|
-
it "should
|
240
|
-
|
241
|
-
|
202
|
+
it "should not log ignored events" do
|
203
|
+
Lograge.ignore(lambda do |event|
|
204
|
+
'GET' == event.payload[:method]
|
205
|
+
end)
|
242
206
|
subscriber.process_action(event)
|
243
|
-
log_output.string.should
|
244
|
-
log_output.string.should include(':_error=>"AbstractController::ActionNotFound:Route not found"')
|
245
|
-
end
|
246
|
-
|
247
|
-
it "should return an unknown status when no status or exception is found" do
|
248
|
-
event.payload[:status] = nil
|
249
|
-
event.payload[:exception] = nil
|
250
|
-
subscriber.process_action(event)
|
251
|
-
log_output.string.should include(':_status=>0')
|
252
|
-
end
|
253
|
-
|
254
|
-
describe "with a redirect" do
|
255
|
-
before do
|
256
|
-
Thread.current[:lograge_location] = "http://www.example.com"
|
257
|
-
end
|
258
|
-
|
259
|
-
it "should add the location to the log line" do
|
260
|
-
subscriber.process_action(event)
|
261
|
-
log_output.string.should include(':_location=>"http://www.example.com"')
|
262
|
-
end
|
263
|
-
|
264
|
-
it "should remove the thread local variable" do
|
265
|
-
subscriber.process_action(event)
|
266
|
-
Thread.current[:lograge_location].should == nil
|
267
|
-
end
|
207
|
+
log_output.string.should be_blank
|
268
208
|
end
|
269
209
|
|
270
|
-
it "should
|
210
|
+
it "should log non-ignored events" do
|
211
|
+
Lograge.ignore(lambda do |event|
|
212
|
+
'foo' == event.payload[:method]
|
213
|
+
end)
|
271
214
|
subscriber.process_action(event)
|
272
|
-
log_output.string.should_not
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
describe "with custom_options configured for graylog2 output" do
|
277
|
-
before do
|
278
|
-
Lograge::log_format = :graylog2
|
215
|
+
log_output.string.should_not be_blank
|
279
216
|
end
|
280
217
|
|
281
|
-
it "should
|
282
|
-
Lograge.
|
218
|
+
it "should not choke on nil ignore_actions input" do
|
219
|
+
Lograge.ignore_actions nil
|
283
220
|
subscriber.process_action(event)
|
284
|
-
log_output.string.
|
221
|
+
log_output.string.should_not be_blank
|
285
222
|
end
|
286
223
|
|
287
|
-
it "should
|
288
|
-
Lograge.
|
224
|
+
it "should not choke on nil ignore input" do
|
225
|
+
Lograge.ignore nil
|
289
226
|
subscriber.process_action(event)
|
290
|
-
log_output.string.
|
291
|
-
end
|
292
|
-
|
293
|
-
it "should work if the method returns nil" do
|
294
|
-
Lograge.custom_options = lambda {|event| nil}
|
295
|
-
subscriber.process_action(event)
|
296
|
-
log_output.string.should be_present
|
227
|
+
log_output.string.should_not be_blank
|
297
228
|
end
|
298
229
|
end
|
299
230
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
231
|
+
it "should fallback to ActiveSupport's logger if one isn't configured" do
|
232
|
+
Lograge.formatter = Lograge::Formatters::KeyValue.new
|
233
|
+
Lograge.logger = nil
|
234
|
+
ActiveSupport::LogSubscriber.logger = logger
|
304
235
|
|
305
|
-
|
306
|
-
Lograge.custom_options = {:data => "value"}
|
307
|
-
subscriber.process_action(event)
|
308
|
-
log_output.string.should =~ / data=value/
|
309
|
-
end
|
310
|
-
it "should combine the output of a lambda properly" do
|
311
|
-
Lograge.custom_options = lambda {|event| {:data => "value"}}
|
312
|
-
subscriber.process_action(event)
|
313
|
-
log_output.string.should =~ / data=value/
|
314
|
-
end
|
315
|
-
it "should work if the method returns nil" do
|
316
|
-
Lograge.custom_options = lambda {|event| nil}
|
317
|
-
subscriber.process_action(event)
|
318
|
-
log_output.string.should be_present
|
319
|
-
end
|
320
|
-
end
|
236
|
+
subscriber.process_action(event)
|
321
237
|
|
322
|
-
|
323
|
-
before do
|
324
|
-
Lograge::log_format = :logstash
|
325
|
-
end
|
326
|
-
|
327
|
-
it "should combine the hash properly for the output" do
|
328
|
-
Lograge.custom_options = {:data => "value"}
|
329
|
-
subscriber.process_action(event)
|
330
|
-
log_output.string.should =~ /"data":"value"/
|
331
|
-
end
|
332
|
-
it "should combine the output of a lambda properly" do
|
333
|
-
Lograge.custom_options = lambda {|event| {:data => "value"}}
|
334
|
-
subscriber.process_action(event)
|
335
|
-
log_output.string.should =~ /"data":"value"/
|
336
|
-
end
|
337
|
-
it "should work if the method returns nil" do
|
338
|
-
Lograge.custom_options = lambda {|event| nil}
|
339
|
-
subscriber.process_action(event)
|
340
|
-
log_output.string.should be_present
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
describe "when processing a redirect" do
|
345
|
-
it "should store the location in a thread local variable" do
|
346
|
-
subscriber.redirect_to(redirect)
|
347
|
-
Thread.current[:lograge_location].should == "http://example.com"
|
348
|
-
end
|
238
|
+
log_output.string.should be_present
|
349
239
|
end
|
350
240
|
end
|
data/spec/lograge_spec.rb
CHANGED
@@ -37,4 +37,48 @@ describe Lograge do
|
|
37
37
|
listeners.size.should > 0
|
38
38
|
end
|
39
39
|
end
|
40
|
+
|
41
|
+
describe 'deprecated log_format interpreter' do
|
42
|
+
let(:app_config) do
|
43
|
+
double(config:
|
44
|
+
ActiveSupport::OrderedOptions.new.tap do |config|
|
45
|
+
config.action_dispatch = double(rack_cache: false)
|
46
|
+
config.lograge = ActiveSupport::OrderedOptions.new
|
47
|
+
config.lograge.log_format = format
|
48
|
+
end
|
49
|
+
)
|
50
|
+
end
|
51
|
+
before { ActiveSupport::Deprecation.silence { Lograge.setup(app_config) } }
|
52
|
+
subject { Lograge.formatter }
|
53
|
+
|
54
|
+
context ':cee' do
|
55
|
+
let(:format) { :cee }
|
56
|
+
it { should be_instance_of(Lograge::Formatters::Cee) }
|
57
|
+
end
|
58
|
+
|
59
|
+
context ':raw' do
|
60
|
+
let(:format) { :raw }
|
61
|
+
it { should be_instance_of(Lograge::Formatters::Raw) }
|
62
|
+
end
|
63
|
+
|
64
|
+
context ':logstash' do
|
65
|
+
let(:format) { :logstash }
|
66
|
+
it { should be_instance_of(Lograge::Formatters::Logstash) }
|
67
|
+
end
|
68
|
+
|
69
|
+
context ':graylog2' do
|
70
|
+
let(:format) { :graylog2 }
|
71
|
+
it { should be_instance_of(Lograge::Formatters::Graylog2) }
|
72
|
+
end
|
73
|
+
|
74
|
+
context ':lograge' do
|
75
|
+
let(:format) { :lograge }
|
76
|
+
it { should be_instance_of(Lograge::Formatters::KeyValue) }
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'default' do
|
80
|
+
let(:format) { nil }
|
81
|
+
it { should be_instance_of(Lograge::Formatters::KeyValue) }
|
82
|
+
end
|
83
|
+
end
|
40
84
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lograge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ! '>='
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
53
|
+
version: '3'
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '3'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: actionpack
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ! '>='
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '3'
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,23 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ! '>='
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: '
|
77
|
+
version: '3'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: railties
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '3'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '3'
|
78
94
|
description: Tame Rails' multi-line logging into a single line per request
|
79
95
|
email:
|
80
96
|
- meyer@paperplanes.de
|
@@ -90,11 +106,21 @@ files:
|
|
90
106
|
- README.md
|
91
107
|
- Rakefile
|
92
108
|
- lib/lograge.rb
|
109
|
+
- lib/lograge/formatters/cee.rb
|
110
|
+
- lib/lograge/formatters/graylog2.rb
|
111
|
+
- lib/lograge/formatters/key_value.rb
|
112
|
+
- lib/lograge/formatters/logstash.rb
|
113
|
+
- lib/lograge/formatters/raw.rb
|
93
114
|
- lib/lograge/log_subscriber.rb
|
94
115
|
- lib/lograge/rails_ext/rack/logger.rb
|
95
116
|
- lib/lograge/railtie.rb
|
96
117
|
- lib/lograge/version.rb
|
97
118
|
- lograge.gemspec
|
119
|
+
- spec/formatters/cee_spec.rb
|
120
|
+
- spec/formatters/graylog2_spec.rb
|
121
|
+
- spec/formatters/key_value_spec.rb
|
122
|
+
- spec/formatters/logstash_spec.rb
|
123
|
+
- spec/formatters/raw_spec.rb
|
98
124
|
- spec/lograge_logsubscriber_spec.rb
|
99
125
|
- spec/lograge_spec.rb
|
100
126
|
- spec/spec_helper.rb
|
@@ -123,6 +149,11 @@ signing_key:
|
|
123
149
|
specification_version: 3
|
124
150
|
summary: Tame Rails' multi-line logging into a single line per request
|
125
151
|
test_files:
|
152
|
+
- spec/formatters/cee_spec.rb
|
153
|
+
- spec/formatters/graylog2_spec.rb
|
154
|
+
- spec/formatters/key_value_spec.rb
|
155
|
+
- spec/formatters/logstash_spec.rb
|
156
|
+
- spec/formatters/raw_spec.rb
|
126
157
|
- spec/lograge_logsubscriber_spec.rb
|
127
158
|
- spec/lograge_spec.rb
|
128
159
|
- spec/spec_helper.rb
|