researchable_loggable 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +1 -4
- data/lib/loggable/logfmt/logger.rb +86 -0
- data/lib/loggable/railtie.rb +20 -12
- data/lib/loggable/version.rb +1 -1
- data/lib/researchable_loggable.rb +1 -2
- metadata +7 -22
- data/lib/loggable/ecs_logging/formatter_monkey_patch.rb +0 -55
- data/lib/loggable/lograge/formatter.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b80bc8fef9e875582f653226ef7bcc8f2bf01c44b7befba142694842800026f
|
4
|
+
data.tar.gz: 55cd5ef8ca78c68dd4e25ebc1cd7e68627f1871d4a2d0f646267a41ab8cab623
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f7821133b81bd0e363fea979048ef084e602860f83a558ed1d923b93f17950855dbc041ddc1eb314eeedfae03fdb8ed88319d4ea589439d4f8d5754c6ac86da
|
7
|
+
data.tar.gz: 1482b7dd44efb2a1177aabccd50f0f3ffb888e0af4448fc4ce27871ee93daf1648e745572f501a4770e42e7b571cd66c9088e7523d17534133362a2735a04dc9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
# [1.4.0](https://gitlab.com/researchable/general/gems/loggable/compare/v1.3.1...v1.4.0) (2024-11-29)
|
2
|
+
|
3
|
+
|
4
|
+
### Features
|
5
|
+
|
6
|
+
* add trace and span id ([6e486e0](https://gitlab.com/researchable/general/gems/loggable/commit/6e486e03f7bef1ecf739195d80472f3cf3c2b7f6))
|
7
|
+
* replace ecs logging format to logfmt ([19eb571](https://gitlab.com/researchable/general/gems/loggable/commit/19eb571719ed294fed4f94094c091c76470cae53))
|
8
|
+
|
9
|
+
## [1.3.1](https://gitlab.com/researchable/general/gems/loggable/compare/v1.3.0...v1.3.1) (2024-11-26)
|
10
|
+
|
11
|
+
|
12
|
+
### Bug Fixes
|
13
|
+
|
14
|
+
* accessing method of undefined in lograge custom_option ([fb44b01](https://gitlab.com/researchable/general/gems/loggable/commit/fb44b01c305f4321a560f8824419abc5d1512874))
|
15
|
+
|
1
16
|
# [1.3.0](https://gitlab.com/researchable/general/gems/loggable/compare/v1.2.0...v1.3.0) (2024-11-11)
|
2
17
|
|
3
18
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
researchable_loggable (1.
|
5
|
-
ecs-logging (~> 1.0)
|
4
|
+
researchable_loggable (1.3.1)
|
6
5
|
lograge
|
7
6
|
logstash-event
|
8
7
|
opentelemetry-exporter-otlp (~> 0.28)
|
@@ -36,7 +35,6 @@ GEM
|
|
36
35
|
concurrent-ruby (1.2.0)
|
37
36
|
crass (1.0.6)
|
38
37
|
diff-lcs (1.5.0)
|
39
|
-
ecs-logging (1.0.0)
|
40
38
|
erubi (1.12.0)
|
41
39
|
google-protobuf (4.27.4-x86_64-linux)
|
42
40
|
bigdecimal
|
@@ -335,7 +333,6 @@ PLATFORMS
|
|
335
333
|
x86_64-linux
|
336
334
|
|
337
335
|
DEPENDENCIES
|
338
|
-
ecs-logging (~> 1.0)
|
339
336
|
lograge
|
340
337
|
logstash-event
|
341
338
|
opentelemetry-exporter-otlp (~> 0.28)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'time'
|
5
|
+
require 'active_support/logger_silence'
|
6
|
+
|
7
|
+
module Loggable
|
8
|
+
module Logfmt
|
9
|
+
# A structured logger that formats log messages in a key-value style using Logfmt formatting
|
10
|
+
# This has been adapted from https://github.com/cyberdelia/logfmt-ruby/
|
11
|
+
class Logger < ::Logger
|
12
|
+
def initialize(*args, **kwargs)
|
13
|
+
super
|
14
|
+
@formatter ||= KeyValueFormatter.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# Include the LoggerSilence module to fix the incompatibility with ActiveSupport::LoggerSilence whe
|
18
|
+
# Rails.application.config.assets.quiet option is set to true, but do not include the module for the
|
19
|
+
# test environment as it causes issues with ActiveSupport::LoggerThreadSafeLevel::IsolatedExecutionState.
|
20
|
+
def self.include_logger_silence
|
21
|
+
include ActiveSupport::LoggerSilence
|
22
|
+
end
|
23
|
+
|
24
|
+
# Custom formatter class that renders logs as in a key-value style using Logfmt formatting
|
25
|
+
class KeyValueFormatter < ::Logger::Formatter
|
26
|
+
def call(severity, timestamp, progname, msg)
|
27
|
+
%(time=#{datetime(timestamp)} severity=#{severity.ljust(5)}#{progname(progname)} #{message(msg)}\n)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def datetime(time)
|
33
|
+
time.utc.iso8601(3)
|
34
|
+
end
|
35
|
+
|
36
|
+
def message(msg)
|
37
|
+
return unless msg
|
38
|
+
|
39
|
+
if msg.respond_to?(:to_hash)
|
40
|
+
pairs = msg.to_hash.map { |k, v| format_pair(k, v) }
|
41
|
+
pairs.compact.join(' ')
|
42
|
+
else
|
43
|
+
format_pair('message', msg)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def format_pair(key, value)
|
48
|
+
return nil if value.nil?
|
49
|
+
|
50
|
+
# Return a bare key when the value is a `TrueClass`
|
51
|
+
return key if value == true
|
52
|
+
|
53
|
+
"#{key}=#{format_value(value)}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def progname(progname)
|
57
|
+
return nil unless progname
|
58
|
+
|
59
|
+
# Format this pair like any other to ensure quoting, escaping, etc…,
|
60
|
+
# But we also need a leading space so we can interpolate the resulting
|
61
|
+
# key/value pair into our log line.
|
62
|
+
" #{format_pair(' progname', progname)}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def format_value(value)
|
66
|
+
if value.is_a?(Float)
|
67
|
+
format('%.3f', value)
|
68
|
+
elsif value.is_a?(Time)
|
69
|
+
datetime(value)
|
70
|
+
elsif value.respond_to?(:to_ary)
|
71
|
+
format_value(
|
72
|
+
"[#{Array(value).map { |v| format_value(v) }.join(', ')}]"
|
73
|
+
)
|
74
|
+
else
|
75
|
+
# Interpolating due to a weird/subtle behaviour possible in #to_s.
|
76
|
+
# Namely, it's possible it doesn't actually return a String:
|
77
|
+
# https://github.com/ruby/spec/blob/3affe1e54fcd11918a242ad5d4a7ba895ee30c4c/language/string_spec.rb#L130-L141
|
78
|
+
value = "#{value}" # rubocop:disable Style/RedundantInterpolation
|
79
|
+
value = value.dump if value.match?(/[[:space:]]|[[:cntrl:]]/) # wrap in quotes and escape control characters
|
80
|
+
value
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/loggable/railtie.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'lograge'
|
4
4
|
require 'rails'
|
5
|
+
require 'opentelemetry/sdk'
|
5
6
|
|
6
7
|
module Loggable
|
7
8
|
# Railtie to configure logging before rails starts
|
@@ -12,13 +13,14 @@ module Loggable
|
|
12
13
|
config.loggable.current_user_method = :current_user
|
13
14
|
|
14
15
|
# Initializer runs before initialize_logger (found in Bootstrap) so from the very beginning we are logging using
|
15
|
-
# the
|
16
|
+
# the logfmt format, even during the initialization process
|
16
17
|
# rubocop:disable Metrics/BlockLength
|
17
18
|
initializer :loggable_web, before: :initialize_logger do
|
18
19
|
Rails.application.configure do
|
19
20
|
production_like = Rails.env.production? || config.loggable.production_like
|
20
21
|
if production_like
|
21
|
-
|
22
|
+
Loggable::Logfmt::Logger.include_logger_silence if Rails.application.config.assets.quiet
|
23
|
+
Rails.logger = Loggable::Logfmt::Logger.new($stdout)
|
22
24
|
Rails.logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase || 'INFO')
|
23
25
|
|
24
26
|
Loggable::OpenTelemetryConfig.configure(Rails.application.class.module_parent_name.underscore.dasherize)
|
@@ -32,20 +34,26 @@ module Loggable
|
|
32
34
|
if controller.respond_to?(config.loggable.current_user_method)
|
33
35
|
user_id = controller.send(config.loggable.current_user_method).try(:id)
|
34
36
|
end
|
37
|
+
|
35
38
|
{
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
status: response_code
|
39
|
+
'source.ip': controller.request.ip,
|
40
|
+
'user.id': user_id,
|
41
|
+
status: response_code,
|
42
|
+
span_id: OpenTelemetry::Trace.current_span.context.hex_span_id,
|
43
|
+
trace_id: OpenTelemetry::Trace.current_span.context.hex_trace_id
|
42
44
|
}
|
43
45
|
end
|
44
46
|
config.lograge.custom_options = lambda do |event|
|
47
|
+
return if event.payload[:params].blank?
|
48
|
+
|
45
49
|
exceptions = %w[controller action format id]
|
46
|
-
|
50
|
+
params = event.payload[:params].except(*exceptions)
|
51
|
+
# append a suffix to each param
|
52
|
+
params.each_with_object({}) do |(key, value), result|
|
53
|
+
result["params.#{key}"] = value
|
54
|
+
end
|
47
55
|
end
|
48
|
-
config.lograge.formatter =
|
56
|
+
config.lograge.formatter = ::Lograge::Formatters::Raw.new
|
49
57
|
end
|
50
58
|
end
|
51
59
|
# rubocop:enable Metrics/BlockLength
|
@@ -54,7 +62,7 @@ module Loggable
|
|
54
62
|
Rails.application.configure do
|
55
63
|
if defined?(Delayed::Worker)
|
56
64
|
if Rails.env.production? || config.loggable.production_like
|
57
|
-
Delayed::Worker.logger = ::
|
65
|
+
Delayed::Worker.logger = Loggable::Logfmt::Logger.new($stdout)
|
58
66
|
Delayed::Worker.logger.level = ActiveSupport::Logger.const_get(config.log_level.to_s.upcase || 'INFO')
|
59
67
|
Loggable::OpenTelemetryConfig.configure("#{Rails.application.class.module_parent_name.underscore.dasherize}
|
60
68
|
-worker")
|
data/lib/loggable/version.rb
CHANGED
@@ -3,8 +3,7 @@
|
|
3
3
|
require_relative 'loggable/version'
|
4
4
|
require_relative 'loggable/railtie' if defined?(Rails::Railtie)
|
5
5
|
require_relative 'loggable/opentelemetry_config'
|
6
|
-
require_relative 'loggable/
|
7
|
-
require_relative 'loggable/lograge/formatter'
|
6
|
+
require_relative 'loggable/logfmt/logger'
|
8
7
|
|
9
8
|
module ResearchableLoggable
|
10
9
|
class Error < StandardError
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: researchable_loggable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Researchable
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: ecs-logging
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: lograge
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,20 +100,19 @@ files:
|
|
114
100
|
- LICENSE.txt
|
115
101
|
- README.md
|
116
102
|
- Rakefile
|
117
|
-
- lib/loggable/
|
118
|
-
- lib/loggable/lograge/formatter.rb
|
103
|
+
- lib/loggable/logfmt/logger.rb
|
119
104
|
- lib/loggable/opentelemetry_config.rb
|
120
105
|
- lib/loggable/railtie.rb
|
121
106
|
- lib/loggable/version.rb
|
122
107
|
- lib/researchable_loggable.rb
|
123
108
|
- sig/loggable.rbs
|
124
|
-
homepage: https://gitlab.com/researchable/general/gems/loggable/-/blob/v1.
|
109
|
+
homepage: https://gitlab.com/researchable/general/gems/loggable/-/blob/v1.4.0/README.md
|
125
110
|
licenses:
|
126
111
|
- MIT
|
127
112
|
metadata:
|
128
|
-
homepage_uri: https://gitlab.com/researchable/general/gems/loggable/-/blob/v1.
|
113
|
+
homepage_uri: https://gitlab.com/researchable/general/gems/loggable/-/blob/v1.4.0/README.md
|
129
114
|
source_code_uri: https://gitlab.com/researchable/general/gems/loggable
|
130
|
-
changelog_uri: https://gitlab.com/researchable/general/gems/loggable/-/blob/v1.
|
115
|
+
changelog_uri: https://gitlab.com/researchable/general/gems/loggable/-/blob/v1.4.0/CHANGELOG.md
|
131
116
|
post_install_message:
|
132
117
|
rdoc_options: []
|
133
118
|
require_paths:
|
@@ -143,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
128
|
- !ruby/object:Gem::Version
|
144
129
|
version: '0'
|
145
130
|
requirements: []
|
146
|
-
rubygems_version: 3.5.
|
131
|
+
rubygems_version: 3.5.22
|
147
132
|
signing_key:
|
148
133
|
specification_version: 4
|
149
134
|
summary: Researchable's gem to standardize logging on all Rails applications.
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'ecs_logging/formatter'
|
4
|
-
|
5
|
-
module Loggable
|
6
|
-
module EcsLogging
|
7
|
-
# A monkey patch to the ::EcsLogging::Formatter to customize how messages from lograge are rendered
|
8
|
-
module FormatterMonkeyPatch
|
9
|
-
def call(severity, time, progname, msg, **extras)
|
10
|
-
base = {
|
11
|
-
'@timestamp': time.utc.iso8601(3),
|
12
|
-
'log.level': severity,
|
13
|
-
message: msg,
|
14
|
-
'ecs.version': '1.4.0'
|
15
|
-
}
|
16
|
-
|
17
|
-
base['log.logger'] = progname if progname
|
18
|
-
|
19
|
-
base.merge!(msg.except(:lograge)) if msg.is_a?(Hash) && msg.key?(:lograge)
|
20
|
-
base.merge!(extras) if extras
|
21
|
-
|
22
|
-
"#{JSON.fast_generate(base)}\n"
|
23
|
-
end
|
24
|
-
|
25
|
-
class << self
|
26
|
-
def apply_patch
|
27
|
-
const = find_const
|
28
|
-
mtd = find_method(const)
|
29
|
-
|
30
|
-
# byebug
|
31
|
-
const.prepend(self) if const && mtd && mtd.arity == -5
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def find_const
|
37
|
-
Kernel.const_get('::EcsLogging::Formatter')
|
38
|
-
rescue NameError
|
39
|
-
puts '[WARN] ::EcsLogging::Formatter not found. Patch could not be applied.' # rubocop:disable Rails/Output
|
40
|
-
end
|
41
|
-
|
42
|
-
def find_method(const)
|
43
|
-
return unless const
|
44
|
-
|
45
|
-
method_name = :call
|
46
|
-
const.instance_method(method_name)
|
47
|
-
rescue NameError
|
48
|
-
puts "[WARN] '#{method_name}' method not found in '#{const}'. Patch could not be applied." # rubocop:disable Rails/Output
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
Loggable::EcsLogging::FormatterMonkeyPatch.apply_patch
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'lograge'
|
4
|
-
require 'active_support/core_ext/array'
|
5
|
-
|
6
|
-
module Loggable
|
7
|
-
module Lograge
|
8
|
-
# Custom formatter class that renders logs as ruby objects with just the ecs fields generated by the logger, the
|
9
|
-
# message, and a lograge flag so the ECS logger knows to process this further before rendering
|
10
|
-
class Formatter < ::Lograge::Formatters::KeyValue
|
11
|
-
def call(data)
|
12
|
-
(data[:ecs] || {}).merge(message: super(data), lograge: true)
|
13
|
-
end
|
14
|
-
|
15
|
-
protected
|
16
|
-
|
17
|
-
def fields_to_display(data)
|
18
|
-
data.keys.excluding(%i[ecs])
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|