Skip to content

Commit

Permalink
remove gauge_with_time, add expired_stats_collector, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
senid231 committed Dec 5, 2023
1 parent a6c7814 commit b608eeb
Show file tree
Hide file tree
Showing 17 changed files with 469 additions and 348 deletions.
13 changes: 8 additions & 5 deletions lib/prometheus_exporter/ext/instrumentation/base_stats.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class << self
end

def initialize(client: PrometheusExporter::Client.default, metric_labels: {})
@metric_labels = metric_labels
@metric_labels = metric_labels.transform_keys(&:to_sym)
@client = client
end

Expand All @@ -25,16 +25,19 @@ def collect

# @param data [Array,Hash]
def collect_data(data)
metric = build_metric(data)
@client.send_json(metric)
data_list = data.is_a?(Array) ? data : [data]
metrics = data_list.map { |data_item| build_metric(data_item) }
metrics.map { |metric| @client.send_json(metric) }
end

# @param data [Hash]
# @return [Hash]
def build_metric(data)
metric = data.dup
metric = data.transform_keys(&:to_sym)
metric[:type] = type
metric[:labels] = (metric[:labels] || {}).merge(@metric_labels)
metric[:labels] ||= {}
metric[:labels].transform_keys!(&:to_sym)
metric[:labels].merge!(@metric_labels)
metric
end
end
Expand Down
7 changes: 0 additions & 7 deletions lib/prometheus_exporter/ext/instrumentation/periodic_stats.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def start(frequency: 30, client: PrometheusExporter::Client.default, **)
rescue StandardError => e
client.logger.error("#{klass} Prometheus Exporter Failed To Collect Stats")
client.logger.error("#{e.class} #{e.backtrace&.join("\n")}")
@on_exception&.call(e) if defined?(@on_exception)
ensure
sleep frequency
end
Expand All @@ -44,12 +43,6 @@ def stop
end
@thread = nil
end

# Adds handler that will be called when exception is raised in the thread.
# @yieldparam exception [Exception]
def on_exception(&block)
@on_exception = block
end
end
end
end
59 changes: 0 additions & 59 deletions lib/prometheus_exporter/ext/metric/gauge_with_time.rb

This file was deleted.

33 changes: 0 additions & 33 deletions lib/prometheus_exporter/ext/metric/type_registry.rb

This file was deleted.

15 changes: 2 additions & 13 deletions lib/prometheus_exporter/ext/rspec/matchers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,19 @@

module PrometheusExporter::Ext::RSpec
module Matchers
def send_metrics(expected = nil)
def send_metrics(*expected)
expected = nil if expected.empty?
PrometheusExporter::Ext::RSpec::SendMetricsMatcher.new(expected)
end

def a_prometheus_metric(klass, name)
MetricMatcher.new(klass, name)
end

# Matches approximate milliseconds since epoch
# @param date_time [DateTime] default DateTime.now
# @param delta [Integer] default 1000 ms
# @return [RSpec::Matchers::BuiltIn::BeWithin]
def ms_since_epoch(date_time: DateTime.now, delta: 1_000)
be_within(delta).of(date_time.strftime('%Q').to_i)
end

def a_gauge_metric(name)
a_prometheus_metric(PrometheusExporter::Metric::Gauge, name)
end

def a_gauge_with_time_metric(name)
a_prometheus_metric(PrometheusExporter::Ext::Metric::GaugeWithTime, name)
end

def a_counter_metric(name)
a_prometheus_metric(PrometheusExporter::Metric::Counter, name)
end
Expand Down
4 changes: 1 addition & 3 deletions lib/prometheus_exporter/ext/rspec/send_metrics_matcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ def description_of(object)
private

def deep_stringify_keys(hash)
hash.transform_keys(&:to_s).transform_values do |value|
value.is_a?(Hash) ? deep_stringify_keys(value) : value
end
JSON.parse JSON.generate(hash)
end
end
end
102 changes: 102 additions & 0 deletions lib/prometheus_exporter/ext/server/base_collector_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# frozen_string_literal: true

require 'prometheus_exporter/metric'

module PrometheusExporter::Ext::Server
module BaseCollectorMethods
class << self
private

def included(klass)
super
klass.singleton_class.attr_accessor :type, :registered_metrics
klass.registered_metrics = {}
klass.extend ClassMethods
end
end

module ClassMethods
# Registers metric observer.
# @param name [Symbol] metric name.
# @param help [String] metric description.
# @param metric_class [Class<PrometheusExporter::Metric::Base>] observer class.
# @param args [Array] additional arguments for observer class.
# rubocop:disable Metrics/ParameterLists
def register_metric(name, help, metric_class, *args)
# rubocop:enable Metrics/ParameterLists
name = name.to_s
raise ArgumentError, "metric #{name} is already registered" if registered_metrics.key?(name)

registered_metrics[name] = { help:, metric_class:, args: }
end

# Registers PrometheusExporter::Metric::Counter observer.
# @param name [Symbol] metric name.
# @param help [String] metric description.
def register_counter(name, help)
register_metric(name, help, PrometheusExporter::Metric::Counter)
end

# Registers PrometheusExporter::Metric::Gauge observer.
# @param name [Symbol] metric name.
# @param help [String] metric description.
def register_gauge(name, help)
register_metric(name, help, PrometheusExporter::Metric::Gauge)
end

# Registers PrometheusExporter::Metric::Summary observer.
# @param name [Symbol] metric name.
# @param help [String] metric description.
# @param opts [Hash] additional options, supports `quantiles` key.
def register_summary(name, help, opts = {})
register_metric(name, help, PrometheusExporter::Metric::Summary, opts)
end

# Registers PrometheusExporter::Metric::Histogram observer.
# @param name [Symbol] metric name.
# @param help [String] metric description.
# @param opts [Hash] additional options, supports `buckets` key.
def register_histogram(name, help, opts = {})
register_metric(name, help, PrometheusExporter::Metric::Histogram, opts)
end
end

# @return [String]
def type
self.class.type
end

private

# Adds metrics to observers with matched name.
# @param observers [Hash] returned by #build_observers.
# @param obj [Hash] metric data.
def fill_observers(observers, obj)
observers.each do |name, observer|
value = obj[name]
observer.observe(value, obj['labels']) if value
end
end

# Generally metrics sent via PrometheusExporter::Ext::Instrumentation::BaseStats populate labels to `labels` key.
# But PrometheusExporter::Client populate it's own labels to `custom_labels` key.
# Here we merge them into single `labels` key.
# @param obj [Hash]
# @return [Hash]
def normalize_labels(obj)
obj['labels'] ||= {}
custom_labels = obj.delete('custom_labels')
obj['labels'].merge!(custom_labels) if custom_labels
obj
end

# @return [Hash] key is metric name, value is observer.
def build_observers
observers = {}
self.class.registered_metrics.each do |name, metric|
observers[name] = metric[:metric_class].new("#{type}_#{name}", metric[:help], *metric[:args])
end
observers
end
end
end
57 changes: 57 additions & 0 deletions lib/prometheus_exporter/ext/server/expired_stats_collector.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

require_relative 'base_collector_methods'
require 'prometheus_exporter/server/metrics_container'

module PrometheusExporter::Ext::Server
module ExpiredStatsCollector
class << self
private

def included(klass)
super
klass.include BaseCollectorMethods
klass.singleton_class.attr_accessor :filter, :ttl
klass.ttl = 60
klass.extend ClassMethods
end
end

module ClassMethods
# Defines a rule how old metric will be replaced with new one.
# @yield compare new metric with existing one.
# @yieldparam new_metric [Hash] new metric data.
# @yieldparam metric [Hash] existing metric data.
# @yieldreturn [Boolean] if true existing metric will be replaced with new one.
def unique_metric_by(&block)
@filter = block
end
end

def initialize
super
@data = PrometheusExporter::Server::MetricsContainer.new(
ttl: self.class.ttl,
filter: self.class.filter
)
end

# Returns all metrics collected by this collector.
# @return [Array<PrometheusExporter::Metric::Base>]
def metrics
observers = build_observers
@data.each do |obj|
fill_observers(observers, obj)
end

observers.values
end

# Collects metric data received from client.
# @param obj [Hash] metric data.
def collect(obj)
normalize_labels(obj)
@data << obj
end
end
end
Loading

0 comments on commit b608eeb

Please sign in to comment.