Class: NatsWork::ErrorTracker

Inherits:
Object
  • Object
show all
Defined in:
lib/natswork/error_tracker.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ErrorTracker

Returns a new instance of ErrorTracker.



11
12
13
14
15
16
17
18
19
20
# File 'lib/natswork/error_tracker.rb', line 11

def initialize(options = {})
  @errors = Concurrent::Hash.new
  @error_counts = Concurrent::Hash.new(0)
  @error_rates = Concurrent::Hash.new { |h, k| h[k] = RateTracker.new }
  @max_errors = options.fetch(:max_errors, 1000)
  @retention_period = options.fetch(:retention_hours, 24) * 3600
  @notifiers = []

  setup_cleanup_timer
end

Instance Attribute Details

#error_ratesObject (readonly)

Returns the value of attribute error_rates.



9
10
11
# File 'lib/natswork/error_tracker.rb', line 9

def error_rates
  @error_rates
end

#errorsObject (readonly)

Returns the value of attribute errors.



9
10
11
# File 'lib/natswork/error_tracker.rb', line 9

def errors
  @errors
end

Class Method Details

.errors(limit = 50, filter = {}) ⇒ Object



231
232
233
# File 'lib/natswork/error_tracker.rb', line 231

def errors(limit = 50, filter = {})
  global.list_errors(limit, filter)
end

.globalObject



219
220
221
# File 'lib/natswork/error_tracker.rb', line 219

def global
  @global ||= new
end

.statsObject



227
228
229
# File 'lib/natswork/error_tracker.rb', line 227

def stats
  global.error_stats
end

.track(error, context = {}) ⇒ Object



223
224
225
# File 'lib/natswork/error_tracker.rb', line 223

def track(error, context = {})
  global.track_error(error, context)
end

Instance Method Details

#add_notifier(&block) ⇒ Object



81
82
83
# File 'lib/natswork/error_tracker.rb', line 81

def add_notifier(&block)
  @notifiers << block if block_given?
end

#categorize_errorsObject



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/natswork/error_tracker.rb', line 91

def categorize_errors
  categories = {
    timeout: [],
    connection: [],
    permission: [],
    validation: [],
    system: [],
    unknown: []
  }

  @errors.each do |key, error|
    category = determine_category(error)
    categories[category] << { key: key, error: error }
  end

  categories
end

#clear_errors!Object



85
86
87
88
89
# File 'lib/natswork/error_tracker.rb', line 85

def clear_errors!
  @errors.clear
  @error_counts.clear
  @error_rates.clear
end

#error_stats(error_key = nil) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/natswork/error_tracker.rb', line 58

def error_stats(error_key = nil)
  if error_key
    error = @errors[error_key]
    return nil unless error

    {
      key: error_key,
      count: error[:count],
      first_seen: error[:first_seen],
      last_seen: error[:last_seen],
      rate_1h: @error_rates[error_key].rate(3600),
      rate_24h: @error_rates[error_key].rate(86_400)
    }
  else
    {
      total_errors: @errors.size,
      total_occurrences: @error_counts.values.sum,
      most_frequent: most_frequent_errors(5),
      recent_errors: recent_errors(10)
    }
  end
end

#get_error(error_key) ⇒ Object



45
46
47
# File 'lib/natswork/error_tracker.rb', line 45

def get_error(error_key)
  @errors[error_key]
end

#list_errors(limit = 50, filter = {}) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/natswork/error_tracker.rb', line 49

def list_errors(limit = 50, filter = {})
  filtered_errors = @errors.select do |_key, error|
    matches_filter?(error, filter)
  end

  sorted_errors = filtered_errors.sort_by { |_key, error| -error[:last_seen].to_f }
  sorted_errors.first(limit).to_h
end

#track_error(error, context = {}) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/natswork/error_tracker.rb', line 22

def track_error(error, context = {})
  error_info = extract_error_info(error, context)
  error_key = generate_error_key(error_info)

  # Store error details
  @errors[error_key] = error_info.merge(
    first_seen: @errors[error_key]&.dig(:first_seen) || Time.now,
    last_seen: Time.now,
    count: @error_counts[error_key] + 1
  )

  @error_counts[error_key] += 1
  @error_rates[error_key].increment

  # Notify error handlers
  notify_error(error_info)

  # Cleanup old errors if we're over the limit
  cleanup_old_errors if @errors.size > @max_errors

  error_info
end