julewire-rails 1.0.0 → 1.1.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 +12 -0
- data/docs/capture-and-filtering.md +4 -3
- data/docs/configuration.md +3 -2
- data/julewire-rails.gemspec +3 -3
- data/lib/julewire/rails/configuration.rb +4 -4
- data/lib/julewire/rails/context_body_proxy.rb +8 -3
- data/lib/julewire/rails/debug_exception_log_silencer.rb +9 -18
- data/lib/julewire/rails/doctor_app.rb +21 -21
- data/lib/julewire/rails/lifecycle_hooks.rb +0 -11
- data/lib/julewire/rails/log_subscriber_silencer.rb +4 -17
- data/lib/julewire/rails/logger.rb +29 -24
- data/lib/julewire/rails/logger_outputs.rb +0 -3
- data/lib/julewire/rails/output_requirement.rb +2 -2
- data/lib/julewire/rails/parameter_filter_plan.rb +13 -37
- data/lib/julewire/rails/parameter_filter_processor.rb +13 -45
- data/lib/julewire/rails/parameter_filters.rb +21 -0
- data/lib/julewire/rails/railtie.rb +42 -28
- data/lib/julewire/rails/request_attributes.rb +37 -16
- data/lib/julewire/rails/request_completion.rb +21 -20
- data/lib/julewire/rails/request_context.rb +29 -7
- data/lib/julewire/rails/request_error_ownership.rb +11 -19
- data/lib/julewire/rails/request_fields.rb +2 -2
- data/lib/julewire/rails/request_lifecycle.rb +7 -13
- data/lib/julewire/rails/request_middleware.rb +14 -13
- data/lib/julewire/rails/request_summary_timeout_scheduler.rb +0 -9
- data/lib/julewire/rails/structured_event_record.rb +11 -39
- data/lib/julewire/rails/subscribers/controller_response.rb +9 -14
- data/lib/julewire/rails/subscribers/error.rb +11 -15
- data/lib/julewire/rails/subscribers/event.rb +6 -8
- data/lib/julewire/rails/subscribers/rendered_exception.rb +12 -16
- data/lib/julewire/rails/version.rb +1 -1
- metadata +9 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0788f684a45eba2f940fb5a836cb45c7aef84ae6c67d68da62c2e38e4376dcae'
|
|
4
|
+
data.tar.gz: 72559f89728d55e90a231d25d3bc60a37453fcbaec0f0c8c5e21728547e0cb5b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 137c77cfabe1a91768ce04b7df57e1c00d44f4ec97103fa21ce5ebc333e48135d034ebaead86dfd9ce945d43aa0a834c0a6f3027d4b63da0c440172c842882d5
|
|
7
|
+
data.tar.gz: 7190bcf29e2aa09995ee3728c9102b25b24ed89ed8d0597c0d51e0de4fe2a1d27c4e8f8e3a20ac7b277a7f9f73c2dc60e8c6faae778c595824a5ead78883288f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
## Unreleased
|
|
2
2
|
|
|
3
|
+
## 1.1.0 - 2026-07-20
|
|
4
|
+
|
|
5
|
+
- Roll back pushed request tags when request instrumentation fails during
|
|
6
|
+
middleware startup.
|
|
7
|
+
- Harden request logging, filtering, suppression, and error ownership around
|
|
8
|
+
Julewire 1.1 record contracts.
|
|
9
|
+
- Require Julewire 1.1.0 internal gems.
|
|
10
|
+
|
|
11
|
+
## 1.0.1 - 2026-06-25
|
|
12
|
+
|
|
13
|
+
- Require julewire 1.0.1 internal gems.
|
|
14
|
+
|
|
3
15
|
## 1.0.0 - 2026-06-21
|
|
4
16
|
|
|
5
17
|
- Initial release: Rails request summaries, structured events, error capture,
|
|
@@ -31,8 +31,8 @@ Captured response summaries include:
|
|
|
31
31
|
- `response_body_bytes`
|
|
32
32
|
- `response_body_truncated`
|
|
33
33
|
|
|
34
|
-
`*_body_bytes` is the content length
|
|
35
|
-
|
|
34
|
+
`*_body_bytes` is the declared content length or the bytes observed while
|
|
35
|
+
capturing. When both are known, Julewire reports the larger value.
|
|
36
36
|
|
|
37
37
|
Request and response headers use `false`, `true`, or an explicit header list:
|
|
38
38
|
|
|
@@ -48,7 +48,8 @@ end
|
|
|
48
48
|
When header capture is `true`, Julewire omits common sensitive headers such as
|
|
49
49
|
`authorization`, `cookie`, `set-cookie`, `proxy-authorization`, and
|
|
50
50
|
`x-api-key`. Use an explicit header list if the application deliberately wants
|
|
51
|
-
one of those fields.
|
|
51
|
+
one of those fields. Treat `headers = true` as controlled debugging; production
|
|
52
|
+
configs should prefer explicit allowlists.
|
|
52
53
|
|
|
53
54
|
Captured request summaries can include:
|
|
54
55
|
|
data/docs/configuration.md
CHANGED
|
@@ -38,8 +38,9 @@ These defaults are intended for a normal Rails app:
|
|
|
38
38
|
| `filter_event_payloads` | `true` | Filter serialized object-event hashes with Rails parameter filters. |
|
|
39
39
|
| `rendered_exceptions` | `false` | Emit diagnostic rendered-exception point records in addition to summaries. |
|
|
40
40
|
|
|
41
|
-
Broad header capture (`*.headers = true`) skips common sensitive headers
|
|
42
|
-
|
|
41
|
+
Broad header capture (`*.headers = true`) skips common sensitive headers but is
|
|
42
|
+
still a debugging shape. Production configs should prefer explicit header
|
|
43
|
+
lists.
|
|
43
44
|
|
|
44
45
|
`structured_event_prefixes = nil` accepts all structured-event names. Use it
|
|
45
46
|
only when the app wants Julewire to consider every Rails event.
|
data/julewire-rails.gemspec
CHANGED
|
@@ -35,9 +35,9 @@ Gem::Specification.new do |spec|
|
|
|
35
35
|
|
|
36
36
|
spec.add_dependency "actionpack", ">= 8.1"
|
|
37
37
|
spec.add_dependency "actionview", ">= 8.1"
|
|
38
|
-
spec.add_dependency "julewire-core", ">= 1.0"
|
|
39
|
-
spec.add_dependency "julewire-rack", ">= 1.0"
|
|
40
|
-
spec.add_dependency "julewire-rails_support", ">= 1.0"
|
|
38
|
+
spec.add_dependency "julewire-core", ">= 1.1.0"
|
|
39
|
+
spec.add_dependency "julewire-rack", ">= 1.1.0"
|
|
40
|
+
spec.add_dependency "julewire-rails_support", ">= 1.1.0"
|
|
41
41
|
spec.add_dependency "logger", ">= 1.7"
|
|
42
42
|
spec.add_dependency "railties", ">= 8.1"
|
|
43
43
|
spec.add_dependency "zeitwerk", ">= 2.8.1"
|
|
@@ -46,14 +46,14 @@ module Julewire
|
|
|
46
46
|
private
|
|
47
47
|
|
|
48
48
|
def validate_carry_request_headers(value)
|
|
49
|
-
return
|
|
49
|
+
return unless value == true
|
|
50
50
|
|
|
51
51
|
raise Error, "carry_request_headers must be an explicit header list"
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def validate_request_summary_timeout(value)
|
|
55
|
-
return
|
|
56
|
-
return
|
|
55
|
+
return if value.nil?
|
|
56
|
+
return if value.is_a?(Numeric) && value.positive?
|
|
57
57
|
|
|
58
58
|
raise Error, "request_summary_timeout must be nil or a positive Numeric"
|
|
59
59
|
end
|
|
@@ -67,7 +67,7 @@ module Julewire
|
|
|
67
67
|
|
|
68
68
|
def validate_capture_settings(settings)
|
|
69
69
|
settings.validate!
|
|
70
|
-
|
|
70
|
+
nil
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
end
|
|
@@ -11,7 +11,7 @@ module Julewire
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def each(&block)
|
|
14
|
-
return enum_for
|
|
14
|
+
return enum_for unless block_given?
|
|
15
15
|
|
|
16
16
|
@handle.with_context do
|
|
17
17
|
@body.each { block.yield(it) }
|
|
@@ -31,8 +31,13 @@ module Julewire
|
|
|
31
31
|
|
|
32
32
|
def closed? = @closed
|
|
33
33
|
|
|
34
|
-
def respond_to_missing?(method_name,
|
|
35
|
-
|
|
34
|
+
def respond_to_missing?(method_name, _include_private)
|
|
35
|
+
case method_name
|
|
36
|
+
when :to_str
|
|
37
|
+
false
|
|
38
|
+
else
|
|
39
|
+
@body.respond_to?(method_name)
|
|
40
|
+
end
|
|
36
41
|
end
|
|
37
42
|
|
|
38
43
|
def method_missing(method_name, ...)
|
|
@@ -5,9 +5,9 @@ require "action_dispatch/middleware/debug_exceptions"
|
|
|
5
5
|
module Julewire
|
|
6
6
|
module Rails
|
|
7
7
|
module DebugExceptionLogSilencer
|
|
8
|
-
Patch
|
|
8
|
+
module Patch
|
|
9
9
|
def log_error(request, wrapper)
|
|
10
|
-
return if
|
|
10
|
+
return if DebugExceptionLogSilencer.suppress?
|
|
11
11
|
|
|
12
12
|
super
|
|
13
13
|
end
|
|
@@ -17,26 +17,11 @@ module Julewire
|
|
|
17
17
|
class << self
|
|
18
18
|
def install!(configuration)
|
|
19
19
|
@configuration = configuration
|
|
20
|
-
return false unless defined?(::ActionDispatch::DebugExceptions)
|
|
21
|
-
return true if @installed
|
|
22
20
|
|
|
23
21
|
::ActionDispatch::DebugExceptions.prepend(Patch)
|
|
24
|
-
@installed = true
|
|
25
22
|
end
|
|
26
23
|
|
|
27
|
-
def suppress?
|
|
28
|
-
suppress_reported_logs?
|
|
29
|
-
rescue StandardError => e
|
|
30
|
-
IntegrationHealth.record_failure(
|
|
31
|
-
e,
|
|
32
|
-
action: :suppress?,
|
|
33
|
-
component: :debug_exception_log_silencer
|
|
34
|
-
)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
def suppress_reported_logs?
|
|
24
|
+
def suppress?
|
|
40
25
|
configuration = @configuration
|
|
41
26
|
return false unless configuration
|
|
42
27
|
|
|
@@ -46,6 +31,12 @@ module Julewire
|
|
|
46
31
|
else
|
|
47
32
|
!configuration.reported_exception_logs
|
|
48
33
|
end
|
|
34
|
+
rescue StandardError => e
|
|
35
|
+
IntegrationHealth.record_failure(
|
|
36
|
+
e,
|
|
37
|
+
action: :suppress?,
|
|
38
|
+
component: :debug_exception_log_silencer
|
|
39
|
+
)
|
|
49
40
|
end
|
|
50
41
|
end
|
|
51
42
|
end
|
|
@@ -67,8 +67,8 @@ module Julewire
|
|
|
67
67
|
"Julewire Doctor",
|
|
68
68
|
[
|
|
69
69
|
"<p>Status: <strong>#{escape(report.fetch(:status))}</strong></p>",
|
|
70
|
-
"<p>Level: <code>#{escape(report.
|
|
71
|
-
"<p>Pipeline: <strong>#{escape(report.
|
|
70
|
+
"<p>Level: <code>#{escape(report.fetch(:runtime).fetch(:level))}</code></p>",
|
|
71
|
+
"<p>Pipeline: <strong>#{escape(report.fetch(:pipeline).fetch(:status))}</strong></p>",
|
|
72
72
|
"<h2>Warnings</h2>",
|
|
73
73
|
warning_items.empty? ? "<p>None</p>" : "<ul>#{warning_items}</ul>",
|
|
74
74
|
nav_links(request, ["/tail", "Tail"], ["/doctor.json", "JSON"])
|
|
@@ -79,14 +79,15 @@ module Julewire
|
|
|
79
79
|
def render_tail(request)
|
|
80
80
|
return page("Julewire Tail", "<p>Tail is not attached.</p>") unless @tail
|
|
81
81
|
|
|
82
|
+
table = <<~HTML
|
|
83
|
+
<table><thead><tr><th>Severity</th><th>Event</th><th>Message</th></tr></thead>
|
|
84
|
+
<tbody data-tail-records data-tail-events-path="#{escape(app_path(request, "/tail/events"))}">
|
|
85
|
+
#{tail_rows}
|
|
86
|
+
</tbody></table>
|
|
87
|
+
HTML
|
|
82
88
|
body = [
|
|
83
89
|
"<p>#{@tail.health.fetch(:size)} / #{@tail.capacity} records</p>",
|
|
84
|
-
|
|
85
|
-
"<table><thead><tr><th>Severity</th><th>Event</th><th>Message</th></tr></thead>",
|
|
86
|
-
%(<tbody data-tail-records data-tail-events-path="#{escape(app_path(request, "/tail/events"))}">),
|
|
87
|
-
tail_rows,
|
|
88
|
-
"</tbody></table>"
|
|
89
|
-
].join,
|
|
90
|
+
table,
|
|
90
91
|
tail_nav(request),
|
|
91
92
|
tail_script
|
|
92
93
|
].join
|
|
@@ -99,13 +100,11 @@ module Julewire
|
|
|
99
100
|
|
|
100
101
|
def tail_row(entry)
|
|
101
102
|
record = entry.record
|
|
102
|
-
|
|
103
|
-
"<
|
|
104
|
-
"<td><code>#{escape(record["
|
|
105
|
-
"<td
|
|
106
|
-
"<td>#{escape(record["message"])}</td>",
|
|
103
|
+
"<tr data-sequence=\"#{entry.sequence}\">" \
|
|
104
|
+
"<td><code>#{escape(record["severity"])}</code></td>" \
|
|
105
|
+
"<td><code>#{escape(record["event"])}</code></td>" \
|
|
106
|
+
"<td>#{escape(record["message"])}</td>" \
|
|
107
107
|
"</tr>"
|
|
108
|
-
].join
|
|
109
108
|
end
|
|
110
109
|
|
|
111
110
|
def tail_nav(request)
|
|
@@ -117,7 +116,7 @@ module Julewire
|
|
|
117
116
|
end
|
|
118
117
|
|
|
119
118
|
def tail_entries
|
|
120
|
-
@tail
|
|
119
|
+
@tail.entries(limit: TAIL_LIMIT)
|
|
121
120
|
end
|
|
122
121
|
|
|
123
122
|
def tail_events(request)
|
|
@@ -135,7 +134,7 @@ module Julewire
|
|
|
135
134
|
def event_cursor(request)
|
|
136
135
|
value = request.get_header("HTTP_LAST_EVENT_ID")
|
|
137
136
|
value = request.params["after"] if value.nil? || value.empty?
|
|
138
|
-
Integer(value
|
|
137
|
+
Integer(value)
|
|
139
138
|
rescue ArgumentError, TypeError
|
|
140
139
|
0
|
|
141
140
|
end
|
|
@@ -190,8 +189,9 @@ module Julewire
|
|
|
190
189
|
end
|
|
191
190
|
|
|
192
191
|
def app_path(request, path)
|
|
193
|
-
base = request.script_name
|
|
194
|
-
|
|
192
|
+
base = request.script_name
|
|
193
|
+
return path if base == "/"
|
|
194
|
+
|
|
195
195
|
"#{base}#{path}"
|
|
196
196
|
end
|
|
197
197
|
|
|
@@ -200,7 +200,7 @@ module Julewire
|
|
|
200
200
|
end
|
|
201
201
|
|
|
202
202
|
def link_to(request, path, label)
|
|
203
|
-
%(<a href="#{escape(app_path(request, path))}">#{
|
|
203
|
+
%(<a href="#{escape(app_path(request, path))}">#{label}</a>)
|
|
204
204
|
end
|
|
205
205
|
|
|
206
206
|
def page(title, body)
|
|
@@ -209,7 +209,7 @@ module Julewire
|
|
|
209
209
|
<html>
|
|
210
210
|
<head>
|
|
211
211
|
<meta charset="utf-8">
|
|
212
|
-
<title>#{
|
|
212
|
+
<title>#{title}</title>
|
|
213
213
|
<style>
|
|
214
214
|
body { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; margin: 2rem; color: #171717; }
|
|
215
215
|
a { color: #0b5fff; margin-right: 1rem; }
|
|
@@ -218,7 +218,7 @@ module Julewire
|
|
|
218
218
|
</style>
|
|
219
219
|
</head>
|
|
220
220
|
<body>
|
|
221
|
-
<h1>#{
|
|
221
|
+
<h1>#{title}</h1>
|
|
222
222
|
#{body}
|
|
223
223
|
</body>
|
|
224
224
|
</html>
|
|
@@ -29,18 +29,8 @@ module Julewire
|
|
|
29
29
|
RequestErrorOwnership.clear
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
# Private testing seam for isolating process lifecycle hooks.
|
|
33
|
-
def reset_for_test!
|
|
34
|
-
@mutex.synchronize do
|
|
35
|
-
@at_exit_installed = false
|
|
36
|
-
@fork_tracker_installed = false
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
32
|
private
|
|
41
33
|
|
|
42
|
-
private :reset_for_test!
|
|
43
|
-
|
|
44
34
|
def install_at_exit!(registrar, configuration)
|
|
45
35
|
return if @at_exit_installed
|
|
46
36
|
|
|
@@ -64,7 +54,6 @@ module Julewire
|
|
|
64
54
|
action: :install_after_fork,
|
|
65
55
|
component: :lifecycle_hooks
|
|
66
56
|
)
|
|
67
|
-
nil
|
|
68
57
|
end
|
|
69
58
|
|
|
70
59
|
def active_support_fork_tracker
|
|
@@ -22,7 +22,10 @@ module Julewire
|
|
|
22
22
|
class << self
|
|
23
23
|
def silence!
|
|
24
24
|
require_log_subscribers
|
|
25
|
-
SUBSCRIBERS.each
|
|
25
|
+
SUBSCRIBERS.each do |class_name, namespace|
|
|
26
|
+
subscriber_class = Julewire::RailsSupport::LogSubscribers.constantize(class_name)
|
|
27
|
+
Julewire::RailsSupport::LogSubscribers.detach(subscriber_class, namespace)
|
|
28
|
+
end
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
private
|
|
@@ -30,22 +33,6 @@ module Julewire
|
|
|
30
33
|
def require_log_subscribers
|
|
31
34
|
LOG_SUBSCRIBER_FILES.each { Core::Integration::Lifecycle.require_optional(it) }
|
|
32
35
|
end
|
|
33
|
-
|
|
34
|
-
def detach(class_name, namespace)
|
|
35
|
-
subscriber_class = constantize(class_name)
|
|
36
|
-
return if subscriber_class.nil?
|
|
37
|
-
|
|
38
|
-
subscriber_class.detach_from(namespace) if subscriber_class.respond_to?(:detach_from)
|
|
39
|
-
Julewire::RailsSupport::EventReporter.unsubscribe_log_subscriber(subscriber_class)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def constantize(class_name)
|
|
43
|
-
class_name.split("::").reject(&:empty?).inject(Object) do |namespace, constant_name|
|
|
44
|
-
break unless namespace.const_defined?(constant_name, false)
|
|
45
|
-
|
|
46
|
-
namespace.const_get(constant_name, false)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
36
|
end
|
|
50
37
|
end
|
|
51
38
|
end
|
|
@@ -24,13 +24,13 @@ module Julewire
|
|
|
24
24
|
return true if severity < level
|
|
25
25
|
return true if Suppression.active?
|
|
26
26
|
|
|
27
|
-
message, progname = resolve_message_and_progname(message, progname) {
|
|
28
|
-
Core::RuntimeLocator.current.emit_without_level(record_for(severity, message, progname))
|
|
27
|
+
message, progname = resolve_message_and_progname(message, progname) { yield if block_given? }
|
|
28
|
+
Julewire::Core::RuntimeLocator.current.emit_without_level(record_for(severity, message, progname))
|
|
29
29
|
true
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def <<(message)
|
|
33
|
-
add(
|
|
33
|
+
add(nil, message)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def debug(progname = nil, &) = add(::Logger::DEBUG, nil, progname, &)
|
|
@@ -43,7 +43,7 @@ module Julewire
|
|
|
43
43
|
|
|
44
44
|
def fatal(progname = nil, &) = add(::Logger::FATAL, nil, progname, &)
|
|
45
45
|
|
|
46
|
-
def unknown(progname = nil, &) = add(
|
|
46
|
+
def unknown(progname = nil, &) = add(nil, nil, progname, &)
|
|
47
47
|
|
|
48
48
|
def debug? = level <= ::Logger::DEBUG
|
|
49
49
|
|
|
@@ -104,9 +104,8 @@ module Julewire
|
|
|
104
104
|
Julewire.flush
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
-
def initialize_copy(
|
|
108
|
-
|
|
109
|
-
@progname = other.progname.is_a?(String) ? other.progname.dup : other.progname
|
|
107
|
+
def initialize_copy(_other)
|
|
108
|
+
@progname = @progname.dup if @progname.is_a?(String)
|
|
110
109
|
@local_level_key = :"julewire_rails_logger_level_#{object_id}"
|
|
111
110
|
end
|
|
112
111
|
|
|
@@ -117,31 +116,41 @@ module Julewire
|
|
|
117
116
|
when Integer
|
|
118
117
|
value
|
|
119
118
|
when Symbol, String
|
|
120
|
-
::Logger::Severity.const_get(value.
|
|
119
|
+
::Logger::Severity.const_get(value.upcase)
|
|
121
120
|
else
|
|
122
|
-
|
|
121
|
+
raise_invalid_level(value)
|
|
123
122
|
end
|
|
124
123
|
rescue NameError
|
|
124
|
+
raise_invalid_level(value)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def raise_invalid_level(value)
|
|
125
128
|
raise ArgumentError, "invalid log level: #{value.inspect}"
|
|
126
129
|
end
|
|
127
130
|
|
|
128
131
|
def resolve_message_and_progname(message, progname)
|
|
129
|
-
return [message, progname
|
|
132
|
+
return [message, progname] unless message.nil?
|
|
130
133
|
|
|
131
134
|
block_message = yield
|
|
132
|
-
return [block_message, progname
|
|
135
|
+
return [block_message, progname] unless block_message.nil?
|
|
133
136
|
|
|
134
|
-
[progname
|
|
137
|
+
[progname]
|
|
135
138
|
end
|
|
136
139
|
|
|
137
140
|
def record_for(severity, message, progname)
|
|
138
141
|
record = message.is_a?(Hash) ? structured_message(message) : scalar_message(message)
|
|
139
|
-
record[:severity] =
|
|
140
|
-
record[:logger] ||= (progname ||
|
|
142
|
+
record[:severity] = record_severity(severity)
|
|
143
|
+
record[:logger] ||= (progname || @progname).to_s
|
|
141
144
|
record[:source] ||= @source
|
|
142
145
|
merge_current_tags(record)
|
|
143
146
|
end
|
|
144
147
|
|
|
148
|
+
def record_severity(value)
|
|
149
|
+
Julewire::Core::Records::Severity.normalize(value)
|
|
150
|
+
rescue ArgumentError
|
|
151
|
+
:unknown
|
|
152
|
+
end
|
|
153
|
+
|
|
145
154
|
def scalar_message(message)
|
|
146
155
|
case message
|
|
147
156
|
when Exception
|
|
@@ -156,28 +165,24 @@ module Julewire
|
|
|
156
165
|
record = fields.slice(*RECORD_KEYS)
|
|
157
166
|
payload = fields.except(*RECORD_KEYS)
|
|
158
167
|
|
|
159
|
-
|
|
160
|
-
record[:payload] = Julewire::Core::Fields::FieldSet.merge(payload_hash(record[:payload]), payload)
|
|
161
|
-
end
|
|
168
|
+
record[:payload] = Julewire::Core::Fields::FieldSet.merge(payload_hash(record[:payload]), payload)
|
|
162
169
|
record
|
|
163
170
|
end
|
|
164
171
|
|
|
165
172
|
def payload_hash(payload)
|
|
166
173
|
return {} if payload.nil?
|
|
167
|
-
return payload if payload.
|
|
174
|
+
return payload if payload.instance_of?(Hash)
|
|
168
175
|
|
|
169
176
|
{ Julewire::Core::Fields::FieldSet::VALUE_KEY => payload }
|
|
170
177
|
end
|
|
171
178
|
|
|
172
179
|
def merge_current_tags(record)
|
|
173
|
-
current_tags = formatter.respond_to?(:current_tags)
|
|
180
|
+
current_tags = formatter.current_tags if formatter.respond_to?(:current_tags)
|
|
174
181
|
return record if current_tags.nil? || current_tags.empty?
|
|
175
182
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
attributes[:rails] = rails
|
|
180
|
-
record[:attributes] = attributes
|
|
183
|
+
record[:attributes] = {
|
|
184
|
+
rails: { tags: current_tags }
|
|
185
|
+
}
|
|
181
186
|
record
|
|
182
187
|
end
|
|
183
188
|
end
|
|
@@ -11,7 +11,7 @@ module Julewire
|
|
|
11
11
|
return unless settings.logger?
|
|
12
12
|
|
|
13
13
|
mode = normalized_mode(settings.require_output)
|
|
14
|
-
return if
|
|
14
|
+
return if health.dig(:pipeline, :configured)
|
|
15
15
|
|
|
16
16
|
case mode
|
|
17
17
|
when :warn
|
|
@@ -25,7 +25,7 @@ module Julewire
|
|
|
25
25
|
|
|
26
26
|
def normalized_mode(value)
|
|
27
27
|
case value
|
|
28
|
-
when false, nil then
|
|
28
|
+
when false, nil then nil
|
|
29
29
|
when true, :warn, "warn" then :warn
|
|
30
30
|
when :raise, "raise" then :raise
|
|
31
31
|
else
|
|
@@ -4,32 +4,31 @@ module Julewire
|
|
|
4
4
|
module Rails
|
|
5
5
|
class ParameterFilterPlan
|
|
6
6
|
FILTERED = ::ActiveSupport::ParameterFilter::FILTERED
|
|
7
|
-
RECORD_CONTAINER_KEYS = Core::Processing::RecordFieldTransform.container_keys
|
|
8
|
-
RECORD_SCALAR_KEYS = Core::Processing::RecordFieldTransform.scalar_keys
|
|
9
7
|
private_constant :FILTERED
|
|
10
|
-
private_constant :RECORD_CONTAINER_KEYS
|
|
11
|
-
private_constant :RECORD_SCALAR_KEYS
|
|
12
|
-
|
|
13
|
-
attr_reader :filtered_field_keys
|
|
14
8
|
|
|
15
9
|
class << self
|
|
16
10
|
def build(filters)
|
|
17
11
|
filters = Array(filters)
|
|
18
12
|
return if filters.any? { it.is_a?(Regexp) || it.is_a?(Proc) }
|
|
19
13
|
|
|
20
|
-
|
|
14
|
+
simple, deep = partition_filters(filters)
|
|
15
|
+
return unless simple.any? && deep.empty?
|
|
16
|
+
|
|
17
|
+
new(simple)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def partition_filters(filters)
|
|
23
|
+
filters.map { it.to_s.downcase }.partition { !it.include?(".") }
|
|
21
24
|
end
|
|
22
25
|
end
|
|
26
|
+
private_class_method :new
|
|
23
27
|
|
|
24
28
|
def initialize(filters)
|
|
25
|
-
|
|
26
|
-
@filtered_field_keys = build_filtered_field_keys(simple, deep)
|
|
27
|
-
@direct_container_filter = simple.any? && deep.empty?
|
|
28
|
-
@simple_pattern = simple_filter_pattern(simple) if @direct_container_filter
|
|
29
|
+
@simple_pattern = simple_filter_pattern(filters)
|
|
29
30
|
end
|
|
30
31
|
|
|
31
|
-
def direct_container_filter? = @direct_container_filter
|
|
32
|
-
|
|
33
32
|
def filter_value(value)
|
|
34
33
|
return filter_hash(value) if value.is_a?(Hash)
|
|
35
34
|
return filter_array(value) if value.is_a?(Array)
|
|
@@ -39,27 +38,6 @@ module Julewire
|
|
|
39
38
|
|
|
40
39
|
private
|
|
41
40
|
|
|
42
|
-
def partition_filters(filters)
|
|
43
|
-
filters.map { it.to_s.downcase }.partition { !it.include?(".") }
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def build_filtered_field_keys(simple, deep)
|
|
47
|
-
(container_filter_keys(simple, deep) + scalar_filter_keys(simple)).uniq.freeze
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def container_filter_keys(simple, deep)
|
|
51
|
-
return RECORD_CONTAINER_KEYS if simple.any?
|
|
52
|
-
|
|
53
|
-
deep.filter_map { it.split(".", 2).first&.to_sym }
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def scalar_filter_keys(simple)
|
|
57
|
-
RECORD_SCALAR_KEYS.filter do |key|
|
|
58
|
-
name = key_name(key)
|
|
59
|
-
simple.any? { name.include?(it) }
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
41
|
def simple_filter_pattern(filters)
|
|
64
42
|
Regexp.new(filters.map { Regexp.escape(it) }.join("|"), Regexp::IGNORECASE)
|
|
65
43
|
end
|
|
@@ -92,9 +70,7 @@ module Julewire
|
|
|
92
70
|
@simple_pattern.match?(key_name(key))
|
|
93
71
|
end
|
|
94
72
|
|
|
95
|
-
def key_name(key)
|
|
96
|
-
key.is_a?(Symbol) ? key.name : key.to_s
|
|
97
|
-
end
|
|
73
|
+
def key_name(key) = key.to_s
|
|
98
74
|
end
|
|
99
75
|
end
|
|
100
76
|
end
|