yabeda 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -0
- data/CHANGELOG.md +33 -0
- data/Gemfile +1 -2
- data/README.md +49 -0
- data/lib/yabeda/base_adapter.rb +7 -0
- data/lib/yabeda/counter.rb +2 -6
- data/lib/yabeda/dsl/class_methods.rb +22 -0
- data/lib/yabeda/gauge.rb +18 -3
- data/lib/yabeda/group.rb +14 -0
- data/lib/yabeda/metric.rb +18 -8
- data/lib/yabeda/null_adapter.rb +25 -0
- data/lib/yabeda/version.rb +1 -1
- data/lib/yabeda.rb +5 -2
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1c0a1298576c5e12a8c7acd4cda088fab78b155e846d6aa0c8865638488a5ab
|
|
4
|
+
data.tar.gz: ef0ba94b3fb39fd022e1aeb272104f46729f22aa10da6ba338cd2d91492883bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0effc951709196bbfb6f266211710704645502997c0ee8864d2514d204467a7206eb4550fde040a00d15dde811d85e0ed6eb237939417a6ce41bbd4c310fe6b8
|
|
7
|
+
data.tar.gz: f74760379893fade4bc37635dbbbd0f851a52635ebc50a210eed5531ca2e4b3a2a225cfdbd3d63e38af9dded14d6eaa518f853ff3b7ec63f7ae6ffb919969589
|
data/.github/workflows/test.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.16.0 - 2026-03-12
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Ability to include/exclude only certain metrics in a group for export via adapter. [@sobrinho][] in [#49](https://github.com/yabeda-rb/yabeda/pull/49)
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
Yabeda.configure do
|
|
18
|
+
group :internal do
|
|
19
|
+
only :foo
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
To exclude certain metrics from a group, use the `except` option:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
Yabeda.configure do
|
|
28
|
+
group :internal do
|
|
29
|
+
adapter :prometheus
|
|
30
|
+
except :bar, :baz
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 0.15.0 - 2026-03-04
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- Concurrency issues with metrics' increment/decrement helper methods. [@cconstantine-onesignal][] in [#45](https://github.com/yabeda-rb/yabeda/pull/45)
|
|
40
|
+
|
|
10
41
|
## 0.14.0 - 2025-09-10
|
|
11
42
|
|
|
12
43
|
### Added
|
|
@@ -215,3 +246,5 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
215
246
|
[@Keallar]: https://github.com/Keallar "Eugene Lysanskiy"
|
|
216
247
|
[@jbockler]: https://github.com/jbockler "Josch Bockler"
|
|
217
248
|
[@killondark]: https://github.com/killondark "Alexander Marychev"
|
|
249
|
+
[@cconstantine-onesignal]: https://github.com/cconstantine-onesignal "Chris Constantine"
|
|
250
|
+
[@sobrinho]: https://github.com/sobrinho "Gabriel Sobrinho"
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -158,6 +158,8 @@ These are developed and maintained by other awesome folks:
|
|
|
158
158
|
- [yabeda-shoryuken](https://github.com/retsef/yabeda-shoryuken) — metrics for [Shoryuken](https://github.com/ruby-shoryuken/shoryuken) jobs execution message queues.
|
|
159
159
|
- [yabeda-rack-ratelimit](https://github.com/basecamp/yabeda-rack-ratelimit) — metrics for [Rack::Ratelimit](https://github.com/jeremy/rack-ratelimit)
|
|
160
160
|
- [yabeda-hanami](https://github.com/mlibrary/yabeda-hanami) — metrics for [Hanami](https://hanamirb.org/) The web, with simplicity.
|
|
161
|
+
- [yabeda-jemalloc](http://github.com/jondavidschober/yabeda-jemalloc) - metrics for [Jemalloc](https://jemalloc.net/) via the `stats` FFI
|
|
162
|
+
- [yabeda-rack-queue](https://github.com/speedshop/yabeda-rack-queue) - metrics for reporting queue times of Rack applications.
|
|
161
163
|
- _…and more! You can write your own adapter and open a pull request to add it into this list._
|
|
162
164
|
|
|
163
165
|
## Configuration
|
|
@@ -260,6 +262,53 @@ Yabeda.configure do
|
|
|
260
262
|
end
|
|
261
263
|
```
|
|
262
264
|
|
|
265
|
+
## Filtering metrics
|
|
266
|
+
|
|
267
|
+
You can control which metrics and groups are exposed for a given group using either an allow-list (`only`) or a deny-list (`except`).
|
|
268
|
+
|
|
269
|
+
To permit only specific metrics for a group, use the `only` option:
|
|
270
|
+
|
|
271
|
+
```ruby
|
|
272
|
+
Yabeda.configure do
|
|
273
|
+
group :internal do
|
|
274
|
+
only :foo
|
|
275
|
+
|
|
276
|
+
counter :foo
|
|
277
|
+
gauge :bar
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
To exclude certain metrics from a group, use the `except` option:
|
|
283
|
+
|
|
284
|
+
```ruby
|
|
285
|
+
Yabeda.configure do
|
|
286
|
+
group :internal do
|
|
287
|
+
adapter :prometheus
|
|
288
|
+
|
|
289
|
+
except :bar
|
|
290
|
+
|
|
291
|
+
counter :foo
|
|
292
|
+
gauge :bar
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
This mechanism is especially useful for disabling unwanted metrics from third-party plugins.
|
|
298
|
+
|
|
299
|
+
For example, [yabeda-activerecord](https://github.com/yabeda-rb/yabeda-activerecord) doesn't provide its own configuration to turn off metrics with high cardinality, such as `queries_total` and `query_duration`. You can disable them like this:
|
|
300
|
+
|
|
301
|
+
```ruby
|
|
302
|
+
require 'yabeda'
|
|
303
|
+
require 'yabeda-activerecord'
|
|
304
|
+
|
|
305
|
+
Yabeda.configure do
|
|
306
|
+
group :activerecord do
|
|
307
|
+
except :queries_total, :query_duration
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
```
|
|
311
|
+
|
|
263
312
|
## Roadmap (aka TODO or Help wanted)
|
|
264
313
|
|
|
265
314
|
- Ability to change metric settings for individual adapters
|
data/lib/yabeda/base_adapter.rb
CHANGED
|
@@ -29,6 +29,13 @@ module Yabeda
|
|
|
29
29
|
raise NotImplementedError, "#{self.class} doesn't support setting gauges"
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
# Optional method that adapters can implement for native gauge increment/decrement
|
|
33
|
+
def perform_gauge_increment!(_gauge, _tags, _increment)
|
|
34
|
+
# used to indicate adapter does not implement this method. return a non-nil value
|
|
35
|
+
# in your adapter to indicate it is supported
|
|
36
|
+
nil
|
|
37
|
+
end
|
|
38
|
+
|
|
32
39
|
def register_histogram!(_metric)
|
|
33
40
|
raise NotImplementedError, "#{self.class} doesn't support histograms as metric type!"
|
|
34
41
|
end
|
data/lib/yabeda/counter.rb
CHANGED
|
@@ -10,15 +10,11 @@ module Yabeda
|
|
|
10
10
|
def increment(*args)
|
|
11
11
|
tags, by = self.class.parse_args(*args)
|
|
12
12
|
all_tags = ::Yabeda::Tags.build(tags, group)
|
|
13
|
-
|
|
13
|
+
value = increment_value(all_tags, by: by)
|
|
14
14
|
adapters.each_value do |adapter|
|
|
15
15
|
adapter.perform_counter_increment!(self, all_tags, by)
|
|
16
16
|
end
|
|
17
|
-
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def values
|
|
21
|
-
@values ||= Concurrent::Hash.new(0)
|
|
17
|
+
value
|
|
22
18
|
end
|
|
23
19
|
|
|
24
20
|
# @api private
|
|
@@ -12,6 +12,7 @@ require "yabeda/dsl/metric_builder"
|
|
|
12
12
|
module Yabeda
|
|
13
13
|
# DSL for ease of work with Yabeda
|
|
14
14
|
module DSL
|
|
15
|
+
# rubocop:disable Metrics/ModuleLength
|
|
15
16
|
module ClassMethods
|
|
16
17
|
# Block for grouping and simplifying configuration of related metrics
|
|
17
18
|
def configure(&block)
|
|
@@ -110,6 +111,26 @@ module Yabeda
|
|
|
110
111
|
ensure @adapter_names = nil
|
|
111
112
|
end
|
|
112
113
|
|
|
114
|
+
def only(*metric_names, group: @group)
|
|
115
|
+
if group
|
|
116
|
+
Yabeda.groups[group] ||= Yabeda::Group.new(group)
|
|
117
|
+
Yabeda.groups[group].only(*metric_names)
|
|
118
|
+
else
|
|
119
|
+
raise ConfigurationError, "Yabeda.only should be called either inside group declaration " \
|
|
120
|
+
"or should have group name provided. No metric group provided."
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def except(*metric_names, group: @group)
|
|
125
|
+
if group
|
|
126
|
+
Yabeda.groups[group] ||= Yabeda::Group.new(group)
|
|
127
|
+
Yabeda.groups[group].except(*metric_names)
|
|
128
|
+
else
|
|
129
|
+
raise ConfigurationError, "Yabeda.except should be called either inside group declaration " \
|
|
130
|
+
"or should have group name provided. No metric group provided."
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
113
134
|
def include_group(group)
|
|
114
135
|
raise ConfigurationError, "Adapter limitation can't be defined without of group name" unless group
|
|
115
136
|
|
|
@@ -142,4 +163,5 @@ module Yabeda
|
|
|
142
163
|
end
|
|
143
164
|
end
|
|
144
165
|
end
|
|
166
|
+
# rubocop:enable Metrics/ModuleLength
|
|
145
167
|
end
|
data/lib/yabeda/gauge.rb
CHANGED
|
@@ -5,7 +5,8 @@ module Yabeda
|
|
|
5
5
|
class Gauge < Metric
|
|
6
6
|
def set(tags, value)
|
|
7
7
|
all_tags = ::Yabeda::Tags.build(tags, group)
|
|
8
|
-
values[all_tags]
|
|
8
|
+
atomic_value = values[all_tags] ||= Concurrent::Atom.new(0)
|
|
9
|
+
atomic_value.swap { |_| value }
|
|
9
10
|
adapters.each_value do |adapter|
|
|
10
11
|
adapter.perform_gauge_set!(self, all_tags, value)
|
|
11
12
|
end
|
|
@@ -18,7 +19,14 @@ module Yabeda
|
|
|
18
19
|
# @param by [Integer] increment value
|
|
19
20
|
def increment(*args)
|
|
20
21
|
tags, by = Counter.parse_args(*args)
|
|
21
|
-
|
|
22
|
+
all_tags = ::Yabeda::Tags.build(tags, group)
|
|
23
|
+
next_value = increment_value(all_tags, by: by)
|
|
24
|
+
adapters.each_value do |adapter|
|
|
25
|
+
if adapter.perform_gauge_increment!(self, all_tags, by).nil?
|
|
26
|
+
adapter.perform_gauge_set!(self, all_tags, next_value)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
next_value
|
|
22
30
|
end
|
|
23
31
|
|
|
24
32
|
# @overload decrement(tags = {}, by: 1)
|
|
@@ -27,7 +35,14 @@ module Yabeda
|
|
|
27
35
|
# @param by [Integer] decrement value
|
|
28
36
|
def decrement(*args)
|
|
29
37
|
tags, by = Counter.parse_args(*args)
|
|
30
|
-
|
|
38
|
+
all_tags = ::Yabeda::Tags.build(tags, group)
|
|
39
|
+
next_value = increment_value(all_tags, by: -by)
|
|
40
|
+
adapters.each_value do |adapter|
|
|
41
|
+
if adapter.perform_gauge_increment!(self, all_tags, -by).nil?
|
|
42
|
+
adapter.perform_gauge_set!(self, all_tags, next_value)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
next_value
|
|
31
46
|
end
|
|
32
47
|
end
|
|
33
48
|
end
|
data/lib/yabeda/group.rb
CHANGED
|
@@ -26,6 +26,20 @@ module Yabeda
|
|
|
26
26
|
@adapter.push(*adapter_names)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
def only(*metric_names)
|
|
30
|
+
return @only_list if metric_names.empty?
|
|
31
|
+
|
|
32
|
+
@only_list ||= Concurrent::Array.new
|
|
33
|
+
@only_list.push(*metric_names.map(&:to_sym))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def except(*metric_names)
|
|
37
|
+
return @except_list if metric_names.empty?
|
|
38
|
+
|
|
39
|
+
@except_list ||= Concurrent::Array.new
|
|
40
|
+
@except_list.push(*metric_names.map(&:to_sym))
|
|
41
|
+
end
|
|
42
|
+
|
|
29
43
|
def register_metric(metric)
|
|
30
44
|
define_singleton_method(metric.name) { metric }
|
|
31
45
|
end
|
data/lib/yabeda/metric.rb
CHANGED
|
@@ -17,14 +17,11 @@ module Yabeda
|
|
|
17
17
|
# rubocop:disable Layout/LineLength
|
|
18
18
|
option :adapter, optional: true, comment: "Monitoring system adapter to register metric in and report metric values to (other adapters won't be used)"
|
|
19
19
|
# rubocop:enable Layout/LineLength
|
|
20
|
+
option :values, optional: true, default: proc { Concurrent::Hash.new }
|
|
20
21
|
|
|
21
22
|
# Returns the value for the given label set
|
|
22
23
|
def get(labels = {})
|
|
23
|
-
values[::Yabeda::Tags.build(labels, group)]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def values
|
|
27
|
-
@values ||= Concurrent::Hash.new
|
|
24
|
+
@values[::Yabeda::Tags.build(labels, group)]&.value
|
|
28
25
|
end
|
|
29
26
|
|
|
30
27
|
# Returns allowed tags for metric (with account for global and group-level +default_tags+)
|
|
@@ -55,12 +52,25 @@ module Yabeda
|
|
|
55
52
|
end
|
|
56
53
|
end
|
|
57
54
|
|
|
58
|
-
# Redefined option reader to get
|
|
59
|
-
#
|
|
55
|
+
# Redefined option reader to get null adapter if metric is excluded from the group or from the only list in group,
|
|
56
|
+
# group-level adapter if not set on metric level, and adapter on metric level if set
|
|
57
|
+
# @api privatee
|
|
60
58
|
def adapter
|
|
61
|
-
|
|
59
|
+
group = ::Yabeda.groups[self.group]
|
|
60
|
+
|
|
61
|
+
return :null_adapter if group&.except&.include?(name.to_sym) ||
|
|
62
|
+
(group&.only && !group.only.include?(name.to_sym))
|
|
63
|
+
|
|
64
|
+
return group&.adapter if @adapter == Dry::Initializer::UNDEFINED
|
|
62
65
|
|
|
63
66
|
super
|
|
64
67
|
end
|
|
68
|
+
|
|
69
|
+
# Atomically increment the stored value, assumed to be given all labels, including group labels
|
|
70
|
+
# @api private
|
|
71
|
+
def increment_value(labels = {}, by: 1)
|
|
72
|
+
atomic_value = values[labels] ||= Concurrent::Atom.new(0)
|
|
73
|
+
atomic_value.swap { |prev| prev + by }
|
|
74
|
+
end
|
|
65
75
|
end
|
|
66
76
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "base_adapter"
|
|
4
|
+
|
|
5
|
+
module Yabeda
|
|
6
|
+
# Adapter that discards all metrics. Use when you want to disable metric export
|
|
7
|
+
# (e.g. in development or when no monitoring backend is configured).
|
|
8
|
+
class NullAdapter < BaseAdapter
|
|
9
|
+
def register_counter!(_metric); end
|
|
10
|
+
|
|
11
|
+
def perform_counter_increment!(_counter, _tags, _increment); end
|
|
12
|
+
|
|
13
|
+
def register_gauge!(_metric); end
|
|
14
|
+
|
|
15
|
+
def perform_gauge_set!(_gauge, _tags, _value); end
|
|
16
|
+
|
|
17
|
+
def register_histogram!(_metric); end
|
|
18
|
+
|
|
19
|
+
def perform_histogram_measure!(_histogram, _tags, _value); end
|
|
20
|
+
|
|
21
|
+
def register_summary!(_metric); end
|
|
22
|
+
|
|
23
|
+
def perform_summary_observe!(_summary, _tags, _value); end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/yabeda/version.rb
CHANGED
data/lib/yabeda.rb
CHANGED
|
@@ -8,6 +8,7 @@ require "yabeda/config"
|
|
|
8
8
|
require "yabeda/dsl"
|
|
9
9
|
require "yabeda/tags"
|
|
10
10
|
require "yabeda/errors"
|
|
11
|
+
require "yabeda/null_adapter"
|
|
11
12
|
|
|
12
13
|
# Extendable framework for collecting and exporting metrics from Ruby apps
|
|
13
14
|
module Yabeda
|
|
@@ -32,7 +33,9 @@ module Yabeda
|
|
|
32
33
|
|
|
33
34
|
# @return [Hash<Symbol, Yabeda::BaseAdapter>] All loaded adapters
|
|
34
35
|
def adapters
|
|
35
|
-
@adapters ||= Concurrent::Hash.new
|
|
36
|
+
@adapters ||= Concurrent::Hash.new.tap do |hash|
|
|
37
|
+
hash[:null_adapter] = Yabeda::NullAdapter.new
|
|
38
|
+
end
|
|
36
39
|
end
|
|
37
40
|
|
|
38
41
|
# @return [Array<Proc>] All collectors for periodical retrieving of metrics
|
|
@@ -138,7 +141,7 @@ module Yabeda
|
|
|
138
141
|
# @api private
|
|
139
142
|
def reset!
|
|
140
143
|
default_tags.clear
|
|
141
|
-
adapters
|
|
144
|
+
@adapters = nil
|
|
142
145
|
groups.each_key { |group| singleton_class.send(:remove_method, group) if group && respond_to?(group) }
|
|
143
146
|
@groups = nil
|
|
144
147
|
metrics.each_key { |metric| singleton_class.send(:remove_method, metric) if respond_to?(metric) }
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yabeda
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.16.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrey Novikov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-03-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: anyway_config
|
|
@@ -96,6 +96,7 @@ files:
|
|
|
96
96
|
- lib/yabeda/group.rb
|
|
97
97
|
- lib/yabeda/histogram.rb
|
|
98
98
|
- lib/yabeda/metric.rb
|
|
99
|
+
- lib/yabeda/null_adapter.rb
|
|
99
100
|
- lib/yabeda/railtie.rb
|
|
100
101
|
- lib/yabeda/rspec.rb
|
|
101
102
|
- lib/yabeda/rspec/base_matcher.rb
|