Skip to content

Commit

Permalink
Move interval to Rate and Gauge metrics, make sure it is not nil and …
Browse files Browse the repository at this point in the history
…positive
  • Loading branch information
anmarchenko committed Jul 3, 2024
1 parent abc845c commit 0cbef5a
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 34 deletions.
58 changes: 36 additions & 22 deletions lib/datadog/core/telemetry/metric.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,38 @@ module Telemetry
module Metric
# Base class for all metric types
class Base
attr_reader :name, :tags, :values, :common, :interval
attr_reader :name, :tags, :values, :common

# @param name [String] metric name
# @param tags [Array<String>|Hash{String=>String}] metric tags as hash of array of "tag:val" strings
# @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric
# @param interval [Integer] metrics aggregation interval in seconds
def initialize(name, tags: {}, common: true, interval: nil)
def initialize(name, tags: {}, common: true)
@name = name
@values = []
@tags = tags_to_array(tags)
@common = common
@interval = interval
end

def id
@id ||= "#{type}::#{name}::#{tags.join(',')}"
end

def track(value); end
def track(value)
raise NotImplementedError, 'method must be implemented in subclasses'
end

def type; end
def type
raise NotImplementedError, 'method must be implemented in subclasses'
end

def to_h
# @type var res: Hash[Symbol, untyped]
res = {
{
metric: name,
points: values,
type: type,
tags: tags,
common: common
}
res[:interval] = interval if interval
res
end

private
Expand All @@ -51,6 +50,29 @@ def tags_to_array(tags)
end
end

# Base class for metrics that require aggregation interval
class IntervalMetric < Base
attr_reader :interval

# @param name [String] metric name
# @param tags [Array<String>|Hash{String=>String}] metric tags as hash of array of "tag:val" strings
# @param common [Boolean] true if the metric is common for all languages, false for Ruby-specific metric
# @param interval [Integer] metrics aggregation interval in seconds
def initialize(name, interval:, tags: {}, common: true)
raise ArgumentError, 'interval must be a positive number' if interval.nil? || interval <= 0

super(name, tags: tags, common: common)

@interval = interval
end

def to_h
res = super
res[:interval] = interval
res
end
end

# Count metric adds up all the submitted values in a time interval. This would be suitable for a
# metric tracking the number of website hits, for instance.
class Count < Base
Expand Down Expand Up @@ -84,7 +106,7 @@ def track(value)
# A gauge type takes the last value reported during the interval. This type would make sense for tracking RAM or
# CPU usage, where taking the last value provides a representative picture of the host’s behavior during the time
# interval.
class Gauge < Base
class Gauge < IntervalMetric
TYPE = 'gauge'

def type
Expand All @@ -104,10 +126,10 @@ def track(value)

# The rate type takes the count and divides it by the length of the time interval. This is useful if you’re
# interested in the number of hits per second.
class Rate < Base
class Rate < IntervalMetric
TYPE = 'rate'

def initialize(name, tags: {}, common: true, interval: nil)
def initialize(name, interval:, tags: {}, common: true)
super

@value = 0.0
Expand All @@ -119,15 +141,7 @@ def type

def track(value = 1.0)
@value += value

rate =
if interval && interval.positive?
@value / interval
else
0.0
end

@values = [[Time.now.to_i, rate]]
@values = [[Time.now.to_i, @value / interval]]
nil
end
end
Expand Down
19 changes: 11 additions & 8 deletions sig/datadog/core/telemetry/metric.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ module Datadog

@common: bool

@interval: Integer?

attr_reader name: String

attr_reader tags: Array[String]
Expand All @@ -32,9 +30,8 @@ module Datadog

attr_reader common: bool

attr_reader interval: Integer?

def initialize: (String name, ?tags: tags_input, ?common: bool, ?interval: Integer?) -> void
def initialize: (String name, ?tags: tags_input, ?common: bool) -> void

def id: () -> String

Expand All @@ -49,6 +46,14 @@ module Datadog
def tags_to_array: (tags_input tags) -> Array[String]
end

class IntervalMetric < Base
@interval: Integer

attr_reader interval: Integer

def initialize: (String name, ?tags: tags_input, ?common: bool, interval: Integer) -> void
end

class Count < Base
TYPE: "count"

Expand All @@ -64,24 +69,22 @@ module Datadog
def track: (input_value value) -> void
end

class Gauge < Base
class Gauge < IntervalMetric
TYPE: "gauge"

def type: () -> "gauge"

def track: (input_value value) -> void
end

class Rate < Base
class Rate < IntervalMetric
@value: Float

@values: Array[metric_value]
attr_reader values: Array[metric_value]

TYPE: "rate"

def initialize: (String name, ?tags: tags_input, ?common: bool, ?interval: Integer?) -> void

def type: () -> "rate"

def track: (?input_value value) -> void
Expand Down
6 changes: 2 additions & 4 deletions spec/datadog/core/telemetry/metric_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
is_expected.to have_attributes(
name: name,
tags: ['tag1:val1', 'tag2:val2'],
interval: nil,
common: true,
values: []
)
Expand Down Expand Up @@ -198,8 +197,8 @@
context 'interval is nil' do
let(:interval) { nil }

it 'sets rate to zero' do
expect { track }.to change { metric.values }.from([]).to([[now, 0.0]])
it 'raises error' do
expect { metric }.to raise_error(ArgumentError, 'interval must be a positive number')
end
end
end
Expand Down Expand Up @@ -235,7 +234,6 @@
is_expected.to have_attributes(
name: name,
tags: ['tag1:val1', 'tag2:val2'],
interval: nil,
common: true,
values: []
)
Expand Down

0 comments on commit 0cbef5a

Please sign in to comment.