Class: PatientHttp::Sidekiq::Stats

Inherits:
Object
  • Object
show all
Defined in:
lib/patient_http/sidekiq/stats.rb

Overview

Stores processor statistics in Redis with automatic expiration.

This singleton class tracks various metrics about async HTTP requests, including total requests, errors, refused requests, and current inflight counts across all processes. Statistics are stored in Redis with appropriate TTLs.

Constant Summary collapse

TOTALS_KEY =

Redis key prefixes

"sidekiq:patient_http:totals"
TOTALS_TTL =

TTLs

30 * 24 * 60 * 60

Instance Method Summary collapse

Constructor Details

#initialize(config = nil) ⇒ Stats

30 days in seconds



17
18
19
20
21
# File 'lib/patient_http/sidekiq/stats.rb', line 17

def initialize(config = nil)
  @hostname = ::Socket.gethostname.force_encoding("UTF-8").freeze
  @pid = ::Process.pid
  @config = config
end

Instance Method Details

#get_totalsHash

Get running totals

Returns:

  • (Hash)

    hash with requests, duration, errors, max_capacity_exceeded, http_status_counts



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/patient_http/sidekiq/stats.rb', line 74

def get_totals
  ::Sidekiq.redis do |redis|
    stats = redis.hgetall(TOTALS_KEY)

    # Extract HTTP status counts and error type counts
    http_status_counts = {}
    error_type_counts = {}
    stats.each do |key, value|
      if key.start_with?("http_status:")
        status = key.sub("http_status:", "").to_i
        http_status_counts[status] = value.to_i
      elsif key.start_with?("errors:") && key != "errors"
        error_type = key.sub("errors:", "")
        error_type_counts[error_type] = value.to_i
      end
    end

    {
      "requests" => (stats["requests"] || 0).to_i,
      "duration" => (stats["duration"] || 0).to_f.round(6),
      "errors" => (stats["errors"] || 0).to_i,
      "max_capacity_exceeded" => (stats["max_capacity_exceeded"] || 0).to_i,
      "http_status_counts" => http_status_counts.sort.to_h,
      "error_type_counts" => error_type_counts.sort.to_h
    }
  end
end

#record_capacity_exceededvoid

This method returns an undefined value.

Record a that a request was refused because the max capacity of the Processor was reached.



60
61
62
63
64
65
66
67
68
69
# File 'lib/patient_http/sidekiq/stats.rb', line 60

def record_capacity_exceeded
  ::Sidekiq.redis do |redis|
    redis.multi do |transaction|
      transaction.hincrby(TOTALS_KEY, "max_capacity_exceeded", 1)
      transaction.expire(TOTALS_KEY, TOTALS_TTL)
    end
  end
rescue => e
  handle_error(e)
end

#record_error(error_type) ⇒ void

This method returns an undefined value.

Record a request error

Parameters:

  • error_type (String)

    the type of error that occurred



45
46
47
48
49
50
51
52
53
54
55
# File 'lib/patient_http/sidekiq/stats.rb', line 45

def record_error(error_type)
  ::Sidekiq.redis do |redis|
    redis.multi do |transaction|
      transaction.hincrby(TOTALS_KEY, "errors", 1)
      transaction.hincrby(TOTALS_KEY, "errors:#{error_type}", 1)
      transaction.expire(TOTALS_KEY, TOTALS_TTL)
    end
  end
rescue => e
  handle_error(e)
end

#record_request(status, duration) ⇒ void

This method returns an undefined value.

Record a completed request.

Parameters:

  • status (Integer, nil)

    HTTP response status code

  • duration (Float)

    request duration in seconds



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/patient_http/sidekiq/stats.rb', line 28

def record_request(status, duration)
  ::Sidekiq.redis do |redis|
    redis.multi do |transaction|
      transaction.hincrby(TOTALS_KEY, "requests", 1)
      transaction.hincrbyfloat(TOTALS_KEY, "duration", duration.to_f)
      transaction.hincrby(TOTALS_KEY, "http_status:#{status}", 1) if status && status >= 100 && status < 600
      transaction.expire(TOTALS_KEY, TOTALS_TTL)
    end
  end
rescue => e
  handle_error(e)
end

#reset!void

This method returns an undefined value.

Reset all stats (useful for testing)



105
106
107
108
109
# File 'lib/patient_http/sidekiq/stats.rb', line 105

def reset!
  ::Sidekiq.redis do |redis|
    redis.del(TOTALS_KEY)
  end
end