yabeda 0.8.0 → 0.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7c6b79b60dd1c6ea62fe35f811be834bb64baecd5a7fcdfcd35b3f42415d45d
4
- data.tar.gz: 7f1d0130e059e95769e8a663edde3c05b0cc0a49f7af91e22a8ba2cf2a55027a
3
+ metadata.gz: 262fe8c41ef493e3792e67b3e569f3820f8fc8de11a5795807d8d81efe8e0d9f
4
+ data.tar.gz: d86b4a968f1894ce65af4976873135957a122672cd58453023d38792b60c4db7
5
5
  SHA512:
6
- metadata.gz: 40a72d78f2a675c8b0b1c476a9dd29345454a341e7cccbc5353862c4783b85f0825ee387a558547f5b796a126b2c229a6347f09bd1cde1c3935002dbabeea3a2
7
- data.tar.gz: 502631f8472f5f474c3cdbfac887e3e62015a6231246f84512b1251446a4f8913fb62a0cd97f7f6c4d60679318fcac421c9563397ec656f16b3fafc0c38b4f6f
6
+ metadata.gz: 22c41d84fb0efbb8ca1802e02c1c4e6636fc8a2ae05c22775d4390ddc5ddfd0926b97464d6b2702e6b82a1b8709d66bf391bcb7aa6ed05df9a640a0143817889
7
+ data.tar.gz: ad5e58fc8b678c0764b6d8f3677c56a08d087dcbc9407b3a6864fa0e85226a773dce2efaa365d8bed0d0c25db300829811688819a407dee86bcefbea439e2232
@@ -0,0 +1,82 @@
1
+ name: Build and release gem to RubyGems
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - v*
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ with:
14
+ fetch-depth: 0 # Fetch current tag as annotated. See https://github.com/actions/checkout/issues/290
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: 2.7
18
+ - name: "Extract data from tag: version, message, body"
19
+ id: tag
20
+ run: |
21
+ git fetch --tags --force # Really fetch annotated tag. See https://github.com/actions/checkout/issues/290#issuecomment-680260080
22
+ echo ::set-output name=version::${GITHUB_REF#refs/tags/v}
23
+ echo ::set-output name=subject::$(git for-each-ref $GITHUB_REF --format='%(contents:subject)')
24
+ BODY="$(git for-each-ref $GITHUB_REF --format='%(contents:body)')"
25
+ # Extract changelog entries between this and previous version headers
26
+ escaped_version=$(echo ${GITHUB_REF#refs/tags/v} | sed -e 's/[]\/$*.^[]/\\&/g')
27
+ changelog=$(awk "BEGIN{inrelease=0} /## ${escaped_version}/{inrelease=1;next} /## [0-9]+\.[0-9]+\.[0-9]+/{inrelease=0;exit} {if (inrelease) print}" CHANGELOG.md)
28
+ # Multiline body for release. See https://github.community/t/set-output-truncates-multiline-strings/16852/5
29
+ BODY="${BODY}"$'\n'"${changelog}"
30
+ BODY="${BODY//'%'/'%25'}"
31
+ BODY="${BODY//$'\n'/'%0A'}"
32
+ BODY="${BODY//$'\r'/'%0D'}"
33
+ echo "::set-output name=body::$BODY"
34
+ # Add pre-release option if tag name has any suffix after vMAJOR.MINOR.PATCH
35
+ if [[ ${GITHUB_REF#refs/tags/} =~ ^v[0-9]+\.[0-9]+\.[0-9]+.+ ]]; then
36
+ echo ::set-output name=prerelease::true
37
+ fi
38
+ - name: Build gem
39
+ run: gem build
40
+ - name: Calculate checksums
41
+ run: sha256sum yabeda-${{ steps.tag.outputs.version }}.gem > SHA256SUM
42
+ - name: Check version
43
+ run: ls -l yabeda-${{ steps.tag.outputs.version }}.gem
44
+ - name: Create Release
45
+ id: create_release
46
+ uses: actions/create-release@v1
47
+ env:
48
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49
+ with:
50
+ tag_name: ${{ github.ref }}
51
+ release_name: ${{ steps.tag.outputs.subject }}
52
+ body: ${{ steps.tag.outputs.body }}
53
+ draft: false
54
+ prerelease: ${{ steps.tag.outputs.prerelease }}
55
+ - name: Upload built gem as release asset
56
+ uses: actions/upload-release-asset@v1
57
+ env:
58
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
59
+ with:
60
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
61
+ asset_path: yabeda-${{ steps.tag.outputs.version }}.gem
62
+ asset_name: yabeda-${{ steps.tag.outputs.version }}.gem
63
+ asset_content_type: application/x-tar
64
+ - name: Upload checksums as release asset
65
+ uses: actions/upload-release-asset@v1
66
+ env:
67
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
68
+ with:
69
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
70
+ asset_path: SHA256SUM
71
+ asset_name: SHA256SUM
72
+ asset_content_type: text/plain
73
+ - name: Publish to GitHub packages
74
+ env:
75
+ GEM_HOST_API_KEY: Bearer ${{ secrets.GITHUB_TOKEN }}
76
+ run: |
77
+ gem push yabeda-${{ steps.tag.outputs.version }}.gem --host https://rubygems.pkg.github.com/${{ github.repository_owner }}
78
+ - name: Publish to RubyGems
79
+ env:
80
+ GEM_HOST_API_KEY: "${{ secrets.RUBYGEMS_API_KEY }}"
81
+ run: |
82
+ gem push yabeda-${{ steps.tag.outputs.version }}.gem
@@ -0,0 +1,48 @@
1
+ name: Tests
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - '**'
8
+ tags-ignore:
9
+ - 'v*'
10
+
11
+ jobs:
12
+ test:
13
+ name: "Ruby ${{ matrix.ruby }}"
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ include:
19
+ - ruby: "3.0"
20
+ - ruby: "2.7"
21
+ - ruby: "2.6"
22
+ - ruby: "2.5"
23
+ - ruby: "2.4"
24
+ - ruby: "2.3"
25
+ container:
26
+ image: ruby:${{ matrix.ruby }}
27
+ env:
28
+ CI: true
29
+ steps:
30
+ - uses: actions/checkout@v2
31
+ - uses: actions/cache@v2
32
+ with:
33
+ path: vendor/bundle
34
+ key: bundle-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}-${{ hashFiles('**/Gemfile') }}
35
+ restore-keys: |
36
+ bundle-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}-${{ hashFiles('**/Gemfile') }}
37
+ bundle-${{ matrix.ruby }}-
38
+ - name: Upgrade Bundler to 2.0 (for older Rubies)
39
+ run: gem install bundler -v '~> 2.0'
40
+ - name: Bundle install
41
+ run: |
42
+ bundle config path vendor/bundle
43
+ bundle install
44
+ bundle update
45
+ - name: Run Rubocop
46
+ run: bundle exec rubocop
47
+ - name: Run RSpec
48
+ run: bundle exec rspec
data/.rubocop.yml CHANGED
@@ -23,6 +23,12 @@ RSpec/LetSetup:
23
23
  RSpec/MultipleExpectations:
24
24
  Enabled: false
25
25
 
26
+ RSpec/DescribeClass:
27
+ Enabled: false
28
+
29
+ RSpec/NestedGroups:
30
+ Max: 4
31
+
26
32
  Bundler/OrderedGems:
27
33
  Enabled: false
28
34
 
@@ -52,3 +58,6 @@ Style/HashTransformKeys:
52
58
 
53
59
  Style/HashTransformValues:
54
60
  Enabled: true
61
+
62
+ Style/Documentation:
63
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -5,6 +5,40 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## Unreleased
9
+
10
+ ## 0.11.0 - 2021-09-25
11
+
12
+ ### Added
13
+
14
+ - RSpec matchers `increment_yabeda_counter`, `update_yabeda_gauge`, and `measure_yabeda_histogram` for convenient testing. [#25](https://github.com/yabeda-rb/yabeda/pull/25) by [@Envek][]
15
+ - Automatic setup of RSpec on `require "yabeda/rspec"`
16
+ - Special test adapter that collects metric changes in memory
17
+
18
+ ## 0.10.1 - 2021-08-30
19
+
20
+ ### Fixed
21
+
22
+ - Compatibility with anyway_config 1.x gem (which is automatically used on older Rubies, older then minimal Ruby 2.5 for anyway_config 2.x)
23
+
24
+ ## 0.10.0 - 2021-07-21
25
+
26
+ ### Added
27
+
28
+ - Ability to pass a block to `Yabeda::Histogram#measure` to automatically measure its runtime in seconds using [monotonic time](https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/).
29
+ - Debug mode that will enable some additional metrics to help debug performance issues with your usage of Yabeda (or Yabeda itself). Use environment variable `YABEDA_DEBUG` to enable it or call `Yabeda.debug!`.
30
+ - Debugging histogram `yabeda_collect_duration` that measures duration of every collect block, as they are used for collecting metrics of application state and usually makes some potentially slow queries to databases, network requests, etc.
31
+
32
+ ### Changed
33
+
34
+ - Adapters now should use method `Yabeda.collect!` instead of manual calling of every collector block.
35
+
36
+ ## 0.9.0 - 2021-05-07
37
+
38
+ ### Added
39
+
40
+ - Ability to set global metric tags only for a specific group [#19](https://github.com/yabeda-rb/yabeda/pull/19) by [@liaden]
41
+
8
42
  ## 0.8.0 - 2020-08-21
9
43
 
10
44
  ### Added
@@ -99,3 +133,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99
133
  [@Envek]: https://github.com/Envek "Andrey Novikov"
100
134
  [@dsalahutdinov]: https://github.com/dsalahutdinov "Dmitry Salahutdinov"
101
135
  [@asusikov]: https://github.com/asusikov "Alexander Susikov"
136
+ [@liaden]: https://github.com/liaden "Joel Johnson"
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Yabeda
1
+ # ![Yabeda](./yabeda-logo.png)
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/yabeda.svg)](https://rubygems.org/gems/yabeda) [![Build Status](https://travis-ci.org/yabeda-rb/yabeda.svg?branch=master)](https://travis-ci.org/yabeda-rb/yabeda)
3
+ [![Gem Version](https://badge.fury.io/rb/yabeda.svg)](https://rubygems.org/gems/yabeda)
4
4
 
5
5
  **This software is Work in Progress: features will appear and disappear, API will be changed, your feedback is always welcome!**
6
6
 
@@ -79,10 +79,14 @@ And then execute:
79
79
  end
80
80
  ```
81
81
 
82
- 5. _Optionally_ setup default tags that will be added to all metrics
82
+ 5. _Optionally_ setup default tags for all appropriate metrics
83
83
  ```ruby
84
84
  Yabeda.configure do
85
+ # matches all metrics in all groups
85
86
  default_tag :rails_environment, 'production'
87
+
88
+ # matches all metrics in the :your_app group
89
+ default_tag :tag_name, 'override', group: :your_app
86
90
  end
87
91
 
88
92
  # You can redefine them for limited amount of time
@@ -91,17 +95,111 @@ And then execute:
91
95
  end
92
96
  ```
93
97
 
94
- 6. See the docs for the adapter you're using
95
- 7. Enjoy!
98
+ **Note**: any usage of `with_tags` **must** have all those tags defined on all metrics that are generated in the block.
99
+
100
+ 6. _Optionally_ override default tags using precedence:
101
+
102
+ The tag precedence from high to low is:
103
+
104
+ * Manually specified tags
105
+ * Thread local tags (specified by `Yabeda.with_tags`)
106
+ * Group specific tags
107
+ * Global tags
108
+
109
+ 7. See the docs for the adapter you're using
110
+ 8. Enjoy!
96
111
 
97
112
  ## Available monitoring system adapters
98
113
 
99
- - [Prometheus](https://github.com/yabeda-rb/yabeda-prometheus)
114
+ ### Maintained by Yabeda
115
+
116
+ - Prometheus:
117
+ - [yabeda-prometheus](https://github.com/yabeda-rb/yabeda-prometheus) — wraps [official Ruby client for Prometheus](https://github.com/prometheus/client_ruby).
118
+ - [yabeda-prometheus-mmap](https://github.com/yabeda-rb/yabeda-prometheus-mmap) — wraps [GitLab's fork of Prometheus Ruby client](https://gitlab.com/gitlab-org/prometheus-client-mmap) which may work better for multi-process application servers.
100
119
  - [Datadog](https://github.com/yabeda-rb/yabeda-datadog)
101
120
  - [NewRelic](https://github.com/yabeda-rb/yabeda-newrelic)
121
+
122
+ ### Third-party adapters
123
+
124
+ These are developed and maintained by other awesome folks:
125
+
102
126
  - [Statsd](https://github.com/asusikov/yabeda-statsd)
103
127
  - _…and more! You can write your own adapter and open a pull request to add it into this list._
104
128
 
129
+ ## Available plugins to collect metrics
130
+
131
+ ### Maintained by Yabeda
132
+
133
+ - [yabeda-rails] — basic request metrics for [Ruby on Rails](https://rubyonrails.org/) applications.
134
+ - [yabeda-sidekiq] — comprehensive set of metrics for monitoring [Sidekiq](https://sidekiq.org/) jobs execution and queues.
135
+ - [yabeda-faktory] — metrics for monitoring jobs execution by Ruby workers of [Faktory](https://contribsys.com/faktory/).
136
+ - [yabeda-graphql] — metrics to query and field-level monitoring for apps using [GraphQL-Ruby](https://graphql-ruby.org/).
137
+ - [yabeda-puma-plugin] — metrics for internal state and performance of [Puma](https://puma.io/) application server.
138
+ - [yabeda-http_requests] — monitor how many outgoing HTTP calls your application does (uses [Sniffer](https://github.com/aderyabin/sniffer)).
139
+ - [yabeda-schked] — monitor number and duration of Cron jobs executed by [Schked](https://github.com/bibendi/schked).
140
+ - [yabeda-anycable] — monitor number, duration, and status of [AnyCable](https://anycable.io/) RPC calls.
141
+
142
+ ### Third-party plugins
143
+
144
+ These are developed and maintained by other awesome folks:
145
+
146
+ - [yabeda-grape](https://github.com/efigence/yabeda-grape) — metrics for [Grape](https://github.com/ruby-grape/grape) framework.
147
+ - [yabeda-gruf](https://github.com/Placewise/yabeda-gruf) — metrics for [gRPC Ruby Framework](https://github.com/bigcommerce/gruf)
148
+ - [yabeda-gc](https://github.com/ianks/yabeda-gc) — metrics for Ruby garbage collection.
149
+ - _…and more! You can write your own adapter and open a pull request to add it into this list._
150
+
151
+ ## Configuration
152
+
153
+ Configuration is handled by [anyway_config] gem. With it you can load settings from environment variables (which names are constructed from config key upcased and prefixed with `YABEDA_`), YAML files, and other sources. See [anyway_config] docs for details.
154
+
155
+ Config key | Type | Default | Description |
156
+ ---------- | -------- | ------- | ----------- |
157
+ `debug` | boolean | `false` | Collects metrics measuring Yabeda performance |
158
+
159
+ ## Debugging metrics
160
+
161
+ - Time of collector block run: `yabeda_collect_duration` (segmented by block source location). Collector blocks are used for collecting metrics of application state and usually makes some potentially slow queries to databases, network requests, etc.
162
+
163
+ These are only enabled in debug mode. To enable it either set `debug` config key to `true` (e.g. by specifying `YABEDA_DEBUG=true` in your environment variables or executing `Yabeda.debug!` in your code).
164
+
165
+ ## Testing
166
+
167
+ ### RSpec
168
+
169
+ Add the following to your `rails_helper.rb` (or `spec_helper.rb`):
170
+
171
+ ```ruby
172
+ require "yabeda/rspec"
173
+ ```
174
+
175
+ Now you can use `increment_yabeda_counter`, `update_yabeda_gauge`, and `measure_yabeda_histogram` matchers:
176
+
177
+ ```ruby
178
+ it "increments counters" do
179
+ expect { subject }.to increment_yabeda_counter(Yabeda.myapp.foo_count).by(3)
180
+ end
181
+ ```
182
+
183
+ You can scope metrics by used tags with `with_tags`:
184
+
185
+ ```ruby
186
+ it "updates gauges" do
187
+ expect { subject }.to \
188
+ update_yabeda_gauge("some_gauge_name").
189
+ with_tags(method: "command", command: "subscribe")
190
+ end
191
+ ```
192
+
193
+ Note that tags you specified doesn't need to be exact, but can be a subset of tags used on metric update. In this example updates with following sets of tags `{ method: "command", command: "subscribe", status: "SUCCESS" }` and `{ method: "command", command: "subscribe", status: "FAILURE" }` will make test example to pass.
194
+
195
+ And check for values with `by` for counters, `to` for gauges, and `with` for gauges and histograms (and you [can use other matchers here](https://relishapp.com/rspec/rspec-expectations/v/3-10/docs/composing-matchers)):
196
+
197
+ ```ruby
198
+ expect { subject }.to \
199
+ measure_yabeda_histogram(Yabeda.something.anything_runtime).
200
+ with(be_between(0.005, 0.05))
201
+ ```
202
+
105
203
  ## Roadmap (aka TODO or Help wanted)
106
204
 
107
205
  - Ability to change metric settings for individual adapters
@@ -130,6 +228,36 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
130
228
 
131
229
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
132
230
 
231
+ ### Releasing
232
+
233
+ 1. Bump version number in `lib/yabeda/version.rb`
234
+
235
+ In case of pre-releases keep in mind [rubygems/rubygems#3086](https://github.com/rubygems/rubygems/issues/3086) and check version with command like `Gem::Version.new(Yabeda::VERSION).to_s`
236
+
237
+ 2. Fill `CHANGELOG.md` with missing changes, add header with version and date.
238
+
239
+ 3. Make a commit:
240
+
241
+ ```sh
242
+ git add lib/yabeda/version.rb CHANGELOG.md
243
+ version=$(ruby -r ./lib/yabeda/version.rb -e "puts Gem::Version.new(Yabeda::VERSION)")
244
+ git commit --message="${version}: " --edit
245
+ ```
246
+
247
+ 3. Create annotated tag:
248
+
249
+ ```sh
250
+ git tag v${version} --annotate --message="${version}: " --edit --sign
251
+ ```
252
+
253
+ 4. Fill version name into subject line and (optionally) some description (changes will be taken from changelog and appended automatically)
254
+
255
+ 5. Push it:
256
+
257
+ ```sh
258
+ git push --follow-tags
259
+ ```
260
+
133
261
  ## Contributing
134
262
 
135
263
  Bug reports and pull requests are welcome on GitHub at https://github.com/yabeda-rb/yabeda.
@@ -139,3 +267,11 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/yabeda
139
267
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
140
268
 
141
269
  [yabeda-rails]: https://github.com/yabeda-rb/yabeda-rails/ "Yabeda plugin for collecting and exporting basic metrics for Rails applications"
270
+ [yabeda-sidekiq]: https://github.com/yabeda-rb/yabeda-sidekiq/ "Yabeda plugin for complete monitoring of Sidekiq metrics"
271
+ [yabeda-faktory]: https://github.com/yabeda-rb/yabeda-faktory/ "Yabeda plugin for complete monitoring of Faktory Ruby Workers"
272
+ [yabeda-graphql]: https://github.com/yabeda-rb/yabeda-graphql/ "Measure and understand how good your GraphQL-Ruby application works"
273
+ [yabeda-puma-plugin]: https://github.com/yabeda-rb/yabeda-puma-plugin/ "Collects Puma web-server metrics from puma control application"
274
+ [yabeda-http_requests]: https://github.com/yabeda-rb/yabeda-http_requests/ "Builtin metrics to monitor external HTTP requests"
275
+ [yabeda-schked]: https://github.com/yabeda-rb/yabeda-schked/ "Built-in metrics for monitoring Schked recurring jobs out of the box"
276
+ [yabeda-anycable]: https://github.com/yabeda-rb/yabeda-anycable "Collect performance metrics for AnyCable RPC server"
277
+ [anyway_config]: https://github.com/palkan/anyway_config "Configuration library for Ruby gems and applications"
@@ -35,5 +35,8 @@ module Yabeda
35
35
  def perform_histogram_measure!(_metric, _tags, _value)
36
36
  raise NotImplementedError, "#{self.class} doesn't support measuring histograms"
37
37
  end
38
+
39
+ # Hook to enable debug mode in adapters when it is enabled in Yabeda itself
40
+ def debug!; end
38
41
  end
39
42
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "anyway"
4
+
5
+ module Yabeda
6
+ # Runtime configuration for the main yabeda gem
7
+ class Config < ::Anyway::Config
8
+ config_name :yabeda
9
+
10
+ # Declare and collect metrics about Yabeda performance
11
+ attr_config debug: false
12
+
13
+ # Implement predicate method from AnywayConfig 2.x to support AnywayConfig 1.x users
14
+ alias debug? debug unless instance_methods.include?(:debug?)
15
+ end
16
+ end
@@ -4,7 +4,7 @@ module Yabeda
4
4
  # Growing-only counter
5
5
  class Counter < Metric
6
6
  def increment(tags, by: 1)
7
- all_tags = ::Yabeda::Tags.build(tags)
7
+ all_tags = ::Yabeda::Tags.build(tags, group)
8
8
  values[all_tags] += by
9
9
  ::Yabeda.adapters.each do |_, adapter|
10
10
  adapter.perform_counter_increment!(self, all_tags, by)
@@ -5,12 +5,12 @@ require "yabeda/counter"
5
5
  require "yabeda/gauge"
6
6
  require "yabeda/histogram"
7
7
  require "yabeda/group"
8
+ require "yabeda/global_group"
8
9
  require "yabeda/dsl/metric_builder"
9
10
 
10
11
  module Yabeda
11
12
  # DSL for ease of work with Yabeda
12
13
  module DSL
13
- # rubocop: disable Style/Documentation
14
14
  module ClassMethods
15
15
  # Block for grouping and simplifying configuration of related metrics
16
16
  def configure(&block)
@@ -30,6 +30,7 @@ module Yabeda
30
30
  # (like NewRelic) it is treated individually and has a special meaning.
31
31
  def group(group_name)
32
32
  @group = group_name
33
+ Yabeda.groups[@group] ||= Yabeda::Group.new(@group)
33
34
  return unless block_given?
34
35
 
35
36
  yield
@@ -58,24 +59,30 @@ module Yabeda
58
59
  #
59
60
  # @param name [Symbol] Name of default tag
60
61
  # @param value [String] Value of default tag
61
- def default_tag(name, value)
62
- ::Yabeda.default_tags[name] = value
62
+ def default_tag(name, value, group: @group)
63
+ if group
64
+ Yabeda.groups[group] ||= Yabeda::Group.new(group)
65
+ Yabeda.groups[group].default_tag(name, value)
66
+ else
67
+ Yabeda.default_tags[name] = value
68
+ end
63
69
  end
64
70
 
65
71
  # Redefine default tags for a limited amount of time
66
72
  # @param tags Hash{Symbol=>#to_s}
67
73
  def with_tags(**tags)
68
- Thread.current[:yabeda_temporary_tags] = tags
74
+ previous_temp_tags = temporary_tags
75
+ Thread.current[:yabeda_temporary_tags] = Thread.current[:yabeda_temporary_tags].merge(tags)
69
76
  yield
70
77
  ensure
71
- Thread.current[:yabeda_temporary_tags] = {}
78
+ Thread.current[:yabeda_temporary_tags] = previous_temp_tags
72
79
  end
73
80
 
74
81
  # Get tags set by +with_tags+
75
82
  # @api private
76
83
  # @return Hash
77
84
  def temporary_tags
78
- Thread.current[:yabeda_temporary_tags] || {}
85
+ Thread.current[:yabeda_temporary_tags] ||= {}
79
86
  end
80
87
 
81
88
  private
@@ -95,12 +102,12 @@ module Yabeda
95
102
  if group.nil?
96
103
  group = Group.new(metric.group)
97
104
  ::Yabeda.groups[metric.group] = group
98
- ::Yabeda.define_singleton_method(metric.group) { group }
99
105
  end
100
106
 
107
+ ::Yabeda.define_singleton_method(metric.group) { group } unless ::Yabeda.respond_to?(metric.group)
108
+
101
109
  group.register_metric(metric)
102
110
  end
103
111
  end
104
- # rubocop: enable Style/Documentation
105
112
  end
106
113
  end
data/lib/yabeda/gauge.rb CHANGED
@@ -4,7 +4,7 @@ module Yabeda
4
4
  # Arbitrary value, can be changed in both sides
5
5
  class Gauge < Metric
6
6
  def set(tags, value)
7
- all_tags = ::Yabeda::Tags.build(tags)
7
+ all_tags = ::Yabeda::Tags.build(tags, group)
8
8
  values[all_tags] = value
9
9
  ::Yabeda.adapters.each do |_, adapter|
10
10
  adapter.perform_gauge_set!(self, all_tags, value)
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require_relative "./group"
5
+
6
+ module Yabeda
7
+ # Represents implicit global group
8
+ class GlobalGroup < Group
9
+ extend Forwardable
10
+
11
+ def_delegators ::Yabeda, :default_tags, :default_tag
12
+ end
13
+ end
data/lib/yabeda/group.rb CHANGED
@@ -9,6 +9,16 @@ module Yabeda
9
9
 
10
10
  param :name
11
11
 
12
+ def default_tags
13
+ @default_tags ||= Concurrent::Hash.new
14
+ ::Yabeda.default_tags.merge(@default_tags)
15
+ end
16
+
17
+ def default_tag(key, value)
18
+ @default_tags ||= Concurrent::Hash.new
19
+ @default_tags[key] = value
20
+ end
21
+
12
22
  def register_metric(metric)
13
23
  define_singleton_method(metric.name) { metric }
14
24
  end
@@ -6,13 +6,25 @@ module Yabeda
6
6
  class Histogram < Metric
7
7
  option :buckets
8
8
 
9
- def measure(tags, value)
10
- all_tags = ::Yabeda::Tags.build(tags)
9
+ # rubocop: disable Metrics/MethodLength
10
+ def measure(tags, value = nil)
11
+ if value.nil? ^ block_given?
12
+ raise ArgumentError, "You must provide either numeric value or block for Yabeda::Histogram#measure!"
13
+ end
14
+
15
+ if block_given?
16
+ starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
17
+ yield
18
+ value = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - starting)
19
+ end
20
+
21
+ all_tags = ::Yabeda::Tags.build(tags, group)
11
22
  values[all_tags] = value
12
23
  ::Yabeda.adapters.each do |_, adapter|
13
24
  adapter.perform_histogram_measure!(self, all_tags, value)
14
25
  end
15
26
  value
16
27
  end
28
+ # rubocop: enable Metrics/MethodLength
17
29
  end
18
30
  end
data/lib/yabeda/metric.rb CHANGED
@@ -17,15 +17,21 @@ module Yabeda
17
17
 
18
18
  # Returns the value for the given label set
19
19
  def get(labels = {})
20
- values[::Yabeda::Tags.build(labels)]
20
+ values[::Yabeda::Tags.build(labels, group)]
21
21
  end
22
22
 
23
23
  def values
24
24
  @values ||= Concurrent::Hash.new
25
25
  end
26
26
 
27
+ # Returns allowed tags for metric (with account for global and group-level +default_tags+)
28
+ # @return Array<Symbol>
27
29
  def tags
28
- (Yabeda.default_tags.keys + Array(super)).uniq
30
+ (Yabeda.groups[group].default_tags.keys + Array(super)).uniq
31
+ end
32
+
33
+ def inspect
34
+ "#<#{self.class.name}: #{[@group, @name].compact.join('.')}>"
29
35
  end
30
36
  end
31
37
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yabeda
4
+ module RSpec
5
+ # Notes:
6
+ # +expected+ is always a metric instance
7
+ # +actual+ is always a block of code
8
+ # Example:
9
+ # expect { anything }.to do_whatever_with_yabeda_metric(Yabeda.something)
10
+ class BaseMatcher < ::RSpec::Matchers::BuiltIn::BaseMatcher
11
+ attr_reader :tags, :metric
12
+
13
+ # Specify a scope of labels (tags). Subset of tags can be specified.
14
+ def with_tags(tags)
15
+ @tags = tags
16
+ self
17
+ end
18
+
19
+ def initialize(expected)
20
+ @expected = @metric = resolve_metric(expected)
21
+ rescue KeyError
22
+ raise ArgumentError, <<~MSG
23
+ Pass metric name or metric instance to matcher (e.g. `increment_yabeda_counter(Yabeda.metric_name)` or \
24
+ increment_yabeda_counter('metric_name')). Got #{expected.inspect} instead
25
+ MSG
26
+ end
27
+
28
+ # RSpec doesn't define this method, but it is more convenient to rely on +match_when_negated+ method presence
29
+ def does_not_match?(actual)
30
+ @actual = actual
31
+ if respond_to?(:match_when_negated)
32
+ match_when_negated(expected, actual)
33
+ else
34
+ !match(expected, actual)
35
+ end
36
+ end
37
+
38
+ def supports_block_expectations?
39
+ true
40
+ end
41
+
42
+ # Pretty print metric name (expected is expected to always be a Yabeda metric instance)
43
+ def expected_formatted
44
+ "Yabeda.#{[metric.group, metric.name].compact.join('.')}"
45
+ end
46
+
47
+ private
48
+
49
+ def resolve_metric(instance_or_name)
50
+ return instance_or_name if instance_or_name.is_a? Yabeda::Metric
51
+
52
+ Yabeda.metrics.fetch(instance_or_name.to_s)
53
+ end
54
+
55
+ # Filter metric changes by tags.
56
+ # If tags specified, treat them as subset of real tags (to avoid bothering with default tags in tests)
57
+ def filter_matching_changes(changes)
58
+ return changes if tags.nil?
59
+
60
+ changes.select { |t, _v| t >= tags }
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./base_matcher"
4
+
5
+ module Yabeda
6
+ module RSpec
7
+ # Checks whether Yabeda counter was incremented during test run or not
8
+ # @param metric [Yabeda::Counter,String,Symbol] metric instance or name
9
+ # @return [Yabeda::RSpec::IncrementYabedaCounter]
10
+ def increment_yabeda_counter(metric)
11
+ IncrementYabedaCounter.new(metric)
12
+ end
13
+
14
+ # Custom matcher class with implementation for +increment_yabeda_counter+
15
+ class IncrementYabedaCounter < BaseMatcher
16
+ def by(increment)
17
+ @expected_increment = increment
18
+ self
19
+ end
20
+
21
+ attr_reader :expected_increment
22
+
23
+ def initialize(*)
24
+ super
25
+ return if metric.is_a? Yabeda::Counter
26
+
27
+ raise ArgumentError, "Pass counter instance/name to `increment_yabeda_counter`. Got #{metric.inspect} instead"
28
+ end
29
+
30
+ def match(metric, block)
31
+ block.call
32
+
33
+ increments = filter_matching_changes(Yabeda::TestAdapter.instance.counters.fetch(metric))
34
+
35
+ increments.values.any? do |actual_increment|
36
+ expected_increment.nil? || values_match?(expected_increment, actual_increment)
37
+ end
38
+ end
39
+
40
+ def match_when_negated(metric, block)
41
+ unless expected_increment.nil?
42
+ raise NotImplementedError, <<~MSG
43
+ `expect(Yabeda.metric_name).not_to increment_yabeda_counter` doesn't support specifying increment
44
+ with `.by` as it can lead to false positives.
45
+ MSG
46
+ end
47
+
48
+ block.call
49
+
50
+ increments = filter_matching_changes(Yabeda::TestAdapter.instance.counters.fetch(metric))
51
+
52
+ increments.none?
53
+ end
54
+
55
+ def failure_message
56
+ "expected #{expected_formatted} " \
57
+ "to be incremented #{"by #{description_of(expected_increment)} " unless expected_increment.nil?}" \
58
+ "#{("with tags #{::RSpec::Support::ObjectFormatter.format(tags)} " if tags)}" \
59
+ "but #{actual_increments_message}"
60
+ end
61
+
62
+ def failure_message_when_negated
63
+ "expected #{expected_formatted} " \
64
+ "not to be incremented " \
65
+ "#{("with tags #{::RSpec::Support::ObjectFormatter.format(tags)} " if tags)}" \
66
+ "but #{actual_increments_message}"
67
+ end
68
+
69
+ def actual_increments_message
70
+ counter_increments = Yabeda::TestAdapter.instance.counters.fetch(metric)
71
+ if counter_increments.empty?
72
+ "no increments of this counter have been made"
73
+ elsif tags && counter_increments.key?(tags)
74
+ "has been incremented by #{counter_increments.fetch(tags)}"
75
+ else
76
+ "following increments have been made: #{::RSpec::Support::ObjectFormatter.format(counter_increments)}"
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./base_matcher"
4
+
5
+ module Yabeda
6
+ module RSpec
7
+ # Checks whether Yabeda histogram was measured during test run or not
8
+ # @param metric [Yabeda::Histogram,String,Symbol] metric instance or name
9
+ # @return [Yabeda::RSpec::MeasureYabedaHistogram]
10
+ def measure_yabeda_histogram(metric)
11
+ MeasureYabedaHistogram.new(metric)
12
+ end
13
+
14
+ # Custom matcher class with implementation for +measure_yabeda_histogram+
15
+ class MeasureYabedaHistogram < BaseMatcher
16
+ def with(value)
17
+ @expected_value = value
18
+ self
19
+ end
20
+
21
+ attr_reader :expected_value
22
+
23
+ def initialize(*)
24
+ super
25
+ return if metric.is_a? Yabeda::Histogram
26
+
27
+ raise ArgumentError, "Pass histogram instance/name to `measure_yabeda_histogram`. Got #{metric.inspect} instead"
28
+ end
29
+
30
+ def match(metric, block)
31
+ block.call
32
+
33
+ measures = filter_matching_changes(Yabeda::TestAdapter.instance.histograms.fetch(metric))
34
+
35
+ measures.values.any? { |measure| expected_value.nil? || values_match?(expected_value, measure) }
36
+ end
37
+
38
+ def match_when_negated(metric, block)
39
+ unless expected_value.nil?
40
+ raise NotImplementedError, <<~MSG
41
+ `expect {}.not_to measure_yabeda_histogram` doesn't support specifying values with `.with`
42
+ as it can lead to false positives.
43
+ MSG
44
+ end
45
+
46
+ block.call
47
+
48
+ measures = filter_matching_changes(Yabeda::TestAdapter.instance.histograms.fetch(metric))
49
+
50
+ measures.none?
51
+ end
52
+
53
+ def failure_message
54
+ "expected #{expected_formatted} " \
55
+ "to be changed #{"to #{expected} " unless expected_value.nil?}" \
56
+ "#{("with tags #{::RSpec::Support::ObjectFormatter.format(tags)} " if tags)}" \
57
+ "but #{actual_changes_message}"
58
+ end
59
+
60
+ def failure_message_when_negated
61
+ "expected #{expected_formatted} " \
62
+ "not to be incremented " \
63
+ "#{("with tags #{::RSpec::Support::ObjectFormatter.format(tags)} " if tags)}" \
64
+ "but #{actual_changes_message}"
65
+ end
66
+
67
+ def actual_changes_message
68
+ measures = Yabeda::TestAdapter.instance.histograms.fetch(metric)
69
+ if measures.empty?
70
+ "no changes of this gauge have been made"
71
+ elsif tags && measures.key?(tags)
72
+ "has been changed to #{measures.fetch(tags)} with tags #{::RSpec::Support::ObjectFormatter.format(tags)}"
73
+ else
74
+ "following changes have been made: #{::RSpec::Support::ObjectFormatter.format(measures)}"
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./base_matcher"
4
+
5
+ module Yabeda
6
+ module RSpec
7
+ # Checks whether Yabeda gauge was set to some value during test run or not
8
+ # @param metric [Yabeda::Gauge,String,Symbol] metric instance or name
9
+ # @return [Yabeda::RSpec::UpdateYabedaGauge]
10
+ def update_yabeda_gauge(metric)
11
+ UpdateYabedaGauge.new(metric)
12
+ end
13
+
14
+ # Custom matcher class with implementation for +update_yabeda_gauge+
15
+ class UpdateYabedaGauge < BaseMatcher
16
+ def with(value)
17
+ @expected_value = value
18
+ self
19
+ end
20
+
21
+ attr_reader :expected_value
22
+
23
+ def initialize(*)
24
+ super
25
+ return if metric.is_a? Yabeda::Gauge
26
+
27
+ raise ArgumentError, "Pass gauge instance/name to `update_yabeda_gauge`. Got #{metric.inspect} instead"
28
+ end
29
+
30
+ def match(metric, block)
31
+ block.call
32
+
33
+ updates = filter_matching_changes(Yabeda::TestAdapter.instance.gauges.fetch(metric))
34
+
35
+ updates.values.any? { |update| expected_value.nil? || values_match?(expected_value, update) }
36
+ end
37
+
38
+ def match_when_negated(metric, block)
39
+ unless expected_value.nil?
40
+ raise NotImplementedError, <<~MSG
41
+ `expect(Yabeda.metric_name).not_to update_yabeda_gauge` doesn't support specifying values with `.with`
42
+ as it can lead to false positives.
43
+ MSG
44
+ end
45
+
46
+ block.call
47
+
48
+ updates = filter_matching_changes(Yabeda::TestAdapter.instance.gauges.fetch(metric))
49
+
50
+ updates.none?
51
+ end
52
+
53
+ def failure_message
54
+ "expected #{expected_formatted} " \
55
+ "to be changed #{"to #{expected_value} " unless expected_value.nil?}" \
56
+ "#{("with tags #{::RSpec::Support::ObjectFormatter.format(tags)} " if tags)}" \
57
+ "but #{actual_changes_message}"
58
+ end
59
+
60
+ def failure_message_when_negated
61
+ "expected #{expected_formatted} " \
62
+ "not to be changed " \
63
+ "#{("with tags #{::RSpec::Support::ObjectFormatter.format(tags)} " if tags)}" \
64
+ "but #{actual_changes_message}"
65
+ end
66
+
67
+ def actual_changes_message
68
+ updates = Yabeda::TestAdapter.instance.gauges.fetch(metric)
69
+ if updates.empty?
70
+ "no changes of this gauge have been made"
71
+ elsif tags && updates.key?(tags)
72
+ "has been changed to #{updates.fetch(tags)} with tags #{::RSpec::Support::ObjectFormatter.format(tags)}"
73
+ else
74
+ "following changes have been made: #{::RSpec::Support::ObjectFormatter.format(updates)}"
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./testing"
4
+
5
+ module Yabeda
6
+ # RSpec integration for Yabeda: custom matchers, etc
7
+ module RSpec
8
+ end
9
+ end
10
+
11
+ require_relative "./rspec/increment_yabeda_counter"
12
+ require_relative "./rspec/update_yabeda_gauge"
13
+ require_relative "./rspec/measure_yabeda_histogram"
14
+
15
+ ::RSpec.configure do |config|
16
+ config.before(:suite) do
17
+ Yabeda.configure! unless Yabeda.already_configured?
18
+ end
19
+
20
+ config.after(:each) do
21
+ Yabeda::TestAdapter.instance.reset!
22
+ end
23
+
24
+ config.include(Yabeda::RSpec)
25
+ end
data/lib/yabeda/tags.rb CHANGED
@@ -3,8 +3,12 @@
3
3
  module Yabeda
4
4
  # Class to merge tags
5
5
  class Tags
6
- def self.build(tags)
7
- ::Yabeda.default_tags.merge(Yabeda.temporary_tags).merge(tags)
6
+ def self.build(tags, group_name = nil)
7
+ Yabeda.default_tags.dup.tap do |result|
8
+ result.merge!(Yabeda.groups[group_name].default_tags) if group_name
9
+ result.merge!(Yabeda.temporary_tags)
10
+ result.merge!(tags)
11
+ end
8
12
  end
9
13
  end
10
14
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ require_relative "./base_adapter"
6
+
7
+ module Yabeda
8
+ # Fake monitoring system adapter that collects latest metric values for later inspection
9
+ class TestAdapter < BaseAdapter
10
+ include Singleton
11
+
12
+ attr_reader :counters, :gauges, :histograms
13
+
14
+ def initialize
15
+ @counters = Hash.new { |ch, ck| ch[ck] = Hash.new { |th, tk| th[tk] = 0 } }
16
+ @gauges = Hash.new { |gh, gk| gh[gk] = Hash.new { |th, tk| th[tk] = nil } }
17
+ @histograms = Hash.new { |hh, hk| hh[hk] = Hash.new { |th, tk| th[tk] = nil } }
18
+ end
19
+
20
+ # Call this method after every test example to quickly get blank state for the next test example
21
+ def reset!
22
+ [@counters, @gauges, @histograms].each do |collection|
23
+ collection.each_value(&:clear) # Reset tag-values hash to be empty
24
+ end
25
+ end
26
+
27
+ def register_counter!(metric)
28
+ @counters[metric]
29
+ end
30
+
31
+ def register_gauge!(metric)
32
+ @gauges[metric]
33
+ end
34
+
35
+ def register_histogram!(metric)
36
+ @histograms[metric]
37
+ end
38
+
39
+ def perform_counter_increment!(counter, tags, increment)
40
+ @counters[counter][tags] += increment
41
+ end
42
+
43
+ def perform_gauge_set!(gauge, tags, value)
44
+ @gauges[gauge][tags] = value
45
+ end
46
+
47
+ def perform_histogram_measure!(histogram, tags, value)
48
+ @histograms[histogram][tags] = value
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Include this file to get things prepared for testing
4
+
5
+ require_relative "./test_adapter"
6
+
7
+ Yabeda.register_adapter(:test, Yabeda::TestAdapter.instance)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Yabeda
4
- VERSION = "0.8.0"
4
+ VERSION = "0.11.0"
5
5
  end
data/lib/yabeda.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "concurrent"
4
+ require "forwardable"
4
5
 
5
6
  require "yabeda/version"
7
+ require "yabeda/config"
6
8
  require "yabeda/dsl"
7
9
  require "yabeda/tags"
8
10
  require "yabeda/errors"
@@ -13,6 +15,8 @@ module Yabeda
13
15
  include DSL
14
16
 
15
17
  class << self
18
+ extend Forwardable
19
+
16
20
  # @return [Hash<String, Yabeda::Metric>] All registered metrics
17
21
  def metrics
18
22
  @metrics ||= Concurrent::Hash.new
@@ -20,7 +24,9 @@ module Yabeda
20
24
 
21
25
  # @return [Hash<String, Yabeda::Group>] All registered metrics
22
26
  def groups
23
- @groups ||= Concurrent::Hash.new
27
+ @groups ||= Concurrent::Hash.new.tap do |hash|
28
+ hash[nil] = Yabeda::GlobalGroup.new(nil)
29
+ end
24
30
  end
25
31
 
26
32
  # @return [Hash<String, Yabeda::BaseAdapter>] All loaded adapters
@@ -33,7 +39,26 @@ module Yabeda
33
39
  @collectors ||= Concurrent::Array.new
34
40
  end
35
41
 
36
- # @return [Hash<Symbol, Symbol>] All added default tags
42
+ def config
43
+ @config ||= Config.new
44
+ end
45
+
46
+ def_delegators :config, :debug?
47
+
48
+ # Execute all collector blocks for periodical retrieval of metrics
49
+ #
50
+ # This method is intended to be used by monitoring systems adapters
51
+ def collect!
52
+ collectors.each do |collector|
53
+ if config.debug?
54
+ yabeda.collect_duration.measure({ location: collector.source_location.join(":") }, &collector)
55
+ else
56
+ collector.call
57
+ end
58
+ end
59
+ end
60
+
61
+ # @return [Hash<Symbol, Symbol>] All added global default tags
37
62
  def default_tags
38
63
  @default_tags ||= Concurrent::Hash.new
39
64
  end
@@ -65,6 +90,8 @@ module Yabeda
65
90
  def configure!
66
91
  raise(AlreadyConfiguredError, @configured_by) if already_configured?
67
92
 
93
+ debug! if config.debug?
94
+
68
95
  configurators.each do |(group, block)|
69
96
  group group
70
97
  class_eval(&block)
@@ -81,19 +108,45 @@ module Yabeda
81
108
 
82
109
  @configured_by = caller_locations(1, 1)[0].to_s
83
110
  end
111
+
112
+ # Enable and setup service metrics to monitor yabeda performance
113
+ def debug!
114
+ return false if @debug_was_enabled_by # Prevent multiple calls
115
+
116
+ config.debug ||= true # Enable debug mode in config if it wasn't enabled from other sources
117
+ @debug_was_enabled_by = caller_locations(1, 1)[0].to_s
118
+
119
+ configure do
120
+ group :yabeda
121
+
122
+ histogram :collect_duration,
123
+ tags: %i[location], unit: :seconds,
124
+ buckets: [0.0001, 0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60].freeze,
125
+ comment: "A histogram for the time required to evaluate collect blocks"
126
+ end
127
+
128
+ adapters.each_value(&:debug!)
129
+
130
+ true
131
+ end
84
132
  # rubocop: enable Metrics/MethodLength, Metrics/AbcSize
85
133
 
86
134
  # Forget all the configuration.
87
135
  # For testing purposes as it doesn't rollback changes in adapters.
88
136
  # @api private
137
+ # rubocop: disable Metrics/AbcSize
89
138
  def reset!
90
139
  default_tags.clear
91
140
  adapters.clear
92
- groups.clear
93
- metrics.clear
141
+ groups.each_key { |group| singleton_class.send(:remove_method, group) if group && respond_to?(group) }
142
+ @groups = nil
143
+ metrics.each_key { |metric| singleton_class.send(:remove_method, metric) if respond_to?(metric) }
144
+ @metrics = nil
94
145
  collectors.clear
95
146
  configurators.clear
96
147
  instance_variable_set(:@configured_by, nil)
148
+ instance_variable_set(:@debug_was_enabled_by, nil)
97
149
  end
150
+ # rubocop: enable Metrics/AbcSize
98
151
  end
99
152
  end
data/yabeda-logo.png ADDED
Binary file
data/yabeda.gemspec CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
26
  spec.require_paths = ["lib"]
27
27
 
28
+ spec.add_dependency "anyway_config", ">= 1.0", "< 3"
28
29
  spec.add_dependency "concurrent-ruby"
29
30
  spec.add_dependency "dry-initializer"
30
31
 
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yabeda
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.11.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: 2020-08-21 00:00:00.000000000 Z
11
+ date: 2021-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: anyway_config
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3'
13
33
  - !ruby/object:Gem::Dependency
14
34
  name: concurrent-ruby
15
35
  requirement: !ruby/object:Gem::Requirement
@@ -111,17 +131,18 @@ dependencies:
111
131
  description: 'Collect statistics about how your application is performing with ease.
112
132
  Export metrics to various monitoring systems.
113
133
 
114
- '
134
+ '
115
135
  email:
116
136
  - envek@envek.name
117
137
  executables: []
118
138
  extensions: []
119
139
  extra_rdoc_files: []
120
140
  files:
141
+ - ".github/workflows/build-release.yml"
142
+ - ".github/workflows/test.yml"
121
143
  - ".gitignore"
122
144
  - ".rspec"
123
145
  - ".rubocop.yml"
124
- - ".travis.yml"
125
146
  - ".yardopts"
126
147
  - CHANGELOG.md
127
148
  - Gemfile
@@ -132,6 +153,7 @@ files:
132
153
  - bin/setup
133
154
  - lib/yabeda.rb
134
155
  - lib/yabeda/base_adapter.rb
156
+ - lib/yabeda/config.rb
135
157
  - lib/yabeda/counter.rb
136
158
  - lib/yabeda/dsl.rb
137
159
  - lib/yabeda/dsl/class_methods.rb
@@ -139,12 +161,21 @@ files:
139
161
  - lib/yabeda/dsl/option_builder.rb
140
162
  - lib/yabeda/errors.rb
141
163
  - lib/yabeda/gauge.rb
164
+ - lib/yabeda/global_group.rb
142
165
  - lib/yabeda/group.rb
143
166
  - lib/yabeda/histogram.rb
144
167
  - lib/yabeda/metric.rb
145
168
  - lib/yabeda/railtie.rb
169
+ - lib/yabeda/rspec.rb
170
+ - lib/yabeda/rspec/base_matcher.rb
171
+ - lib/yabeda/rspec/increment_yabeda_counter.rb
172
+ - lib/yabeda/rspec/measure_yabeda_histogram.rb
173
+ - lib/yabeda/rspec/update_yabeda_gauge.rb
146
174
  - lib/yabeda/tags.rb
175
+ - lib/yabeda/test_adapter.rb
176
+ - lib/yabeda/testing.rb
147
177
  - lib/yabeda/version.rb
178
+ - yabeda-logo.png
148
179
  - yabeda.gemspec
149
180
  homepage: https://github.com/yabeda-rb/yabeda
150
181
  licenses:
@@ -165,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
196
  - !ruby/object:Gem::Version
166
197
  version: '0'
167
198
  requirements: []
168
- rubygems_version: 3.1.2
199
+ rubygems_version: 3.1.6
169
200
  signing_key:
170
201
  specification_version: 4
171
202
  summary: Extensible framework for collecting metric for your Ruby application
data/.travis.yml DELETED
@@ -1,9 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.0
6
- - 2.6.5
7
- - 2.5.7
8
- - 2.4.9
9
- before_install: gem install bundler -v "~> 2.0"