lograge 0.11.0 → 0.12.0
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.
- checksums.yaml +5 -5
- data/lib/lograge/formatters/cee.rb +2 -0
- data/lib/lograge/formatters/graylog2.rb +5 -13
- data/lib/lograge/formatters/helpers/method_and_path.rb +2 -0
- data/lib/lograge/formatters/json.rb +2 -0
- data/lib/lograge/formatters/key_value.rb +2 -0
- data/lib/lograge/formatters/l2met.rb +16 -14
- data/lib/lograge/formatters/lines.rb +2 -0
- data/lib/lograge/formatters/logstash.rb +2 -0
- data/lib/lograge/formatters/ltsv.rb +2 -0
- data/lib/lograge/formatters/raw.rb +2 -0
- data/lib/lograge/log_subscribers/action_cable.rb +6 -4
- data/lib/lograge/log_subscribers/action_controller.rb +2 -0
- data/lib/lograge/log_subscribers/base.rb +7 -5
- data/lib/lograge/ordered_options.rb +3 -0
- data/lib/lograge/rails_ext/action_cable/channel/base.rb +9 -14
- data/lib/lograge/rails_ext/action_cable/connection/base.rb +9 -30
- data/lib/lograge/rails_ext/action_cable/server/base.rb +2 -0
- data/lib/lograge/rails_ext/rack/logger.rb +9 -4
- data/lib/lograge/railtie.rb +2 -0
- data/lib/lograge/silent_logger.rb +7 -5
- data/lib/lograge/version.rb +3 -1
- data/lib/lograge.rb +11 -14
- metadata +35 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a8dc3fd38bfe24b9f1816ac75fa2d600037fd308b1b355de309d81deae032cd9
|
|
4
|
+
data.tar.gz: f3627f7956278364545987b845a16011463592a78dbf9ae0a409b0c8640b63e4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5787201d587cee662987f2aef1db3b971a60b7feec4dc630d509520713e2c746aee9a1249817f0d1bb8752d22eadcf5e79259c73213e75ce7127e49115795b95
|
|
7
|
+
data.tar.gz: 055daf5493eb1a053a8b995d5037973587782c8edf9a48fd0d860f3d5e5c2bb419957c0df8610eda6e0cc26c54bdcf7bd900ba0113c780c4569fb22330e9b00e
|
|
@@ -1,23 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Lograge
|
|
2
4
|
module Formatters
|
|
3
5
|
class Graylog2
|
|
4
6
|
include Lograge::Formatters::Helpers::MethodAndPath
|
|
5
7
|
|
|
6
8
|
def call(data)
|
|
7
|
-
# Cloning because we don't want to mess with the original when mutating keys.
|
|
8
|
-
data_clone = data.clone
|
|
9
|
-
|
|
10
|
-
base = {
|
|
11
|
-
short_message: short_message(data_clone)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
9
|
# Add underscore to every key to follow GELF additional field syntax.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
data_clone.merge(base)
|
|
10
|
+
data.transform_keys { |k| underscore_prefix(k) }.merge(
|
|
11
|
+
short_message: short_message(data)
|
|
12
|
+
)
|
|
21
13
|
end
|
|
22
14
|
|
|
23
15
|
def underscore_prefix(key)
|
|
@@ -1,24 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'lograge/formatters/key_value'
|
|
2
4
|
|
|
3
5
|
module Lograge
|
|
4
6
|
module Formatters
|
|
5
7
|
class L2met < KeyValue
|
|
6
|
-
L2MET_FIELDS = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
L2MET_FIELDS = %i[
|
|
9
|
+
method
|
|
10
|
+
path
|
|
11
|
+
format
|
|
12
|
+
source
|
|
13
|
+
status
|
|
14
|
+
error
|
|
15
|
+
duration
|
|
16
|
+
view
|
|
17
|
+
db
|
|
18
|
+
location
|
|
17
19
|
].freeze
|
|
18
20
|
|
|
19
|
-
UNWANTED_FIELDS = [
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
UNWANTED_FIELDS = %i[
|
|
22
|
+
controller
|
|
23
|
+
action
|
|
22
24
|
].freeze
|
|
23
25
|
|
|
24
26
|
def call(data)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Lograge
|
|
2
4
|
module LogSubscribers
|
|
3
5
|
class ActionCable < Base
|
|
4
|
-
%i
|
|
6
|
+
%i[perform_action subscribe unsubscribe connect disconnect].each do |method_name|
|
|
5
7
|
define_method(method_name) do |event|
|
|
6
8
|
process_main_event(event)
|
|
7
9
|
end
|
|
@@ -11,9 +13,9 @@ module Lograge
|
|
|
11
13
|
|
|
12
14
|
def initial_data(payload)
|
|
13
15
|
{
|
|
14
|
-
method:
|
|
15
|
-
path:
|
|
16
|
-
format:
|
|
16
|
+
method: nil,
|
|
17
|
+
path: nil,
|
|
18
|
+
format: nil,
|
|
17
19
|
params: payload[:data],
|
|
18
20
|
controller: payload[:channel_class] || payload[:connection_class],
|
|
19
21
|
action: payload[:action]
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'json'
|
|
2
4
|
require 'action_pack'
|
|
5
|
+
require 'active_support'
|
|
3
6
|
require 'active_support/core_ext/class/attribute'
|
|
4
7
|
require 'active_support/log_subscriber'
|
|
5
8
|
require 'request_store'
|
|
@@ -32,8 +35,8 @@ module Lograge
|
|
|
32
35
|
data.merge!(custom_options(event))
|
|
33
36
|
end
|
|
34
37
|
|
|
35
|
-
%i
|
|
36
|
-
extract_location extract_unpermitted_params
|
|
38
|
+
%i[initial_data extract_status extract_runtimes
|
|
39
|
+
extract_location extract_unpermitted_params].each do |method_name|
|
|
37
40
|
define_method(method_name) { |*_arg| {} }
|
|
38
41
|
end
|
|
39
42
|
|
|
@@ -52,9 +55,8 @@ module Lograge
|
|
|
52
55
|
0
|
|
53
56
|
end
|
|
54
57
|
|
|
55
|
-
def get_error_status_code(
|
|
56
|
-
|
|
57
|
-
Rack::Utils.status_code(status)
|
|
58
|
+
def get_error_status_code(exception_class_name)
|
|
59
|
+
ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
|
|
58
60
|
end
|
|
59
61
|
|
|
60
62
|
def custom_options(event)
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
module Channel
|
|
3
|
-
class Base
|
|
4
|
-
def subscribe_to_channel
|
|
5
|
-
ActiveSupport::Notifications.instrument('subscribe.action_cable', notification_payload('subscribe')) do
|
|
6
|
-
run_callbacks :subscribe do
|
|
7
|
-
subscribed
|
|
8
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
9
2
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
module Lograge
|
|
4
|
+
module ActionCable
|
|
5
|
+
module ChannelInstrumentation
|
|
6
|
+
def subscribe_to_channel
|
|
7
|
+
ActiveSupport::Notifications.instrument('subscribe.action_cable', notification_payload('subscribe')) { super }
|
|
13
8
|
end
|
|
14
9
|
|
|
15
10
|
def unsubscribe_from_channel
|
|
16
11
|
ActiveSupport::Notifications.instrument('unsubscribe.action_cable', notification_payload('unsubscribe')) do
|
|
17
|
-
|
|
18
|
-
unsubscribed
|
|
19
|
-
end
|
|
12
|
+
super
|
|
20
13
|
end
|
|
21
14
|
end
|
|
22
15
|
|
|
@@ -28,3 +21,5 @@ module ActionCable
|
|
|
28
21
|
end
|
|
29
22
|
end
|
|
30
23
|
end
|
|
24
|
+
|
|
25
|
+
ActionCable::Channel::Base.prepend(Lograge::ActionCable::ChannelInstrumentation)
|
|
@@ -1,42 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
module Connection
|
|
3
|
-
class Base
|
|
4
|
-
# rubocop:disable Metrics/MethodLength
|
|
5
|
-
def handle_open
|
|
6
|
-
ActiveSupport::Notifications.instrument('connect.action_cable', notification_payload('connect')) do
|
|
7
|
-
begin
|
|
8
|
-
@protocol = websocket.protocol
|
|
9
|
-
connect if respond_to?(:connect)
|
|
10
|
-
subscribe_to_internal_channel
|
|
11
|
-
send_welcome_message
|
|
1
|
+
# frozen_string_literal: true
|
|
12
2
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
end
|
|
3
|
+
module Lograge
|
|
4
|
+
module ActionCable
|
|
5
|
+
module ConnectionInstrumentation
|
|
6
|
+
def handle_open
|
|
7
|
+
ActiveSupport::Notifications.instrument('connect.action_cable', notification_payload('connect')) { super }
|
|
19
8
|
end
|
|
20
|
-
# rubocop:enable Metrics/MethodLength
|
|
21
9
|
|
|
22
10
|
def handle_close
|
|
23
|
-
ActiveSupport::Notifications.instrument('disconnect.action_cable', notification_payload('disconnect'))
|
|
24
|
-
logger.info finished_request_message if Lograge.lograge_config.keep_original_rails_log
|
|
25
|
-
|
|
26
|
-
server.remove_connection(self)
|
|
27
|
-
|
|
28
|
-
subscriptions.unsubscribe_from_all
|
|
29
|
-
unsubscribe_from_internal_channel
|
|
30
|
-
|
|
31
|
-
disconnect if respond_to?(:disconnect)
|
|
32
|
-
end
|
|
11
|
+
ActiveSupport::Notifications.instrument('disconnect.action_cable', notification_payload('disconnect')) { super }
|
|
33
12
|
end
|
|
34
13
|
|
|
35
|
-
private
|
|
36
|
-
|
|
37
14
|
def notification_payload(method_name)
|
|
38
15
|
{ connection_class: self.class.name, action: method_name, data: request.params }
|
|
39
16
|
end
|
|
40
17
|
end
|
|
41
18
|
end
|
|
42
19
|
end
|
|
20
|
+
|
|
21
|
+
ActionCable::Connection::Base.prepend(Lograge::ActionCable::ConnectionInstrumentation)
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support'
|
|
1
4
|
require 'active_support/concern'
|
|
2
5
|
require 'rails/rack/logger'
|
|
3
6
|
|
|
@@ -9,17 +12,19 @@ module Rails
|
|
|
9
12
|
# that say:
|
|
10
13
|
# Started GET / for 192.168.2.1...
|
|
11
14
|
class Logger
|
|
12
|
-
# Overwrites Rails
|
|
15
|
+
# Overwrites Rails code that logs new requests
|
|
13
16
|
def call_app(*args)
|
|
14
17
|
env = args.last
|
|
15
|
-
@app.call(env)
|
|
18
|
+
status, headers, body = @app.call(env)
|
|
19
|
+
# needs to have same return type as the Rails builtins being overridden, see https://github.com/roidrage/lograge/pull/333
|
|
20
|
+
# https://github.com/rails/rails/blob/be9d34b9bcb448b265114ebc28bef1a5b5e4c272/railties/lib/rails/rack/logger.rb#L37
|
|
21
|
+
[status, headers, ::Rack::BodyProxy.new(body) {}] # rubocop:disable Lint/EmptyBlock
|
|
16
22
|
ensure
|
|
17
23
|
ActiveSupport::LogSubscriber.flush_all!
|
|
18
24
|
end
|
|
19
25
|
|
|
20
26
|
# Overwrites Rails 3.0/3.1 code that logs new requests
|
|
21
|
-
def before_dispatch(_env)
|
|
22
|
-
end
|
|
27
|
+
def before_dispatch(_env); end
|
|
23
28
|
end
|
|
24
29
|
end
|
|
25
30
|
end
|
data/lib/lograge/railtie.rb
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'delegate'
|
|
4
|
+
|
|
1
5
|
module Lograge
|
|
2
6
|
class SilentLogger < SimpleDelegator
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
%i(debug info warn error fatal unknown).each do |method_name|
|
|
7
|
+
%i[debug info warn error fatal unknown].each do |method_name|
|
|
8
|
+
# rubocop:disable Lint/EmptyBlock
|
|
8
9
|
define_method(method_name) { |*_args| }
|
|
10
|
+
# rubocop:enable Lint/EmptyBlock
|
|
9
11
|
end
|
|
10
12
|
end
|
|
11
13
|
end
|
data/lib/lograge/version.rb
CHANGED
data/lib/lograge.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'lograge/version'
|
|
2
4
|
require 'lograge/formatters/helpers/method_and_path'
|
|
3
5
|
require 'lograge/formatters/cee'
|
|
@@ -14,15 +16,11 @@ require 'lograge/log_subscribers/action_cable'
|
|
|
14
16
|
require 'lograge/log_subscribers/action_controller'
|
|
15
17
|
require 'lograge/silent_logger'
|
|
16
18
|
require 'lograge/ordered_options'
|
|
19
|
+
require 'active_support'
|
|
17
20
|
require 'active_support/core_ext/module/attribute_accessors'
|
|
18
21
|
require 'active_support/core_ext/string/inflections'
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
require 'lograge/rails_ext/action_cable/channel/base'
|
|
22
|
-
require 'lograge/rails_ext/action_cable/connection/base'
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# rubocop:disable ModuleLength
|
|
23
|
+
# rubocop:disable Metrics/ModuleLength
|
|
26
24
|
module Lograge
|
|
27
25
|
module_function
|
|
28
26
|
|
|
@@ -122,9 +120,7 @@ module Lograge
|
|
|
122
120
|
events = subscriber.public_methods(false).reject { |method| method.to_s == 'call' }
|
|
123
121
|
events.each do |event|
|
|
124
122
|
ActiveSupport::Notifications.notifier.listeners_for("#{event}.#{component}").each do |listener|
|
|
125
|
-
if listener.instance_variable_get('@delegate') == subscriber
|
|
126
|
-
ActiveSupport::Notifications.unsubscribe listener
|
|
127
|
-
end
|
|
123
|
+
ActiveSupport::Notifications.unsubscribe listener if listener.instance_variable_get('@delegate') == subscriber
|
|
128
124
|
end
|
|
129
125
|
end
|
|
130
126
|
end
|
|
@@ -158,6 +154,9 @@ module Lograge
|
|
|
158
154
|
end
|
|
159
155
|
|
|
160
156
|
def attach_to_action_cable
|
|
157
|
+
require 'lograge/rails_ext/action_cable/channel/base'
|
|
158
|
+
require 'lograge/rails_ext/action_cable/connection/base'
|
|
159
|
+
|
|
161
160
|
Lograge::LogSubscribers::ActionCable.attach_to :action_cable
|
|
162
161
|
end
|
|
163
162
|
|
|
@@ -166,10 +165,7 @@ module Lograge
|
|
|
166
165
|
|
|
167
166
|
base_classes = Array(lograge_config.base_controller_class)
|
|
168
167
|
base_classes.map! { |klass| klass.try(:constantize) }
|
|
169
|
-
if base_classes.empty?
|
|
170
|
-
base_classes << ActionController::Base
|
|
171
|
-
base_classes << ActionCable::Channel::Base if defined?(ActionCable)
|
|
172
|
-
end
|
|
168
|
+
base_classes << ActionController::Base if base_classes.empty?
|
|
173
169
|
|
|
174
170
|
base_classes.each do |base_class|
|
|
175
171
|
extend_base_class(base_class)
|
|
@@ -208,7 +204,7 @@ module Lograge
|
|
|
208
204
|
end
|
|
209
205
|
|
|
210
206
|
def rack_cache_hashlike?(app)
|
|
211
|
-
app.config.action_dispatch.rack_cache
|
|
207
|
+
app.config.action_dispatch.rack_cache&.respond_to?(:[]=)
|
|
212
208
|
end
|
|
213
209
|
private_class_method :rack_cache_hashlike?
|
|
214
210
|
|
|
@@ -228,5 +224,6 @@ module Lograge
|
|
|
228
224
|
application.config.lograge
|
|
229
225
|
end
|
|
230
226
|
end
|
|
227
|
+
# rubocop:enable Metrics/ModuleLength
|
|
231
228
|
|
|
232
229
|
require 'lograge/railtie' if defined?(Rails)
|
metadata
CHANGED
|
@@ -1,46 +1,61 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lograge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mathias Meyer
|
|
8
8
|
- Ben Lovell
|
|
9
|
-
|
|
9
|
+
- Michael Bianco
|
|
10
|
+
autorequire:
|
|
10
11
|
bindir: bin
|
|
11
12
|
cert_chain: []
|
|
12
|
-
date:
|
|
13
|
+
date: 2022-03-30 00:00:00.000000000 Z
|
|
13
14
|
dependencies:
|
|
14
15
|
- !ruby/object:Gem::Dependency
|
|
15
16
|
name: rspec
|
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
|
17
18
|
requirements:
|
|
18
|
-
- - "
|
|
19
|
+
- - "~>"
|
|
19
20
|
- !ruby/object:Gem::Version
|
|
20
|
-
version: '
|
|
21
|
+
version: '3.1'
|
|
21
22
|
type: :development
|
|
22
23
|
prerelease: false
|
|
23
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
24
25
|
requirements:
|
|
25
|
-
- - "
|
|
26
|
+
- - "~>"
|
|
26
27
|
- !ruby/object:Gem::Version
|
|
27
|
-
version: '
|
|
28
|
+
version: '3.1'
|
|
28
29
|
- !ruby/object:Gem::Dependency
|
|
29
30
|
name: rubocop
|
|
30
31
|
requirement: !ruby/object:Gem::Requirement
|
|
31
32
|
requirements:
|
|
32
|
-
- -
|
|
33
|
+
- - "~>"
|
|
33
34
|
- !ruby/object:Gem::Version
|
|
34
|
-
version:
|
|
35
|
+
version: '1.23'
|
|
35
36
|
type: :development
|
|
36
37
|
prerelease: false
|
|
37
38
|
version_requirements: !ruby/object:Gem::Requirement
|
|
38
39
|
requirements:
|
|
39
|
-
- -
|
|
40
|
+
- - "~>"
|
|
40
41
|
- !ruby/object:Gem::Version
|
|
41
|
-
version:
|
|
42
|
+
version: '1.23'
|
|
42
43
|
- !ruby/object:Gem::Dependency
|
|
43
|
-
name:
|
|
44
|
+
name: simplecov
|
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - "~>"
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '0.21'
|
|
50
|
+
type: :development
|
|
51
|
+
prerelease: false
|
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
53
|
+
requirements:
|
|
54
|
+
- - "~>"
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '0.21'
|
|
57
|
+
- !ruby/object:Gem::Dependency
|
|
58
|
+
name: actionpack
|
|
44
59
|
requirement: !ruby/object:Gem::Requirement
|
|
45
60
|
requirements:
|
|
46
61
|
- - ">="
|
|
@@ -54,7 +69,7 @@ dependencies:
|
|
|
54
69
|
- !ruby/object:Gem::Version
|
|
55
70
|
version: '4'
|
|
56
71
|
- !ruby/object:Gem::Dependency
|
|
57
|
-
name:
|
|
72
|
+
name: activesupport
|
|
58
73
|
requirement: !ruby/object:Gem::Requirement
|
|
59
74
|
requirements:
|
|
60
75
|
- - ">="
|
|
@@ -99,6 +114,7 @@ description: Tame Rails' multi-line logging into a single line per request
|
|
|
99
114
|
email:
|
|
100
115
|
- meyer@paperplanes.de
|
|
101
116
|
- benjamin.lovell@gmail.com
|
|
117
|
+
- mike@mikebian.co
|
|
102
118
|
executables: []
|
|
103
119
|
extensions: []
|
|
104
120
|
extra_rdoc_files: []
|
|
@@ -129,8 +145,9 @@ files:
|
|
|
129
145
|
homepage: https://github.com/roidrage/lograge
|
|
130
146
|
licenses:
|
|
131
147
|
- MIT
|
|
132
|
-
metadata:
|
|
133
|
-
|
|
148
|
+
metadata:
|
|
149
|
+
rubygems_mfa_required: 'true'
|
|
150
|
+
post_install_message:
|
|
134
151
|
rdoc_options: []
|
|
135
152
|
require_paths:
|
|
136
153
|
- lib
|
|
@@ -138,16 +155,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
138
155
|
requirements:
|
|
139
156
|
- - ">="
|
|
140
157
|
- !ruby/object:Gem::Version
|
|
141
|
-
version: '
|
|
158
|
+
version: '2.5'
|
|
142
159
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
160
|
requirements:
|
|
144
161
|
- - ">="
|
|
145
162
|
- !ruby/object:Gem::Version
|
|
146
163
|
version: '0'
|
|
147
164
|
requirements: []
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
signing_key:
|
|
165
|
+
rubygems_version: 3.1.6
|
|
166
|
+
signing_key:
|
|
151
167
|
specification_version: 4
|
|
152
168
|
summary: Tame Rails' multi-line logging into a single line per request
|
|
153
169
|
test_files: []
|