-
-
Notifications
You must be signed in to change notification settings - Fork 300
/
Copy pathlograge.rb
245 lines (200 loc) · 7.25 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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# frozen_string_literal: true
require 'lograge/version'
require 'lograge/formatters/helpers/method_and_path'
require 'lograge/formatters/cee'
require 'lograge/formatters/json'
require 'lograge/formatters/graylog2'
require 'lograge/formatters/key_value'
require 'lograge/formatters/key_value_deep'
require 'lograge/formatters/l2met'
require 'lograge/formatters/lines'
require 'lograge/formatters/logstash'
require 'lograge/formatters/ltsv'
require 'lograge/formatters/raw'
require 'lograge/log_subscribers/base'
require 'lograge/log_subscribers/action_cable'
require 'lograge/log_subscribers/action_controller'
require 'lograge/silent_logger'
require 'lograge/ordered_options'
require 'active_support'
require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/string/inflections'
# rubocop:disable Metrics/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?("#{controller_field(params)}##{params[:action]}")
end)
end
def controller_field(params)
params[:controller] || params[:channel_class] || params[:connection_class]
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|
Lograge.notification_listeners_for("#{event}.#{component}").each do |listener|
ActiveSupport::Notifications.unsubscribe listener if listener.instance_variable_get('@delegate') == subscriber
end
end
end
def setup(app)
self.application = app
disable_rack_cache_verbose_output
keep_original_rails_log
attach_to_action_controller
attach_to_action_cable if defined?(ActionCable)
set_lograge_log_options
setup_custom_payload
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::LogSubscribers::ActionController.attach_to :action_controller
end
def attach_to_action_cable
require 'lograge/rails_ext/action_cable/channel/base'
require 'lograge/rails_ext/action_cable/connection/base'
Lograge::LogSubscribers::ActionCable.attach_to :action_cable
end
def setup_custom_payload
return unless lograge_config.custom_payload_method.respond_to?(:call)
base_classes = Array(lograge_config.base_controller_class)
base_classes.map! { |klass| klass.try(:constantize) }
base_classes << ActionController::Base if base_classes.empty?
base_classes.each do |base_class|
extend_base_class(base_class)
end
end
def extend_base_class(klass)
append_payload_method = klass.instance_method(:append_info_to_payload)
custom_payload_method = lograge_config.custom_payload_method
klass.send(:define_method, :append_info_to_payload) do |payload|
append_payload_method.bind(self).call(payload)
payload[:custom_payload] = custom_payload_method.call(self)
end
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'
require 'lograge/rails_ext/action_cable/server/base' if defined?(ActionCable)
Lograge.remove_existing_log_subscriptions
end
def rack_cache_hashlike?(app)
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.'
deprecator.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
def deprecator
@deprecator ||= ActiveSupport::Deprecation.new('1.0', 'Lograge')
end
if ::ActiveSupport::VERSION::MAJOR >= 8 ||
(::ActiveSupport::VERSION::MAJOR >= 7 && ::ActiveSupport::VERSION::MINOR >= 1)
def notification_listeners_for(name)
ActiveSupport::Notifications.notifier.all_listeners_for(name)
end
else
def notification_listeners_for(name)
ActiveSupport::Notifications.notifier.listeners_for(name)
end
end
end
# rubocop:enable Metrics/ModuleLength
require 'lograge/railtie' if defined?(Rails)