Skip to content

Commit

Permalink
Merge pull request #1071 from appsignal/unregister-probe
Browse files Browse the repository at this point in the history
Allow probes to be unregistered
  • Loading branch information
tombruijn committed Apr 29, 2024
2 parents 9922140 + 97e154f commit f0cee05
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 6 deletions.
6 changes: 6 additions & 0 deletions .changesets/unregister-probes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
bump: "patch"
type: "change"
---

Allow unregistering minutely probes. Use `Appsignal::Probes.unregister` to unregister probes registered with `Appsignal::Probes.register` if you do not need a certain probe, including default probes.
38 changes: 35 additions & 3 deletions lib/appsignal/probes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ def internal_register(name, probe)
probes[name] = probe
end

# @api private
def unregister(name)
probes.delete(name)
end

# @api private
def each(&block)
probes.each(&block)
Expand Down Expand Up @@ -128,9 +133,10 @@ def probes
# # "started" # Printed on Appsignal::Probes.start
# # "called" # Repeated every minute
#
# @param name [Symbol/String] Name of the probe. Can be used with {[]}.
# This name will be used in errors in the log and allows overwriting of
# probes by registering new ones with the same name.
# @param name [Symbol/String] Name of the probe. Can be used with
# {ProbeCollection#[]}. This name will be used in errors in the log and
# allows overwriting of probes by registering new ones with the same
# name.
# @param probe [Object] Any object that listens to the `call` method will
# be used as a probe.
# @return [void]
Expand All @@ -140,6 +146,26 @@ def register(name, probe)
initialize_probe(name, probe) if started?
end

# Unregister a probe that's registered with {register}.
# Can also be used to unregister automatically registered probes by the
# gem.
#
# @example Unregister probes
# # First register a probe
# Appsignal::Probes.register :my_probe, lambda {}
#
# # Then unregister a probe if needed
# Appsignal::Probes.unregister :my_probe
#
# @param name [Symbol/String] Name of the probe used to {register} the
# probe.
# @return [void]
def unregister(name)
probes.unregister(name)

uninitialize_probe(name)
end

# @api private
def start
stop
Expand Down Expand Up @@ -228,6 +254,12 @@ def initialize_probe(name, probe)
logger.debug error.backtrace.join("\n")
end

def uninitialize_probe(name)
mutex.synchronize do
probe_instances.delete(name)
end
end

def dependencies_present?(probe)
return true unless probe.respond_to? :dependencies_present?

Expand Down
52 changes: 49 additions & 3 deletions spec/lib/appsignal/probes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,7 @@ def call
let(:log) { log_contents(log_stream) }
before do
Appsignal.internal_logger = test_logger(log_stream)
# Speed up test time
allow(Appsignal::Probes).to receive(:initial_wait_time).and_return(0.001)
allow(Appsignal::Probes).to receive(:wait_time).and_return(0.001)
speed_up_tests!
end

describe ".started?" do
Expand Down Expand Up @@ -261,6 +259,35 @@ def call
end
end

describe ".unregister" do
let(:log_stream) { StringIO.new }
let(:log) { log_contents(log_stream) }
before do
Appsignal.internal_logger = test_logger(log_stream)
speed_up_tests!
end

it "does not call the initialized probe after unregistering" do
probe1_calls = 0
probe2_calls = 0
probe1 = lambda { probe1_calls += 1 }
probe2 = lambda { probe2_calls += 1 }
Appsignal::Probes.register :probe1, probe1
Appsignal::Probes.register :probe2, probe2
Appsignal::Probes.start
wait_for("enough probe1 calls") { probe1_calls >= 2 }
wait_for("enough probe2 calls") { probe2_calls >= 2 }

Appsignal::Probes.unregister :probe2
probe1_calls = 0
probe2_calls = 0
# Check the probe 1 calls to make sure the probes have been called before
# testing if the unregistered probe has not been called
wait_for("enough probe1 calls") { probe1_calls >= 2 }
expect(probe2_calls).to eq(0)
end
end

describe ".stop" do
before do
allow(Appsignal::Probes).to receive(:initial_wait_time).and_return(0.001)
Expand Down Expand Up @@ -411,6 +438,19 @@ def call
end
end

describe "#unregister" do
it "removes the probe from the collection" do
expect(Appsignal::Probes).to receive(:probes).and_return(collection)

probe = lambda {}
silence { collection.register :my_probe, probe }
expect(collection[:my_probe]).to eql(probe)

silence { collection.unregister :my_probe }
expect(collection[:my_probe]).to be_nil
end
end

describe "#each" do
it "loops over the registered probes" do
probe = lambda {}
Expand All @@ -423,4 +463,10 @@ def call
end
end
end

# Speed up test time by decreasing wait times in the probes mechanism
def speed_up_tests!
allow(Appsignal::Probes).to receive(:initial_wait_time).and_return(0.001)
allow(Appsignal::Probes).to receive(:wait_time).and_return(0.001)
end
end

0 comments on commit f0cee05

Please sign in to comment.