Class: Aesop::Aesop

Inherits:
Object
  • Object
show all
Includes:
Aesop, Singleton
Defined in:
lib/aesop/aesop.rb

Constant Summary

Constants included from Aesop

VERSION

Instance Method Summary collapse

Methods included from Aesop

#configuration, configuration

Instance Method Details

#catch_exception(exception) ⇒ Object



29
30
31
32
33
34
35
# File 'lib/aesop/aesop.rb', line 29

def catch_exception(exception)
  log_exception(exception)
  store_exception_occurrence(exception)
  if should_dispatch?(exception)
    dispatch_exception(exception)
  end
end

#catch_exceptions(exceptions) ⇒ Object



21
22
23
24
25
26
27
# File 'lib/aesop/aesop.rb', line 21

def catch_exceptions( exceptions )
  if exceptions.is_a?(Array)
    exceptions.each{ |e| catch_exception(e) }
  else
    raise IllegalArgumentException.new("#catch_exceptions should be called with an Array as argument, maybe use #catch_exception instead?")
  end
end

#dispatch_exception(exception) ⇒ Object



68
69
70
71
# File 'lib/aesop/aesop.rb', line 68

def dispatch_exception(exception)
  record_exception_dispatch(exception)
  Aesop::Dispatcher.instance.dispatch_exception(exception)
end

#exception_already_dispatched?(exception) ⇒ Boolean

Returns:

  • (Boolean)


73
74
75
76
77
# File 'lib/aesop/aesop.rb', line 73

def exception_already_dispatched?(exception)
  res = !redis.get( "#{exception_prefix}:#{exception.class.to_s}:dispatched" ).nil?
  Aesop::Logger.debug("#{exception.class.to_s} has #{res ? "already" : "not yet"} been dispatched")
  res
end

#exception_count_threshold(exception) ⇒ Object



60
61
62
# File 'lib/aesop/aesop.rb', line 60

def exception_count_threshold(exception)
  configuration.exception_count_threshold
end

#exception_prefixObject



85
86
87
# File 'lib/aesop/aesop.rb', line 85

def exception_prefix
  configuration.exception_prefix
end

#exception_time_threshold(exception) ⇒ Object



109
110
111
# File 'lib/aesop/aesop.rb', line 109

def exception_time_threshold( exception )
  configuration.exception_time_threshold
end

#initObject



6
7
8
9
# File 'lib/aesop/aesop.rb', line 6

def init
  load_configuration
  Aesop::Bootloader.new.boot
end

#internal_exception?(exception) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
56
57
58
# File 'lib/aesop/aesop.rb', line 53

def internal_exception?(exception)
  parts = exception.class.name.split("::")
  res = (parts.size > 1 && parts.first == "Aesop")
  Aesop::Logger.debug("#{exception.class.to_s} is #{res ? "": "not "}an internal exception and will #{res ? "" : "not "}be dispatched right away")
  res
end

#is_excluded?(exception) ⇒ Boolean

Returns:

  • (Boolean)


99
100
101
102
103
104
105
106
107
# File 'lib/aesop/aesop.rb', line 99

def is_excluded?( exception )
  res = if (exceptions = configuration.excluded_exceptions)
    exceptions.include?( exception.class )
  else
    false
  end
  Aesop::Logger.debug( "#{exception.class.to_s} is#{res ? " " : " not "}excluded")
  res
end

#load_configurationObject



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

def load_configuration
  config_file = if File.exist?("config/aesop.rb")
    File.expand_path("config/aesop.rb")
  else
    File.expand_path(File.join( File.dirname(__FILE__), '..', '..', 'config', 'init.rb'))
  end
  load config_file
  Aesop::Logger.debug("Loaded config in #{config_file}")
end

#log_exception(exception) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/aesop/aesop.rb', line 37

def log_exception(exception)
  Aesop::Logger.debug(exception.message)
  if trace = exception.backtrace
    trace.each do |line|
      Aesop::Logger.debug(line)
    end
  end
end

#record_exception_dispatch(exception) ⇒ Object



64
65
66
# File 'lib/aesop/aesop.rb', line 64

def record_exception_dispatch(exception)
  redis.set( "#{exception_prefix}:#{exception.class.to_s}:dispatched", Time.now.to_i )
end

#redisObject



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/aesop/aesop.rb', line 141

def redis
  if @redis.nil? || (@redis.client && !@redis.client.connected?)
    begin
      @redis = Redis.new(redis_options)
      @redis.select( configuration.redis.database )
    rescue => e
      raise RedisConnectionException.new( e )
    end
  end
  @redis
end

#redis_host_or_socket_optionsObject



130
131
132
133
134
135
136
137
138
139
# File 'lib/aesop/aesop.rb', line 130

def redis_host_or_socket_options
  if configuration.redis.path
    { path: configuration.redis.path }
  else
    {
      host: configuration.redis.host,
      port: configuration.redis.port,
    }
  end
end

#redis_optionsObject



122
123
124
125
126
127
128
# File 'lib/aesop/aesop.rb', line 122

def redis_options
  options = redis_host_or_socket_options
  if (password = configuration.redis.password) && !password.empty?
    options.merge!(:password => password)
  end
  options
end

#retrieve_deployment_timeObject



113
114
115
116
# File 'lib/aesop/aesop.rb', line 113

def retrieve_deployment_time
  timestamp = redis.get( configuration.deployment_key ).to_i
  Time.at(timestamp)
end

#retrieve_exception_count(exception) ⇒ Object



79
80
81
82
83
# File 'lib/aesop/aesop.rb', line 79

def retrieve_exception_count(exception)
  res = redis.get( "#{exception_prefix}:#{exception.class.to_s}:count" ).to_i
  Aesop::Logger.debug("This is occurrence number #{res} of #{exception.class.to_s}")
  res
end

#should_dispatch?(exception) ⇒ Boolean

Returns:

  • (Boolean)


46
47
48
49
50
51
# File 'lib/aesop/aesop.rb', line 46

def should_dispatch?(exception)
  return false if is_excluded?(exception) || exception_already_dispatched?(exception)
  return true if internal_exception?(exception)
  current_amount = retrieve_exception_count(exception)
  within_window?(exception) && (current_amount >= exception_count_threshold(exception))
end

#store_exception_occurrence(exception) ⇒ Object



118
119
120
# File 'lib/aesop/aesop.rb', line 118

def store_exception_occurrence(exception)
  redis.incr( "#{exception_prefix}:#{exception.class.to_s}:count" )
end

#within_window?(exception) ⇒ Boolean

Returns:

  • (Boolean)


89
90
91
92
93
94
95
96
97
# File 'lib/aesop/aesop.rb', line 89

def within_window?( exception )
  res = if deployed_time = retrieve_deployment_time
    (Time.now - deployed_time) < exception_time_threshold(exception)
  else
    false
  end
  Aesop::Logger.debug("#{exception.class.to_s} is#{res ? " " : " not "}within the window")
  res
end