yabeda浅析
TL;DR
- Github:yabeda-rb/yabeda
- 使用
Yabeda.configure
定义指标 - 记得记得使用
Yabeda.configure!
执行指标定义!(在rails中是自动的) - 使用
Yabeda.group_name.metric_name.increment
设置指数
跟踪
跟踪github示例代码
# declare.rb
require 'yabeda'
require 'trace_tree'
binding.trace_tree(htmp: 'configure') do
Yabeda.configure do
group :your_app do
counter :bells_rang_count, comment: "Total number of bells being rang", tags: %i[bell_size]
gauge :whistles_active, comment: "Number of whistles ready to whistle"
histogram :whistle_runtime do
comment "How long whistles are being active"
unit :ms
buckets [0.1, 10, 100]
end
end
end
end
binding.trace_tree(htmp: 'configure_bang') do
Yabeda.configure!
end
得:
![[yabedaconfigtrace.html]]
![[yabedaconfigbang_trace.html]]
使用configure定义指标
这里
configure
的逻辑比较简单,只是将配置收集起来,等待configure!
调用时再执行# yabeda-0.11.0/lib/yabeda/dsl/class_methods.rb
def configure(&block)
Yabeda.configurators.push([@group, block])
class_exec(&block) if Yabeda.configured?
@group = nil
end
configure!
执行时,会将block中的配置对应到lib/yabeda/dsl/class_methods.rb
中的DSL方法来运行
counter
、gauge
、histogram
DSL方法定义如下# yabeda-0.11.0/lib/yabeda/dsl/class_methods.rb
def counter(*args, **kwargs, &block)
metric = MetricBuilder.new(Counter).build(args, kwargs, @group, &block)
register_metric(metric)
end
# Register a gauge
def gauge(*args, **kwargs, &block)
metric = MetricBuilder.new(Gauge).build(args, kwargs, @group, &block)
register_metric(metric)
end
# Register a histogram
def histogram(*args, **kwargs, &block)
metric = MetricBuilder.new(Histogram).build(args, kwargs, @group, &block)
register_metric(metric)
end
生成
Counter
、Gauge
、Histogram
对象后,还会在::Yabeda
上定义类方法以便用户获取它们例如上述的
bells_rang_count
,可以用Yabeda.your_app_bells_rang_count
取得,也可以用Yabeda.your_app.bells_rang_count
实现如下
# yabeda-0.11.0/lib/yabeda/dsl/class_methods.rb
def register_metric(metric)
name = [metric.group, metric.name].compact.join("_")
::Yabeda.define_singleton_method(name) { metric }
::Yabeda.metrics[name] = metric
register_group_for(metric) if metric.group
::Yabeda.adapters.each_value { |adapter| adapter.register!(metric) } if ::Yabeda.configured?
metric
end
def register_group_for(metric)
group = ::Yabeda.groups[metric.group]
if group.nil?
group = Group.new(metric.group)
::Yabeda.groups[metric.group] = group
end
::Yabeda.define_singleton_method(metric.group) { group } unless ::Yabeda.respond_to?(metric.group)
group.register_metric(metric)
end
Histogram类
调用
Yabeda.xxxx_histogram.measure
记录分布值可以直接给它时长:
Yabeda.xx_histogram({k: v}, 0.03)
;也可以让它帮你计时:Yabeda.xx_histogram({k: v}){ ... }
,默认计算秒数# yabeda-0.11.0/lib/yabeda/histogram.rb
module Yabeda
class Histogram < Metric
option :buckets
def measure(tags, value = nil)
# 异或:不准同时提供value和block
if value.nil? ^ block_given?
raise ArgumentError, "You must provide either numeric value or block for Yabeda::Histogram#measure!"
end
if block_given?
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
yield
value = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - starting)
end
# 记录到values这个hash中
all_tags = ::Yabeda::Tags.build(tags, group)
values[all_tags] = value
# 如果有其它监控系统的适配器,则将标签和值传给它们
::Yabeda.adapters.each do |_, adapter|
adapter.perform_histogram_measure!(self, all_tags, value)
end
value
end
end
end
非事件产生的指标
按照其README所说,对于一些非事件产生的指标,可以使用
collect
来定义Yabeda.configure do
# This block will be executed periodically few times in a minute
# (by timer or external request depending on adapter you're using)
# Keep it fast and simple!
collect do
your_app.whistles_active.set({}, Whistle.where(state: :active).count)
end
end
当监控系统例如yabeda-prometheus拉取数据时,会调用
collect!
方法,计算上述指标# yabeda-0.11.0/lib/yabeda.rb
def collect!
collectors.each do |collector|
if config.debug?
yabeda.collect_duration.measure({ location: collector.source_location.join(":") }, &collector)
else
collector.call
end
end
end