eventhub-processor2 1.28.1 → 1.29.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/.github/workflows/01_test.yml +1 -1
- data/.github/workflows/02_test_build_and_release.yml +2 -2
- data/.tool-versions +1 -1
- data/CHANGELOG.md +12 -0
- data/README.md +52 -5
- data/eventhub-processor2.gemspec +1 -1
- data/lib/eventhub/actor_listener_amqp.rb +6 -0
- data/lib/eventhub/actor_listener_http.rb +3 -4
- data/lib/eventhub/correlation_id.rb +12 -10
- data/lib/eventhub/docs_renderer.rb +36 -25
- data/lib/eventhub/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 84f9fe3b6c2f1eca60c496eb71a647df7f9fc08f4841475cf26b65ff4fc024a6
|
|
4
|
+
data.tar.gz: ae79889b953ff8af2c9efbd87c396d645fe803153b20a4a56fcc952c64d40214
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cdb5378dc754624ec452602fea4eb4cefe7e50e074491d7d48f4d2ae0f7b4fa07839d31e29fecae53c4c2f5836a9010891cd9045e30af4e03e1cdef40892aa4c
|
|
7
|
+
data.tar.gz: 956bf56d3b193ab891c393b7fa56151b22cdfd31222c4ce66ab6f9d18d9edee860d54eca98cb68264185cf797c71257447dc773ff9006d8d31e8bc94f462e9ff
|
|
@@ -13,7 +13,7 @@ jobs:
|
|
|
13
13
|
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
|
14
14
|
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
16
|
+
- uses: actions/checkout@v7
|
|
17
17
|
|
|
18
18
|
- name: Set up Ruby
|
|
19
19
|
uses: ruby/setup-ruby@v1
|
|
@@ -41,7 +41,7 @@ jobs:
|
|
|
41
41
|
|
|
42
42
|
steps:
|
|
43
43
|
- name: Checkout current code
|
|
44
|
-
uses: actions/checkout@
|
|
44
|
+
uses: actions/checkout@v7
|
|
45
45
|
with:
|
|
46
46
|
ref: main
|
|
47
47
|
|
data/.tool-versions
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby 4.0.
|
|
1
|
+
ruby 4.0.6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog of EventHub::Processor2
|
|
2
2
|
|
|
3
|
+
# 1.29.0 / 2026-08-26
|
|
4
|
+
|
|
5
|
+
* Docs configuration page: sensitive keys now match by substring with an extended default list (e.g. `base_url`, `api_port` are redacted automatically). Exceptions like `vhost` stay visible and can be customized via `non_sensitive_keys`, analogous to `sensitive_keys`. See README for details.
|
|
6
|
+
* Docs configuration page: redaction keeps hash/array structures visible and masks only the scalar values inside.
|
|
7
|
+
* Test coverage raised to 100% lines; removed a dead duplicate route mount in the HTTP listener.
|
|
8
|
+
|
|
9
|
+
# 1.28.2 / 2026-05-20
|
|
10
|
+
|
|
11
|
+
* Fix `CorrelationId.current` leaking across messages on the same Bunny consumer thread. `CorrelationId.with` now always saves and restores, even when called with nil/empty. Symptom in production: deadletter messages stamped with an earlier message's `execution_id`.
|
|
12
|
+
* Listener now also resets `correlation_id` after each message (extra safety on top of the fix above, in case some future code writes it outside of `CorrelationId.with`).
|
|
13
|
+
* README: clarify `correlation_id` is the AMQP **property** (envelope-level), not a custom field in the headers table. Producers must set the property; a header named `correlation_id` is invisible to the gem.
|
|
14
|
+
|
|
3
15
|
# 1.28.1 / 2026-05-19
|
|
4
16
|
|
|
5
17
|
* Fix `LoggerProxy` double-wrapping when callers pass a Hash to a logger method. Hash inputs are now merged (not nested under `:message`), so the resulting structured event has the caller's fields at the top level - restoring the behaviour that existed before `LoggerProxy` was introduced in 1.26.0, while keeping automatic thread-local injection of `correlation_id` and `execution_id`. Caller-provided values win over thread-locals via `||=`.
|
data/README.md
CHANGED
|
@@ -117,6 +117,31 @@ I, [2018-02-09T15:22:35.658522 #37966] INFO -- : Listener is starting...
|
|
|
117
117
|
I, [2018-02-09T15:22:35.699161 #37966] INFO -- : Listening to queue [example]
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
+
## Concurrency Model
|
|
121
|
+
|
|
122
|
+
Processor2 runs **one consumer thread per queue** listed in `listener_queues`. Each consumer holds a Bunny worker thread with `prefetch(1)`, so it processes its messages sequentially. Multiple queues run their consumers in parallel.
|
|
123
|
+
|
|
124
|
+
| `listener_queues` | Concurrency |
|
|
125
|
+
|-------------------------------|------------------------------------------------|
|
|
126
|
+
| `["q1"]` | 1 consumer thread, sequential |
|
|
127
|
+
| `["q1", "q2"]` | 2 consumer threads, parallel (one per queue) |
|
|
128
|
+
| `["q1", "q1", "q1"]` | 3 consumer threads, all on the same queue |
|
|
129
|
+
|
|
130
|
+
To increase throughput for a single queue, either list it multiple times in `listener_queues` (each entry gets its own consumer thread) or run multiple processes. The single-process / single-consumer-per-queue model is what the gem is designed for.
|
|
131
|
+
|
|
132
|
+
Correlation context (`correlation_id`, `execution_id`) is held in thread-local storage, so concurrent consumer threads cannot interfere with each other - each message's outbound `correlation_id` is the one it received (or its body's fallback), regardless of what other threads are doing.
|
|
133
|
+
|
|
134
|
+
### A note on `prefetch`
|
|
135
|
+
|
|
136
|
+
The AMQP `prefetch` value is **fixed at 1** and not currently exposed via configuration. Raising it would require:
|
|
137
|
+
|
|
138
|
+
- bumping Bunny's `channel.work_pool.size` in lockstep (raising `prefetch` alone only buffers messages in Bunny - it does not add parallelism);
|
|
139
|
+
- pooling or removing `ActorPublisher`'s single-mailbox bottleneck, otherwise N parallel consumers serialize through one publisher;
|
|
140
|
+
- making `handle_message` a thread-safety contract for gem users (today it is implicitly single-threaded - any `@ivar` on the processor class is safe by accident);
|
|
141
|
+
- making `Statistics` and any other shared state thread-safe.
|
|
142
|
+
|
|
143
|
+
These trade-offs change the gem's call-surface contract, so a configurable `prefetch` would be a minor-version feature, not a patch. For now, the supported way to scale a single queue is to list it multiple times in `listener_queues` or run multiple processes.
|
|
144
|
+
|
|
120
145
|
## Logging
|
|
121
146
|
|
|
122
147
|
By default, Processor2 logs to both stdout (standard format) and a logstash file. For containerized environments (Docker, Kubernetes), use the `--console-log-only` option to output structured JSON logs to stdout only:
|
|
@@ -135,10 +160,21 @@ This outputs logs in JSON format suitable for log aggregation systems:
|
|
|
135
160
|
|
|
136
161
|
Processor2 supports automatic propagation of correlation IDs for distributed tracing. While EventHub messages already contain an `execution_id` in the message body for tracing, the AMQP `correlation_id` provides an additional benefit: it's part of the message metadata (envelope), not the payload. This means it's available even when the JSON body is invalid and cannot be parsed - useful for error tracking and debugging malformed messages.
|
|
137
162
|
|
|
138
|
-
|
|
163
|
+
> **Important: `correlation_id` is an AMQP `property`, not a `header`.**
|
|
164
|
+
>
|
|
165
|
+
> In AMQP 0.9.1, `correlation_id` is one of the 14 standard message *properties* (top-level envelope fields, alongside `message_id`, `reply_to`, `content_type`, etc.). The *headers table* is a separate, optional dictionary inside the property block for application-defined fields. They are not interchangeable.
|
|
166
|
+
>
|
|
167
|
+
> Producers must set `correlation_id` as a property. A custom field called `correlation_id` placed inside the headers table is **invisible to this gem** and will silently fall back to the message body's `execution_id`.
|
|
168
|
+
>
|
|
169
|
+
> Concretely:
|
|
170
|
+
> - In Bunny: `channel.default_exchange.publish(payload, correlation_id: "...")` ✅ property
|
|
171
|
+
> - In Bunny: `... publish(payload, headers: { "correlation_id" => "..." })` ❌ custom header, not seen
|
|
172
|
+
> - In the RabbitMQ Management UI's "Publish message" form: set the value in the **Properties** section, not in the **Headers** section. When inspecting a queued message, look at "Properties → correlation_id", not at "Headers".
|
|
173
|
+
|
|
174
|
+
When an incoming AMQP message includes a `correlation_id` in its metadata (as a property):
|
|
139
175
|
|
|
140
176
|
1. **Automatic logging**: All log messages during message processing will include `correlation_id` as a separate field in structured JSON output
|
|
141
|
-
2. **Automatic publishing**: Any messages published during processing will automatically include the same correlation_id
|
|
177
|
+
2. **Automatic publishing**: Any messages published during processing will automatically include the same correlation_id as an AMQP `correlation_id` property (envelope-level, not in the headers table)
|
|
142
178
|
3. **Available in args**: The correlation_id is passed to `handle_message` via `args[:correlation_id]`
|
|
143
179
|
4. **Consistent execution_id**: When creating new messages, `execution_id` is automatically set to match `correlation_id`, ensuring consistent tracing across both AMQP metadata and message body
|
|
144
180
|
|
|
@@ -174,7 +210,7 @@ If no `correlation_id` is present in the AMQP metadata, the message body's `exec
|
|
|
174
210
|
3. **Stored**: The value is stored in thread-local storage (`Thread.current`) for the duration of message processing
|
|
175
211
|
4. **Passed**: The `correlation_id` is passed to `handle_message` via `args[:correlation_id]`
|
|
176
212
|
5. **Logging**: The logger automatically reads from thread-local storage and includes it in JSON output
|
|
177
|
-
6. **Publishing**: The publisher automatically reads from thread-local storage and
|
|
213
|
+
6. **Publishing**: The publisher automatically reads from thread-local storage and sets it as the outgoing AMQP `correlation_id` property (can be overwritten by passing `correlation_id:` explicitly)
|
|
178
214
|
7. **New messages**: When creating a new `EventHub::Message`:
|
|
179
215
|
- With `correlation_id` present → `execution_id` is set to match `correlation_id`
|
|
180
216
|
- Without `correlation_id` → `execution_id` is set to a new UUID (default behavior)
|
|
@@ -463,7 +499,7 @@ end
|
|
|
463
499
|
|
|
464
500
|
### Configuration
|
|
465
501
|
|
|
466
|
-
Displays the active configuration as an HTML table. Sensitive values (passwords, tokens, keys) are automatically redacted at any depth — keys matching the sensitive list are masked whether they appear at the top level, inside nested hashes, or inside hashes nested in arrays.
|
|
502
|
+
Displays the active configuration as an HTML table. Sensitive values (passwords, tokens, keys) are automatically redacted at any depth — keys matching the sensitive list are masked whether they appear at the top level, inside nested hashes, or inside hashes nested in arrays. The structure is always preserved: when a sensitive key holds a hash or array, its keys stay visible and only the scalar values inside are replaced by `***`.
|
|
467
503
|
|
|
468
504
|
```
|
|
469
505
|
GET {base_path}/docs/configuration
|
|
@@ -471,7 +507,7 @@ GET {base_path}/docs/configuration
|
|
|
471
507
|
|
|
472
508
|
**Response:** `200 OK` with HTML page
|
|
473
509
|
|
|
474
|
-
By default, the
|
|
510
|
+
Matching is by substring: a key is redacted if it *contains* one of the sensitive patterns (case-insensitive). By default, the patterns are: `password`, `secret`, `token`, `api_key`, `credential`, `user`, `login`, `host`, `port`, `database`, `instance`, `url`, `endpoint`, `scheme`. So `base_url`, `api_port`, `username`, or `userpwd` are redacted as well. `vhost` is an explicit exception and stays visible, even though it contains `host`. You can customize the list by defining a `sensitive_keys` method in your processor:
|
|
475
511
|
|
|
476
512
|
```ruby
|
|
477
513
|
# Override the entire list
|
|
@@ -489,6 +525,17 @@ class MyProcessor < EventHub::Processor2
|
|
|
489
525
|
end
|
|
490
526
|
```
|
|
491
527
|
|
|
528
|
+
Exceptions work the other way around: keys listed as exceptions are never redacted, even if they match a sensitive pattern. Unlike the patterns, exceptions match the whole key exactly (case-insensitive). The default is `vhost`; you can customize the list by defining a `non_sensitive_keys` method:
|
|
529
|
+
|
|
530
|
+
```ruby
|
|
531
|
+
# Keep username and user visible although they match the user pattern
|
|
532
|
+
class MyProcessor < EventHub::Processor2
|
|
533
|
+
def non_sensitive_keys
|
|
534
|
+
EventHub::DocsRenderer::DEFAULT_NON_SENSITIVE_KEYS + %w[username user]
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
```
|
|
538
|
+
|
|
492
539
|
Or override the entire page by defining a `configuration_as_html` method:
|
|
493
540
|
|
|
494
541
|
```ruby
|
data/eventhub-processor2.gemspec
CHANGED
|
@@ -32,6 +32,6 @@ Gem::Specification.new do |spec|
|
|
|
32
32
|
|
|
33
33
|
spec.add_development_dependency "rake", "~> 13.2"
|
|
34
34
|
spec.add_development_dependency "rspec", "~> 3.13"
|
|
35
|
-
spec.add_development_dependency "simplecov", "~> 0
|
|
35
|
+
spec.add_development_dependency "simplecov", "~> 1.0"
|
|
36
36
|
spec.add_development_dependency "standard", "~> 1.39"
|
|
37
37
|
end
|
|
@@ -90,6 +90,12 @@ module EventHub
|
|
|
90
90
|
" acknowledged")
|
|
91
91
|
ensure
|
|
92
92
|
ExecutionId.clear
|
|
93
|
+
# Belt-and-suspenders: CorrelationId.with's ensure already
|
|
94
|
+
# restores the prior value, but clearing here protects any
|
|
95
|
+
# future code path that writes CorrelationId.current outside
|
|
96
|
+
# of `.with` (e.g. handle_payload's fallback was the original
|
|
97
|
+
# leak source pre-1.28.2).
|
|
98
|
+
CorrelationId.clear
|
|
93
99
|
end
|
|
94
100
|
end
|
|
95
101
|
queue.subscribe_with(consumer, block: false)
|
|
@@ -43,13 +43,12 @@ module EventHub
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def mount_resources
|
|
46
|
-
# Redirect base path to docs
|
|
46
|
+
# Redirect base path to docs. WEBrick normalizes mount points by
|
|
47
|
+
# stripping the trailing slash, so this single mount serves both
|
|
48
|
+
# "#{@base_path}" and "#{@base_path}/".
|
|
47
49
|
@server.mount_proc @base_path do |req, res|
|
|
48
50
|
handle_base_redirect(req, res)
|
|
49
51
|
end
|
|
50
|
-
@server.mount_proc "#{@base_path}/" do |req, res|
|
|
51
|
-
handle_base_redirect(req, res)
|
|
52
|
-
end
|
|
53
52
|
|
|
54
53
|
# API resources
|
|
55
54
|
@server.mount_proc "#{@base_path}/heartbeat" do |req, res|
|
|
@@ -16,18 +16,20 @@ module EventHub
|
|
|
16
16
|
Thread.current[:eventhub_correlation_id] = nil
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
# Execute block with correlation_id set, ensures cleanup
|
|
19
|
+
# Execute block with correlation_id set, ensures cleanup.
|
|
20
|
+
#
|
|
21
|
+
# Always saves the prior value and restores it on exit, even when
|
|
22
|
+
# called with nil/empty - otherwise any value written to `current`
|
|
23
|
+
# inside the block (e.g. handle_payload's fallback to the message
|
|
24
|
+
# body's execution_id) would leak onto the consumer thread and be
|
|
25
|
+
# picked up by the next message's processing.
|
|
20
26
|
def with(correlation_id)
|
|
21
|
-
|
|
27
|
+
old_value = current
|
|
28
|
+
begin
|
|
29
|
+
self.current = correlation_id unless correlation_id.nil? || correlation_id.to_s.empty?
|
|
22
30
|
yield
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
begin
|
|
26
|
-
self.current = correlation_id
|
|
27
|
-
yield
|
|
28
|
-
ensure
|
|
29
|
-
self.current = old_value
|
|
30
|
-
end
|
|
31
|
+
ensure
|
|
32
|
+
self.current = old_value
|
|
31
33
|
end
|
|
32
34
|
end
|
|
33
35
|
end
|
|
@@ -159,29 +159,30 @@ module EventHub
|
|
|
159
159
|
intro + filter + config_to_html_table(config) + script
|
|
160
160
|
end
|
|
161
161
|
|
|
162
|
-
def config_to_html_table(hash, depth = 0, prefix = "")
|
|
162
|
+
def config_to_html_table(hash, depth = 0, prefix = "", redact: false)
|
|
163
163
|
rows = hash.map do |key, value|
|
|
164
164
|
full_key = prefix.empty? ? key.to_s : "#{prefix}.#{key}"
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
elsif depth == 0 && value.is_a?(Hash) && !value.empty?
|
|
165
|
+
hide = redact || sensitive_key?(key)
|
|
166
|
+
if depth == 0 && value.is_a?(Hash) && !value.empty?
|
|
168
167
|
"<tr class=\"is-section is-section-top\"><td colspan=\"2\"><strong>#{ERB::Util.html_escape(full_key)}</strong></td></tr>\n" \
|
|
169
|
-
"#{config_to_html_table(value, 1, full_key)}"
|
|
168
|
+
"#{config_to_html_table(value, 1, full_key, redact: hide)}"
|
|
170
169
|
elsif value.is_a?(Hash) && value.empty?
|
|
171
170
|
"<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td><span class=\"not-set\">(empty)</span></td></tr>"
|
|
172
171
|
elsif value.is_a?(Hash) && value.values.all? { |v| v.is_a?(Hash) && v.empty? }
|
|
173
172
|
items = value.keys.map { |k| "<li>#{ERB::Util.html_escape(k)}</li>" }.join("\n")
|
|
174
173
|
"<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td><ul class=\"config-array\">#{items}</ul></td></tr>"
|
|
175
174
|
elsif value.is_a?(Hash) && compact_hash?(value)
|
|
176
|
-
"<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td>#{format_nested_value(value)}</td></tr>"
|
|
175
|
+
"<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td>#{format_nested_value(value, redact: hide)}</td></tr>"
|
|
177
176
|
elsif value.is_a?(Hash)
|
|
178
177
|
"<tr class=\"is-section\"><td colspan=\"2\"><strong>#{ERB::Util.html_escape(full_key)}</strong></td></tr>\n" \
|
|
179
|
-
"#{config_to_html_table(value, depth + 1, full_key)}"
|
|
178
|
+
"#{config_to_html_table(value, depth + 1, full_key, redact: hide)}"
|
|
180
179
|
elsif value.is_a?(Array)
|
|
181
|
-
format_array_rows(full_key,
|
|
180
|
+
format_array_rows(full_key, value, depth, redact: hide)
|
|
182
181
|
else
|
|
183
182
|
display_value = if value.nil? || value.to_s.strip.empty?
|
|
184
183
|
"<span class=\"not-set\">(not set)</span>"
|
|
184
|
+
elsif hide
|
|
185
|
+
redacted_html
|
|
185
186
|
else
|
|
186
187
|
ERB::Util.html_escape(value.to_s)
|
|
187
188
|
end
|
|
@@ -196,44 +197,42 @@ module EventHub
|
|
|
196
197
|
end
|
|
197
198
|
end
|
|
198
199
|
|
|
199
|
-
def format_array_rows(full_key,
|
|
200
|
+
def format_array_rows(full_key, array, _depth, redact: false)
|
|
200
201
|
return "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td><span class=\"not-set\">(empty)</span></td></tr>" if array.empty?
|
|
201
202
|
|
|
202
|
-
|
|
203
|
-
return "<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td>#{redacted_html}</td></tr>"
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
inner = array.map { |item| format_array_item(item) }.join("\n")
|
|
203
|
+
inner = array.map { |item| format_array_item(item, redact: redact) }.join("\n")
|
|
207
204
|
"<tr><td class=\"config-key\">#{ERB::Util.html_escape(full_key)}</td><td><ul class=\"config-array\">#{inner}</ul></td></tr>"
|
|
208
205
|
end
|
|
209
206
|
|
|
210
|
-
def format_array_item(item)
|
|
207
|
+
def format_array_item(item, redact: false)
|
|
211
208
|
if item.is_a?(Hash)
|
|
212
209
|
rows = item.map do |k, v|
|
|
213
|
-
|
|
214
|
-
"<tr><td>#{ERB::Util.html_escape(k)}</td><td>#{
|
|
210
|
+
hide = redact || sensitive_key?(k)
|
|
211
|
+
"<tr><td>#{ERB::Util.html_escape(k)}</td><td>#{format_nested_value(v, redact: hide)}</td></tr>"
|
|
215
212
|
end.join
|
|
216
213
|
"<li><table class=\"table is-bordered is-narrow config-subtable\">#{rows}</table></li>"
|
|
217
214
|
elsif item.is_a?(Array)
|
|
218
|
-
inner = item.map { |i| format_array_item(i) }.join("\n")
|
|
215
|
+
inner = item.map { |i| format_array_item(i, redact: redact) }.join("\n")
|
|
219
216
|
"<li><ul class=\"config-array\">#{inner}</ul></li>"
|
|
220
217
|
else
|
|
221
|
-
"<li>#{ERB::Util.html_escape(item.to_s)}</li>"
|
|
218
|
+
"<li>#{redact ? redacted_html : ERB::Util.html_escape(item.to_s)}</li>"
|
|
222
219
|
end
|
|
223
220
|
end
|
|
224
221
|
|
|
225
|
-
def format_nested_value(value)
|
|
222
|
+
def format_nested_value(value, redact: false)
|
|
226
223
|
if value.is_a?(Hash)
|
|
227
224
|
rows = value.map do |k, v|
|
|
228
|
-
|
|
229
|
-
"<tr><td>#{ERB::Util.html_escape(k)}</td><td>#{
|
|
225
|
+
hide = redact || sensitive_key?(k)
|
|
226
|
+
"<tr><td>#{ERB::Util.html_escape(k)}</td><td>#{format_nested_value(v, redact: hide)}</td></tr>"
|
|
230
227
|
end.join
|
|
231
228
|
"<table class=\"table is-bordered is-narrow config-subtable\">#{rows}</table>"
|
|
232
229
|
elsif value.is_a?(Array)
|
|
233
|
-
items = value.map { |i| format_array_item(i) }.join("\n")
|
|
230
|
+
items = value.map { |i| format_array_item(i, redact: redact) }.join("\n")
|
|
234
231
|
"<ul class=\"config-array\">#{items}</ul>"
|
|
235
232
|
elsif value.nil? || value.to_s.strip.empty?
|
|
236
233
|
"<span class=\"not-set\">(not set)</span>"
|
|
234
|
+
elsif redact
|
|
235
|
+
redacted_html
|
|
237
236
|
else
|
|
238
237
|
ERB::Util.html_escape(value.to_s)
|
|
239
238
|
end
|
|
@@ -253,15 +252,27 @@ module EventHub
|
|
|
253
252
|
end
|
|
254
253
|
end
|
|
255
254
|
|
|
256
|
-
DEFAULT_SENSITIVE_KEYS = %w[password secret token api_key credential
|
|
255
|
+
DEFAULT_SENSITIVE_KEYS = %w[password secret token api_key credential user login host port database instance url endpoint scheme].freeze
|
|
256
|
+
DEFAULT_NON_SENSITIVE_KEYS = %w[vhost].freeze
|
|
257
257
|
|
|
258
258
|
def sensitive_key?(key)
|
|
259
|
+
normalized = key.to_s.downcase
|
|
260
|
+
return false if non_sensitive_keys.any? { |exception| normalized == exception.downcase }
|
|
261
|
+
|
|
259
262
|
keys = if @processor&.class&.method_defined?(:sensitive_keys)
|
|
260
263
|
@processor.sensitive_keys
|
|
261
264
|
else
|
|
262
265
|
DEFAULT_SENSITIVE_KEYS
|
|
263
266
|
end
|
|
264
|
-
keys.any? { |pattern|
|
|
267
|
+
keys.any? { |pattern| normalized.include?(pattern.downcase) }
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def non_sensitive_keys
|
|
271
|
+
if @processor&.class&.method_defined?(:non_sensitive_keys)
|
|
272
|
+
@processor.non_sensitive_keys
|
|
273
|
+
else
|
|
274
|
+
DEFAULT_NON_SENSITIVE_KEYS
|
|
275
|
+
end
|
|
265
276
|
end
|
|
266
277
|
|
|
267
278
|
def markdown_to_html(markdown)
|
data/lib/eventhub/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: eventhub-processor2
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.29.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Steiner, Thomas
|
|
@@ -141,14 +141,14 @@ dependencies:
|
|
|
141
141
|
requirements:
|
|
142
142
|
- - "~>"
|
|
143
143
|
- !ruby/object:Gem::Version
|
|
144
|
-
version: '0
|
|
144
|
+
version: '1.0'
|
|
145
145
|
type: :development
|
|
146
146
|
prerelease: false
|
|
147
147
|
version_requirements: !ruby/object:Gem::Requirement
|
|
148
148
|
requirements:
|
|
149
149
|
- - "~>"
|
|
150
150
|
- !ruby/object:Gem::Version
|
|
151
|
-
version: '0
|
|
151
|
+
version: '1.0'
|
|
152
152
|
- !ruby/object:Gem::Dependency
|
|
153
153
|
name: standard
|
|
154
154
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -247,7 +247,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
247
247
|
- !ruby/object:Gem::Version
|
|
248
248
|
version: '0'
|
|
249
249
|
requirements: []
|
|
250
|
-
rubygems_version: 4.0.
|
|
250
|
+
rubygems_version: 4.0.16
|
|
251
251
|
specification_version: 4
|
|
252
252
|
summary: Next generation gem to build ruby based eventhub processor
|
|
253
253
|
test_files: []
|