dontbugme 0.1.3 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3c88f3e8468ff48582e0dca26ddeea1ebb66b378c57a7e96b888bdb0ca991d7
4
- data.tar.gz: ae3982763c6d291f3f1a4873fb168c9718dc296ace4053779b7c82d3f1b4b271
3
+ metadata.gz: f1bab13c641c7fb30659e5ed19ef54331355ae7239d722a585e094115b47a0a9
4
+ data.tar.gz: ab863ecd3c380117ae77c731b9a917795c0fa4bc89c0a6cbe2f0d780b5597b59
5
5
  SHA512:
6
- metadata.gz: 5c3d6729e5e7fac64ca625d0e1e4a0ec54498f124acc3cfafa47afff56839e269aa64795f1060b5bddae665f58b94ee57247ec9d26de200e7f44976cd9d726ca
7
- data.tar.gz: 86133c069405f2c75d9605fed551f2a5361ce5a0072fcfbcfde77d878da7f2934e4d0fe6ac0cb35c6301a0ddba1e9f1dcc7f44b879013338aaeaa5d0e8d8e7bb
6
+ metadata.gz: a1b4ee5fdbd1a36898a712ce07ceca1016b487d9362a61745116172250eb9cecb905919d1b327f4c2ae4e3a6e0c66cf4c97e53b4f91e8247de658cc9621e5059
7
+ data.tar.gz: e033607a2dad279edd380e60ab2633fa940a8d04189bcb2c7b0289e99bf599b2d6ecada08b590b39f137717179d03576f289e6c3e375fda634eab84b36a75878
@@ -24,7 +24,7 @@ module Dontbugme
24
24
  @trace_a = params[:a].present? ? store.find_trace(params[:a]) : nil
25
25
  @trace_b = params[:b].present? ? store.find_trace(params[:b]) : nil
26
26
  @diff_output = if @trace_a && @trace_b
27
- Formatters::Diff.format(@trace_a, @trace_b)
27
+ Dontbugme::Formatters::Diff.format(@trace_a, @trace_b)
28
28
  else
29
29
  nil
30
30
  end
@@ -6,7 +6,7 @@
6
6
  · <%= link_to "Follow chain", root_path(correlation_id: @trace.correlation_id) %>
7
7
  <% end %>
8
8
  </p>
9
- <div class="timeline"><%= Formatters::Timeline.format(@trace) %></div>
9
+ <div class="timeline"><%= Dontbugme::Formatters::Timeline.format(@trace) %></div>
10
10
  </div>
11
11
 
12
12
  <p style="margin-top: 16px;">
@@ -3,6 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <%= csrf_meta_tags %>
6
7
  <title>Dontbugme</title>
7
8
  <style>
8
9
  * { box-sizing: border-box; }
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Rails.application.routes.draw do
4
- root to: 'traces#index', as: :root
3
+ Dontbugme::Engine.routes.draw do
4
+ root to: 'traces#index'
5
5
  get 'diff', to: 'traces#diff', as: :diff
6
6
  get ':id', to: 'traces#show', as: :trace, constraints: { id: /tr_[a-f0-9]+/ }
7
7
  end
@@ -134,13 +134,11 @@ module Dontbugme
134
134
  private
135
135
 
136
136
  def retention_seconds(value, unit)
137
- return value if value.is_a?(Integer)
138
- return value.to_i if defined?(ActiveSupport) && value.respond_to?(:to_i)
139
-
140
137
  case unit
141
- when :hours then value * 3600
142
- when :days then value * 86400
143
- else value
138
+ when nil, :seconds then value.to_i
139
+ when :hours then (value.to_f * 3600).to_i
140
+ when :days then (value.to_f * 86400).to_i
141
+ else value.to_i
144
142
  end
145
143
  end
146
144
  end
@@ -9,6 +9,7 @@ module Dontbugme
9
9
 
10
10
  def call(env)
11
11
  return @app.call(env) unless Dontbugme.config.recording?
12
+ return @app.call(env) unless Dontbugme.config.should_record_request?(env)
12
13
 
13
14
  request = ::Rack::Request.new(env)
14
15
  request_id = env['action_dispatch.request_id'] || request.get_header('HTTP_X_REQUEST_ID') || SecureRandom.uuid
@@ -7,6 +7,7 @@ module Dontbugme
7
7
  return yield unless Dontbugme.config.recording?
8
8
 
9
9
  job_class = job['class'] || job[:class] || 'Unknown'
10
+ return yield unless Dontbugme.config.should_record_job?(job_class)
10
11
  jid = job['jid'] || job[:jid] || SecureRandom.hex(8)
11
12
  correlation_id = job['correlation_id'] || job[:correlation_id] || Correlation.current
12
13
  Correlation.current = correlation_id
@@ -38,7 +38,7 @@ module Dontbugme
38
38
  end
39
39
 
40
40
  def self.from_h(hash)
41
- new(
41
+ span = new(
42
42
  category: hash[:category] || hash['category'],
43
43
  operation: hash[:operation] || hash['operation'],
44
44
  detail: hash[:detail] || hash['detail'],
@@ -47,6 +47,8 @@ module Dontbugme
47
47
  duration_ms: hash[:duration_ms] || hash['duration_ms'],
48
48
  source: hash[:source] || hash['source']
49
49
  )
50
+ span.instance_variable_set(:@id, (hash[:id] || hash['id']).to_s) if hash[:id] || hash['id']
51
+ span
50
52
  end
51
53
 
52
54
  private
@@ -6,10 +6,12 @@ module Dontbugme
6
6
  def initialize(backend)
7
7
  @backend = backend
8
8
  @queue = Queue.new
9
+ @pid = Process.pid
9
10
  @thread = start_worker
10
11
  end
11
12
 
12
13
  def save_trace(trace)
14
+ restart_worker_if_forked
13
15
  @queue << [:save, trace]
14
16
  end
15
17
 
@@ -22,11 +24,19 @@ module Dontbugme
22
24
  end
23
25
 
24
26
  def cleanup(before:)
27
+ restart_worker_if_forked
25
28
  @queue << [:cleanup, before]
26
29
  end
27
30
 
28
31
  private
29
32
 
33
+ def restart_worker_if_forked
34
+ return if Process.pid == @pid
35
+
36
+ @pid = Process.pid
37
+ @thread = start_worker
38
+ end
39
+
30
40
  def start_worker
31
41
  Thread.new do
32
42
  loop do
@@ -37,6 +47,8 @@ module Dontbugme
37
47
  when :cleanup
38
48
  @backend.cleanup(before: arg)
39
49
  end
50
+ rescue StandardError => e
51
+ warn "[Dontbugme] Async store error: #{e.class} #{e.message}"
40
52
  end
41
53
  end
42
54
  end
@@ -24,7 +24,7 @@ module Dontbugme
24
24
  def search(filters = {})
25
25
  traces = @mutex.synchronize { @traces.values.dup }
26
26
  traces = apply_filters(traces, filters)
27
- traces.sort_by { |t| t[:started_at] || '' }.reverse.map { |h| Trace.from_h(h) }
27
+ traces.map { |h| Trace.from_h(h) }
28
28
  end
29
29
 
30
30
  def cleanup(before:)
@@ -37,8 +37,8 @@ module Dontbugme
37
37
  private
38
38
 
39
39
  def apply_filters(traces, filters)
40
- traces = traces.select { |t| t[:status] == filters[:status].to_s } if filters[:status]
41
- traces = traces.select { |t| t[:status] == filters['status'].to_s } if filters['status']
40
+ traces = traces.select { |t| t[:status].to_s == filters[:status].to_s } if filters[:status]
41
+ traces = traces.select { |t| t[:status].to_s == filters['status'].to_s } if filters['status']
42
42
  traces = traces.select { |t| t[:kind].to_s == filters[:kind].to_s } if filters[:kind]
43
43
  if filters[:identifier]
44
44
  pattern = /#{Regexp.escape(filters[:identifier].to_s)}/i
@@ -48,8 +48,8 @@ module Dontbugme
48
48
  cid = filters[:correlation_id].to_s
49
49
  traces = traces.select { |t| (t[:correlation_id] || t.dig(:metadata, :correlation_id)).to_s == cid }
50
50
  end
51
- traces = traces.first(filters[:limit] || filters['limit'] || 100)
52
- traces
51
+ limit = filters[:limit] || filters['limit'] || 100
52
+ traces.sort_by { |t| t[:started_at] || '' }.reverse.first(limit)
53
53
  end
54
54
 
55
55
  def parse_time(val)
@@ -14,22 +14,7 @@ module Dontbugme
14
14
  def save_trace(trace)
15
15
  data = trace.to_h
16
16
  correlation_id = data[:correlation_id] || data[:metadata]&.dig(:correlation_id)
17
- exec_params(
18
- <<~SQL,
19
- INSERT INTO dontbugme_traces
20
- (id, kind, identifier, status, started_at, duration_ms, correlation_id, metadata_json, spans_json, error_json)
21
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
22
- ON CONFLICT (id) DO UPDATE SET
23
- kind = EXCLUDED.kind,
24
- identifier = EXCLUDED.identifier,
25
- status = EXCLUDED.status,
26
- started_at = EXCLUDED.started_at,
27
- duration_ms = EXCLUDED.duration_ms,
28
- correlation_id = EXCLUDED.correlation_id,
29
- metadata_json = EXCLUDED.metadata_json,
30
- spans_json = EXCLUDED.spans_json,
31
- error_json = EXCLUDED.error_json
32
- SQL
17
+ params = [
33
18
  data[:id],
34
19
  data[:kind].to_s,
35
20
  data[:identifier],
@@ -40,7 +25,22 @@ module Dontbugme
40
25
  data[:metadata].to_json,
41
26
  data[:spans].to_json,
42
27
  data[:error]&.to_json
43
- )
28
+ ]
29
+ exec_params(<<~SQL, params)
30
+ INSERT INTO dontbugme_traces
31
+ (id, kind, identifier, status, started_at, duration_ms, correlation_id, metadata_json, spans_json, error_json)
32
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
33
+ ON CONFLICT (id) DO UPDATE SET
34
+ kind = EXCLUDED.kind,
35
+ identifier = EXCLUDED.identifier,
36
+ status = EXCLUDED.status,
37
+ started_at = EXCLUDED.started_at,
38
+ duration_ms = EXCLUDED.duration_ms,
39
+ correlation_id = EXCLUDED.correlation_id,
40
+ metadata_json = EXCLUDED.metadata_json,
41
+ spans_json = EXCLUDED.spans_json,
42
+ error_json = EXCLUDED.error_json
43
+ SQL
44
44
  end
45
45
 
46
46
  def find_trace(trace_id)
@@ -92,6 +92,8 @@ module Dontbugme
92
92
  exec_params('DELETE FROM dontbugme_traces WHERE started_at < $1', [cutoff])
93
93
  end
94
94
 
95
+ private
96
+
95
97
  def query_result(sql, params)
96
98
  if conn.respond_to?(:exec_query)
97
99
  conn.exec_query(sql, 'Dontbugme', params)
@@ -106,8 +108,6 @@ module Dontbugme
106
108
  row
107
109
  end
108
110
 
109
- private
110
-
111
111
  def conn
112
112
  @connection
113
113
  end
@@ -159,8 +159,8 @@ module Dontbugme
159
159
  conn.execute('CREATE INDEX IF NOT EXISTS idx_dontbugme_started_at ON dontbugme_traces(started_at)')
160
160
  conn.execute('CREATE INDEX IF NOT EXISTS idx_dontbugme_status ON dontbugme_traces(status)')
161
161
  conn.execute('CREATE INDEX IF NOT EXISTS idx_dontbugme_correlation_id ON dontbugme_traces(correlation_id)')
162
- rescue StandardError
163
- # Schema might already exist
162
+ rescue StandardError => e
163
+ raise e if e.message !~ /already exists/i
164
164
  end
165
165
 
166
166
  def row_to_trace(row)
@@ -75,7 +75,10 @@ module Dontbugme
75
75
  def db
76
76
  @db ||= begin
77
77
  require 'sqlite3'
78
- SQLite3::Database.new(@path)
78
+ db = SQLite3::Database.new(@path)
79
+ db.execute('PRAGMA journal_mode=WAL')
80
+ db.execute('PRAGMA busy_timeout=5000')
81
+ db
79
82
  end
80
83
  end
81
84
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Dontbugme
4
4
  module Subscribers
5
- class ActionMailer
5
+ class ActionMailer < Base
6
6
  EVENT = 'deliver.action_mailer'
7
7
 
8
8
  def self.subscribe
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Dontbugme
4
4
  module Subscribers
5
- class ActiveJob
5
+ class ActiveJob < Base
6
6
  EVENT = 'enqueue.active_job'
7
7
 
8
8
  def self.subscribe
@@ -43,7 +43,7 @@ module Dontbugme
43
43
  end
44
44
 
45
45
  def raw_spans
46
- @spans.freeze
46
+ @spans.dup
47
47
  end
48
48
 
49
49
  def finish!(error: nil)
@@ -74,12 +74,13 @@ module Dontbugme
74
74
  end
75
75
 
76
76
  def to_h
77
+ finished_at_time = @finished_at ? (@started_at_utc + (duration_ms || 0) / 1000.0) : nil
77
78
  {
78
79
  id: id,
79
80
  kind: kind,
80
81
  identifier: identifier,
81
82
  started_at: format_time(started_at_utc),
82
- finished_at: @finished_at ? format_time(Time.at(@finished_at / 1000.0).utc) : nil,
83
+ finished_at: finished_at_time ? format_time(finished_at_time) : nil,
83
84
  duration_ms: duration_ms,
84
85
  status: status,
85
86
  error: error,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dontbugme
4
- VERSION = '0.1.3'
4
+ VERSION = '0.1.4'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dontbugme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Inspector Contributors