Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ executors:
- image: quay.io/minio/minio
command: ["server", "/data"]
- image: s12v/sns
- image: public.ecr.aws/docker/library/rabbitmq:latest
- image: public.ecr.aws/docker/library/rabbitmq:4.2
- image: public.ecr.aws/sprig/elasticmq-native
- image: public.ecr.aws/docker/library/mongo:5-focal
mysql2:
Expand Down
37 changes: 33 additions & 4 deletions lib/instana/backend/host_agent_reporting_observer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,59 @@ class HostAgentReportingObserver
TRACES_DATA_URL = "/com.instana.plugin.ruby/traces.%i".freeze
TRACE_METRICS_URL = "/tracermetrics".freeze

attr_reader :report_timer
attr_reader :metrics_timer, :traces_timer

# @param [RequestClient] client used to make requests to the backend
# @param [Concurrent::Atom] discovery object used to store discovery response in
def initialize(client, discovery, logger: ::Instana.logger, timer_class: Concurrent::TimerTask, processor: ::Instana.processor)
@client = client
@discovery = discovery
@logger = logger
@report_timer = timer_class.new(execution_interval: 1, run_now: true) { report_to_backend }
@timer_class = timer_class
@nonce = Time.now
@processor = processor

# Initialize timers with default 1 second interval
@metrics_timer = @timer_class.new(execution_interval: 1, run_now: true) { report_metrics_to_backend }
@traces_timer = @timer_class.new(execution_interval: 1, run_now: true) { report_traces_to_backend }
end

def update(time, _old_version, new_version)
return unless time > @nonce

@nonce = time
new_version.nil? ? @report_timer.shutdown : @report_timer.execute

if new_version.nil?
@metrics_timer&.shutdown
@traces_timer&.shutdown
else
# Read poll_rate directly from discovery payload
discovery = @discovery.value
poll_rate = discovery&.dig('pollRate') || 1

# Only recreate metrics_timer if poll_rate is different from current interval
if @metrics_timer.nil? || @metrics_timer.opts[:execution_interval] != poll_rate
@metrics_timer&.shutdown
@metrics_timer = @timer_class.new(execution_interval: poll_rate, run_now: true) { report_metrics_to_backend }
end
@metrics_timer.execute

# Traces timer always uses 1 second interval
@traces_timer&.shutdown
@traces_timer = @timer_class.new(execution_interval: 1, run_now: true) { report_traces_to_backend }
@traces_timer.execute
end
end

private

def report_to_backend
def report_metrics_to_backend
report_metrics if ::Instana.config[:metrics][:enabled]
rescue StandardError => e
@logger.error(%(#{e}\n#{e.backtrace.join("\n")}))
end

def report_traces_to_backend
report_traces if ::Instana.config[:tracing][:enabled]
report_trace_stats if ::Instana.config[:tracing][:enabled]
rescue StandardError => e
Expand Down
66 changes: 49 additions & 17 deletions test/backend/host_agent_reporting_observer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ def test_start_stop

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

refute subject.report_timer.running
refute subject.metrics_timer.running
refute subject.traces_timer.running

subject.update(Time.now, nil, true)
assert subject.report_timer.running
assert subject.metrics_timer.running
assert subject.traces_timer.running

subject.update(Time.now, nil, nil)
refute subject.report_timer.running
refute subject.metrics_timer.running
refute subject.traces_timer.running

subject.update(Time.now - 500, nil, true)
refute subject.report_timer.running
refute subject.metrics_timer.running
refute subject.traces_timer.running
end

def test_report
Expand All @@ -33,7 +37,7 @@ def test_report

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.metrics_timer.block.call
end

def test_report_fail
Expand All @@ -53,7 +57,7 @@ def test_report_fail

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.metrics_timer.block.call
assert_nil discovery.value
end

Expand All @@ -80,7 +84,7 @@ def test_agent_action

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.metrics_timer.block.call
end

def test_agent_actions
Expand All @@ -104,7 +108,7 @@ def test_agent_actions

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.metrics_timer.block.call
end

def test_agent_action_error
Expand All @@ -119,7 +123,7 @@ def test_agent_action_error

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.metrics_timer.block.call
end

def test_disable_metrics
Expand All @@ -130,7 +134,7 @@ def test_disable_metrics

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.metrics_timer.block.call
ensure
::Instana.config[:metrics][:enabled] = true
end
Expand All @@ -153,7 +157,7 @@ def test_disable_metrics_memory

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.metrics_timer.block.call
ensure
::Instana.config[:metrics][:memory][:enabled] = true
end
Expand All @@ -176,7 +180,7 @@ def test_disable_gc

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.metrics_timer.block.call
ensure
::Instana.config[:metrics][:gc][:enabled] = true
end
Expand All @@ -199,7 +203,7 @@ def test_disable_thread

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.metrics_timer.block.call
ensure
::Instana.config[:metrics][:thread][:enabled] = true
end
Expand All @@ -212,7 +216,7 @@ def test_disable_tracing

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

subject.report_timer.block.call
subject.traces_timer.block.call
ensure
::Instana.config[:tracing][:enabled] = true
end
Expand All @@ -235,7 +239,7 @@ def send

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer, processor: processor)

subject.report_timer.block.call
subject.traces_timer.block.call
refute_nil discovery.value
end

Expand Down Expand Up @@ -264,7 +268,7 @@ def send

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer, processor: processor)

subject.report_timer.block.call
subject.traces_timer.block.call
assert_nil discovery.value
end

Expand All @@ -283,7 +287,35 @@ def send

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer, processor: processor, logger: Logger.new('/dev/null'))

subject.report_timer.block.call
subject.traces_timer.block.call
assert_equal({"pid" => 1234}, discovery.value)
end

def test_poll_rate_changes_metrics_timer_interval
client = Instana::Backend::RequestClient.new('10.10.10.10', 9292)
discovery = Concurrent::Atom.new(nil)

subject = Instana::Backend::HostAgentReportingObserver.new(client, discovery, timer_class: MockTimer)

# Initially, metrics_timer should have 1 second interval (default)
assert_equal 1, subject.metrics_timer.opts[:execution_interval]
refute subject.metrics_timer.running

# Simulate first discovery with pollRate = 1 (should keep 1 second interval)
discovery.swap { {'pid' => 1234, 'pollRate' => 1} }
subject.update(Time.now, nil, true)
assert subject.metrics_timer.running
assert_equal 1, subject.metrics_timer.opts[:execution_interval]
assert_equal({'pid' => 1234, 'pollRate' => 1}, discovery.value)

# Simulate discovery cycle changing pollRate to 5 seconds
discovery.swap { {'pid' => 1234, 'pollRate' => 5} }
subject.update(Time.now + 1, nil, true)
assert subject.metrics_timer.running
assert_equal 5, subject.metrics_timer.opts[:execution_interval]
assert_equal({'pid' => 1234, 'pollRate' => 5}, discovery.value)

# Verify traces_timer always stays at 1 second
assert_equal 1, subject.traces_timer.opts[:execution_interval]
end
end
Loading