rails_discord_notifier 0.3.0 → 0.3.2
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 +23 -0
- data/README.md +13 -5
- data/lib/rails_discord_notifier/google_chat_payload.rb +5 -2
- data/lib/rails_discord_notifier/payload.rb +21 -15
- data/lib/rails_discord_notifier/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 78212ad50963b77ccf50a72b4d7c0d79efd23557465c73cd829dc6bcc3c88251
|
|
4
|
+
data.tar.gz: c394690be33b31b3ff588041ccbe8232079657a479b204f968c9e58b3f30b6d0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6b2c309fd867f9b24963e37b04958c081a984fd4c3cadb1a969b08ed981d5776dfaeea0555b87ea89722dd22249600ed7ff792ffac426d7fa367d9c57a1aba31
|
|
7
|
+
data.tar.gz: 39e26aa259b490ddfd3227183350a4a8dd74123e6c93527f2a228519da99ab67d83703b50c21d3179918e8c70a67a0b21ae1ed668413b9536bb2b150edfaaeca
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.2] - 2026-10-28
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
|
|
14
|
+
- **The URL field no longer includes the query string.** Query values were
|
|
15
|
+
sent twice, filtered, in the URL and in Params, and the URL copy was still
|
|
16
|
+
sent with `config.include_params = false`. The query string is now sent only
|
|
17
|
+
as part of Params, so `include_params = false` leaves it out. An exception
|
|
18
|
+
message that quotes a value is still sent, with its best-effort scrub.
|
|
19
|
+
|
|
20
|
+
## [0.3.1] - 2026-10-28
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- **Backtraces show your app's frames.** The backtrace goes through
|
|
25
|
+
`Rails.backtrace_cleaner`, so your own lines are no longer crowded out by gem
|
|
26
|
+
frames and cut off at the size limit. An error that never reaches your code
|
|
27
|
+
keeps its library frames, with short gem paths.
|
|
28
|
+
- **`Host` shows the Heroku dyno name** (`web.1`, `worker.2`) instead of the
|
|
29
|
+
dyno's random hostname.
|
|
30
|
+
- **Google Chat reports from outside a request no longer repeat the error
|
|
31
|
+
class** as a heading above the message.
|
|
32
|
+
|
|
10
33
|
## [0.3.0] - 2026-10-28
|
|
11
34
|
|
|
12
35
|
### Added
|
data/README.md
CHANGED
|
@@ -63,7 +63,7 @@ Exception in POST /orders
|
|
|
63
63
|
ActiveRecord::RecordInvalid: Validation failed: Email can't be blank
|
|
64
64
|
Caused by ArgumentError: missing email
|
|
65
65
|
|
|
66
|
-
URL https://shop.example.com/orders
|
|
66
|
+
URL https://shop.example.com/orders
|
|
67
67
|
Controller orders Action create
|
|
68
68
|
Environment production Release a1b2c3d
|
|
69
69
|
Request ID 8f3c… Host web-01
|
|
@@ -75,6 +75,12 @@ In Google Chat, the same details as a single text message, with the params and
|
|
|
75
75
|
backtrace in code blocks. Chat has no per-message sender name or avatar: those
|
|
76
76
|
come from the name and avatar you gave the webhook when you created it.
|
|
77
77
|
|
|
78
|
+
The backtrace goes through `Rails.backtrace_cleaner`, as on Rails' own error
|
|
79
|
+
pages, so it shows your app's frames rather than gem internals. When an error
|
|
80
|
+
never reaches your code, such as a job class that doesn't exist, the library
|
|
81
|
+
frames are shown with short gem paths instead. On Heroku, `Host` is the dyno
|
|
82
|
+
name (`web.1`, `worker.2`) rather than the dyno's random hostname.
|
|
83
|
+
|
|
78
84
|
## Configuration
|
|
79
85
|
|
|
80
86
|
Everything is optional except `webhook_url`.
|
|
@@ -90,7 +96,7 @@ Everything is optional except `webhook_url`.
|
|
|
90
96
|
| `ignored_exceptions` | routing/404-style noise (see below) | Exception class names, matched including subclasses. |
|
|
91
97
|
| `include_params` | `true` | Include filtered request parameters. |
|
|
92
98
|
| `filter_parameters` | `[]` | Extra redaction matchers, unioned with your app's `config.filter_parameters` and the gem's built-in list. |
|
|
93
|
-
| `backtrace_lines` | `10` | Backtrace lines to send, trimmed to fit the message size limit. |
|
|
99
|
+
| `backtrace_lines` | `10` | Backtrace lines to send after cleaning, trimmed to fit the message size limit. |
|
|
94
100
|
| `open_timeout` / `read_timeout` / `write_timeout` | `2` / `5` / `5` | Seconds. |
|
|
95
101
|
| `environment` | `Rails.env`, else `RAILS_ENV`/`RACK_ENV` | Shown as a field, and decides the `enabled` default. |
|
|
96
102
|
| `release` | `nil` | Shown as a field; handy for matching an error to a deploy. |
|
|
@@ -134,9 +140,11 @@ Parameters and query strings are filtered recursively with
|
|
|
134
140
|
`session`, `credential`).
|
|
135
141
|
|
|
136
142
|
Because it is a union, enabling this gem can never redact less than your
|
|
137
|
-
application already does.
|
|
138
|
-
|
|
139
|
-
`config.
|
|
143
|
+
application already does. The URL field leaves out the query string, so the
|
|
144
|
+
query string is sent only as part of the filtered params. To leave out params
|
|
145
|
+
and the query string, set `config.include_params = false`. An exception message
|
|
146
|
+
that quotes a parameter value is still sent (see below). The same filter
|
|
147
|
+
applies to extra fields from `config.context` and from `Rails.error` context.
|
|
140
148
|
|
|
141
149
|
Exception messages are free text rather than structured parameters, so they get
|
|
142
150
|
a best-effort scrub instead: `token=abc`, `password="x"`, `Api_Key: abc`,
|
|
@@ -22,8 +22,11 @@ module RailsDiscordNotifier
|
|
|
22
22
|
|
|
23
23
|
private
|
|
24
24
|
|
|
25
|
+
# Outside a request the title is only the class name, which the description
|
|
26
|
+
# already opens with, so it is left out rather than repeated.
|
|
25
27
|
def render(embed)
|
|
26
|
-
heading = [
|
|
28
|
+
heading = [embed[:description], ""]
|
|
29
|
+
heading.unshift(bold(embed[:title])) if request
|
|
27
30
|
(heading + embed[:fields].map { |field| render_field(field) }).join("\n")
|
|
28
31
|
end
|
|
29
32
|
|
|
@@ -42,7 +45,7 @@ module RailsDiscordNotifier
|
|
|
42
45
|
end
|
|
43
46
|
|
|
44
47
|
def formatted_backtrace
|
|
45
|
-
lines =
|
|
48
|
+
lines = clean_backtrace
|
|
46
49
|
return "No backtrace available" if lines.empty?
|
|
47
50
|
|
|
48
51
|
fence(lines.join("\n"))
|
|
@@ -112,7 +112,7 @@ module RailsDiscordNotifier
|
|
|
112
112
|
|
|
113
113
|
def request_fields
|
|
114
114
|
[
|
|
115
|
-
{ name: "URL", value:
|
|
115
|
+
{ name: "URL", value: request_url },
|
|
116
116
|
{ name: "Controller", value: rails_params["controller"], inline: true },
|
|
117
117
|
{ name: "Action", value: rails_params["action"], inline: true },
|
|
118
118
|
{ name: "Environment", value: config.environment, inline: true },
|
|
@@ -169,7 +169,7 @@ module RailsDiscordNotifier
|
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
def formatted_backtrace
|
|
172
|
-
lines =
|
|
172
|
+
lines = clean_backtrace
|
|
173
173
|
return "No backtrace available" if lines.empty?
|
|
174
174
|
|
|
175
175
|
lines.each_with_object(+"") do |line, out|
|
|
@@ -181,21 +181,25 @@ module RailsDiscordNotifier
|
|
|
181
181
|
end
|
|
182
182
|
end
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
# The app's own frames, as on Rails' error pages, so the lines that matter
|
|
185
|
+
# fit the message. An error raised entirely inside library code keeps its
|
|
186
|
+
# library frames, with gem paths shortened. Raw frames when the cleaner is
|
|
187
|
+
# unavailable (no Rails) or raises, and without an app root: Rails 6.1 and
|
|
188
|
+
# 7.0 would then strip the leading "/" from every path.
|
|
189
|
+
def clean_backtrace
|
|
190
|
+
lines = Array(exception.backtrace)
|
|
191
|
+
return lines.first(config.backtrace_lines) unless Rails.root
|
|
186
192
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
193
|
+
app_frames = Rails.backtrace_cleaner.clean(lines)
|
|
194
|
+
(app_frames.empty? ? Rails.backtrace_cleaner.clean(lines, :all) : app_frames).first(config.backtrace_lines)
|
|
195
|
+
rescue StandardError
|
|
196
|
+
Array(exception.backtrace).first(config.backtrace_lines)
|
|
190
197
|
end
|
|
191
198
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
Rack::Utils.build_nested_query(parameter_filter.filter(Rack::Utils.parse_nested_query(raw)))
|
|
197
|
-
rescue StandardError
|
|
198
|
-
""
|
|
199
|
+
# Without the query string, which is sent only as part of the filtered
|
|
200
|
+
# Params field, so include_params = false leaves it out.
|
|
201
|
+
def request_url
|
|
202
|
+
request && "#{request.base_url}#{request.path}"
|
|
199
203
|
end
|
|
200
204
|
|
|
201
205
|
def request_params
|
|
@@ -232,8 +236,10 @@ module RailsDiscordNotifier
|
|
|
232
236
|
@parameter_filter ||= ActiveSupport::ParameterFilter.new(config.filter_parameters)
|
|
233
237
|
end
|
|
234
238
|
|
|
239
|
+
# Heroku hostnames are random IDs; DYNO ("web.1", "worker.2") names the process.
|
|
235
240
|
def hostname
|
|
236
|
-
|
|
241
|
+
dyno = ENV.fetch("DYNO", "")
|
|
242
|
+
@hostname ||= dyno.empty? ? Socket.gethostname : dyno
|
|
237
243
|
rescue StandardError
|
|
238
244
|
nil
|
|
239
245
|
end
|