/
lograge.rb
184 lines (153 loc) · 5.33 KB
/
lograge.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
require 'lograge/version'
require 'lograge/formatters/cee'
require 'lograge/formatters/json'
require 'lograge/formatters/graylog2'
require 'lograge/formatters/key_value'
require 'lograge/formatters/l2met'
require 'lograge/formatters/lines'
require 'lograge/formatters/logstash'
require 'lograge/formatters/ltsv'
require 'lograge/formatters/raw'
require 'lograge/log_subscriber'
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/string/inflections'
require 'active_support/ordered_options'
# rubocop:disable ModuleLength
module Lograge
module_function
mattr_accessor :logger, :application, :ignore_tests
# Custom options that will be appended to log line
#
# Currently supported formats are:
# - Hash
# - Any object that responds to call and returns a hash
#
mattr_writer :custom_options
self.custom_options = nil
def custom_options(event)
if @@custom_options.respond_to?(:call)
@@custom_options.call(event)
else
@@custom_options
end
end
# Before format allows you to change the structure of the output.
# You've to pass in something callable
#
mattr_writer :before_format
self.before_format = nil
def before_format(data, payload)
result = nil
result = @@before_format.call(data, payload) if @@before_format
result || data
end
# Set conditions for events that should be ignored
#
# Currently supported formats are:
# - A single string representing a controller action, e.g. 'UsersController#sign_in'
# - An array of strings representing controller actions
# - An object that responds to call with an event argument and returns
# true iff the event should be ignored.
#
# The action ignores are given to 'ignore_actions'. The callable ignores
# are given to 'ignore'. Both methods can be called multiple times, which
# just adds more ignore conditions to a list that is checked before logging.
def ignore_actions(actions)
ignore(lambda do |event|
params = event.payload
Array(actions).include?("#{params[:controller]}##{params[:action]}")
end)
end
def ignore_tests
@ignore_tests ||= []
end
def ignore(test)
ignore_tests.push(test) if test
end
def ignore_nothing
@ignore_tests = []
end
def ignore?(event)
ignore_tests.any? { |ignore_test| ignore_test.call(event) }
end
# Loglines are emitted with this log level
mattr_accessor :log_level
self.log_level = :info
# The emitted log format
#
# Currently supported formats are>
# - :lograge - The custom tense lograge format
# - :logstash - JSON formatted as a Logstash Event.
mattr_accessor :formatter
def remove_existing_log_subscriptions
ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
case subscriber
when ActionView::LogSubscriber
unsubscribe(:action_view, subscriber)
when ActionController::LogSubscriber
unsubscribe(:action_controller, subscriber)
end
end
end
def unsubscribe(component, subscriber)
events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
events.each do |event|
ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
if listener.instance_variable_get('@delegate') == subscriber
ActiveSupport::Notifications.unsubscribe listener
end
end
end
end
def setup(app)
self.application = app
disable_rack_cache_verbose_output
keep_original_rails_log
attach_to_action_controller
set_lograge_log_options
support_deprecated_config # TODO: Remove with version 1.0
set_formatter
set_ignores
end
def set_ignores
Lograge.ignore_actions(lograge_config.ignore_actions)
Lograge.ignore(lograge_config.ignore_custom)
end
def set_formatter
Lograge.formatter = lograge_config.formatter || Lograge::Formatters::KeyValue.new
end
def attach_to_action_controller
Lograge::RequestLogSubscriber.attach_to :action_controller
end
def set_lograge_log_options
Lograge.logger = lograge_config.logger
Lograge.custom_options = lograge_config.custom_options
Lograge.before_format = lograge_config.before_format
Lograge.log_level = lograge_config.log_level || :info
end
def disable_rack_cache_verbose_output
application.config.action_dispatch.rack_cache[:verbose] = false if rack_cache_hashlike?(application)
end
def keep_original_rails_log
return if lograge_config.keep_original_rails_log
require 'lograge/rails_ext/rack/logger'
Lograge.remove_existing_log_subscriptions
end
def rack_cache_hashlike?(app)
app.config.action_dispatch.rack_cache && app.config.action_dispatch.rack_cache.respond_to?(:[]=)
end
private_class_method :rack_cache_hashlike?
# TODO: Remove with version 1.0
def support_deprecated_config
return unless lograge_config.log_format
legacy_log_format = lograge_config.log_format
warning = 'config.lograge.log_format is deprecated. Use config.lograge.formatter instead.'
ActiveSupport::Deprecation.warn(warning, caller)
legacy_log_format = :key_value if legacy_log_format == :lograge
lograge_config.formatter = "Lograge::Formatters::#{legacy_log_format.to_s.classify}".constantize.new
end
def lograge_config
application.config.lograge
end
end
require 'lograge/railtie' if defined?(Rails)