yabeda-activerecord 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0c70f9b0924926fec4e5346d38bc65a9a821260d8904926c88a8584b050c93c7
4
+ data.tar.gz: 60808116a424d5852d037995bd14040c2f0cc758c242faa4a8e4381898b45685
5
+ SHA512:
6
+ metadata.gz: a11ba38c80c349b9ad490b1908a7915fb716b9e01a653ad8553bbdcb3738b46e7af71ad6c764b346097d467cdaa5781c33dddf19c4112e410603e7f611148d90
7
+ data.tar.gz: c31e9c3628b8d19c04b90aaada7bb86f4d9069a75dbde92f5af0ebe7cb4258401efb6939914e5b6cfd77951ec168c239b370f820aa5b1d646fa5ae5ea2f809dc
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,28 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.5
3
+
4
+ Style/StringLiterals:
5
+ Enabled: true
6
+ EnforcedStyle: double_quotes
7
+
8
+ Style/StringLiteralsInInterpolation:
9
+ Enabled: true
10
+ EnforcedStyle: double_quotes
11
+
12
+ Layout/LineLength:
13
+ Max: 120
14
+
15
+ Style/TrailingCommaInHashLiteral:
16
+ EnforcedStyleForMultiline: consistent_comma
17
+
18
+ Style/TrailingCommaInArguments:
19
+ EnforcedStyleForMultiline: consistent_comma
20
+
21
+ Style/TrailingCommaInArrayLiteral:
22
+ EnforcedStyleForMultiline: consistent_comma
23
+
24
+ Metrics/BlockLength:
25
+ Enabled: false
26
+
27
+ Bundler/DuplicatedGem:
28
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ ## Unreleased
2
+
3
+ ## 0.1.0 - 2022-05-27
4
+
5
+ - Initial release: query performance metrics and connection pool stats. [@Envek][]
6
+
7
+ [@Envek]: https://github.com/Envek/ "Andrey Novikov"
data/Gemfile ADDED
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in yabeda-activerecord.gemspec
6
+ gemspec
7
+
8
+ yabeda_version = ENV.fetch("YABEDA_VERSION", "~> 0.11")
9
+
10
+ case yabeda_version
11
+ when "HEAD"
12
+ gem "yabeda", git: "https://github.com/yabeda-rb/yabeda"
13
+ else
14
+ yabeda_version = "~> #{yabeda_version}.0" if yabeda_version.match?(/^\d+\.\d+$/)
15
+ gem "yabeda", yabeda_version
16
+ end
17
+
18
+ activerecord_version = ENV.fetch("ACTIVERECORD_VERSION", "~> 7.0")
19
+ case activerecord_version
20
+ when "HEAD"
21
+ git "https://github.com/rails/rails.git" do
22
+ gem "activerecord"
23
+ gem "rails"
24
+ end
25
+ else
26
+ activerecord_version = "~> #{activerecord_version}.0" if activerecord_version.match?(/^\d+\.\d+$/)
27
+ gem "activerecord", activerecord_version
28
+ end
29
+
30
+ gem "sqlite3"
31
+
32
+ gem "rake", "~> 13.0"
33
+
34
+ gem "rspec", "~> 3.0"
35
+
36
+ gem "rubocop", "~> 1.30"
37
+
38
+ gem "debug"
data/Gemfile.lock ADDED
@@ -0,0 +1,95 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ yabeda-activerecord (0.1.0)
5
+ activerecord (>= 6.0)
6
+ yabeda (~> 0.6)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activemodel (7.0.3)
12
+ activesupport (= 7.0.3)
13
+ activerecord (7.0.3)
14
+ activemodel (= 7.0.3)
15
+ activesupport (= 7.0.3)
16
+ activesupport (7.0.3)
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ i18n (>= 1.6, < 2)
19
+ minitest (>= 5.1)
20
+ tzinfo (~> 2.0)
21
+ anyway_config (2.3.0)
22
+ ruby-next-core (>= 0.14.0)
23
+ ast (2.4.2)
24
+ concurrent-ruby (1.1.10)
25
+ debug (1.5.0)
26
+ irb (>= 1.3.6)
27
+ reline (>= 0.2.7)
28
+ diff-lcs (1.5.0)
29
+ dry-initializer (3.1.1)
30
+ i18n (1.10.0)
31
+ concurrent-ruby (~> 1.0)
32
+ io-console (0.5.11)
33
+ irb (1.4.1)
34
+ reline (>= 0.3.0)
35
+ minitest (5.15.0)
36
+ parallel (1.22.1)
37
+ parser (3.1.2.0)
38
+ ast (~> 2.4.1)
39
+ rainbow (3.1.1)
40
+ rake (13.0.6)
41
+ regexp_parser (2.4.0)
42
+ reline (0.3.1)
43
+ io-console (~> 0.5)
44
+ rexml (3.2.5)
45
+ rspec (3.11.0)
46
+ rspec-core (~> 3.11.0)
47
+ rspec-expectations (~> 3.11.0)
48
+ rspec-mocks (~> 3.11.0)
49
+ rspec-core (3.11.0)
50
+ rspec-support (~> 3.11.0)
51
+ rspec-expectations (3.11.0)
52
+ diff-lcs (>= 1.2.0, < 2.0)
53
+ rspec-support (~> 3.11.0)
54
+ rspec-mocks (3.11.1)
55
+ diff-lcs (>= 1.2.0, < 2.0)
56
+ rspec-support (~> 3.11.0)
57
+ rspec-support (3.11.0)
58
+ rubocop (1.30.0)
59
+ parallel (~> 1.10)
60
+ parser (>= 3.1.0.0)
61
+ rainbow (>= 2.2.2, < 4.0)
62
+ regexp_parser (>= 1.8, < 3.0)
63
+ rexml (>= 3.2.5, < 4.0)
64
+ rubocop-ast (>= 1.18.0, < 2.0)
65
+ ruby-progressbar (~> 1.7)
66
+ unicode-display_width (>= 1.4.0, < 3.0)
67
+ rubocop-ast (1.18.0)
68
+ parser (>= 3.1.1.0)
69
+ ruby-next-core (0.15.1)
70
+ ruby-progressbar (1.11.0)
71
+ sqlite3 (1.4.2)
72
+ tzinfo (2.0.4)
73
+ concurrent-ruby (~> 1.0)
74
+ unicode-display_width (2.1.0)
75
+ yabeda (0.11.0)
76
+ anyway_config (>= 1.0, < 3)
77
+ concurrent-ruby
78
+ dry-initializer
79
+
80
+ PLATFORMS
81
+ ruby
82
+ x86_64-linux
83
+
84
+ DEPENDENCIES
85
+ activerecord (~> 7.0)
86
+ debug
87
+ rake (~> 13.0)
88
+ rspec (~> 3.0)
89
+ rubocop (~> 1.30)
90
+ sqlite3
91
+ yabeda (~> 0.11)
92
+ yabeda-activerecord!
93
+
94
+ BUNDLED WITH
95
+ 2.3.14
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Andrey Novikov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # ![`Yabeda::ActiveRecord`](./yabeda-activerecord-logo.png)
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/yabeda-activerecord.svg)](https://rubygems.org/gems/yabeda-activerecord)
4
+ [![Tests status](https://github.com/yabeda-rb/yabeda-activerecord/actions/workflows/test.yml/badge.svg)](https://github.com/yabeda-rb/yabeda-activerecord/actions/workflows/test.yml)
5
+
6
+ [Yabeda] plugin to collect essential metrics for database query performance and connection pool stats.
7
+
8
+ <a href="https://evilmartians.com/?utm_source=yabeda-activerecord">
9
+ <picture>
10
+ <source media="(prefers-color-scheme: dark)" srcset="https://evilmartians.com/badges/sponsored-by-evil-martians_v2.0_for-dark-bg@2x.png">
11
+ <img alt="Sponsored by Evil Martians" src="https://evilmartians.com/badges/sponsored-by-evil-martians_v2.0@2x.png" width="236" height="54">
12
+ </picture>
13
+ </a>
14
+
15
+ ## Installation
16
+
17
+ Install the gem and add to the application's Gemfile by executing:
18
+
19
+ $ bundle add yabeda-activerecord
20
+
21
+ Launch/restart your application and that's it: metrics are being collected.
22
+
23
+ To expose metrics Don't forget to also add one of [Yabeda adapters](https://github.com/yabeda-rb/yabeda#available-monitoring-system-adapters) to your Gemfile.
24
+
25
+ ## Metrics
26
+
27
+ ### Query performance
28
+ | Metric | Type | Tags | Description |
29
+ |-------------------|-------------|-----------------------------|--------------------------------------------------------------------|
30
+ | `queries_total` | counter | config, kind, cached, async | Total number of SQL queries issued by application via ActiveRecord |
31
+ | `query_duration` | histogram | config, kind, cached, async | Duration for SQL queries generated by ActiveRecord |
32
+
33
+ ### Connection pool stats
34
+
35
+ | Metric | Type | Tags | Description |
36
+ |------------------------------------|-------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
37
+ | `connection_pool_size` | gauge | config | Connection pool size |
38
+ | `connection_pool_connections` | gauge | config | Total number of connections currently created in the pool (sum of busy, dead, and idle). |
39
+ | `connection_pool_busy` | gauge | config | Number of connections that has been checked out by some thread and are in use now. |
40
+ | `connection_pool_dead` | gauge | config | Number of lost connections for the pool. A lost connection can occur if a programmer forgets to checkin a connection at the end of a thread or a thread dies unexpectedly. |
41
+ | `connection_pool_idle` | gauge | config | Number of free connections, that are available for checkout. |
42
+ | `connection_pool_waiting` | gauge | config | Number of threads waiting for a connection to become available for checkout. |
43
+ | `connection_pool_checkout_timeout` | gauge | config | Checkout waiting timeout in seconds |
44
+
45
+ ### Tags
46
+
47
+ - `config` — database configuration name in the `database.yml`
48
+ - `kind` — query kind, usually referring to action over model. E.g. `Post Load`
49
+ - `cached` — `true` if query wasn't executed against the database, results was retrieved from in-memory cache.
50
+ - `async` — `true` if query was loaded in background via [`load_async`](https://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-load_async)
51
+
52
+ ## Development
53
+
54
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
55
+
56
+ To install this gem onto your local machine, run `bundle exec rake install`.
57
+
58
+
59
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yabeda-rb/yabeda-activerecord.
60
+
61
+ ### Releasing
62
+
63
+ 1. Bump version number in `lib/yabeda/activerecord/version.rb`
64
+
65
+ 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::ActiveRecord::VERSION).to_s`
66
+
67
+ 2. Fill `CHANGELOG.md` with missing changes, add header with version and date.
68
+
69
+ 3. Make a commit:
70
+
71
+ ```sh
72
+ git add lib/yabeda/active_record/version.rb CHANGELOG.md
73
+ version=$(ruby -r ./lib/yabeda/active_record/version.rb -e "puts Gem::Version.new(Yabeda::ActiveRecord::VERSION)")
74
+ git commit --message="${version}: " --edit
75
+ ```
76
+
77
+ 4. Create annotated tag:
78
+
79
+ ```sh
80
+ git tag v${version} --annotate --message="${version}: " --edit --sign
81
+ ```
82
+
83
+ 5. Fill version name into subject line and (optionally) some description (list of changes will be taken from changelog and appended automatically)
84
+
85
+ 6. Push it:
86
+
87
+ ```sh
88
+ git push --follow-tags
89
+ ```
90
+
91
+ 7. GitHub Actions will create a new release, build and push gem into RubyGems! You're done!
92
+
93
+
94
+ ## Contributing
95
+
96
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yabeda-rb/yabeda-activerecord.
97
+
98
+ ## License
99
+
100
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
101
+
102
+ [Yabeda]: https://github.com/yabeda-rb/yabeda "Extendable framework for collecting and exporting metrics from your Ruby application"
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yabeda
4
+ module ActiveRecord
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yabeda"
4
+ require "active_record"
5
+
6
+ require_relative "active_record/version"
7
+
8
+ module Yabeda
9
+ # ActiveRecord Yabeda plugin to collect metrics for query performance, connection pool stats, etc
10
+ module ActiveRecord
11
+ class Error < StandardError; end
12
+
13
+ LONG_RUNNING_QUERY_RUNTIME_BUCKETS = [
14
+ 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, # standard (from Prometheus)
15
+ 30, 60, 120, 300, 1800, 3600, 21_600, # Well, sometime queries can execute way too long
16
+ ].freeze
17
+
18
+ # rubocop: disable Layout/LineLength
19
+ Yabeda.configure do
20
+ group :activerecord do
21
+ counter :queries_total, tags: %i[config kind cached async],
22
+ comment: "Total number of SQL queries issued by application via ActiveRecord"
23
+ histogram :query_duration, tags: %i[config kind cached async],
24
+ unit: :seconds, buckets: LONG_RUNNING_QUERY_RUNTIME_BUCKETS,
25
+ comment: "Duration of SQL queries generated by ActiveRecord"
26
+
27
+ gauge :connection_pool_size,
28
+ tags: %i[config],
29
+ comment: "Connection pool size"
30
+ gauge :connection_pool_connections,
31
+ tags: %i[config],
32
+ comment: "Total number of connections currently created in the pool (sum of busy, dead, and idle)."
33
+ gauge :connection_pool_busy,
34
+ tags: %i[config],
35
+ comment: "Number of connections that has been checked out by some thread and are in use now."
36
+ gauge :connection_pool_dead,
37
+ tags: %i[config],
38
+ comment: "Number of lost connections for the pool. A lost connection can occur if a programmer forgets to checkin a connection at the end of a thread or a thread dies unexpectedly."
39
+ gauge :connection_pool_idle,
40
+ tags: %i[config],
41
+ comment: "Number of free connections, that are available for checkout."
42
+ gauge :connection_pool_waiting,
43
+ tags: %i[config],
44
+ comment: "Number of threads waiting for a connection to become available for checkout."
45
+ gauge :connection_pool_checkout_timeout,
46
+ tags: %i[config],
47
+ unit: :seconds,
48
+ comment: "Checkout waiting timeout in seconds"
49
+ end
50
+ # rubocop: enable Layout/LineLength
51
+
52
+ # Query performance metrics collection
53
+ ActiveSupport::Notifications.subscribe "sql.active_record" do |*args|
54
+ event = ActiveSupport::Notifications::Event.new(*args)
55
+
56
+ pool = event.payload[:connection].pool
57
+ next if !pool || pool.is_a?(::ActiveRecord::ConnectionAdapters::NullPool)
58
+
59
+ db_config_name = pool.respond_to?(:db_config) ? pool.db_config.name : pool.spec.name
60
+
61
+ labels = {
62
+ config: db_config_name,
63
+ kind: event.payload[:name],
64
+ cached: !event.payload[:cached].nil?,
65
+ async: !event.payload[:async].nil?,
66
+ }
67
+
68
+ Yabeda.activerecord.queries_total.increment(labels)
69
+ Yabeda.activerecord.query_duration.measure(labels, (event.duration.to_f / 1000).round(3))
70
+ end
71
+
72
+ # Connection pool metrics collection
73
+ collect do
74
+ connection_pools = ::ActiveRecord::Base.connection_handler.connection_pool_list
75
+
76
+ connection_pools.each do |connection_pool|
77
+ stats = connection_pool.stat
78
+ name =
79
+ if connection_pool.respond_to?(:db_config)
80
+ connection_pool.db_config.name
81
+ else
82
+ connection_pool.spec.name
83
+ end
84
+
85
+ tags = { config: name }
86
+ Yabeda.activerecord.connection_pool_size.set(tags, stats[:size])
87
+ Yabeda.activerecord.connection_pool_connections.set(tags, stats[:connections])
88
+ Yabeda.activerecord.connection_pool_busy.set(tags, stats[:busy])
89
+ Yabeda.activerecord.connection_pool_dead.set(tags, stats[:dead])
90
+ Yabeda.activerecord.connection_pool_idle.set(tags, stats[:idle])
91
+ Yabeda.activerecord.connection_pool_waiting.set(tags, stats[:waiting])
92
+ Yabeda.activerecord.connection_pool_checkout_timeout.set(tags, stats[:checkout_timeout])
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "active_record"
@@ -0,0 +1,6 @@
1
+ module Yabeda
2
+ module ActiveRecord
3
+ VERSION: String
4
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ end
6
+ end
data/tmp/.keep ADDED
File without changes
Binary file
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yabeda-activerecord
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrey Novikov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-05-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: yabeda
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.6'
41
+ description: 'Yabeda plugin for easy collection of ActiveRecord metrics: query performance,
42
+ connection pool stats, etc.
43
+
44
+ '
45
+ email:
46
+ - envek@envek.name
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - ".rspec"
52
+ - ".rubocop.yml"
53
+ - CHANGELOG.md
54
+ - Gemfile
55
+ - Gemfile.lock
56
+ - LICENSE.txt
57
+ - README.md
58
+ - Rakefile
59
+ - lib/yabeda/active_record.rb
60
+ - lib/yabeda/active_record/version.rb
61
+ - lib/yabeda/activerecord.rb
62
+ - sig/yabeda/activerecord.rbs
63
+ - tmp/.keep
64
+ - yabeda-activerecord-logo.png
65
+ homepage: https://github.com/yabeda-rb/yabeda-activerecord
66
+ licenses:
67
+ - MIT
68
+ metadata:
69
+ homepage_uri: https://github.com/yabeda-rb/yabeda-activerecord
70
+ source_code_uri: https://github.com/yabeda-rb/yabeda-activerecord
71
+ changelog_uri: https://github.com/yabeda-rb/yabeda-activerecord/blob/master/CHANGELOG.md
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 2.5.0
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubygems_version: 3.1.6
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: 'Yabeda plugin to collect ActiveRecord metrics: query performance, connection
91
+ pool stats, etc.'
92
+ test_files: []