newshound 0.1.1 → 0.2.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.
@@ -0,0 +1,288 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Newshound
4
+ module Middleware
5
+ class BannerInjector
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ status, headers, response = @app.call(env)
12
+
13
+ # Only inject into HTML responses
14
+ return [status, headers, response] unless html_response?(headers)
15
+ return [status, headers, response] unless status == 200
16
+
17
+ # Check authorization
18
+ controller = env['action_controller.instance']
19
+ return [status, headers, response] unless controller
20
+ return [status, headers, response] unless Newshound::Authorization.authorized?(controller)
21
+
22
+ # Get banner HTML
23
+ banner_html = generate_banner_html
24
+
25
+ # Inject banner after <body> tag
26
+ new_response = inject_banner(response, banner_html)
27
+
28
+ # Update Content-Length header
29
+ if headers['Content-Length']
30
+ headers['Content-Length'] = new_response.bytesize.to_s
31
+ end
32
+
33
+ [status, headers, [new_response]]
34
+ end
35
+
36
+ private
37
+
38
+ def html_response?(headers)
39
+ content_type = headers['Content-Type']
40
+ content_type && content_type.include?('text/html')
41
+ end
42
+
43
+ def inject_banner(response, banner_html)
44
+ body = response_body(response)
45
+
46
+ # Inject after <body> tag
47
+ body.sub(/(<body[^>]*>)/i, "\\1\n#{banner_html}")
48
+ end
49
+
50
+ def response_body(response)
51
+ body = ""
52
+ response.each { |part| body << part }
53
+ body
54
+ end
55
+
56
+ def generate_banner_html
57
+ exception_reporter = Newshound::ExceptionReporter.new
58
+ que_reporter = Newshound::QueReporter.new
59
+
60
+ exception_data = exception_reporter.report
61
+ job_data = que_reporter.report
62
+
63
+ # Generate HTML from template
64
+ render_banner(exception_data, job_data)
65
+ end
66
+
67
+ def render_banner(exception_data, job_data)
68
+ <<~HTML
69
+ <div id="newshound-banner" class="newshound-banner newshound-collapsed">
70
+ #{render_styles}
71
+ <div class="newshound-header" onclick="document.getElementById('newshound-banner').classList.toggle('newshound-collapsed')">
72
+ <span class="newshound-title">
73
+ 🐕 Newshound
74
+ #{summary_badge(exception_data, job_data)}
75
+ </span>
76
+ <span class="newshound-toggle">▼</span>
77
+ </div>
78
+ <div class="newshound-content">
79
+ #{render_exceptions(exception_data)}
80
+ #{render_jobs(job_data)}
81
+ </div>
82
+ </div>
83
+ HTML
84
+ end
85
+
86
+ def render_styles
87
+ <<~CSS
88
+ <style>
89
+ .newshound-banner {
90
+ position: fixed;
91
+ top: 0;
92
+ left: 0;
93
+ right: 0;
94
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
95
+ color: white;
96
+ z-index: 10000;
97
+ box-shadow: 0 2px 10px rgba(0,0,0,0.3);
98
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
99
+ font-size: 14px;
100
+ }
101
+ .newshound-header {
102
+ padding: 12px 20px;
103
+ cursor: pointer;
104
+ display: flex;
105
+ justify-content: space-between;
106
+ align-items: center;
107
+ user-select: none;
108
+ }
109
+ .newshound-title {
110
+ font-weight: 600;
111
+ display: flex;
112
+ align-items: center;
113
+ gap: 10px;
114
+ }
115
+ .newshound-badge {
116
+ display: inline-block;
117
+ padding: 2px 8px;
118
+ border-radius: 12px;
119
+ font-size: 12px;
120
+ font-weight: 600;
121
+ background: rgba(255,255,255,0.2);
122
+ }
123
+ .newshound-badge.error {
124
+ background: #ef4444;
125
+ }
126
+ .newshound-badge.warning {
127
+ background: #f59e0b;
128
+ }
129
+ .newshound-badge.success {
130
+ background: #10b981;
131
+ }
132
+ .newshound-toggle {
133
+ transition: transform 0.3s;
134
+ }
135
+ .newshound-banner.newshound-collapsed .newshound-toggle {
136
+ transform: rotate(-90deg);
137
+ }
138
+ .newshound-content {
139
+ max-height: 400px;
140
+ overflow-y: auto;
141
+ border-top: 1px solid rgba(255,255,255,0.2);
142
+ transition: max-height 0.3s ease-out;
143
+ }
144
+ .newshound-banner.newshound-collapsed .newshound-content {
145
+ max-height: 0;
146
+ overflow: hidden;
147
+ border-top: none;
148
+ }
149
+ .newshound-section {
150
+ padding: 15px 20px;
151
+ border-bottom: 1px solid rgba(255,255,255,0.1);
152
+ }
153
+ .newshound-section:last-child {
154
+ border-bottom: none;
155
+ }
156
+ .newshound-section-title {
157
+ font-weight: 600;
158
+ margin-bottom: 10px;
159
+ font-size: 15px;
160
+ }
161
+ .newshound-item {
162
+ background: rgba(255,255,255,0.1);
163
+ padding: 10px;
164
+ margin-bottom: 8px;
165
+ border-radius: 6px;
166
+ font-size: 13px;
167
+ }
168
+ .newshound-item:last-child {
169
+ margin-bottom: 0;
170
+ }
171
+ .newshound-item-title {
172
+ font-weight: 600;
173
+ margin-bottom: 4px;
174
+ }
175
+ .newshound-item-detail {
176
+ opacity: 0.9;
177
+ font-size: 12px;
178
+ }
179
+ .newshound-grid {
180
+ display: grid;
181
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
182
+ gap: 10px;
183
+ }
184
+ .newshound-stat {
185
+ background: rgba(255,255,255,0.1);
186
+ padding: 12px;
187
+ border-radius: 6px;
188
+ text-align: center;
189
+ }
190
+ .newshound-stat-value {
191
+ font-size: 24px;
192
+ font-weight: 700;
193
+ display: block;
194
+ }
195
+ .newshound-stat-label {
196
+ font-size: 11px;
197
+ opacity: 0.8;
198
+ text-transform: uppercase;
199
+ letter-spacing: 0.5px;
200
+ }
201
+ </style>
202
+ CSS
203
+ end
204
+
205
+ def summary_badge(exception_data, job_data)
206
+ exception_count = exception_data[:exceptions]&.length || 0
207
+ failed_jobs = job_data.dig(:queue_stats, :failed) || 0
208
+
209
+ if exception_count > 0 || failed_jobs > 10
210
+ badge_class = "error"
211
+ text = "#{exception_count} exceptions, #{failed_jobs} failed jobs"
212
+ elsif failed_jobs > 5
213
+ badge_class = "warning"
214
+ text = "#{failed_jobs} failed jobs"
215
+ else
216
+ badge_class = "success"
217
+ text = "All clear"
218
+ end
219
+
220
+ %(<span class="newshound-badge #{badge_class}">#{text}</span>)
221
+ end
222
+
223
+ def render_exceptions(data)
224
+ exceptions = data[:exceptions] || []
225
+
226
+ if exceptions.empty?
227
+ return %(<div class="newshound-section"><div class="newshound-section-title">✅ Exceptions</div><div class="newshound-item">No exceptions in the last 24 hours</div></div>)
228
+ end
229
+
230
+ items = exceptions.take(5).map do |ex|
231
+ <<~HTML
232
+ <div class="newshound-item">
233
+ <div class="newshound-item-title">#{escape_html(ex[:title])}</div>
234
+ <div class="newshound-item-detail">
235
+ #{escape_html(ex[:message])} • #{escape_html(ex[:location])} • #{escape_html(ex[:time])}
236
+ </div>
237
+ </div>
238
+ HTML
239
+ end.join
240
+
241
+ <<~HTML
242
+ <div class="newshound-section">
243
+ <div class="newshound-section-title">⚠️ Recent Exceptions (#{exceptions.length})</div>
244
+ #{items}
245
+ </div>
246
+ HTML
247
+ end
248
+
249
+ def render_jobs(data)
250
+ stats = data[:queue_stats] || {}
251
+
252
+ <<~HTML
253
+ <div class="newshound-section">
254
+ <div class="newshound-section-title">📊 Job Queue Status</div>
255
+ <div class="newshound-grid">
256
+ <div class="newshound-stat">
257
+ <span class="newshound-stat-value">#{stats[:ready_to_run] || 0}</span>
258
+ <span class="newshound-stat-label">Ready</span>
259
+ </div>
260
+ <div class="newshound-stat">
261
+ <span class="newshound-stat-value">#{stats[:scheduled] || 0}</span>
262
+ <span class="newshound-stat-label">Scheduled</span>
263
+ </div>
264
+ <div class="newshound-stat">
265
+ <span class="newshound-stat-value">#{stats[:failed] || 0}</span>
266
+ <span class="newshound-stat-label">Failed</span>
267
+ </div>
268
+ <div class="newshound-stat">
269
+ <span class="newshound-stat-value">#{stats[:completed_today] || 0}</span>
270
+ <span class="newshound-stat-label">Completed Today</span>
271
+ </div>
272
+ </div>
273
+ </div>
274
+ HTML
275
+ end
276
+
277
+ def escape_html(text)
278
+ return "" unless text
279
+ text.to_s
280
+ .gsub('&', '&amp;')
281
+ .gsub('<', '&lt;')
282
+ .gsub('>', '&gt;')
283
+ .gsub('"', '&quot;')
284
+ .gsub("'", '&#39;')
285
+ end
286
+ end
287
+ end
288
+ end
@@ -4,59 +4,55 @@ require "rails/railtie"
4
4
 
5
5
  module Newshound
6
6
  class Railtie < Rails::Railtie
7
+ # Register middleware to inject banner
8
+ initializer "newshound.middleware" do |app|
9
+ if Newshound.configuration.enabled
10
+ app.middleware.use Newshound::Middleware::BannerInjector
11
+ end
12
+ end
13
+
7
14
  rake_tasks do
8
15
  namespace :newshound do
9
- desc "Send daily report immediately"
10
- task report_now: :environment do
11
- puts "Sending Newshound daily report..."
12
- Newshound.report!
13
- puts "Report sent successfully!"
14
- rescue StandardError => e
15
- puts "Failed to send report: #{e.message}"
16
- end
17
-
18
- desc "Schedule daily report job"
19
- task schedule: :environment do
20
- puts "Scheduling Newshound daily report..."
21
- Newshound::Scheduler.run_now!
22
- puts "Job enqueued successfully!"
23
- end
24
-
25
16
  desc "Show current configuration"
26
17
  task config: :environment do
27
18
  config = Newshound.configuration
28
19
  puts "Newshound Configuration:"
29
20
  puts " Enabled: #{config.enabled}"
30
- puts " Slack Webhook: #{config.slack_webhook_url.present? ? '[CONFIGURED]' : '[NOT SET]'}"
31
- puts " Slack Channel: #{config.slack_channel}"
32
- puts " Report Time: #{config.report_time}"
33
21
  puts " Exception Limit: #{config.exception_limit}"
34
- puts " Time Zone: #{config.time_zone}"
35
- puts " Valid: #{config.valid?}"
22
+ puts " Authorized Roles: #{config.authorized_roles.join(', ')}"
23
+ puts " Current User Method: #{config.current_user_method}"
24
+ puts " Custom Authorization: #{config.authorization_block.present? ? 'Yes' : 'No'}"
25
+ end
26
+
27
+ desc "Test exception reporter"
28
+ task test_exceptions: :environment do
29
+ reporter = Newshound::ExceptionReporter.new
30
+ data = reporter.report
31
+ puts "Exception Report:"
32
+ puts " Total exceptions: #{data[:exceptions]&.length || 0}"
33
+ data[:exceptions]&.each_with_index do |ex, i|
34
+ puts " #{i + 1}. #{ex[:title]} - #{ex[:message]}"
35
+ end
36
36
  end
37
- end
38
- end
39
37
 
40
- initializer "newshound.configure_que_scheduler" do
41
- ActiveSupport.on_load(:active_record) do
42
- if defined?(::Que::Scheduler)
43
- require_relative "scheduler"
44
-
45
- # Add our job to the que-scheduler configuration
46
- schedule = Newshound::Scheduler.schedule_daily_report
47
-
48
- Rails.logger.info "Newshound: Scheduled daily report at #{Newshound.configuration.report_time}"
49
- else
50
- Rails.logger.warn "Newshound: que-scheduler not found. Daily reports will need to be triggered manually."
38
+ desc "Test job reporter"
39
+ task test_jobs: :environment do
40
+ reporter = Newshound::QueReporter.new
41
+ data = reporter.report
42
+ puts "Job Queue Report:"
43
+ puts " Ready to run: #{data.dig(:queue_stats, :ready_to_run)}"
44
+ puts " Scheduled: #{data.dig(:queue_stats, :scheduled)}"
45
+ puts " Failed: #{data.dig(:queue_stats, :failed)}"
46
+ puts " Completed today: #{data.dig(:queue_stats, :completed_today)}"
51
47
  end
52
48
  end
53
49
  end
54
50
 
55
51
  config.after_initialize do
56
52
  if Newshound.configuration.valid?
57
- Rails.logger.info "Newshound initialized and ready to report!"
53
+ Rails.logger.info "Newshound initialized - banner will be shown to authorized users"
58
54
  else
59
- Rails.logger.warn "Newshound is not properly configured. Please check your configuration."
55
+ Rails.logger.warn "Newshound is disabled"
60
56
  end
61
57
  end
62
58
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Newshound
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/newshound.rb CHANGED
@@ -4,9 +4,8 @@ require_relative "newshound/version"
4
4
  require_relative "newshound/configuration"
5
5
  require_relative "newshound/exception_reporter"
6
6
  require_relative "newshound/que_reporter"
7
- require_relative "newshound/slack_notifier"
8
- require_relative "newshound/daily_report_job"
9
- require_relative "newshound/scheduler"
7
+ require_relative "newshound/authorization"
8
+ require_relative "newshound/middleware/banner_injector"
10
9
  require_relative "newshound/railtie" if defined?(Rails)
11
10
 
12
11
  module Newshound
@@ -21,46 +20,9 @@ module Newshound
21
20
  yield(configuration)
22
21
  end
23
22
 
24
- def report!
25
- slack_notifier = SlackNotifier.new
26
-
27
- exception_report = ExceptionReporter.new.generate_report
28
- que_report = QueReporter.new.generate_report
29
-
30
- message = format_daily_report(exception_report, que_report)
31
- slack_notifier.post(message)
32
- end
33
-
34
- private
35
-
36
- def format_daily_report(exception_report, que_report)
37
- {
38
- blocks: [
39
- {
40
- type: "header",
41
- text: {
42
- type: "plain_text",
43
- text: "🐕 Daily Newshound Report",
44
- emoji: true
45
- }
46
- },
47
- {
48
- type: "section",
49
- text: {
50
- type: "mrkdwn",
51
- text: "*Date:* #{Date.current.strftime('%B %d, %Y')}"
52
- }
53
- },
54
- {
55
- type: "divider"
56
- },
57
- *exception_report,
58
- {
59
- type: "divider"
60
- },
61
- *que_report
62
- ]
63
- }
23
+ # Allow setting custom authorization logic
24
+ def authorize_with(&block)
25
+ configuration.authorize_with(&block)
64
26
  end
65
27
  end
66
28
  end
data/newshound.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["salbanez"]
9
9
  spec.email = ["salbanez@example.com"]
10
10
 
11
- spec.summary = "Daily Slack reporter for Que jobs status and exception tracking"
12
- spec.description = "Newshound sniffs out exceptions and job statuses in your Rails app and reports them daily to Slack"
11
+ spec.summary = "Real-time web UI banner for monitoring Que jobs and exception tracking"
12
+ spec.description = "Newshound displays exceptions and job statuses in a collapsible banner for authorized users in your Rails app"
13
13
  spec.homepage = "https://github.com/salbanez/newshound"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = ">= 2.7.0"
@@ -29,11 +29,6 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  # Runtime dependencies
31
31
  spec.add_dependency "rails", ">= 6.0"
32
- spec.add_dependency "slack-ruby-client", "~> 2.0"
33
32
  spec.add_dependency "que", ">= 1.0"
34
- spec.add_dependency "que-scheduler", ">= 4.0"
35
33
  spec.add_dependency "exception-track", ">= 0.1"
36
-
37
- # Optional dependency for SNS transport
38
- spec.add_development_dependency "aws-sdk-sns", "~> 1.0"
39
34
  end
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: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - salbanez
@@ -23,20 +23,6 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: '6.0'
26
- - !ruby/object:Gem::Dependency
27
- name: slack-ruby-client
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - "~>"
31
- - !ruby/object:Gem::Version
32
- version: '2.0'
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '2.0'
40
26
  - !ruby/object:Gem::Dependency
41
27
  name: que
42
28
  requirement: !ruby/object:Gem::Requirement
@@ -51,20 +37,6 @@ dependencies:
51
37
  - - ">="
52
38
  - !ruby/object:Gem::Version
53
39
  version: '1.0'
54
- - !ruby/object:Gem::Dependency
55
- name: que-scheduler
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: '4.0'
61
- type: :runtime
62
- prerelease: false
63
- version_requirements: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- version: '4.0'
68
40
  - !ruby/object:Gem::Dependency
69
41
  name: exception-track
70
42
  requirement: !ruby/object:Gem::Requirement
@@ -79,22 +51,8 @@ dependencies:
79
51
  - - ">="
80
52
  - !ruby/object:Gem::Version
81
53
  version: '0.1'
82
- - !ruby/object:Gem::Dependency
83
- name: aws-sdk-sns
84
- requirement: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '1.0'
89
- type: :development
90
- prerelease: false
91
- version_requirements: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '1.0'
96
- description: Newshound sniffs out exceptions and job statuses in your Rails app and
97
- reports them daily to Slack
54
+ description: Newshound displays exceptions and job statuses in a collapsible banner
55
+ for authorized users in your Rails app
98
56
  email:
99
57
  - salbanez@example.com
100
58
  executables: []
@@ -110,16 +68,12 @@ files:
110
68
  - lib/generators/newshound/install/install_generator.rb
111
69
  - lib/generators/newshound/install/templates/newshound.rb
112
70
  - lib/newshound.rb
71
+ - lib/newshound/authorization.rb
113
72
  - lib/newshound/configuration.rb
114
- - lib/newshound/daily_report_job.rb
115
73
  - lib/newshound/exception_reporter.rb
74
+ - lib/newshound/middleware/banner_injector.rb
116
75
  - lib/newshound/que_reporter.rb
117
76
  - lib/newshound/railtie.rb
118
- - lib/newshound/scheduler.rb
119
- - lib/newshound/slack_notifier.rb
120
- - lib/newshound/transport/base.rb
121
- - lib/newshound/transport/slack.rb
122
- - lib/newshound/transport/sns.rb
123
77
  - lib/newshound/version.rb
124
78
  - newshound.gemspec
125
79
  homepage: https://github.com/salbanez/newshound
@@ -145,5 +99,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
99
  requirements: []
146
100
  rubygems_version: 3.6.9
147
101
  specification_version: 4
148
- summary: Daily Slack reporter for Que jobs status and exception tracking
102
+ summary: Real-time web UI banner for monitoring Que jobs and exception tracking
149
103
  test_files: []
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Newshound
4
- if defined?(::Que::Job)
5
- class DailyReportJob < ::Que::Job
6
- def run
7
- return unless Newshound.configuration.valid?
8
-
9
- Newshound.report!
10
-
11
- destroy
12
- rescue StandardError => e
13
- Rails.logger.error "Newshound::DailyReportJob failed: #{e.message}"
14
- Rails.logger.error e.backtrace.join("\n")
15
-
16
- # Re-raise to let Que handle retry logic
17
- raise
18
- end
19
- end
20
- else
21
- class DailyReportJob
22
- def self.enqueue(*args)
23
- Rails.logger.warn "Que is not available. DailyReportJob cannot be enqueued."
24
- end
25
-
26
- def run
27
- Rails.logger.warn "Que is not available. DailyReportJob cannot be run."
28
- end
29
- end
30
- end
31
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Newshound
4
- class Scheduler
5
- def self.schedule_daily_report
6
- return unless defined?(::Que::Scheduler)
7
-
8
- config = Newshound.configuration
9
- return unless config.valid?
10
-
11
- # Note: Que-scheduler uses a YAML config file (config/que_schedule.yml)
12
- # This method returns the configuration that should be added to that file
13
- # or can be used to manually schedule the job
14
- schedule_config = {
15
- "newshound_daily_report" => {
16
- "class" => "Newshound::DailyReportJob",
17
- "cron" => build_cron_expression(config.report_time),
18
- "queue" => "default",
19
- "args" => []
20
- }
21
- }
22
-
23
- # Log the configuration for visibility
24
- if defined?(Rails) && Rails.logger
25
- Rails.logger.info "Newshound daily report scheduled for #{config.report_time} (cron: #{schedule_config['newshound_daily_report']['cron']})"
26
- end
27
-
28
- schedule_config
29
- end
30
-
31
- def self.build_cron_expression(time_string)
32
- # Convert "09:00" format to cron expression
33
- # Format: minute hour * * *
34
- hour, minute = time_string.split(":").map(&:to_i)
35
- "#{minute} #{hour} * * *"
36
- end
37
-
38
- def self.run_now!
39
- Newshound::DailyReportJob.enqueue
40
- end
41
- end
42
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "slack-ruby-client"
4
-
5
- module Newshound
6
- class SlackNotifier
7
- attr_reader :configuration, :logger, :transport
8
-
9
- def initialize(configuration: nil, logger: nil, transport: nil)
10
- @configuration = configuration || Newshound.configuration
11
- @logger = logger || (defined?(Rails) ? Rails.logger : Logger.new(STDOUT))
12
- @transport = transport || build_transport
13
- end
14
-
15
- def post(message)
16
- return unless configuration.valid?
17
-
18
- transport.deliver(message)
19
- rescue StandardError => e
20
- logger.error "Newshound: Failed to send notification: #{e.message}"
21
- end
22
-
23
- private
24
-
25
- def build_transport
26
- case configuration.transport_adapter
27
- when :sns, "sns"
28
- require_relative "transport/sns"
29
- Transport::Sns.new(configuration: configuration, logger: logger)
30
- when :slack, "slack", nil
31
- require_relative "transport/slack"
32
- Transport::Slack.new(configuration: configuration, logger: logger)
33
- else
34
- if configuration.transport_adapter.is_a?(Class)
35
- configuration.transport_adapter.new(configuration: configuration, logger: logger)
36
- elsif configuration.transport_adapter.respond_to?(:new)
37
- configuration.transport_adapter.new(configuration: configuration, logger: logger)
38
- else
39
- raise ArgumentError, "Invalid transport adapter: #{configuration.transport_adapter}"
40
- end
41
- end
42
- end
43
- end
44
- end