activesupport-json_logging 1.2.1 → 1.3.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 +4 -4
- data/CHANGELOG.md +27 -0
- data/README.md +66 -10
- data/lib/activesupport/json_logging/railtie.rb +11 -0
- data/lib/json_logging/event_subscriber.rb +146 -0
- data/lib/json_logging/formatter.rb +13 -9
- data/lib/json_logging/formatter_with_tags.rb +12 -9
- data/lib/json_logging/helpers.rb +16 -1
- data/lib/json_logging/json_logger.rb +1 -3
- data/lib/json_logging/json_logger_extension.rb +47 -71
- data/lib/json_logging/line_encoder.rb +245 -0
- data/lib/json_logging/payload_builder.rb +57 -21
- data/lib/json_logging/sanitizer.rb +112 -11
- data/lib/json_logging/severity.rb +18 -0
- data/lib/json_logging/structured_hash_json_encoder.rb +111 -0
- data/lib/json_logging/structured_hash_sanitizer.rb +206 -0
- data/lib/json_logging/version.rb +1 -1
- data/lib/json_logging.rb +85 -11
- data/sig/json_logging.rbs +8 -0
- metadata +53 -33
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
module JsonLogging
|
|
2
|
+
module Sanitizer
|
|
3
|
+
module StructuredHash
|
|
4
|
+
JsonableResult = Struct.new(:tree, :owned, :leaf_count)
|
|
5
|
+
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def structured_log_hash?(hash, seen = nil)
|
|
9
|
+
seen ||= Set.new.compare_by_identity
|
|
10
|
+
return false unless seen.add?(hash)
|
|
11
|
+
|
|
12
|
+
result = hash.all? { |_key, value| structured_log_value?(value, seen) }
|
|
13
|
+
seen.delete(hash)
|
|
14
|
+
result
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def structured_log_value?(value, seen = nil)
|
|
18
|
+
case value
|
|
19
|
+
when String, Numeric, TrueClass, FalseClass, NilClass
|
|
20
|
+
Sanitizer.primitive_log_value?(value)
|
|
21
|
+
when Hash
|
|
22
|
+
structured_log_hash?(value, seen)
|
|
23
|
+
when Array
|
|
24
|
+
structured_log_array?(value, seen)
|
|
25
|
+
else
|
|
26
|
+
false
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def structured_log_array?(array, seen = nil)
|
|
31
|
+
array.all? { |value| structured_log_value?(value, seen) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def sanitize(hash, depth: 0)
|
|
35
|
+
return {"error" => "max_depth_exceeded"} if depth > Sanitizer::MAX_DEPTH
|
|
36
|
+
|
|
37
|
+
filter = Sanitizer.rails_parameter_filter
|
|
38
|
+
if filter
|
|
39
|
+
filter.filter(stringify(hash))
|
|
40
|
+
else
|
|
41
|
+
sanitize_without_filter(hash, depth: depth)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def sanitize_without_filter(hash, depth: 0)
|
|
46
|
+
jsonable = jsonable_tree(hash, depth: depth)
|
|
47
|
+
if jsonable.owned
|
|
48
|
+
stringify(jsonable.tree)
|
|
49
|
+
else
|
|
50
|
+
jsonable.tree.dup
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def jsonable_tree(hash, depth: 0, seen: nil, parent_key: nil, omit_keys: nil, count_leaves: false, leaf_counter: nil)
|
|
55
|
+
seen ||= Set.new.compare_by_identity
|
|
56
|
+
leaf_counter = [0] if count_leaves && leaf_counter.nil?
|
|
57
|
+
if depth > Sanitizer::MAX_DEPTH
|
|
58
|
+
return JsonableResult.new(tree: {"error" => "max_depth_exceeded"}, owned: true, leaf_count: leaf_counter&.[](0))
|
|
59
|
+
end
|
|
60
|
+
unless seen.add?(hash)
|
|
61
|
+
return JsonableResult.new(tree: {"error" => "cyclic_reference"}, owned: true, leaf_count: leaf_counter&.[](0))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
entries = []
|
|
65
|
+
owned = false
|
|
66
|
+
|
|
67
|
+
hash.each do |key, value|
|
|
68
|
+
entry = process_jsonable_entry(
|
|
69
|
+
key,
|
|
70
|
+
value,
|
|
71
|
+
depth: depth,
|
|
72
|
+
seen: seen,
|
|
73
|
+
parent_key: parent_key,
|
|
74
|
+
omit_keys: omit_keys,
|
|
75
|
+
leaf_counter: leaf_counter
|
|
76
|
+
)
|
|
77
|
+
next unless entry
|
|
78
|
+
|
|
79
|
+
key_string, encoded_value, pair_owned = entry
|
|
80
|
+
owned ||= pair_owned
|
|
81
|
+
entries << [key_string, encoded_value, pair_owned]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
seen.delete(hash)
|
|
85
|
+
leaf_count = leaf_counter&.[](0)
|
|
86
|
+
unless owned
|
|
87
|
+
tree = omit_root_keys(hash, omit_keys, depth: depth)
|
|
88
|
+
return JsonableResult.new(tree: tree, owned: false, leaf_count: leaf_count)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
result = entries.each_with_object({}) do |(key_string, encoded_value, _pair_owned), object|
|
|
92
|
+
object[key_string] = encoded_value
|
|
93
|
+
end
|
|
94
|
+
JsonableResult.new(tree: result, owned: true, leaf_count: leaf_count)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def jsonable_value(value, depth:, seen:, parent_key:, leaf_counter: nil)
|
|
98
|
+
case value
|
|
99
|
+
when String
|
|
100
|
+
leaf_counter[0] += 1 if leaf_counter
|
|
101
|
+
sanitized = Sanitizer.sanitize_string(value)
|
|
102
|
+
JsonableResult.new(tree: sanitized, owned: sanitized != value, leaf_count: nil)
|
|
103
|
+
when Hash
|
|
104
|
+
jsonable_tree(value, depth: depth + 1, seen: seen, parent_key: parent_key, leaf_counter: leaf_counter)
|
|
105
|
+
when Array
|
|
106
|
+
jsonable_array(value, depth: depth, seen: seen, parent_key: parent_key, leaf_counter: leaf_counter)
|
|
107
|
+
else
|
|
108
|
+
leaf_counter[0] += 1 if leaf_counter
|
|
109
|
+
JsonableResult.new(tree: value, owned: false, leaf_count: nil)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def jsonable_array(array, depth:, seen:, parent_key:, leaf_counter: nil)
|
|
114
|
+
owned = false
|
|
115
|
+
result = nil
|
|
116
|
+
|
|
117
|
+
array.each_with_index do |entry, index|
|
|
118
|
+
child = jsonable_value(entry, depth: depth, seen: seen, parent_key: parent_key, leaf_counter: leaf_counter)
|
|
119
|
+
next unless child.owned
|
|
120
|
+
|
|
121
|
+
owned = true
|
|
122
|
+
result ||= array.dup
|
|
123
|
+
result[index] = child.tree
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
JsonableResult.new(tree: owned ? result : array, owned: owned, leaf_count: nil)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def process_jsonable_entry(key, value, depth:, seen:, parent_key:, omit_keys:, leaf_counter:)
|
|
130
|
+
key_string = key.to_s
|
|
131
|
+
if root_key_omitted?(depth, key_string, omit_keys)
|
|
132
|
+
count_leaves_in_value(value, leaf_counter, depth: depth, seen: seen) if leaf_counter
|
|
133
|
+
return
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
if Sanitizer::SENSITIVE_KEY_PATTERNS.match?(key_string)
|
|
137
|
+
return [Sanitizer.sensitive_filtered_key_name(key_string), "[FILTERED]", true]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
nested_parent = parent_key ? "#{parent_key}.#{key_string}" : key_string
|
|
141
|
+
child = jsonable_value(
|
|
142
|
+
value,
|
|
143
|
+
depth: depth,
|
|
144
|
+
seen: seen,
|
|
145
|
+
parent_key: nested_parent,
|
|
146
|
+
leaf_counter: leaf_counter
|
|
147
|
+
)
|
|
148
|
+
encoded_value = child.owned ? child.tree : value
|
|
149
|
+
[key_string, encoded_value, child.owned]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def root_key_omitted?(depth, key_string, omit_keys)
|
|
153
|
+
depth.zero? && omit_keys&.include?(key_string)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def omit_root_keys(hash, omit_keys, depth:)
|
|
157
|
+
return hash unless depth.zero? && omit_keys&.any?
|
|
158
|
+
|
|
159
|
+
hash.each_with_object({}) do |(key, value), object|
|
|
160
|
+
object[key] = value unless omit_keys.include?(key.to_s)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def count_leaves_in_value(value, leaf_counter, depth:, seen:)
|
|
165
|
+
case value
|
|
166
|
+
when Hash
|
|
167
|
+
return unless seen.add?(value)
|
|
168
|
+
|
|
169
|
+
value.each_value do |entry|
|
|
170
|
+
count_leaves_in_value(entry, leaf_counter, depth: depth + 1, seen: seen)
|
|
171
|
+
end
|
|
172
|
+
seen.delete(value)
|
|
173
|
+
when Array
|
|
174
|
+
value.each { |entry| count_leaves_in_value(entry, leaf_counter, depth: depth, seen: seen) }
|
|
175
|
+
else
|
|
176
|
+
leaf_counter[0] += 1
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def stringify(hash)
|
|
181
|
+
hash.each_with_object({}) do |(key, value), result|
|
|
182
|
+
result[key.to_s] = stringify_value(value)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def stringify_value(value)
|
|
187
|
+
case value
|
|
188
|
+
when Hash
|
|
189
|
+
stringify(value)
|
|
190
|
+
when Array
|
|
191
|
+
value.map { |entry| stringify_value(entry) }
|
|
192
|
+
when String
|
|
193
|
+
Sanitizer.sanitize_string(value)
|
|
194
|
+
else
|
|
195
|
+
value
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def stringify_keys_copy(hash)
|
|
200
|
+
return hash if hash.keys.all? { |key| key.is_a?(String) }
|
|
201
|
+
|
|
202
|
+
hash.transform_keys(&:to_s)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
data/lib/json_logging/version.rb
CHANGED
data/lib/json_logging.rb
CHANGED
|
@@ -7,20 +7,37 @@ require_relative "json_logging/helpers"
|
|
|
7
7
|
require_relative "json_logging/sanitizer"
|
|
8
8
|
require_relative "json_logging/message_parser"
|
|
9
9
|
require_relative "json_logging/payload_builder"
|
|
10
|
+
require_relative "json_logging/line_encoder"
|
|
10
11
|
require_relative "json_logging/formatter"
|
|
11
12
|
require_relative "json_logging/formatter_with_tags"
|
|
12
13
|
require_relative "json_logging/json_logger_extension"
|
|
13
14
|
require_relative "json_logging/json_logger"
|
|
15
|
+
require_relative "json_logging/event_subscriber"
|
|
14
16
|
|
|
15
17
|
module JsonLogging
|
|
16
18
|
THREAD_CONTEXT_KEY = :__json_logging_context
|
|
19
|
+
SANITIZED_CONTEXT_CACHE_KEY = :__json_logging_sanitized_context
|
|
20
|
+
@additional_context_warned = Set.new
|
|
21
|
+
@additional_context_transformer = nil
|
|
22
|
+
|
|
23
|
+
def self.context_storage
|
|
24
|
+
if defined?(ActiveSupport::IsolatedExecutionState)
|
|
25
|
+
ActiveSupport::IsolatedExecutionState
|
|
26
|
+
else
|
|
27
|
+
Thread.current
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
private_class_method :context_storage
|
|
17
31
|
|
|
18
32
|
def self.with_context(extra_context)
|
|
19
|
-
|
|
20
|
-
|
|
33
|
+
storage = context_storage
|
|
34
|
+
original = storage[THREAD_CONTEXT_KEY]
|
|
35
|
+
storage[THREAD_CONTEXT_KEY] = (original || {}).merge(safe_hash(extra_context))
|
|
36
|
+
invalidate_sanitized_context_cache(storage)
|
|
21
37
|
yield
|
|
22
38
|
ensure
|
|
23
|
-
|
|
39
|
+
storage[THREAD_CONTEXT_KEY] = original
|
|
40
|
+
invalidate_sanitized_context_cache(storage)
|
|
24
41
|
end
|
|
25
42
|
|
|
26
43
|
# Returns the current thread-local context when called without arguments,
|
|
@@ -42,8 +59,9 @@ module JsonLogging
|
|
|
42
59
|
end
|
|
43
60
|
|
|
44
61
|
begin
|
|
45
|
-
base_context = (
|
|
46
|
-
rescue
|
|
62
|
+
base_context = (context_storage[THREAD_CONTEXT_KEY] || {}).dup
|
|
63
|
+
rescue => e
|
|
64
|
+
warn_additional_context_once(:dup, "thread context dup failed", e)
|
|
47
65
|
base_context = {}
|
|
48
66
|
end
|
|
49
67
|
|
|
@@ -51,7 +69,8 @@ module JsonLogging
|
|
|
51
69
|
if transformer.is_a?(Proc)
|
|
52
70
|
begin
|
|
53
71
|
transformer.call(base_context)
|
|
54
|
-
rescue
|
|
72
|
+
rescue => e
|
|
73
|
+
warn_additional_context_once(:transformer, "additional_context transformer failed", e)
|
|
55
74
|
base_context
|
|
56
75
|
end
|
|
57
76
|
else
|
|
@@ -61,6 +80,26 @@ module JsonLogging
|
|
|
61
80
|
|
|
62
81
|
def self.additional_context=(proc_or_block)
|
|
63
82
|
@additional_context_transformer = proc_or_block
|
|
83
|
+
invalidate_sanitized_context_cache(context_storage)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.additional_context_for_payload
|
|
87
|
+
if @additional_context_transformer.is_a?(Proc)
|
|
88
|
+
return sanitized_context_from(compact_context(additional_context))
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
storage = context_storage
|
|
92
|
+
cached = storage[SANITIZED_CONTEXT_CACHE_KEY]
|
|
93
|
+
return cached if cached
|
|
94
|
+
|
|
95
|
+
raw_context = storage[THREAD_CONTEXT_KEY]
|
|
96
|
+
if raw_context.nil? || (raw_context.is_a?(Hash) && raw_context.empty?)
|
|
97
|
+
return storage[SANITIZED_CONTEXT_CACHE_KEY] = {}.freeze
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
sanitized = sanitized_context_from(compact_context(raw_context))
|
|
101
|
+
storage[SANITIZED_CONTEXT_CACHE_KEY] = sanitized.freeze
|
|
102
|
+
sanitized
|
|
64
103
|
end
|
|
65
104
|
|
|
66
105
|
def self.safe_hash(obj)
|
|
@@ -69,6 +108,34 @@ module JsonLogging
|
|
|
69
108
|
{}
|
|
70
109
|
end
|
|
71
110
|
|
|
111
|
+
def self.warn_additional_context_once(key, message, error)
|
|
112
|
+
return if @additional_context_warned.include?(key)
|
|
113
|
+
|
|
114
|
+
@additional_context_warned.add(key)
|
|
115
|
+
warn "[activesupport-json_logging] #{message} (#{error.class}: #{error.message})"
|
|
116
|
+
end
|
|
117
|
+
private_class_method :warn_additional_context_once
|
|
118
|
+
|
|
119
|
+
def self.compact_context(context)
|
|
120
|
+
return {} unless context.is_a?(Hash)
|
|
121
|
+
return {} if context.empty?
|
|
122
|
+
|
|
123
|
+
context.compact
|
|
124
|
+
end
|
|
125
|
+
private_class_method :compact_context
|
|
126
|
+
|
|
127
|
+
def self.sanitized_context_from(compacted_context)
|
|
128
|
+
return {} if compacted_context.empty?
|
|
129
|
+
|
|
130
|
+
Sanitizer.sanitize_hash(compacted_context)
|
|
131
|
+
end
|
|
132
|
+
private_class_method :sanitized_context_from
|
|
133
|
+
|
|
134
|
+
def self.invalidate_sanitized_context_cache(storage)
|
|
135
|
+
storage[SANITIZED_CONTEXT_CACHE_KEY] = nil
|
|
136
|
+
end
|
|
137
|
+
private_class_method :invalidate_sanitized_context_cache
|
|
138
|
+
|
|
72
139
|
# Returns an `ActiveSupport::Logger` that has already been wrapped with JSON logging concern.
|
|
73
140
|
#
|
|
74
141
|
# @param *args Arguments passed to ActiveSupport::Logger.new
|
|
@@ -97,6 +164,17 @@ module JsonLogging
|
|
|
97
164
|
# logger.tagged("BCX") { logger.info("Stuff") } # Logs with tags
|
|
98
165
|
# logger.tagged("BCX").info("Stuff") # Logs with tags (non-block form)
|
|
99
166
|
def self.new(logger)
|
|
167
|
+
logger = prepare_logger_clone(logger)
|
|
168
|
+
logger.extend(JsonLoggerExtension)
|
|
169
|
+
formatter_with_tags = FormatterWithTags.new(logger)
|
|
170
|
+
logger.instance_variable_set(:@formatter_with_tags, formatter_with_tags)
|
|
171
|
+
# Custom formatters are not supported: JSON output requires FormatterWithTags.
|
|
172
|
+
logger.formatter = formatter_with_tags
|
|
173
|
+
|
|
174
|
+
logger
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def self.prepare_logger_clone(logger)
|
|
100
178
|
logger = logger.clone
|
|
101
179
|
if logger.formatter
|
|
102
180
|
logger.formatter = logger.formatter.clone
|
|
@@ -114,11 +192,7 @@ module JsonLogging
|
|
|
114
192
|
end
|
|
115
193
|
end
|
|
116
194
|
|
|
117
|
-
logger.extend(JsonLoggerExtension)
|
|
118
|
-
formatter_with_tags = FormatterWithTags.new(logger)
|
|
119
|
-
logger.instance_variable_set(:@formatter_with_tags, formatter_with_tags)
|
|
120
|
-
logger.formatter = formatter_with_tags
|
|
121
|
-
|
|
122
195
|
logger
|
|
123
196
|
end
|
|
197
|
+
private_class_method :prepare_logger_clone
|
|
124
198
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activesupport-json_logging
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrei Makarov
|
|
@@ -15,7 +15,7 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '
|
|
18
|
+
version: '7.0'
|
|
19
19
|
- - "<"
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
21
|
version: '9.0'
|
|
@@ -25,7 +25,7 @@ dependencies:
|
|
|
25
25
|
requirements:
|
|
26
26
|
- - ">="
|
|
27
27
|
- !ruby/object:Gem::Version
|
|
28
|
-
version: '
|
|
28
|
+
version: '7.0'
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: '9.0'
|
|
@@ -35,7 +35,7 @@ dependencies:
|
|
|
35
35
|
requirements:
|
|
36
36
|
- - ">="
|
|
37
37
|
- !ruby/object:Gem::Version
|
|
38
|
-
version: '
|
|
38
|
+
version: '7.0'
|
|
39
39
|
- - "<"
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
41
|
version: '9.0'
|
|
@@ -45,7 +45,7 @@ dependencies:
|
|
|
45
45
|
requirements:
|
|
46
46
|
- - ">="
|
|
47
47
|
- !ruby/object:Gem::Version
|
|
48
|
-
version: '
|
|
48
|
+
version: '7.0'
|
|
49
49
|
- - "<"
|
|
50
50
|
- !ruby/object:Gem::Version
|
|
51
51
|
version: '9.0'
|
|
@@ -64,47 +64,47 @@ dependencies:
|
|
|
64
64
|
- !ruby/object:Gem::Version
|
|
65
65
|
version: '3'
|
|
66
66
|
- !ruby/object:Gem::Dependency
|
|
67
|
-
name:
|
|
67
|
+
name: polyrun
|
|
68
68
|
requirement: !ruby/object:Gem::Requirement
|
|
69
69
|
requirements:
|
|
70
|
-
- - "
|
|
70
|
+
- - ">="
|
|
71
71
|
- !ruby/object:Gem::Version
|
|
72
|
-
version:
|
|
72
|
+
version: 2.2.0
|
|
73
73
|
type: :development
|
|
74
74
|
prerelease: false
|
|
75
75
|
version_requirements: !ruby/object:Gem::Requirement
|
|
76
76
|
requirements:
|
|
77
|
-
- - "
|
|
77
|
+
- - ">="
|
|
78
78
|
- !ruby/object:Gem::Version
|
|
79
|
-
version:
|
|
79
|
+
version: 2.2.0
|
|
80
80
|
- !ruby/object:Gem::Dependency
|
|
81
|
-
name:
|
|
81
|
+
name: webmock
|
|
82
82
|
requirement: !ruby/object:Gem::Requirement
|
|
83
83
|
requirements:
|
|
84
84
|
- - "~>"
|
|
85
85
|
- !ruby/object:Gem::Version
|
|
86
|
-
version: '
|
|
86
|
+
version: '3'
|
|
87
87
|
type: :development
|
|
88
88
|
prerelease: false
|
|
89
89
|
version_requirements: !ruby/object:Gem::Requirement
|
|
90
90
|
requirements:
|
|
91
91
|
- - "~>"
|
|
92
92
|
- !ruby/object:Gem::Version
|
|
93
|
-
version: '
|
|
93
|
+
version: '3'
|
|
94
94
|
- !ruby/object:Gem::Dependency
|
|
95
|
-
name:
|
|
95
|
+
name: rake
|
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
|
97
97
|
requirements:
|
|
98
98
|
- - "~>"
|
|
99
99
|
- !ruby/object:Gem::Version
|
|
100
|
-
version: '
|
|
100
|
+
version: '13'
|
|
101
101
|
type: :development
|
|
102
102
|
prerelease: false
|
|
103
103
|
version_requirements: !ruby/object:Gem::Requirement
|
|
104
104
|
requirements:
|
|
105
105
|
- - "~>"
|
|
106
106
|
- !ruby/object:Gem::Version
|
|
107
|
-
version: '
|
|
107
|
+
version: '13'
|
|
108
108
|
- !ruby/object:Gem::Dependency
|
|
109
109
|
name: rspec_junit_formatter
|
|
110
110
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -119,20 +119,6 @@ dependencies:
|
|
|
119
119
|
- - "~>"
|
|
120
120
|
- !ruby/object:Gem::Version
|
|
121
121
|
version: '0.6'
|
|
122
|
-
- !ruby/object:Gem::Dependency
|
|
123
|
-
name: simplecov-cobertura
|
|
124
|
-
requirement: !ruby/object:Gem::Requirement
|
|
125
|
-
requirements:
|
|
126
|
-
- - "~>"
|
|
127
|
-
- !ruby/object:Gem::Version
|
|
128
|
-
version: '3'
|
|
129
|
-
type: :development
|
|
130
|
-
prerelease: false
|
|
131
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
132
|
-
requirements:
|
|
133
|
-
- - "~>"
|
|
134
|
-
- !ruby/object:Gem::Version
|
|
135
|
-
version: '3'
|
|
136
122
|
- !ruby/object:Gem::Dependency
|
|
137
123
|
name: standard
|
|
138
124
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -301,8 +287,36 @@ dependencies:
|
|
|
301
287
|
- - "~>"
|
|
302
288
|
- !ruby/object:Gem::Version
|
|
303
289
|
version: '0.5'
|
|
290
|
+
- !ruby/object:Gem::Dependency
|
|
291
|
+
name: benchmark-ips
|
|
292
|
+
requirement: !ruby/object:Gem::Requirement
|
|
293
|
+
requirements:
|
|
294
|
+
- - "~>"
|
|
295
|
+
- !ruby/object:Gem::Version
|
|
296
|
+
version: '2'
|
|
297
|
+
type: :development
|
|
298
|
+
prerelease: false
|
|
299
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
300
|
+
requirements:
|
|
301
|
+
- - "~>"
|
|
302
|
+
- !ruby/object:Gem::Version
|
|
303
|
+
version: '2'
|
|
304
|
+
- !ruby/object:Gem::Dependency
|
|
305
|
+
name: stackprof
|
|
306
|
+
requirement: !ruby/object:Gem::Requirement
|
|
307
|
+
requirements:
|
|
308
|
+
- - "~>"
|
|
309
|
+
- !ruby/object:Gem::Version
|
|
310
|
+
version: '0.2'
|
|
311
|
+
type: :development
|
|
312
|
+
prerelease: false
|
|
313
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
314
|
+
requirements:
|
|
315
|
+
- - "~>"
|
|
316
|
+
- !ruby/object:Gem::Version
|
|
317
|
+
version: '0.2'
|
|
304
318
|
description: Lightweight JSON logger and formatter integrating with Rails/ActiveSupport.
|
|
305
|
-
No extra deps beyond Rails/Activesupport. Compatible with Rails
|
|
319
|
+
No extra deps beyond Rails/Activesupport. Compatible with Rails 7–8.
|
|
306
320
|
email:
|
|
307
321
|
- contact@kiskolabs.com
|
|
308
322
|
executables: []
|
|
@@ -315,15 +329,21 @@ files:
|
|
|
315
329
|
- lib/activesupport/json_logging.rb
|
|
316
330
|
- lib/activesupport/json_logging/railtie.rb
|
|
317
331
|
- lib/json_logging.rb
|
|
332
|
+
- lib/json_logging/event_subscriber.rb
|
|
318
333
|
- lib/json_logging/formatter.rb
|
|
319
334
|
- lib/json_logging/formatter_with_tags.rb
|
|
320
335
|
- lib/json_logging/helpers.rb
|
|
321
336
|
- lib/json_logging/json_logger.rb
|
|
322
337
|
- lib/json_logging/json_logger_extension.rb
|
|
338
|
+
- lib/json_logging/line_encoder.rb
|
|
323
339
|
- lib/json_logging/message_parser.rb
|
|
324
340
|
- lib/json_logging/payload_builder.rb
|
|
325
341
|
- lib/json_logging/sanitizer.rb
|
|
342
|
+
- lib/json_logging/severity.rb
|
|
343
|
+
- lib/json_logging/structured_hash_json_encoder.rb
|
|
344
|
+
- lib/json_logging/structured_hash_sanitizer.rb
|
|
326
345
|
- lib/json_logging/version.rb
|
|
346
|
+
- sig/json_logging.rbs
|
|
327
347
|
homepage: https://github.com/amkisko/activesupport-json_logging.rb
|
|
328
348
|
licenses:
|
|
329
349
|
- MIT
|
|
@@ -338,14 +358,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
338
358
|
requirements:
|
|
339
359
|
- - ">="
|
|
340
360
|
- !ruby/object:Gem::Version
|
|
341
|
-
version: '2
|
|
361
|
+
version: '3.2'
|
|
342
362
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
343
363
|
requirements:
|
|
344
364
|
- - ">="
|
|
345
365
|
- !ruby/object:Gem::Version
|
|
346
366
|
version: '0'
|
|
347
367
|
requirements: []
|
|
348
|
-
rubygems_version: 4.0.
|
|
368
|
+
rubygems_version: 4.0.6
|
|
349
369
|
specification_version: 4
|
|
350
370
|
summary: Structured JSON logging for Rails/ActiveSupport with safe, single-line entries.
|
|
351
371
|
test_files: []
|