brainzlab 0.1.2 → 0.1.4

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.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +6 -21
  3. data/README.md +16 -2
  4. data/lib/brainzlab/beacon/client.rb +38 -40
  5. data/lib/brainzlab/beacon/provisioner.rb +1 -1
  6. data/lib/brainzlab/beacon.rb +15 -15
  7. data/lib/brainzlab/configuration.rb +112 -90
  8. data/lib/brainzlab/context.rb +2 -3
  9. data/lib/brainzlab/cortex/client.rb +29 -31
  10. data/lib/brainzlab/cortex/provisioner.rb +1 -1
  11. data/lib/brainzlab/cortex.rb +7 -11
  12. data/lib/brainzlab/dendrite/client.rb +42 -44
  13. data/lib/brainzlab/dendrite/provisioner.rb +1 -1
  14. data/lib/brainzlab/dendrite.rb +4 -4
  15. data/lib/brainzlab/devtools/data/collector.rb +22 -22
  16. data/lib/brainzlab/devtools/middleware/asset_server.rb +14 -14
  17. data/lib/brainzlab/devtools/middleware/database_handler.rb +52 -55
  18. data/lib/brainzlab/devtools/middleware/debug_panel.rb +19 -19
  19. data/lib/brainzlab/devtools/middleware/error_page.rb +45 -44
  20. data/lib/brainzlab/devtools/renderers/debug_panel_renderer.rb +39 -35
  21. data/lib/brainzlab/devtools/renderers/error_page_renderer.rb +13 -9
  22. data/lib/brainzlab/devtools.rb +11 -11
  23. data/lib/brainzlab/flux/buffer.rb +3 -3
  24. data/lib/brainzlab/flux/client.rb +14 -16
  25. data/lib/brainzlab/flux/provisioner.rb +13 -13
  26. data/lib/brainzlab/flux.rb +8 -8
  27. data/lib/brainzlab/instrumentation/action_cable.rb +351 -0
  28. data/lib/brainzlab/instrumentation/action_controller.rb +649 -0
  29. data/lib/brainzlab/instrumentation/action_dispatch.rb +259 -0
  30. data/lib/brainzlab/instrumentation/action_mailbox.rb +197 -0
  31. data/lib/brainzlab/instrumentation/action_mailer.rb +14 -13
  32. data/lib/brainzlab/instrumentation/action_view.rb +380 -0
  33. data/lib/brainzlab/instrumentation/active_job.rb +569 -0
  34. data/lib/brainzlab/instrumentation/active_record.rb +467 -36
  35. data/lib/brainzlab/instrumentation/active_storage.rb +541 -0
  36. data/lib/brainzlab/instrumentation/active_support_cache.rb +700 -0
  37. data/lib/brainzlab/instrumentation/aws.rb +43 -39
  38. data/lib/brainzlab/instrumentation/dalli.rb +20 -20
  39. data/lib/brainzlab/instrumentation/delayed_job.rb +27 -29
  40. data/lib/brainzlab/instrumentation/elasticsearch.rb +23 -24
  41. data/lib/brainzlab/instrumentation/excon.rb +27 -27
  42. data/lib/brainzlab/instrumentation/faraday.rb +3 -4
  43. data/lib/brainzlab/instrumentation/good_job.rb +28 -28
  44. data/lib/brainzlab/instrumentation/grape.rb +24 -24
  45. data/lib/brainzlab/instrumentation/graphql.rb +24 -23
  46. data/lib/brainzlab/instrumentation/httparty.rb +13 -14
  47. data/lib/brainzlab/instrumentation/mongodb.rb +7 -7
  48. data/lib/brainzlab/instrumentation/net_http.rb +6 -6
  49. data/lib/brainzlab/instrumentation/rails_deprecation.rb +139 -0
  50. data/lib/brainzlab/instrumentation/railties.rb +134 -0
  51. data/lib/brainzlab/instrumentation/redis.rb +14 -21
  52. data/lib/brainzlab/instrumentation/resque.rb +23 -24
  53. data/lib/brainzlab/instrumentation/sidekiq.rb +29 -28
  54. data/lib/brainzlab/instrumentation/solid_queue.rb +37 -41
  55. data/lib/brainzlab/instrumentation/stripe.rb +36 -37
  56. data/lib/brainzlab/instrumentation/typhoeus.rb +19 -17
  57. data/lib/brainzlab/instrumentation.rb +111 -21
  58. data/lib/brainzlab/nerve/client.rb +38 -40
  59. data/lib/brainzlab/nerve/provisioner.rb +1 -1
  60. data/lib/brainzlab/nerve.rb +6 -6
  61. data/lib/brainzlab/pulse/client.rb +15 -11
  62. data/lib/brainzlab/pulse/instrumentation.rb +61 -57
  63. data/lib/brainzlab/pulse/propagation.rb +28 -28
  64. data/lib/brainzlab/pulse/provisioner.rb +12 -12
  65. data/lib/brainzlab/pulse/tracer.rb +3 -3
  66. data/lib/brainzlab/pulse.rb +13 -13
  67. data/lib/brainzlab/rails/log_formatter.rb +127 -121
  68. data/lib/brainzlab/rails/log_subscriber.rb +70 -76
  69. data/lib/brainzlab/rails/railtie.rb +66 -89
  70. data/lib/brainzlab/recall/buffer.rb +1 -1
  71. data/lib/brainzlab/recall/client.rb +14 -10
  72. data/lib/brainzlab/recall/logger.rb +16 -18
  73. data/lib/brainzlab/recall/provisioner.rb +16 -16
  74. data/lib/brainzlab/recall.rb +11 -13
  75. data/lib/brainzlab/reflex/breadcrumbs.rb +2 -2
  76. data/lib/brainzlab/reflex/client.rb +14 -10
  77. data/lib/brainzlab/reflex/provisioner.rb +12 -12
  78. data/lib/brainzlab/reflex.rb +29 -29
  79. data/lib/brainzlab/sentinel/client.rb +40 -42
  80. data/lib/brainzlab/sentinel/provisioner.rb +1 -1
  81. data/lib/brainzlab/sentinel.rb +5 -5
  82. data/lib/brainzlab/signal/client.rb +12 -14
  83. data/lib/brainzlab/signal/provisioner.rb +12 -12
  84. data/lib/brainzlab/signal.rb +7 -7
  85. data/lib/brainzlab/synapse/client.rb +42 -44
  86. data/lib/brainzlab/synapse/provisioner.rb +1 -1
  87. data/lib/brainzlab/synapse.rb +6 -6
  88. data/lib/brainzlab/utilities/circuit_breaker.rb +37 -41
  89. data/lib/brainzlab/utilities/health_check.rb +53 -55
  90. data/lib/brainzlab/utilities/log_formatter.rb +38 -40
  91. data/lib/brainzlab/utilities/rate_limiter.rb +5 -5
  92. data/lib/brainzlab/utilities.rb +4 -4
  93. data/lib/brainzlab/vault/cache.rb +1 -1
  94. data/lib/brainzlab/vault/client.rb +39 -41
  95. data/lib/brainzlab/vault/provisioner.rb +1 -1
  96. data/lib/brainzlab/vault.rb +19 -25
  97. data/lib/brainzlab/version.rb +1 -1
  98. data/lib/brainzlab/vision/client.rb +20 -20
  99. data/lib/brainzlab/vision/provisioner.rb +21 -21
  100. data/lib/brainzlab/vision.rb +17 -19
  101. data/lib/brainzlab-sdk.rb +1 -1
  102. data/lib/brainzlab.rb +22 -24
  103. data/lib/generators/brainzlab/install/install_generator.rb +29 -27
  104. metadata +11 -1
@@ -0,0 +1,259 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BrainzLab
4
+ module Instrumentation
5
+ class ActionDispatch
6
+ # Thresholds for slow operations (in milliseconds)
7
+ SLOW_MIDDLEWARE_THRESHOLD = 50
8
+ VERY_SLOW_MIDDLEWARE_THRESHOLD = 200
9
+
10
+ class << self
11
+ def install!
12
+ return unless defined?(::ActionDispatch)
13
+ return if @installed
14
+
15
+ install_process_middleware_subscriber!
16
+ install_redirect_subscriber!
17
+ install_request_subscriber!
18
+
19
+ @installed = true
20
+ BrainzLab.debug_log('ActionDispatch instrumentation installed')
21
+ end
22
+
23
+ def installed?
24
+ @installed == true
25
+ end
26
+
27
+ private
28
+
29
+ # ============================================
30
+ # process_middleware.action_dispatch
31
+ # Fired when a middleware in the stack runs
32
+ # ============================================
33
+ def install_process_middleware_subscriber!
34
+ ActiveSupport::Notifications.subscribe('process_middleware.action_dispatch') do |*args|
35
+ event = ActiveSupport::Notifications::Event.new(*args)
36
+ handle_process_middleware(event)
37
+ end
38
+ end
39
+
40
+ def handle_process_middleware(event)
41
+ payload = event.payload
42
+ duration = event.duration.round(2)
43
+
44
+ middleware = payload[:middleware]
45
+
46
+ # Skip fast middleware to reduce noise
47
+ return if duration < 1
48
+
49
+ # Determine level based on duration
50
+ level = case duration
51
+ when 0...SLOW_MIDDLEWARE_THRESHOLD then :info
52
+ when SLOW_MIDDLEWARE_THRESHOLD...VERY_SLOW_MIDDLEWARE_THRESHOLD then :warning
53
+ else :error
54
+ end
55
+
56
+ # Record breadcrumb
57
+ if BrainzLab.configuration.reflex_effectively_enabled?
58
+ BrainzLab::Reflex.add_breadcrumb(
59
+ "Middleware: #{middleware} (#{duration}ms)",
60
+ category: 'dispatch.middleware',
61
+ level: level,
62
+ data: {
63
+ middleware: middleware,
64
+ duration_ms: duration
65
+ }.compact
66
+ )
67
+ end
68
+
69
+ # Add Pulse span
70
+ record_middleware_span(event, middleware, duration)
71
+
72
+ # Log slow middleware
73
+ if duration >= SLOW_MIDDLEWARE_THRESHOLD && BrainzLab.configuration.recall_effectively_enabled?
74
+ log_level = duration >= VERY_SLOW_MIDDLEWARE_THRESHOLD ? :error : :warn
75
+ BrainzLab::Recall.send(
76
+ log_level,
77
+ "Slow middleware: #{middleware} (#{duration}ms)",
78
+ middleware: middleware,
79
+ duration_ms: duration
80
+ )
81
+ end
82
+ rescue StandardError => e
83
+ BrainzLab.debug_log("ActionDispatch process_middleware instrumentation failed: #{e.message}")
84
+ end
85
+
86
+ # ============================================
87
+ # redirect.action_dispatch
88
+ # Fired when a redirect response is sent
89
+ # ============================================
90
+ def install_redirect_subscriber!
91
+ ActiveSupport::Notifications.subscribe('redirect.action_dispatch') do |*args|
92
+ event = ActiveSupport::Notifications::Event.new(*args)
93
+ handle_redirect(event)
94
+ end
95
+ end
96
+
97
+ def handle_redirect(event)
98
+ payload = event.payload
99
+ duration = event.duration.round(2)
100
+
101
+ status = payload[:status]
102
+ location = payload[:location]
103
+ request = payload[:request]
104
+
105
+ # Record breadcrumb
106
+ if BrainzLab.configuration.reflex_effectively_enabled?
107
+ BrainzLab::Reflex.add_breadcrumb(
108
+ "Redirect #{status}: #{truncate_url(location)}",
109
+ category: 'dispatch.redirect',
110
+ level: :info,
111
+ data: {
112
+ status: status,
113
+ location: truncate_url(location),
114
+ duration_ms: duration
115
+ }.compact
116
+ )
117
+ end
118
+
119
+ # Add Pulse span
120
+ record_redirect_span(event, status, location, duration)
121
+ rescue StandardError => e
122
+ BrainzLab.debug_log("ActionDispatch redirect instrumentation failed: #{e.message}")
123
+ end
124
+
125
+ # ============================================
126
+ # request.action_dispatch
127
+ # Fired for the full request lifecycle
128
+ # ============================================
129
+ def install_request_subscriber!
130
+ ActiveSupport::Notifications.subscribe('request.action_dispatch') do |*args|
131
+ event = ActiveSupport::Notifications::Event.new(*args)
132
+ handle_request(event)
133
+ end
134
+ end
135
+
136
+ def handle_request(event)
137
+ payload = event.payload
138
+ duration = event.duration.round(2)
139
+
140
+ request = payload[:request]
141
+ response = payload[:response]
142
+
143
+ method = request&.method
144
+ path = request&.path
145
+ status = response&.status
146
+
147
+ # Record breadcrumb
148
+ if BrainzLab.configuration.reflex_effectively_enabled?
149
+ level = status && status >= 400 ? :warning : :info
150
+ level = :error if status && status >= 500
151
+
152
+ BrainzLab::Reflex.add_breadcrumb(
153
+ "Request: #{method} #{path} -> #{status} (#{duration}ms)",
154
+ category: 'dispatch.request',
155
+ level: level,
156
+ data: {
157
+ method: method,
158
+ path: path,
159
+ status: status,
160
+ duration_ms: duration
161
+ }.compact
162
+ )
163
+ end
164
+
165
+ # Add Pulse span
166
+ record_request_span(event, method, path, status, duration)
167
+ rescue StandardError => e
168
+ BrainzLab.debug_log("ActionDispatch request instrumentation failed: #{e.message}")
169
+ end
170
+
171
+ # ============================================
172
+ # Span Recording Helpers
173
+ # ============================================
174
+ def record_middleware_span(event, middleware, duration)
175
+ return unless BrainzLab.configuration.pulse_effectively_enabled?
176
+
177
+ tracer = BrainzLab::Pulse.tracer
178
+ return unless tracer.current_trace
179
+
180
+ span_data = {
181
+ span_id: SecureRandom.uuid,
182
+ name: "middleware.#{middleware.to_s.demodulize.underscore}",
183
+ kind: 'middleware',
184
+ started_at: event.time,
185
+ ended_at: event.end,
186
+ duration_ms: duration,
187
+ error: false,
188
+ data: {
189
+ 'middleware.class' => middleware
190
+ }.compact
191
+ }
192
+
193
+ tracer.current_spans << span_data
194
+ end
195
+
196
+ def record_redirect_span(event, status, location, duration)
197
+ return unless BrainzLab.configuration.pulse_effectively_enabled?
198
+
199
+ tracer = BrainzLab::Pulse.tracer
200
+ return unless tracer.current_trace
201
+
202
+ span_data = {
203
+ span_id: SecureRandom.uuid,
204
+ name: 'dispatch.redirect',
205
+ kind: 'http',
206
+ started_at: event.time,
207
+ ended_at: event.end,
208
+ duration_ms: duration,
209
+ error: false,
210
+ data: {
211
+ 'http.status' => status,
212
+ 'http.redirect_location' => truncate_url(location)
213
+ }.compact
214
+ }
215
+
216
+ tracer.current_spans << span_data
217
+ end
218
+
219
+ def record_request_span(event, method, path, status, duration)
220
+ return unless BrainzLab.configuration.pulse_effectively_enabled?
221
+
222
+ tracer = BrainzLab::Pulse.tracer
223
+ return unless tracer.current_trace
224
+
225
+ span_data = {
226
+ span_id: SecureRandom.uuid,
227
+ name: 'dispatch.request',
228
+ kind: 'http',
229
+ started_at: event.time,
230
+ ended_at: event.end,
231
+ duration_ms: duration,
232
+ error: status && status >= 500,
233
+ data: {
234
+ 'http.method' => method,
235
+ 'http.path' => path,
236
+ 'http.status' => status
237
+ }.compact
238
+ }
239
+
240
+ tracer.current_spans << span_data
241
+ end
242
+
243
+ # ============================================
244
+ # Helper Methods
245
+ # ============================================
246
+ def truncate_url(url, max_length = 200)
247
+ return 'unknown' unless url
248
+
249
+ url_str = url.to_s
250
+ if url_str.length > max_length
251
+ "#{url_str[0, max_length - 3]}..."
252
+ else
253
+ url_str
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BrainzLab
4
+ module Instrumentation
5
+ class ActionMailbox
6
+ # Thresholds for slow processing (in milliseconds)
7
+ SLOW_PROCESSING_THRESHOLD = 1000 # 1 second
8
+ VERY_SLOW_PROCESSING_THRESHOLD = 5000 # 5 seconds
9
+
10
+ class << self
11
+ def install!
12
+ return unless defined?(::ActionMailbox)
13
+ return if @installed
14
+
15
+ install_process_subscriber!
16
+
17
+ @installed = true
18
+ BrainzLab.debug_log('ActionMailbox instrumentation installed')
19
+ end
20
+
21
+ def installed?
22
+ @installed == true
23
+ end
24
+
25
+ private
26
+
27
+ # ============================================
28
+ # process.action_mailbox
29
+ # Fired when an inbound email is processed
30
+ # ============================================
31
+ def install_process_subscriber!
32
+ ActiveSupport::Notifications.subscribe('process.action_mailbox') do |*args|
33
+ event = ActiveSupport::Notifications::Event.new(*args)
34
+ handle_process(event)
35
+ end
36
+ end
37
+
38
+ def handle_process(event)
39
+ payload = event.payload
40
+ duration = event.duration.round(2)
41
+
42
+ mailbox = payload[:mailbox]
43
+ inbound_email = payload[:inbound_email]
44
+
45
+ mailbox_class = mailbox.is_a?(Class) ? mailbox.name : mailbox.class.name
46
+ email_id = inbound_email&.id
47
+ email_status = inbound_email&.status
48
+ message_id = inbound_email&.message_id
49
+
50
+ # Extract sender/recipient info if available
51
+ from = extract_from(inbound_email)
52
+ to = extract_to(inbound_email)
53
+ subject = extract_subject(inbound_email)
54
+
55
+ # Determine level based on duration
56
+ level = case duration
57
+ when 0...SLOW_PROCESSING_THRESHOLD then :info
58
+ when SLOW_PROCESSING_THRESHOLD...VERY_SLOW_PROCESSING_THRESHOLD then :warning
59
+ else :error
60
+ end
61
+
62
+ # Record breadcrumb
63
+ if BrainzLab.configuration.reflex_effectively_enabled?
64
+ BrainzLab::Reflex.add_breadcrumb(
65
+ "Mailbox process: #{mailbox_class} (#{duration}ms)",
66
+ category: 'mailbox.process',
67
+ level: level,
68
+ data: {
69
+ mailbox: mailbox_class,
70
+ email_id: email_id,
71
+ status: email_status,
72
+ message_id: truncate(message_id),
73
+ from: truncate(from),
74
+ subject: truncate(subject, 100),
75
+ duration_ms: duration
76
+ }.compact
77
+ )
78
+ end
79
+
80
+ # Add Pulse span
81
+ record_process_span(event, mailbox_class, email_id, duration, email_status, from, to, subject)
82
+
83
+ # Log to Recall
84
+ log_email_processing(mailbox_class, email_id, email_status, duration, from, to, subject)
85
+ rescue StandardError => e
86
+ BrainzLab.debug_log("ActionMailbox process instrumentation failed: #{e.message}")
87
+ end
88
+
89
+ # ============================================
90
+ # Span Recording
91
+ # ============================================
92
+ def record_process_span(event, mailbox_class, email_id, duration, status, from, to, subject)
93
+ return unless BrainzLab.configuration.pulse_effectively_enabled?
94
+
95
+ tracer = BrainzLab::Pulse.tracer
96
+ return unless tracer.current_trace
97
+
98
+ span_data = {
99
+ span_id: SecureRandom.uuid,
100
+ name: "mailbox.process.#{mailbox_class.underscore}",
101
+ kind: 'mailbox',
102
+ started_at: event.time,
103
+ ended_at: event.end,
104
+ duration_ms: duration,
105
+ error: status == 'bounced' || status == 'failed',
106
+ data: {
107
+ 'mailbox.class' => mailbox_class,
108
+ 'mailbox.email_id' => email_id,
109
+ 'mailbox.status' => status,
110
+ 'mailbox.from' => truncate(from),
111
+ 'mailbox.to' => truncate(to),
112
+ 'mailbox.subject' => truncate(subject, 100)
113
+ }.compact
114
+ }
115
+
116
+ tracer.current_spans << span_data
117
+ end
118
+
119
+ # ============================================
120
+ # Logging
121
+ # ============================================
122
+ def log_email_processing(mailbox_class, email_id, status, duration, from, to, subject)
123
+ return unless BrainzLab.configuration.recall_effectively_enabled?
124
+
125
+ # Determine log level based on status and duration
126
+ if status == 'bounced' || status == 'failed'
127
+ BrainzLab::Recall.error(
128
+ "Mailbox processing failed: #{mailbox_class}",
129
+ mailbox: mailbox_class,
130
+ email_id: email_id,
131
+ status: status,
132
+ from: from,
133
+ to: to,
134
+ subject: truncate(subject, 200),
135
+ duration_ms: duration
136
+ )
137
+ elsif duration >= SLOW_PROCESSING_THRESHOLD
138
+ level = duration >= VERY_SLOW_PROCESSING_THRESHOLD ? :error : :warn
139
+ BrainzLab::Recall.send(
140
+ level,
141
+ "Slow mailbox processing: #{mailbox_class} (#{duration}ms)",
142
+ mailbox: mailbox_class,
143
+ email_id: email_id,
144
+ status: status,
145
+ duration_ms: duration,
146
+ threshold_exceeded: duration >= VERY_SLOW_PROCESSING_THRESHOLD ? 'critical' : 'warning'
147
+ )
148
+ end
149
+ end
150
+
151
+ # ============================================
152
+ # Helper Methods
153
+ # ============================================
154
+ def extract_from(inbound_email)
155
+ return nil unless inbound_email
156
+
157
+ if inbound_email.respond_to?(:mail) && inbound_email.mail.respond_to?(:from)
158
+ Array(inbound_email.mail.from).first
159
+ end
160
+ rescue StandardError
161
+ nil
162
+ end
163
+
164
+ def extract_to(inbound_email)
165
+ return nil unless inbound_email
166
+
167
+ if inbound_email.respond_to?(:mail) && inbound_email.mail.respond_to?(:to)
168
+ Array(inbound_email.mail.to).first
169
+ end
170
+ rescue StandardError
171
+ nil
172
+ end
173
+
174
+ def extract_subject(inbound_email)
175
+ return nil unless inbound_email
176
+
177
+ if inbound_email.respond_to?(:mail) && inbound_email.mail.respond_to?(:subject)
178
+ inbound_email.mail.subject
179
+ end
180
+ rescue StandardError
181
+ nil
182
+ end
183
+
184
+ def truncate(value, max_length = 200)
185
+ return nil unless value
186
+
187
+ str = value.to_s
188
+ if str.length > max_length
189
+ "#{str[0, max_length - 3]}..."
190
+ else
191
+ str
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
@@ -11,19 +11,19 @@ module BrainzLab
11
11
  return if @installed
12
12
 
13
13
  # Subscribe to deliver notification
14
- ActiveSupport::Notifications.subscribe("deliver.action_mailer") do |*args|
14
+ ActiveSupport::Notifications.subscribe('deliver.action_mailer') do |*args|
15
15
  event = ActiveSupport::Notifications::Event.new(*args)
16
16
  record_delivery(event)
17
17
  end
18
18
 
19
19
  # Subscribe to process notification (when mail is being prepared)
20
- ActiveSupport::Notifications.subscribe("process.action_mailer") do |*args|
20
+ ActiveSupport::Notifications.subscribe('process.action_mailer') do |*args|
21
21
  event = ActiveSupport::Notifications::Event.new(*args)
22
22
  record_process(event)
23
23
  end
24
24
 
25
25
  @installed = true
26
- BrainzLab.debug_log("ActionMailer instrumentation installed")
26
+ BrainzLab.debug_log('ActionMailer instrumentation installed')
27
27
  end
28
28
 
29
29
  def installed?
@@ -46,13 +46,13 @@ module BrainzLab
46
46
  mail = payload[:mail]
47
47
  to = sanitize_recipients(mail&.to)
48
48
  subject = mail&.subject
49
- delivery_method = payload[:perform_deliveries] ? "delivered" : "skipped"
49
+ delivery_method = payload[:perform_deliveries] ? 'delivered' : 'skipped'
50
50
 
51
51
  # Add breadcrumb for Reflex
52
52
  if BrainzLab.configuration.reflex_enabled
53
53
  BrainzLab::Reflex.add_breadcrumb(
54
54
  "Mail #{delivery_method}: #{mailer}",
55
- category: "mailer.deliver",
55
+ category: 'mailer.deliver',
56
56
  level: :info,
57
57
  data: {
58
58
  mailer: mailer,
@@ -67,13 +67,13 @@ module BrainzLab
67
67
  # Record span for Pulse
68
68
  record_span(
69
69
  name: "Mail deliver #{mailer}",
70
- kind: "mailer",
70
+ kind: 'mailer',
71
71
  started_at: event.time,
72
72
  ended_at: event.end,
73
73
  duration_ms: duration_ms,
74
74
  data: {
75
75
  mailer: mailer,
76
- action: "deliver",
76
+ action: 'deliver',
77
77
  to: to,
78
78
  subject: truncate_subject(subject),
79
79
  message_id: message_id,
@@ -106,7 +106,7 @@ module BrainzLab
106
106
  if BrainzLab.configuration.reflex_enabled
107
107
  BrainzLab::Reflex.add_breadcrumb(
108
108
  "Mail process: #{mailer}##{action}",
109
- category: "mailer.process",
109
+ category: 'mailer.process',
110
110
  level: :info,
111
111
  data: {
112
112
  mailer: mailer,
@@ -119,7 +119,7 @@ module BrainzLab
119
119
  # Record span for Pulse
120
120
  record_span(
121
121
  name: "Mail process #{mailer}##{action}",
122
- kind: "mailer",
122
+ kind: 'mailer',
123
123
  started_at: event.time,
124
124
  ended_at: event.end,
125
125
  duration_ms: duration_ms,
@@ -152,27 +152,28 @@ module BrainzLab
152
152
 
153
153
  case recipients
154
154
  when Array
155
- recipients.map { |r| mask_email(r) }.join(", ")
155
+ recipients.map { |r| mask_email(r) }.join(', ')
156
156
  else
157
157
  mask_email(recipients.to_s)
158
158
  end
159
159
  end
160
160
 
161
161
  def mask_email(email)
162
- return email unless email.include?("@")
162
+ return email unless email.include?('@')
163
163
 
164
- local, domain = email.split("@", 2)
164
+ local, domain = email.split('@', 2)
165
165
  if local.length > 2
166
166
  "#{local[0..1]}***@#{domain}"
167
167
  else
168
168
  "***@#{domain}"
169
169
  end
170
170
  rescue StandardError
171
- "[email]"
171
+ '[email]'
172
172
  end
173
173
 
174
174
  def truncate_subject(subject)
175
175
  return nil unless subject
176
+
176
177
  subject.to_s[0, 100]
177
178
  end
178
179
  end