diff --git a/lib/datadog/core/telemetry/component.rb b/lib/datadog/core/telemetry/component.rb index 37c69eb8252..5b6a7335568 100644 --- a/lib/datadog/core/telemetry/component.rb +++ b/lib/datadog/core/telemetry/component.rb @@ -2,6 +2,7 @@ require_relative 'emitter' require_relative 'event' +require_relative 'metrics_manager' require_relative 'worker' require_relative '../utils/forking' @@ -29,6 +30,11 @@ def initialize( @enabled = enabled @stopped = false + @metrics_manager = MetricsManager.new( + enabled: enabled && metrics_enabled, + aggregation_interval: metrics_aggregation_interval_seconds + ) + @worker = Telemetry::Worker.new( enabled: @enabled, heartbeat_interval_seconds: heartbeat_interval_seconds, @@ -69,6 +75,61 @@ def client_configuration_change!(changes) @worker.enqueue(Event::AppClientConfigurationChange.new(changes, 'remote_config')) end + + # Increments a count metric. + # @param namespace [String] metric namespace (per product, such as 'civisibility', 'tracers', 'profilers') + # @param metric_name [String] metric name + # @param value [Float] metric value + # @param tags [Array|Hash{String=>String}] metric tags as hash of tag:value pairs or array of "tag:val" + # strings + # @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric + def inc(namespace, metric_name, value, tags: {}, common: true) + @metrics_manager.inc(namespace, metric_name, value, tags: tags, common: common) + end + + # Decremenets a count metric. + # @param namespace [String] metric namespace (per product, such as 'civisibility', 'tracers', 'profilers') + # @param metric_name [String] metric name + # @param value [Float] metric value + # @param tags [Array|Hash{String=>String}] metric tags as hash of tag:value pairs or array of "tag:val" + # strings + # @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric + def dec(namespace, metric_name, value, tags: {}, common: true) + @metrics_manager.dec(namespace, metric_name, value, tags: tags, common: common) + end + + # Tracks gauge metric. + # @param namespace [String] metric namespace (per product, such as 'civisibility', 'tracers', 'profilers') + # @param metric_name [String] metric name + # @param value [Float] metric value + # @param tags [Array|Hash{String=>String}] metric tags as hash of tag:value pairs or array of "tag:val" + # strings + # @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric + def gauge(namespace, metric_name, value, tags: {}, common: true) + @metrics_manager.gauge(namespace, metric_name, value, tags: tags, common: common) + end + + # Tracks rate metric. + # @param namespace [String] metric namespace (per product, such as 'civisibility', 'tracers', 'profilers') + # @param metric_name [String] metric name + # @param value [Float] metric value + # @param tags [Array|Hash{String=>String}] metric tags as hash of tag:value pairs or array of "tag:val" + # strings + # @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric + def rate(namespace, metric_name, value, tags: {}, common: true) + @metrics_manager.rate(namespace, metric_name, value, tags: tags, common: common) + end + + # Tracks distribution metric. + # @param namespace [String] metric namespace (per product, such as 'civisibility', 'tracers', 'profilers') + # @param metric_name [String] metric name + # @param value [Float] metric value + # @param tags [Array|Hash{String=>String}] metric tags as hash of tag:value pairs or array of "tag:val" + # strings + # @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric + def distribution(namespace, metric_name, value, tags: {}, common: true) + @metrics_manager.distribution(namespace, metric_name, value, tags: tags, common: common) + end end end end diff --git a/lib/datadog/core/telemetry/metric.rb b/lib/datadog/core/telemetry/metric.rb index bbbc649bd5b..a1d459c4aa3 100644 --- a/lib/datadog/core/telemetry/metric.rb +++ b/lib/datadog/core/telemetry/metric.rb @@ -10,7 +10,7 @@ class Base attr_reader :name, :tags, :values, :common # @param name [String] metric name - # @param tags [Array|Hash{String=>String}] metric tags as hash of array of "tag:val" strings + # @param tags [Array|Hash{String=>String}] metric tags as hash or array of "tag:val" strings # @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric def initialize(name, tags: {}, common: true) @name = name diff --git a/sig/datadog/core/telemetry/component.rbs b/sig/datadog/core/telemetry/component.rbs index dac3d41bba4..d9d54fae227 100644 --- a/sig/datadog/core/telemetry/component.rbs +++ b/sig/datadog/core/telemetry/component.rbs @@ -4,6 +4,7 @@ module Datadog class Component @enabled: bool @stopped: bool + @metrics_manager: Datadog::Core::Telemetry::MetricsManager @worker: Datadog::Core::Telemetry::Worker attr_reader enabled: bool diff --git a/sig/datadog/core/telemetry/metric.rbs b/sig/datadog/core/telemetry/metric.rbs index e0874765d98..09d9bcef3f5 100644 --- a/sig/datadog/core/telemetry/metric.rbs +++ b/sig/datadog/core/telemetry/metric.rbs @@ -47,11 +47,11 @@ module Datadog end class IntervalMetric < Base - @interval: Integer + @interval: Float - attr_reader interval: Integer + attr_reader interval: Float - def initialize: (String name, ?tags: tags_input, ?common: bool, interval: Integer) -> void + def initialize: (String name, ?tags: tags_input, ?common: bool, interval: Float) -> void end class Count < Base diff --git a/sig/datadog/core/telemetry/metrics_collection.rbs b/sig/datadog/core/telemetry/metrics_collection.rbs index fa2cdc0cb3b..1edcf24a121 100644 --- a/sig/datadog/core/telemetry/metrics_collection.rbs +++ b/sig/datadog/core/telemetry/metrics_collection.rbs @@ -8,7 +8,7 @@ module Datadog @namespace: String - @interval: Integer + @interval: Float @mutex: Thread::Mutex @@ -18,7 +18,7 @@ module Datadog attr_reader namespace: String - def initialize: (String namespace, aggregation_interval: Integer) -> void + def initialize: (String namespace, aggregation_interval: Float) -> void def inc: (String metric_name, Datadog::Core::Telemetry::Metric::input_value value, ?tags: Datadog::Core::Telemetry::Metric::tags_input, ?common: bool) -> void diff --git a/sig/datadog/core/telemetry/metrics_manager.rbs b/sig/datadog/core/telemetry/metrics_manager.rbs index 53e279c86e6..7083e155edb 100644 --- a/sig/datadog/core/telemetry/metrics_manager.rbs +++ b/sig/datadog/core/telemetry/metrics_manager.rbs @@ -6,7 +6,7 @@ module Datadog def enqueue: (Datadog::Core::Telemetry::Event::Base event) -> void end - @interval: Integer + @interval: Float @enabled: bool @@ -16,7 +16,7 @@ module Datadog attr_reader enabled: bool - def initialize: (aggregation_interval: Integer, enabled: bool) -> void + def initialize: (aggregation_interval: Float, enabled: bool) -> void def inc: (String namespace, String metric_name, Datadog::Core::Telemetry::Metric::input_value value, ?tags: Datadog::Core::Telemetry::Metric::tags_input, ?common: bool) -> void diff --git a/spec/datadog/core/telemetry/component_spec.rb b/spec/datadog/core/telemetry/component_spec.rb index b641e48bbda..eee7639ba1e 100644 --- a/spec/datadog/core/telemetry/component_spec.rb +++ b/spec/datadog/core/telemetry/component_spec.rb @@ -210,4 +210,79 @@ end end end + + context 'metrics support' do + let(:metrics_manager) { spy(:metrics_manager) } + let(:namespace) { double('namespace') } + let(:metric_name) { double('metric_name') } + let(:value) { double('value') } + let(:tags) { double('tags') } + let(:common) { double('common') } + before do + expect(Datadog::Core::Telemetry::MetricsManager).to receive(:new).with( + aggregation_interval: metrics_aggregation_interval_seconds, + enabled: enabled && metrics_enabled + ).and_return(metrics_manager) + end + + describe '#inc' do + subject(:inc) { telemetry.inc(namespace, metric_name, value, tags: tags, common: common) } + + it do + inc + + expect(metrics_manager).to have_received(:inc).with( + namespace, metric_name, value, tags: tags, common: common + ) + end + end + + describe '#dec' do + subject(:dec) { telemetry.dec(namespace, metric_name, value, tags: tags, common: common) } + + it do + dec + + expect(metrics_manager).to have_received(:dec).with( + namespace, metric_name, value, tags: tags, common: common + ) + end + end + + describe '#gauge' do + subject(:gauge) { telemetry.gauge(namespace, metric_name, value, tags: tags, common: common) } + + it do + gauge + + expect(metrics_manager).to have_received(:gauge).with( + namespace, metric_name, value, tags: tags, common: common + ) + end + end + + describe '#rate' do + subject(:rate) { telemetry.rate(namespace, metric_name, value, tags: tags, common: common) } + + it do + rate + + expect(metrics_manager).to have_received(:rate).with( + namespace, metric_name, value, tags: tags, common: common + ) + end + end + + describe '#distribution' do + subject(:distribution) { telemetry.distribution(namespace, metric_name, value, tags: tags, common: common) } + + it do + distribution + + expect(metrics_manager).to have_received(:distribution).with( + namespace, metric_name, value, tags: tags, common: common + ) + end + end + end end