Class: RightSupport::Stats::Exceptions

Inherits:
Object
  • Object
show all
Includes:
Log::Mixin
Defined in:
lib/right_support/stats/exceptions.rb

Overview

Track statistics for exceptions

Constant Summary collapse

MAX_RECENT_EXCEPTIONS =

Maximum number of recent exceptions to track per category

10

Constants included from Log::Mixin

Log::Mixin::Decorator, Log::Mixin::UNDELEGATED

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Log::Mixin

default_logger, default_logger=, included

Constructor Details

#initialize(server = nil, callback = nil) ⇒ Exceptions

Initialize exception data

Parameters:

  • server (Object) (defaults to: nil)

    Server where exceptions are originating, must be defined for callbacks

  • callback (Proc) (defaults to: nil)

    Block with following parameters to be activated when an exception occurs exception [Exception] Exception message [Packet] Message being processed server [Server] Server where exception occurred



45
46
47
48
49
# File 'lib/right_support/stats/exceptions.rb', line 45

def initialize(server = nil, callback = nil)
  @server = server
  @callback = callback
  reset
end

Instance Attribute Details

#statsObject (readonly) Also known as: all

Hash

Exceptions raised per category with keys

"total" [Integer] Total exceptions for this category
"recent" [Array] Most recent as a hash of "count", "type", "message", "when", and "where"


35
36
37
# File 'lib/right_support/stats/exceptions.rb', line 35

def stats
  @stats
end

Class Method Details

.all(stats) ⇒ Hash, NilClass

Aggregate the stats from multiple ‘all’ calls

Parameters:

  • stats (Array)

    Hashes that are to be aggregated

Returns:

  • (Hash, NilClass)

    Exceptions raised per category with keys “total” [Integer] Total exceptions for this category “recent” [Array] Most recent as a hash of “count”, “type”, “message”, “when”, and “where”



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/right_support/stats/exceptions.rb', line 103

def self.all(stats)
  all = nil
  stats.each do |s|
    if s
      all ||= {}
      s.each do |category, exceptions|
        if (all_exceptions = all[category])
          all_exceptions["total"] += exceptions["total"]
          all_recent = all_exceptions["recent"]
          exceptions["recent"].each do |e|
            i = 0
            last = nil
            all_recent.each do |all_e|
              break if e["when"] < all_e["when"] && (last.nil? || e["when"] >= last["when"])
              last = all_e
              i += 1
            end
            if last && last["type"] == e["type"] && last["message"] == e["message"] && last["where"] == e["where"]
              last["count"] += e["count"]
              last["when"] = e["when"]
            else
              all_recent.insert(i, e)
              all_recent.shift if all_recent.size > MAX_RECENT_EXCEPTIONS
            end
          end
        else
          all[category] = exceptions
        end
      end
    end
  end
  all
end

Instance Method Details

#resetTrueClass

Reset statistics

Returns:

  • (TrueClass)

    Always return true



54
55
56
57
# File 'lib/right_support/stats/exceptions.rb', line 54

def reset
  @stats = nil
  true
end

#track(category, exception, message = nil) ⇒ TrueClass

Track exception statistics and optionally make callback to report exception Catch any exceptions since this function may be called from within an EM block and an exception here would then derail EM

Parameters:

  • category (String)

    Exception category

  • exception (Exception)

    Exception

Returns:

  • (TrueClass)

    Always return true



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/right_support/stats/exceptions.rb', line 67

def track(category, exception, message = nil)
  begin
    if @callback && @server
      if @callback.respond_to?(:arity) && @callback.arity.abs == 4
        @callback.call(exception, message, @server, category)
      else
        @callback.call(exception, message, @server)
      end
    end
    @stats ||= {}
    exceptions = (@stats[category] ||= {"total" => 0, "recent" => []})
    exceptions["total"] += 1
    recent = exceptions["recent"]
    last = recent.last
    where = exception.backtrace && exception.backtrace.first
    if last && last["type"] == exception.class.name && last["message"] == exception.message && last["where"] == where
      last["count"] += 1
      last["when"] = Time.now.to_i
    else
      recent.shift if recent.size >= MAX_RECENT_EXCEPTIONS
      recent.push({"count" => 1, "when" => Time.now.to_i, "type" => exception.class.name,
                   "message" => exception.message, "where" => where})
    end
  rescue Exception => e
    logger.exception("Failed to track exception '#{exception}'", e, :trace) rescue nil
  end
  true
end