Module: Appsignal::Probes

Defined in:
lib/appsignal/probes.rb,
lib/appsignal/probes/gvl.rb,
lib/appsignal/probes/mri.rb,
lib/appsignal/probes/helpers.rb,
lib/appsignal/probes/sidekiq.rb

Defined Under Namespace

Modules: Helpers Classes: GvlProbe, MriProbe, ProbeCollection, SidekiqProbe

Constant Summary collapse

ITERATION_IN_SECONDS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

60

Class Method Summary collapse

Class Method Details

.mutexObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



62
63
64
# File 'lib/appsignal/probes.rb', line 62

def mutex
  @mutex ||= Thread::Mutex.new
end

.probesProbeCollection

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns list of probes.

Returns:

See Also:



69
70
71
# File 'lib/appsignal/probes.rb', line 69

def probes
  @probes ||= ProbeCollection.new
end

.register(name, probe) ⇒ void

This method returns an undefined value.

Register a new minutely probe.

Supported probe types are:

  • Lambda - A lambda is an object that listens to a ‘call` method call. This `call` method is called every minute.

  • Class - A class object is an object that listens to a ‘new` and `call` method call. The `new` method is called when the minutely probe thread is started to initialize all probes. This allows probes to load dependencies once beforehand. Their `call` method is called every minute.

  • Class instance - A class instance object is an object that listens to a ‘call` method call. The `call` method is called every minute.

Examples:

Register a new probe

Appsignal::Probes.register :my_probe, lambda {}

Overwrite an existing registered probe

Appsignal::Probes.register :my_probe, lambda {}
Appsignal::Probes.register :my_probe, lambda { puts "hello" }

Add a lambda as a probe

Appsignal::Probes.register :my_probe, lambda { puts "hello" }
# "hello" # printed every minute

Add a probe instance

class MyProbe
  def initialize
    puts "started"
  end

  def call
    puts "called"
  end
end

Appsignal::Probes.register :my_probe, MyProbe.new
# "started" # printed immediately
# "called" # printed every minute

Add a probe class

class MyProbe
  def initialize
    # Add things that only need to be done on start up for this probe
    require "some/library/dependency"
    @cache = {} # initialize a local cache variable
    puts "started"
  end

  def call
    puts "called"
  end
end

Appsignal::Probes.register :my_probe, MyProbe
Appsignal::Probes.start # This is called for you
# "started" # Printed on Appsignal::Probes.start
# "called" # Repeated every minute

Parameters:

  • name (Symbol/String)

    Name of the probe. Can be used with Appsignal::Probes::ProbeCollection#[]. This name will be used in errors in the log and allows overwriting of probes by registering new ones with the same name.

  • probe (Object)

    Any object that listens to the ‘call` method will be used as a probe.



139
140
141
142
143
# File 'lib/appsignal/probes.rb', line 139

def register(name, probe)
  probes.internal_register(name, probe)

  initialize_probe(name, probe) if started?
end

.startObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/appsignal/probes.rb', line 166

def start
  stop
  @started = true
  @thread = Thread.new do
    # Advise multi-threaded app servers to ignore this thread
    # for the purposes of fork safety warnings
    if Thread.current.respond_to?(:thread_variable_set)
      Thread.current.thread_variable_set(:fork_safe, true)
    end

    sleep initial_wait_time
    initialize_probes
    loop do
      start_time = Time.now
      logger = Appsignal.internal_logger
      mutex.synchronize do
        logger.debug("Gathering minutely metrics with #{probe_instances.count} probes")
        probe_instances.each do |name, probe|
          logger.debug("Gathering minutely metrics with '#{name}' probe")
          probe.call
        rescue => ex
          logger.error "Error in minutely probe '#{name}': #{ex}"
          logger.debug ex.backtrace.join("\n")
        end
      end
      end_time = Time.now
      duration = end_time - start_time
      if duration >= ITERATION_IN_SECONDS
        logger.error(
          "The minutely probes took more than 60 seconds. " \
            "The probes should not take this long as metrics will not " \
            "be accurately reported."
        )
      end
      sleep wait_time
    end
  end
end

.started?Boolean?

Returns if the probes thread has been started. If the value is false or nil, it has not been started yet.

Returns:

  • (Boolean, nil)


209
210
211
# File 'lib/appsignal/probes.rb', line 209

def started?
  @started
end

.stopObject

Stop the minutely probes mechanism. Stop the thread and clear all probe instances.



215
216
217
218
219
# File 'lib/appsignal/probes.rb', line 215

def stop
  defined?(@thread) && @thread.kill
  @started = false
  probe_instances.clear
end

.unregister(name) ⇒ void

This method returns an undefined value.

Unregister a probe that’s registered with register. Can also be used to unregister automatically registered probes by the gem.

Examples:

Unregister probes

# First register a probe
Appsignal::Probes.register :my_probe, lambda {}

# Then unregister a probe if needed
Appsignal::Probes.unregister :my_probe

Parameters:

  • name (Symbol/String)

    Name of the probe used to register the probe.



159
160
161
162
163
# File 'lib/appsignal/probes.rb', line 159

def unregister(name)
  probes.unregister(name)

  uninitialize_probe(name)
end

.wait_timeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



222
223
224
# File 'lib/appsignal/probes.rb', line 222

def wait_time
  ITERATION_IN_SECONDS - Time.now.sec
end