mirror of
https://github.com/cmur2/dyndnsd.git
synced 2026-11-14 12:55:58 +01:00
gems: include vendored metrisk without hitime dependency
hitime is only needed for Metriks::Timer and requires native extensions. Those do not compile with default settings under Ubuntu 26.04 or Alpine 3.24.
This commit is contained in:
1 parent
645469f41e
commit
7fa9f499e1
10 files changed
+502
-29
No files matched your search
@@ -2,9 +2,15 @@ plugins:
|
|||||||
- rubocop-rake
|
- rubocop-rake
|
||||||
- rubocop-rspec
|
- rubocop-rspec
|
||||||
|
|
||||||
|
inherit_mode:
|
||||||
|
merge: [Exclude]
|
||||||
|
|
||||||
AllCops:
|
AllCops:
|
||||||
TargetRubyVersion: '3.0'
|
TargetRubyVersion: '3.0'
|
||||||
NewCops: enable
|
NewCops: enable
|
||||||
|
Exclude:
|
||||||
|
- 'lib/metriks/**/*'
|
||||||
|
- 'lib/metriks.rb'
|
||||||
|
|
||||||
Gemspec/DevelopmentDependencies:
|
Gemspec/DevelopmentDependencies:
|
||||||
EnforcedStyle: gemspec
|
EnforcedStyle: gemspec
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ Gem::Specification.new do |s|
|
|||||||
s.add_dependency 'async-dns', '~> 1.3.0'
|
s.add_dependency 'async-dns', '~> 1.3.0'
|
||||||
s.add_dependency 'base64', '~> 0.3.0' # needed for async
|
s.add_dependency 'base64', '~> 0.3.0' # needed for async
|
||||||
s.add_dependency 'logger', '>= 1.6', '< 1.8'
|
s.add_dependency 'logger', '>= 1.6', '< 1.8'
|
||||||
s.add_dependency 'metriks'
|
|
||||||
s.add_dependency 'opentelemetry-exporter-jaeger', '~> 0.22.0'
|
s.add_dependency 'opentelemetry-exporter-jaeger', '~> 0.22.0'
|
||||||
s.add_dependency 'opentelemetry-instrumentation-rack', '~> 0.22.0'
|
s.add_dependency 'opentelemetry-instrumentation-rack', '~> 0.22.0'
|
||||||
s.add_dependency 'opentelemetry-sdk', '~> 1.2.0'
|
s.add_dependency 'opentelemetry-sdk', '~> 1.2.0'
|
||||||
|
|||||||
@@ -58,34 +58,6 @@ module Dyndnsd
|
|||||||
:count, :one_minute_rate, :five_minute_rate,
|
:count, :one_minute_rate, :five_minute_rate,
|
||||||
:fifteen_minute_rate, :mean_rate
|
:fifteen_minute_rate, :mean_rate
|
||||||
]
|
]
|
||||||
when Metriks::Counter
|
|
||||||
write_metric f, name, metric, [
|
|
||||||
:count
|
|
||||||
]
|
|
||||||
when Metriks::UtilizationTimer
|
|
||||||
write_metric f, name, metric, [
|
|
||||||
:count, :one_minute_rate, :five_minute_rate,
|
|
||||||
:fifteen_minute_rate, :mean_rate,
|
|
||||||
:min, :max, :mean, :stddev,
|
|
||||||
:one_minute_utilization, :five_minute_utilization,
|
|
||||||
:fifteen_minute_utilization, :mean_utilization
|
|
||||||
], [
|
|
||||||
:median, :get_95th_percentile
|
|
||||||
]
|
|
||||||
when Metriks::Timer
|
|
||||||
write_metric f, name, metric, [
|
|
||||||
:count, :one_minute_rate, :five_minute_rate,
|
|
||||||
:fifteen_minute_rate, :mean_rate,
|
|
||||||
:min, :max, :mean, :stddev
|
|
||||||
], [
|
|
||||||
:median, :get_95th_percentile
|
|
||||||
]
|
|
||||||
when Metriks::Histogram
|
|
||||||
write_metric f, name, metric, [
|
|
||||||
:count, :min, :max, :mean, :stddev
|
|
||||||
], [
|
|
||||||
:median, :get_95th_percentile
|
|
||||||
]
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Vendored from metriks 0.9.9.8 — https://github.com/eric/metriks
|
||||||
|
# Copyright (c) 2012 Eric Lindvall, MIT licensed.
|
||||||
|
# Trimmed to the subset dyndnsd uses (meters + registry + reporters);
|
||||||
|
# counter/gauge/timer/utilization_timer/histogram support was removed,
|
||||||
|
# and the 'atomic'/'avl_tree'/'hitimes' dependencies were replaced or dropped.
|
||||||
|
|
||||||
|
module Metriks
|
||||||
|
VERSION = '0.9.9.8'
|
||||||
|
|
||||||
|
def self.get(name)
|
||||||
|
Registry.default.get(name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.meter(name)
|
||||||
|
Registry.default.meter(name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.registry
|
||||||
|
Registry.default
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'metriks/atomic'
|
||||||
|
require 'metriks/ewma'
|
||||||
|
require 'metriks/meter'
|
||||||
|
require 'metriks/registry'
|
||||||
|
require 'metriks/reporter/proc_title'
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Minimal pure-Ruby replacement for the 'atomic' gem, covering the exact API
|
||||||
|
# the vendored metriks code uses (Atomic.new, #value, #value=, #update,
|
||||||
|
# #compare_and_swap). Mutex-guarded instead of relying on a native extension.
|
||||||
|
module Metriks
|
||||||
|
class Atomic
|
||||||
|
def initialize(value = nil)
|
||||||
|
@value = value
|
||||||
|
@mutex = Mutex.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def value
|
||||||
|
@mutex.synchronize { @value }
|
||||||
|
end
|
||||||
|
|
||||||
|
def value=(new_value)
|
||||||
|
@mutex.synchronize { @value = new_value }
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@mutex.synchronize { @value = yield(@value) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def compare_and_swap(expected, new_value)
|
||||||
|
@mutex.synchronize do
|
||||||
|
if @value == expected
|
||||||
|
@value = new_value
|
||||||
|
true
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# Vendored from metriks 0.9.9.8 — https://github.com/eric/metriks
|
||||||
|
# Copyright (c) 2012 Eric Lindvall, MIT licensed.
|
||||||
|
# Trimmed to the subset dyndnsd uses (meters + registry + reporters).
|
||||||
|
|
||||||
|
|
||||||
|
module Metriks
|
||||||
|
class EWMA
|
||||||
|
INTERVAL = 5.0
|
||||||
|
SECONDS_PER_MINUTE = 60.0
|
||||||
|
|
||||||
|
ONE_MINUTE = 1
|
||||||
|
FIVE_MINUTES = 5
|
||||||
|
FIFTEEN_MINUTES = 15
|
||||||
|
|
||||||
|
M1_ALPHA = 1 - Math.exp(-INTERVAL / SECONDS_PER_MINUTE / ONE_MINUTE)
|
||||||
|
M5_ALPHA = 1 - Math.exp(-INTERVAL / SECONDS_PER_MINUTE / FIVE_MINUTES)
|
||||||
|
M15_ALPHA = 1 - Math.exp(-INTERVAL / SECONDS_PER_MINUTE / FIFTEEN_MINUTES)
|
||||||
|
|
||||||
|
def self.new_m1
|
||||||
|
new(M1_ALPHA, INTERVAL)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.new_m5
|
||||||
|
new(M5_ALPHA, INTERVAL)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.new_m15
|
||||||
|
new(M15_ALPHA, INTERVAL)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(alpha, interval)
|
||||||
|
@alpha = alpha
|
||||||
|
@interval = interval
|
||||||
|
|
||||||
|
@initialized = false
|
||||||
|
@rate = Atomic.new(0.0)
|
||||||
|
@uncounted = Atomic.new(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear
|
||||||
|
@initialized = false
|
||||||
|
@rate.value = 0.0
|
||||||
|
@uncounted.value = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(value)
|
||||||
|
@uncounted.update { |v| v + value }
|
||||||
|
end
|
||||||
|
|
||||||
|
def tick
|
||||||
|
count = @uncounted.swap(0)
|
||||||
|
instant_rate = count / @interval.to_f
|
||||||
|
|
||||||
|
if @initialized
|
||||||
|
@rate.update { |v| v + @alpha * (instant_rate - v) }
|
||||||
|
else
|
||||||
|
@rate.value = instant_rate
|
||||||
|
@initialized = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def rate
|
||||||
|
@rate.value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
# Vendored from metriks 0.9.9.8 — https://github.com/eric/metriks
|
||||||
|
# Copyright (c) 2012 Eric Lindvall, MIT licensed.
|
||||||
|
# Trimmed to the subset dyndnsd uses (meters + registry + reporters).
|
||||||
|
|
||||||
|
|
||||||
|
require 'metriks/ewma'
|
||||||
|
|
||||||
|
module Metriks
|
||||||
|
class Meter
|
||||||
|
TICK_INTERVAL = 5.0
|
||||||
|
|
||||||
|
def initialize(averager_klass = Metriks::EWMA)
|
||||||
|
@count = Atomic.new(0)
|
||||||
|
@start_time = Time.now.to_f
|
||||||
|
@last_tick = Atomic.new(@start_time)
|
||||||
|
|
||||||
|
@m1_rate = averager_klass.new_m1
|
||||||
|
@m5_rate = averager_klass.new_m5
|
||||||
|
@m15_rate = averager_klass.new_m15
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear
|
||||||
|
@count.value = 0
|
||||||
|
@start_time = Time.now.to_f
|
||||||
|
@last_tick.value = @start_time
|
||||||
|
@m1_rate.clear
|
||||||
|
@m5_rate.clear
|
||||||
|
@m15_rate.clear
|
||||||
|
end
|
||||||
|
|
||||||
|
def tick
|
||||||
|
@m1_rate.tick
|
||||||
|
@m5_rate.tick
|
||||||
|
@m15_rate.tick
|
||||||
|
end
|
||||||
|
|
||||||
|
def tick_if_nessesary
|
||||||
|
old_tick = @last_tick.value
|
||||||
|
new_tick = Time.new.to_f
|
||||||
|
age = new_tick - old_tick
|
||||||
|
if age > TICK_INTERVAL && @last_tick.compare_and_swap(old_tick, new_tick)
|
||||||
|
required_ticks = age / TICK_INTERVAL
|
||||||
|
required_ticks.to_i.times do
|
||||||
|
tick
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def mark(val = 1)
|
||||||
|
tick_if_nessesary
|
||||||
|
@count.update { |v| v + val }
|
||||||
|
@m1_rate.update(val)
|
||||||
|
@m5_rate.update(val)
|
||||||
|
@m15_rate.update(val)
|
||||||
|
end
|
||||||
|
|
||||||
|
def count
|
||||||
|
@count.value
|
||||||
|
end
|
||||||
|
|
||||||
|
def one_minute_rate
|
||||||
|
tick_if_nessesary
|
||||||
|
@m1_rate.rate
|
||||||
|
end
|
||||||
|
|
||||||
|
def five_minute_rate
|
||||||
|
tick_if_nessesary
|
||||||
|
@m5_rate.rate
|
||||||
|
end
|
||||||
|
|
||||||
|
def fifteen_minute_rate
|
||||||
|
tick_if_nessesary
|
||||||
|
@m15_rate.rate
|
||||||
|
end
|
||||||
|
|
||||||
|
def mean_rate
|
||||||
|
if count == 0
|
||||||
|
return 0.0
|
||||||
|
else
|
||||||
|
elapsed = Time.now.to_f - @start_time
|
||||||
|
count / elapsed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
# Vendored from metriks 0.9.9.8 — https://github.com/eric/metriks
|
||||||
|
# Copyright (c) 2012 Eric Lindvall, MIT licensed.
|
||||||
|
# Trimmed to the subset dyndnsd uses (meters + registry + reporters).
|
||||||
|
|
||||||
|
require 'metriks/meter'
|
||||||
|
|
||||||
|
module Metriks
|
||||||
|
# Public: A collection of metrics
|
||||||
|
class Registry
|
||||||
|
# Public: The default registry for the process.
|
||||||
|
#
|
||||||
|
# Returns the default Registry for the process.
|
||||||
|
def self.default
|
||||||
|
@default ||= new
|
||||||
|
end
|
||||||
|
|
||||||
|
# Public: Initializes a new Registry.
|
||||||
|
def initialize
|
||||||
|
@mutex = Mutex.new
|
||||||
|
@metrics = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Public: Clear all of the metrics in the Registry. This ensures all
|
||||||
|
# metrics that have been added are stopped.
|
||||||
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
def clear
|
||||||
|
@mutex.synchronize do
|
||||||
|
@metrics.each do |key, metric|
|
||||||
|
metric.stop if metric.respond_to?(:stop)
|
||||||
|
end
|
||||||
|
|
||||||
|
@metrics = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Public: Clear all of the metrics in the Registry. This has the same
|
||||||
|
# effect as calling #clear.
|
||||||
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
def stop
|
||||||
|
clear
|
||||||
|
end
|
||||||
|
|
||||||
|
# Public: Iterate over all of the counters.
|
||||||
|
#
|
||||||
|
# Examples
|
||||||
|
#
|
||||||
|
# registry.each do |name, metric|
|
||||||
|
# puts name
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
def each(&block)
|
||||||
|
metrics = @mutex.synchronize do
|
||||||
|
@metrics.dup
|
||||||
|
end
|
||||||
|
|
||||||
|
metrics.each(&block)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Public: Fetch or create a new meter metric. Meters are a counter that
|
||||||
|
# tracks throughput along with the count.
|
||||||
|
#
|
||||||
|
# name - The String name of the metric to define or fetch
|
||||||
|
#
|
||||||
|
# Examples
|
||||||
|
#
|
||||||
|
# registry.meter('resque.calls')
|
||||||
|
#
|
||||||
|
# Returns the Metriks::Meter identified by the name.
|
||||||
|
def meter(name)
|
||||||
|
add_or_get(name, Metriks::Meter)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Public: Fetch an existing metric.
|
||||||
|
#
|
||||||
|
# name - The String name of the metric to fetch
|
||||||
|
#
|
||||||
|
# Examples
|
||||||
|
#
|
||||||
|
# registry.get('rack.utilization')
|
||||||
|
#
|
||||||
|
# Returns the metric or nil.
|
||||||
|
def get(name)
|
||||||
|
@mutex.synchronize do
|
||||||
|
@metrics[name]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Public: Add a new metric.
|
||||||
|
#
|
||||||
|
# name - The String name of the metric to add
|
||||||
|
# metric - The metric instance to add
|
||||||
|
#
|
||||||
|
# Examples
|
||||||
|
#
|
||||||
|
# registry.add('method.calls', Metriks::Counter.new)
|
||||||
|
#
|
||||||
|
# Returns nothing.
|
||||||
|
# Raises RuntimeError if the metric name is already defined
|
||||||
|
def add(name, metric)
|
||||||
|
@mutex.synchronize do
|
||||||
|
if @metrics[name]
|
||||||
|
raise "Metric '#{name}' already defined"
|
||||||
|
else
|
||||||
|
@metrics[name] = metric
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
def add_or_get(name, klass, &create_metric)
|
||||||
|
@mutex.synchronize do
|
||||||
|
if metric = @metrics[name]
|
||||||
|
if !metric.is_a?(klass)
|
||||||
|
raise "Metric already defined as '#{metric.class}'"
|
||||||
|
else
|
||||||
|
return metric
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@metrics[name] = create_metric ? create_metric.call : klass.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# Vendored from metriks 0.9.9.8 — https://github.com/eric/metriks
|
||||||
|
# Copyright (c) 2012 Eric Lindvall, MIT licensed.
|
||||||
|
# Trimmed to the subset dyndnsd uses (meters + registry + reporters).
|
||||||
|
|
||||||
|
require 'socket'
|
||||||
|
|
||||||
|
module Metriks::Reporter
|
||||||
|
class Graphite
|
||||||
|
attr_reader :host, :port
|
||||||
|
|
||||||
|
def initialize(host, port, options = {})
|
||||||
|
@host = host
|
||||||
|
@port = port
|
||||||
|
|
||||||
|
@prefix = options[:prefix]
|
||||||
|
|
||||||
|
@registry = options[:registry] || Metriks::Registry.default
|
||||||
|
@interval = options[:interval] || 60
|
||||||
|
@on_error = options[:on_error] || proc { |ex| }
|
||||||
|
end
|
||||||
|
|
||||||
|
def socket
|
||||||
|
@socket = nil if @socket && @socket.closed?
|
||||||
|
@socket ||= TCPSocket.new(@host, @port)
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
@thread ||= Thread.new do
|
||||||
|
loop do
|
||||||
|
sleep @interval
|
||||||
|
|
||||||
|
Thread.new do
|
||||||
|
begin
|
||||||
|
write
|
||||||
|
rescue Exception => ex
|
||||||
|
@on_error[ex] rescue nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
@thread.kill if @thread
|
||||||
|
@thread = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def restart
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
end
|
||||||
|
|
||||||
|
def write
|
||||||
|
@registry.each do |name, metric|
|
||||||
|
case metric
|
||||||
|
when Metriks::Meter
|
||||||
|
write_metric name, metric, [
|
||||||
|
:count, :one_minute_rate, :five_minute_rate,
|
||||||
|
:fifteen_minute_rate, :mean_rate
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_metric(base_name, metric, keys, snapshot_keys = [])
|
||||||
|
time = Time.now.to_i
|
||||||
|
|
||||||
|
base_name = base_name.to_s.gsub(/ +/, '_')
|
||||||
|
if @prefix
|
||||||
|
base_name = "#{@prefix}.#{base_name}"
|
||||||
|
end
|
||||||
|
|
||||||
|
keys.flatten.each do |key|
|
||||||
|
name = key.to_s.gsub(/^get_/, '')
|
||||||
|
value = metric.send(key)
|
||||||
|
socket.write("#{base_name}.#{name} #{value} #{time}\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
unless snapshot_keys.empty?
|
||||||
|
snapshot = metric.snapshot
|
||||||
|
snapshot_keys.flatten.each do |key|
|
||||||
|
name = key.to_s.gsub(/^get_/, '')
|
||||||
|
value = snapshot.send(key)
|
||||||
|
socket.write("#{base_name}.#{name} #{value} #{time}\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue Errno::EPIPE
|
||||||
|
socket.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# Vendored from metriks 0.9.9.8 — https://github.com/eric/metriks
|
||||||
|
# Copyright (c) 2012 Eric Lindvall, MIT licensed.
|
||||||
|
# Trimmed to the subset dyndnsd uses (meters + registry + reporters).
|
||||||
|
|
||||||
|
module Metriks::Reporter
|
||||||
|
class ProcTitle
|
||||||
|
def initialize(options = {})
|
||||||
|
@rounding = options[:rounding] || 1
|
||||||
|
@prefix = options[:prefix] || $0.dup
|
||||||
|
|
||||||
|
@interval = options[:interval] || 5
|
||||||
|
@on_error = options[:on_error] || proc { |ex| }
|
||||||
|
|
||||||
|
@metrics = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def add(name, suffix = nil, &block)
|
||||||
|
@metrics << [ name, suffix, block ]
|
||||||
|
end
|
||||||
|
|
||||||
|
def empty?
|
||||||
|
@metrics.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
@thread ||= Thread.new do
|
||||||
|
loop do
|
||||||
|
begin
|
||||||
|
unless @metrics.empty?
|
||||||
|
title = generate_title
|
||||||
|
if title && !title.empty?
|
||||||
|
$0 = "#{@prefix} #{title}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue Exception => ex
|
||||||
|
@on_error[ex] rescue nil
|
||||||
|
end
|
||||||
|
sleep @interval
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
@thread.kill if @thread
|
||||||
|
@thread = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def restart
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
def generate_title
|
||||||
|
@metrics.collect do |name, suffix, block|
|
||||||
|
val = block.call
|
||||||
|
val = "%.#{@rounding}f" % val if val.is_a?(Float)
|
||||||
|
|
||||||
|
"#{name}: #{val}#{suffix}"
|
||||||
|
end.join(' ')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in new issue
Block a user