Class: Tasker::Telemetry::MetricTypes::Counter

Inherits:
Object
  • Object
show all
Defined in:
lib/tasker/telemetry/metric_types.rb

Overview

Counter represents a monotonically increasing metric value

Counters are thread-safe and use atomic operations for increment operations. They follow the fail-fast principle with explicit validation and meaningful error messages for invalid operations.

Examples:

Production usage

counter = Counter.new('api_requests_total', labels: { endpoint: '/tasks' })
counter.increment                  # Increment by 1
counter.increment(batch_size)      # Increment by batch size
counter.value                      # Get current value (thread-safe read)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, labels: {}) ⇒ Counter

Initialize a new counter metric

Parameters:

  • name (String)

    The metric name (must be present)

  • labels (Hash) (defaults to: {})

    Optional labels for dimensional metrics

Raises:

  • (ArgumentError)

    If name is nil or empty



53
54
55
56
57
58
59
60
# File 'lib/tasker/telemetry/metric_types.rb', line 53

def initialize(name, labels: {})
  raise ArgumentError, 'Metric name cannot be nil or empty' if name.nil? || name.strip.empty?

  @name = name.to_s.freeze
  @labels = labels.freeze
  @value = Concurrent::AtomicFixnum.new(0)
  @created_at = Time.current.freeze
end

Instance Attribute Details

#created_atTime (readonly)

Returns When this metric was first created.

Returns:

  • (Time)

    When this metric was first created



46
47
48
# File 'lib/tasker/telemetry/metric_types.rb', line 46

def created_at
  @created_at
end

#labelsHash (readonly)

Returns The metric labels for dimensional data.

Returns:

  • (Hash)

    The metric labels for dimensional data



43
44
45
# File 'lib/tasker/telemetry/metric_types.rb', line 43

def labels
  @labels
end

#nameString (readonly)

Returns The metric name.

Returns:

  • (String)

    The metric name



40
41
42
# File 'lib/tasker/telemetry/metric_types.rb', line 40

def name
  @name
end

Instance Method Details

#descriptionString

Get a description of this metric for debugging

Returns:

  • (String)

    Human-readable description



102
103
104
105
# File 'lib/tasker/telemetry/metric_types.rb', line 102

def description
  label_str = labels.empty? ? '' : format_labels_for_description(labels)
  "#{name}#{label_str} = #{value} (counter)"
end

#increment(amount = 1) ⇒ Integer

Increment the counter by a specified amount

Parameters:

  • amount (Integer) (defaults to: 1)

    Amount to increment (must be non-negative)

Returns:

  • (Integer)

    The new counter value

Raises:

  • (ArgumentError)

    If amount is negative or not an integer



67
68
69
70
71
72
# File 'lib/tasker/telemetry/metric_types.rb', line 67

def increment(amount = 1)
  return false unless amount.is_a?(Integer)
  raise ArgumentError, "Counter increment amount must be positive, got: #{amount}" if amount.negative?

  @value.update { |current| current + amount }
end

#reset!Integer

Reset the counter to zero (primarily for testing)

Returns:

  • (Integer)

    The reset value (0)



82
83
84
# File 'lib/tasker/telemetry/metric_types.rb', line 82

def reset!
  @value.value = 0
end

#to_hHash

Get a hash representation of this metric

Returns:

  • (Hash)

    Metric data including name, labels, value, type



89
90
91
92
93
94
95
96
97
# File 'lib/tasker/telemetry/metric_types.rb', line 89

def to_h
  {
    name: name,
    labels: labels,
    value: value,
    type: :counter,
    created_at: created_at
  }
end

#valueInteger

Get the current counter value (thread-safe read)

Returns:

  • (Integer)

    Current counter value



77
# File 'lib/tasker/telemetry/metric_types.rb', line 77

delegate :value, to: :@value