newshound 1.0.1 → 1.0.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 +8 -26
- data/lib/newshound/configuration.rb +2 -0
- data/lib/newshound/exception_reporter.rb +1 -1
- data/lib/newshound/exceptions/base.rb +4 -0
- data/lib/newshound/exceptions/bugsink.rb +77 -0
- data/lib/newshound/exceptions.rb +2 -2
- data/lib/newshound/middleware/banner_injector.rb +54 -1
- data/lib/newshound/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c28e3edb5bdc1e1c6af7b0ec4ea8e171fc912670515c19a1bef53f0a2e78f2c5
|
|
4
|
+
data.tar.gz: e15c37e225e9140e112fd250ac860e555fe02606d1a6dfed40094f435fa94600
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f89d1b069823ba254f663caf2efe01d4667d560bfc47739b04a98f4653fd3f6f747998aa3594be7848a770bf5f26bbeb705dfa0873d937fbb53565f5310dd252
|
|
7
|
+
data.tar.gz: ce5a04dfc26b9782da9a308299d9ccc04273aa3ceb260256b9deb951ddf2f9b25b771cbcbcab5d56f46d33b4155b17821d02ca9e55cb6fafd4772c12388f9425
|
data/CHANGELOG.md
CHANGED
|
@@ -5,39 +5,21 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [1.0.
|
|
9
|
-
|
|
10
|
-
### Changed
|
|
11
|
-
|
|
12
|
-
- The authorize_with initializer will generate with the method inside the configure block. (2d6ef48)
|
|
8
|
+
## [1.0.2] - 2026-04-03
|
|
13
9
|
|
|
14
10
|
### Added
|
|
15
11
|
|
|
16
|
-
-
|
|
17
|
-
-
|
|
12
|
+
- Bugsink exception source adapter for HTTP-based error tracking (6d3e2a1)
|
|
13
|
+
- exception_source_config option for passing connection details to adapters (6d3e2a1)
|
|
14
|
+
- Minimize button for banner (c686227)
|
|
18
15
|
|
|
19
|
-
## [0.
|
|
16
|
+
## [1.0.1] - 2026-03-17
|
|
20
17
|
|
|
21
18
|
### Changed
|
|
22
19
|
|
|
23
|
-
-
|
|
24
|
-
- Job monitoring uses configurable adapter pattern via config.job_source (8d33d30)
|
|
25
|
-
|
|
26
|
-
### Removed
|
|
27
|
-
|
|
28
|
-
- Ruby 3.1 and 3.2 support (24e5b86)
|
|
29
|
-
- Hard dependency on que gem (8d33d30)
|
|
30
|
-
- QueReporter class (replaced by JobReporter + Jobs adapters) Version: major (8d33d30)
|
|
31
|
-
|
|
32
|
-
### Fixed
|
|
33
|
-
|
|
34
|
-
- Set the correct location for the repository on the web. (cb7bb88)
|
|
35
|
-
- test_exceptions rake task calling report instead of banner_data (e440188)
|
|
36
|
-
- Banner overlaying content in apps with !important body padding-top rules (16f22f1)
|
|
20
|
+
- The authorize_with initializer will generate with the method inside the configure block. (2d6ef48)
|
|
37
21
|
|
|
38
22
|
### Added
|
|
39
23
|
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
- JobReporter that delegates to a configurable job source adapter (c50ba9c)
|
|
43
|
-
- ExceptionReporter#formatted_exception_count and #exception_summary helpers (e440188)
|
|
24
|
+
- Configurable banner links for exceptions, jobs, and warnings via string path patterns (1df1636)
|
|
25
|
+
- Record ID in format_for_banner output for linking to individual records (e06d040)
|
|
@@ -4,6 +4,7 @@ module Newshound
|
|
|
4
4
|
class Configuration
|
|
5
5
|
attr_accessor :exception_limit, :enabled, :authorized_roles,
|
|
6
6
|
:current_user_method, :authorization_block, :exception_source,
|
|
7
|
+
:exception_source_config,
|
|
7
8
|
:warning_source, :warning_limit, :job_source,
|
|
8
9
|
:exception_links, :job_links, :warning_links
|
|
9
10
|
|
|
@@ -14,6 +15,7 @@ module Newshound
|
|
|
14
15
|
@current_user_method = :current_user
|
|
15
16
|
@authorization_block = nil
|
|
16
17
|
@exception_source = :exception_track
|
|
18
|
+
@exception_source_config = {}
|
|
17
19
|
@warning_source = nil
|
|
18
20
|
@warning_limit = 10
|
|
19
21
|
@job_source = nil
|
|
@@ -51,7 +51,7 @@ module Newshound
|
|
|
51
51
|
|
|
52
52
|
def resolve_exception_source(source)
|
|
53
53
|
source ||= @configuration.exception_source
|
|
54
|
-
source.is_a?(Symbol) ? Exceptions.source(source) : source
|
|
54
|
+
source.is_a?(Symbol) ? Exceptions.source(source, @configuration.exception_source_config) : source
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def recent_exceptions
|
|
@@ -10,6 +10,10 @@ module Newshound
|
|
|
10
10
|
# - #format_for_report(exception) - Formats a single exception for Slack/report display
|
|
11
11
|
# - #format_for_banner(exception) - Formats a single exception for banner UI
|
|
12
12
|
class Base
|
|
13
|
+
def initialize(config = {})
|
|
14
|
+
@config = config
|
|
15
|
+
end
|
|
16
|
+
|
|
13
17
|
# Fetches recent exceptions from the exception tracking system
|
|
14
18
|
#
|
|
15
19
|
# @param time_range [ActiveSupport::Duration] Time duration to look back (e.g., 24.hours)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "net/http"
|
|
4
|
+
require "json"
|
|
5
|
+
require "uri"
|
|
6
|
+
require "time"
|
|
7
|
+
|
|
8
|
+
module Newshound
|
|
9
|
+
module Exceptions
|
|
10
|
+
class Bugsink < Base
|
|
11
|
+
def self.required_keys
|
|
12
|
+
%i[url token project_id].freeze
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(config = {})
|
|
16
|
+
super
|
|
17
|
+
config = config.transform_keys(&:to_sym)
|
|
18
|
+
|
|
19
|
+
missing = self.class.required_keys.select { |key| config[key].nil? }
|
|
20
|
+
if missing.any?
|
|
21
|
+
raise ArgumentError,
|
|
22
|
+
"Bugsink requires #{missing.map { |k| ":#{k}" }.join(", ")} in exception_source_config"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
@url = config[:url]
|
|
26
|
+
@token = config[:token]
|
|
27
|
+
@project_id = config[:project_id]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def recent(time_range:, limit:)
|
|
31
|
+
issues = fetch_issues
|
|
32
|
+
cutoff = Time.now.utc - time_range
|
|
33
|
+
|
|
34
|
+
issues
|
|
35
|
+
.select { |i| Time.parse(i["last_seen"]) >= cutoff }
|
|
36
|
+
.first(limit)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def format_for_report(issue, number)
|
|
40
|
+
<<~TEXT
|
|
41
|
+
*#{number}. #{issue["calculated_type"] || "Unknown"}*
|
|
42
|
+
• *Time:* #{Time.parse(issue["last_seen"]).strftime("%I:%M %p")}
|
|
43
|
+
• *Message:* `#{(issue["calculated_value"] || "").truncate(100)}`
|
|
44
|
+
TEXT
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def format_for_banner(issue)
|
|
48
|
+
{
|
|
49
|
+
id: issue["id"],
|
|
50
|
+
title: issue["calculated_type"] || "Unknown",
|
|
51
|
+
message: (issue["calculated_value"] || "").truncate(100),
|
|
52
|
+
location: issue["transaction"] || "",
|
|
53
|
+
time: Time.parse(issue["last_seen"]).strftime("%I:%M %p")
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def fetch_issues
|
|
60
|
+
uri = URI("#{@url.chomp("/")}/api/canonical/0/issues/")
|
|
61
|
+
uri.query = URI.encode_www_form(project: @project_id, sort: "last_seen", order: "desc")
|
|
62
|
+
|
|
63
|
+
request = Net::HTTP::Get.new(uri)
|
|
64
|
+
request["Authorization"] = "Bearer #{@token}"
|
|
65
|
+
request["Accept"] = "application/json"
|
|
66
|
+
|
|
67
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
|
|
68
|
+
http.request(request)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
raise "Bugsink API error: #{response.code}" unless response.is_a?(Net::HTTPSuccess)
|
|
72
|
+
|
|
73
|
+
JSON.parse(response.body)["results"] || []
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
data/lib/newshound/exceptions.rb
CHANGED
|
@@ -2,11 +2,11 @@ Dir[File.join(__dir__, "exceptions", "*.rb")].each { |file| require file }
|
|
|
2
2
|
|
|
3
3
|
module Newshound
|
|
4
4
|
module Exceptions
|
|
5
|
-
def self.source(source)
|
|
5
|
+
def self.source(source, config = {})
|
|
6
6
|
constant = constants.find { |c| c.to_s.gsub(/(?<!^)([A-Z])/, "_\\1").downcase == source.to_s }
|
|
7
7
|
raise "Invalid exception source: #{source}" unless constant
|
|
8
8
|
|
|
9
|
-
const_get(constant).new
|
|
9
|
+
const_get(constant).new(config)
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -75,13 +75,19 @@ module Newshound
|
|
|
75
75
|
🐕 Newshound
|
|
76
76
|
#{summary_badge(exception_data, job_data, warning_data)}
|
|
77
77
|
</span>
|
|
78
|
-
<span class="newshound-
|
|
78
|
+
<span class="newshound-header-controls">
|
|
79
|
+
<span class="newshound-minimize" onclick="event.stopPropagation(); document.getElementById('newshound-banner').classList.add('newshound-minimized'); localStorage.setItem('newshound-minimized','1'); window.newshoundUpdatePadding();" title="Minimize">−</span>
|
|
80
|
+
<span class="newshound-toggle">▼</span>
|
|
81
|
+
</span>
|
|
79
82
|
</div>
|
|
80
83
|
<div class="newshound-content">
|
|
81
84
|
#{render_exceptions(exception_data)}
|
|
82
85
|
#{render_warnings(warning_data)}
|
|
83
86
|
#{render_jobs(job_data)}
|
|
84
87
|
</div>
|
|
88
|
+
<div class="newshound-restore" onclick="document.getElementById('newshound-banner').classList.remove('newshound-minimized'); localStorage.removeItem('newshound-minimized'); window.newshoundUpdatePadding();" title="Restore Newshound">
|
|
89
|
+
🐕
|
|
90
|
+
</div>
|
|
85
91
|
</div>
|
|
86
92
|
#{render_script}
|
|
87
93
|
HTML
|
|
@@ -91,6 +97,11 @@ module Newshound
|
|
|
91
97
|
<<~JS
|
|
92
98
|
<script>
|
|
93
99
|
(function() {
|
|
100
|
+
// Restore minimized state from localStorage
|
|
101
|
+
if (localStorage.getItem('newshound-minimized')) {
|
|
102
|
+
document.getElementById('newshound-banner').classList.add('newshound-minimized');
|
|
103
|
+
}
|
|
104
|
+
|
|
94
105
|
var cachedPriority, cachedBodyRule;
|
|
95
106
|
|
|
96
107
|
// Detect once whether any non-newshound stylesheet uses !important on body padding-top
|
|
@@ -290,6 +301,48 @@ module Newshound
|
|
|
290
301
|
a.newshound-stat:hover {
|
|
291
302
|
background: rgba(255,255,255,0.2);
|
|
292
303
|
}
|
|
304
|
+
.newshound-header-controls {
|
|
305
|
+
display: flex;
|
|
306
|
+
align-items: center;
|
|
307
|
+
gap: 12px;
|
|
308
|
+
}
|
|
309
|
+
.newshound-minimize {
|
|
310
|
+
cursor: pointer;
|
|
311
|
+
font-size: 18px;
|
|
312
|
+
font-weight: 700;
|
|
313
|
+
line-height: 1;
|
|
314
|
+
opacity: 0.7;
|
|
315
|
+
padding: 0 4px;
|
|
316
|
+
}
|
|
317
|
+
.newshound-minimize:hover {
|
|
318
|
+
opacity: 1;
|
|
319
|
+
}
|
|
320
|
+
.newshound-restore {
|
|
321
|
+
display: none;
|
|
322
|
+
}
|
|
323
|
+
.newshound-banner.newshound-minimized .newshound-header {
|
|
324
|
+
display: none;
|
|
325
|
+
}
|
|
326
|
+
.newshound-banner.newshound-minimized .newshound-content {
|
|
327
|
+
max-height: 0;
|
|
328
|
+
overflow: hidden;
|
|
329
|
+
border-top: none;
|
|
330
|
+
}
|
|
331
|
+
.newshound-banner.newshound-minimized .newshound-restore {
|
|
332
|
+
display: flex;
|
|
333
|
+
align-items: center;
|
|
334
|
+
justify-content: center;
|
|
335
|
+
width: 36px;
|
|
336
|
+
height: 36px;
|
|
337
|
+
cursor: pointer;
|
|
338
|
+
font-size: 16px;
|
|
339
|
+
user-select: none;
|
|
340
|
+
}
|
|
341
|
+
.newshound-banner.newshound-minimized {
|
|
342
|
+
left: auto;
|
|
343
|
+
border-radius: 0 0 0 8px;
|
|
344
|
+
box-shadow: -2px 2px 6px rgba(0,0,0,0.2);
|
|
345
|
+
}
|
|
293
346
|
</style>
|
|
294
347
|
CSS
|
|
295
348
|
end
|
data/lib/newshound/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: newshound
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Savannah Moore
|
|
@@ -49,6 +49,7 @@ files:
|
|
|
49
49
|
- lib/newshound/exception_reporter.rb
|
|
50
50
|
- lib/newshound/exceptions.rb
|
|
51
51
|
- lib/newshound/exceptions/base.rb
|
|
52
|
+
- lib/newshound/exceptions/bugsink.rb
|
|
52
53
|
- lib/newshound/exceptions/exception_track.rb
|
|
53
54
|
- lib/newshound/exceptions/solid_errors.rb
|
|
54
55
|
- lib/newshound/job_reporter.rb
|