lograge 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - 1.9.2
4
+ - 2.0.0
5
5
  script: bundle exec rspec
data/Gemfile CHANGED
@@ -5,5 +5,5 @@ gemspec
5
5
 
6
6
  group :test do
7
7
  gem 'actionpack'
8
- gem 'logstash-event'
8
+ gem 'logstash-event', '1.1.5'
9
9
  end
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 JSON
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.log_format = :logstash
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 :log_format
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.log_format = app.config.lograge.log_format || :lograge
64
- case Lograge.log_format.to_s
65
- when "logstash"
66
- begin
67
- require "logstash-event"
68
- rescue LoadError
69
- puts "You need to install the logstash-event gem to use the logstash output."
70
- raise
71
- end
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,9 @@
1
+ module Lograge
2
+ module Formatters
3
+ class Cee
4
+ def call(data)
5
+ "@cee: #{JSON.dump(data)}"
6
+ end
7
+ end
8
+ end
9
+ 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
@@ -0,0 +1,9 @@
1
+ module Lograge
2
+ module Formatters
3
+ class Raw
4
+ def call(data)
5
+ data
6
+ end
7
+ end
8
+ end
9
+ 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
- logger.info send(:"process_action_#{Lograge.log_format}", data)
16
- end
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],
@@ -1,3 +1,4 @@
1
+ require 'active_support/concern'
1
2
  require 'rails/rack/logger'
2
3
 
3
4
  module Rails
@@ -1,3 +1,3 @@
1
1
  module Lograge
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
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,7 @@
1
+ require 'spec_helper'
2
+ require 'lograge'
3
+
4
+ describe Lograge::Formatters::Cee do
5
+ it { expect( subject.call({})).to match(/^@cee/) }
6
+ it { expect(subject.call({ custom: 'data'})).to match('{"custom":"data"}') }
7
+ 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
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+ require 'lograge'
3
+
4
+ describe Lograge::Formatters::Raw do
5
+ it { expect( subject.call({ custom: 'data' })).to eq({ custom: 'data' }) }
6
+ 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
- logger = Logger.new(log_output)
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::log_format = :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 "when processing an action with logstash output" do
143
+ describe "with custom_options configured for lograge output" do
121
144
  before do
122
- require 'logstash-event'
123
- Lograge::log_format = :logstash
145
+ Lograge.formatter = Lograge::Formatters::KeyValue.new
124
146
  end
125
147
 
126
- it "should include the URL in the log output" do
127
- subscriber.process_action(event)
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 =~ /"status":500/
167
- log_output.string.should =~ /"error":"AbstractController::ActionNotFound:Route not found"/
151
+ log_output.string.should =~ / data=value/
168
152
  end
169
-
170
- it "should return an unknown status when no status or exception is found" do
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 =~ /"status":0/
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
- it "should not include a location by default" do
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.should_not =~ /"location":/
161
+ log_output.string.should be_present
196
162
  end
197
163
  end
198
164
 
199
- describe "when processing an action with graylog2 output" do
165
+ describe "with ignore configured" do
200
166
  before do
201
- Lograge::log_format = :graylog2
202
- end
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 start include the HTTP method" do
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 include(':_method=>"GET"')
174
+ log_output.string.should be_blank
212
175
  end
213
176
 
214
- it "should include the status code" do
215
- subscriber.process_action(event)
216
- log_output.string.should include(':_status=>200') end
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 include(':_controller=>"home"')
221
- log_output.string.should include(':_action=>"index"')
181
+ log_output.string.should be_blank
222
182
  end
223
183
 
224
- it "should include the duration" do
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.should =~ /:_duration=>\d+\.\d{0,2}/
187
+ log_output.string.should_not be_blank
227
188
  end
228
189
 
229
- it "should include the view rendering time" do
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 include(':_view=>0.01')
193
+ log_output.string.should be_blank
232
194
  end
233
195
 
234
- it "should include the database rendering time" do
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.should include(':_db=>0.02')
199
+ log_output.string.should_not be_blank
237
200
  end
238
201
 
239
- it "should add a 500 status when an exception occurred" do
240
- event.payload[:status] = nil
241
- event.payload[:exception] = ['AbstractController::ActionNotFound', 'Route not found']
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 include(':_status=>500')
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 not include a location by default" do
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 =~ /"location":/
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 combine the hash properly for the output" do
282
- Lograge.custom_options = {:data => "value"}
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.should include(':_data=>"value"')
221
+ log_output.string.should_not be_blank
285
222
  end
286
223
 
287
- it "should combine the output of a lambda properly" do
288
- Lograge.custom_options = lambda {|event| {:data => "value"}}
224
+ it "should not choke on nil ignore input" do
225
+ Lograge.ignore nil
289
226
  subscriber.process_action(event)
290
- log_output.string.should include(':_data=>"value"')
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
- describe "with custom_options configured for lograge output" do
301
- before do
302
- Lograge::log_format = :lograge
303
- end
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
- it "should combine the hash properly for the output" do
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
- describe "with custom_options configured for logstash output" do
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.0
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-02-08 00:00:00.000000000 Z
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: '0'
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: '0'
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: '0'
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: '0'
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