evil-metrics-sidekiq 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: de3126c7e5682d96325b81bbef7cfb5a432eab92257f557cba134c337cb5cc5d
4
+ data.tar.gz: 0a1bfcbc03fda0a05cbc5b12d86e3835c67d72b713bde0b3609291fdab94829c
5
+ SHA512:
6
+ metadata.gz: 0af5fb775ea6fba35ac0ff9302abb445ba843fe5240a425e4a18ab7822f587e204a15a724dc9cde261237063a0192be19ab5a2ff4c81fae6a81bfefe271bb1e3
7
+ data.tar.gz: e8dba821ab1d688b91150b43fe15987a997e18cc284aa02e8a3d6ec840bd188beb47bfb95e7a29b50ca763dc26ad70de9406fd778a4513fc986334bf9699d058
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ Gemfile.lock
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,46 @@
1
+ ---
2
+ require:
3
+ - rubocop-rspec
4
+
5
+ AllCops:
6
+ TargetRubyVersion: 2.3
7
+
8
+ Metrics/BlockLength:
9
+ Exclude:
10
+ - "Gemfile"
11
+ - "spec/**/*"
12
+
13
+ Style/BracesAroundHashParameters:
14
+ EnforcedStyle: context_dependent
15
+
16
+ Style/StringLiterals:
17
+ EnforcedStyle: double_quotes
18
+
19
+ # Allow to use let!
20
+ RSpec/LetSetup:
21
+ Enabled: false
22
+
23
+ RSpec/MultipleExpectations:
24
+ Enabled: false
25
+
26
+ Bundler/OrderedGems:
27
+ Enabled: false
28
+
29
+ Style/TrailingCommaInArguments:
30
+ Description: 'Checks for trailing comma in argument lists.'
31
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-params-comma'
32
+ Enabled: true
33
+ EnforcedStyleForMultiline: consistent_comma
34
+
35
+ Style/TrailingCommaInArrayLiteral:
36
+ Description: 'Checks for trailing comma in array literals.'
37
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
38
+ Enabled: true
39
+ EnforcedStyleForMultiline: consistent_comma
40
+
41
+ Style/TrailingCommaInHashLiteral:
42
+ Description: 'Checks for trailing comma in hash literals.'
43
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
44
+ Enabled: true
45
+ EnforcedStyleForMultiline: consistent_comma
46
+
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+ before_install: gem install bundler -v 1.16.1
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in evil-metrics-sidekiq.gemspec
8
+ gemspec
9
+
10
+ group :development, :test do
11
+ gem "pry"
12
+ gem "pry-byebug", platform: :mri
13
+
14
+ gem "rubocop"
15
+ gem "rubocop-rspec"
16
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 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.
@@ -0,0 +1,78 @@
1
+ # Evil::Metrics::[Sidekiq]
2
+
3
+ Built-in metrics for [Sidekiq] monitoring out of the box!
4
+
5
+ ## Installation
6
+
7
+ 1. Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'evil-metrics-rails'
11
+ # Then add monitoring system adapter, e.g.:
12
+ # gem 'evil-metrics-prometheus'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+
20
+ 2. Add middlewares to your Sidekiq server and client:
21
+
22
+ ```ruby
23
+ # config/initializers/sidekiq or elsewhere
24
+ Sidekiq.configure_server do |config|
25
+ config.redis = your_redis_credentials
26
+ config.server_middleware do |chain|
27
+ chain.add Evil::Metrics::Sidekiq::ServerMiddleware
28
+ end
29
+ # Additional setup may be required depending on adapter. E.g. for prometheus:
30
+ # Evil::Metrics::Prometheus::Exporter.start_metrics_server!
31
+ end
32
+
33
+ Sidekiq.configure_client do |config|
34
+ config.redis = your_redis_credentials
35
+ config.client_middleware do |chain|
36
+ chain.add Evil::Metrics::Sidekiq::ClientMiddleware
37
+ end
38
+ end
39
+ ```
40
+
41
+ 3. You're done!
42
+
43
+ ## Metrics
44
+
45
+ - Total number of executed jobs: `sidekiq_jobs_executed_total` - (segmented by queue and class name)
46
+ - Number of jobs have been finished successfully: `sidekiq_jobs_success_total` (segmented by queue and class name)
47
+ - Number of jobs have been failed: `sidekiq_jobs_failed_total` (segmented by queue and class name)
48
+ - Time of job run: `sidekiq_job_runtime` (seconds per job execution, segmented by queue and class name)
49
+ - Number of jobs in queues: `sidekiq_jobs_waiting_count` (segmented by queue)
50
+ - Number of scheduled jobs:`sidekiq_jobs_scheduled_count`
51
+ - Number of jobs in retry set: `sidekiq_jobs_retry_count`
52
+ - Number of jobs in dead set (“morgue”): `sidekiq_jobs_dead_count`
53
+ - Active workers count: `sidekiq_active_processes`
54
+ - Active processes count: `sidekiq_active_workers_count`
55
+
56
+ # Roadmap (TODO or Help wanted)
57
+
58
+ - Implement optional segmentation of retry/schedule/dead sets
59
+
60
+ It should be disabled by default as it requires to iterate over all jobs in sets and may be very slow on large sets.
61
+
62
+ - Maybe hooks for ease of plugging in metrics for myriads of Sidekiq plugins?
63
+
64
+ ## Development
65
+
66
+ 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.
67
+
68
+ 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).
69
+
70
+ ## Contributing
71
+
72
+ Bug reports and pull requests are welcome on GitHub at https://github.com/evil-metrics/evil-metrics-sidekiq.
73
+
74
+ ## License
75
+
76
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
77
+
78
+ [Sidekiq]: https://github.com/mperham/sidekiq/ "Simple, efficient background processing for Ruby"
@@ -0,0 +1,8 @@
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
+ task default: :spec
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "evil/metrics/sidekiq"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require "evil/metrics/sidekiq/version"
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "evil-metrics-sidekiq"
9
+ spec.version = Evil::Metrics::Sidekiq::VERSION
10
+ spec.authors = ["Andrey Novikov"]
11
+ spec.email = ["envek@envek.name"]
12
+
13
+ spec.summary = "Extensible Prometheus exporter for monitoring your Sidekiq"
14
+ spec.description = "Prometheus exporter for easy collecting most important of your Sidekiq metrics"
15
+ spec.homepage = "https://github.com/evil-metrics/evil-metrics-sidekiq"
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_dependency "evil-metrics"
26
+ spec.add_dependency "sidekiq"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.16"
29
+ spec.add_development_dependency "rake", "~> 10.0"
30
+ spec.add_development_dependency "rspec", "~> 3.0"
31
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sidekiq"
4
+ require "sidekiq/api"
5
+
6
+ require "evil/metrics/sidekiq/version"
7
+ require "evil/metrics/sidekiq/client_middleware"
8
+ require "evil/metrics/sidekiq/server_middleware"
9
+
10
+ module Evil
11
+ module Metrics
12
+ module Sidekiq
13
+ LONG_RUNNING_JOB_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 # Sidekiq tasks may be very long-running
16
+ ].freeze
17
+
18
+ Evil::Metrics.configure do
19
+ group :sidekiq
20
+
21
+ counter :jobs_enqueued_total, comment: "A counter of the total number of jobs sidekiq enqueued."
22
+
23
+ next unless ::Sidekiq.server?
24
+
25
+ counter :jobs_executed_total, comment: "A counter of the total number of jobs sidekiq executed."
26
+ counter :jobs_success_total, comment: "A counter of the total number of jobs successfully processed by sidekiq."
27
+ counter :jobs_failed_total, comment: "A counter of the total number of jobs failed in sidekiq."
28
+ gauge :jobs_waiting_count, comment: "The number of jobs waiting to process in sidekiq."
29
+ gauge :active_workers_count, comment: "The number of currently running machines with sidekiq workers."
30
+ gauge :jobs_scheduled_count, comment: "The number of jobs scheduled for later execution."
31
+ gauge :jobs_retry_count, comment: "The number of failed jobs waiting to be retried"
32
+ gauge :jobs_dead_count, comment: "The number of jobs exceeded their retry count."
33
+ gauge :active_processes, comment: "The number of active Sidekiq worker processes."
34
+ histogram :job_runtime, unit: :seconds, per: :job, comment: "A histogram of the job execution time.",
35
+ buckets: LONG_RUNNING_JOB_RUNTIME_BUCKETS
36
+
37
+ collect do
38
+ stats = ::Sidekiq::Stats.new
39
+
40
+ stats.queues.each do |k, v|
41
+ sidekiq_jobs_waiting_count.set({ queue: k }, v)
42
+ end
43
+ sidekiq_active_workers_count.set({}, stats.workers_size)
44
+ sidekiq_jobs_scheduled_count.set({}, stats.scheduled_size)
45
+ sidekiq_jobs_dead_count.set({}, stats.dead_size)
46
+ sidekiq_active_processes.set({}, stats.processes_size)
47
+ sidekiq_jobs_retry_count.set({}, stats.retry_size)
48
+
49
+ # That is quite slow if your retry set is large
50
+ # I don't want to enable it by default
51
+ # retries_by_queues =
52
+ # ::Sidekiq::RetrySet.new.each_with_object(Hash.new(0)) do |job, cntr|
53
+ # cntr[job["queue"]] += 1
54
+ # end
55
+ # retries_by_queues.each do |queue, count|
56
+ # sidekiq_jobs_retry_count.set({ queue: queue }, count)
57
+ # end
58
+ end
59
+ end
60
+
61
+ class << self
62
+ def labelize(worker, _job, queue)
63
+ { queue: queue, worker: worker_class(worker) }
64
+ end
65
+
66
+ def worker_class(worker)
67
+ if defined?(ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper)
68
+ return job["wrapped"] if worker.is_a?(ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper)
69
+ end
70
+ (worker.is_a?(String) ? worker : worker.class).to_s
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Evil
4
+ module Metrics
5
+ module Sidekiq
6
+ # Client middleware to count number of enqueued jobs
7
+ class ClientMiddleware
8
+ def call(worker, job, queue, _redis_pool)
9
+ labels = Evil::Metrics::Sidekiq.labelize(worker, job, queue)
10
+ Evil::Metrics.sidekiq_jobs_enqueued_total.increment(labels)
11
+ yield
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Evil
4
+ module Metrics
5
+ module Sidekiq
6
+ # Sidekiq worker middleware
7
+ class ServerMiddleware
8
+ def call(worker, job, queue)
9
+ labels = Evil::Metrics::Sidekiq.labelize(worker, job, queue)
10
+ start = Time.now
11
+ begin
12
+ yield
13
+ Evil::Metrics.sidekiq_jobs_success_total.increment(labels)
14
+ rescue Exception # rubocop: disable Lint/RescueException
15
+ Evil::Metrics.sidekiq_jobs_failed_total.increment(labels)
16
+ raise
17
+ ensure
18
+ Evil::Metrics.sidekiq_job_runtime.measure(labels, elapsed(start))
19
+ Evil::Metrics.sidekiq_jobs_executed_total.increment(labels)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def elapsed(start)
26
+ (Time.now - start).round(3)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Evil
4
+ module Metrics
5
+ module Sidekiq
6
+ VERSION = "0.1.0"
7
+ end
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: evil-metrics-sidekiq
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: 2018-10-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: evil-metrics
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sidekiq
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.16'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.16'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ description: Prometheus exporter for easy collecting most important of your Sidekiq
84
+ metrics
85
+ email:
86
+ - envek@envek.name
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".rubocop.yml"
94
+ - ".travis.yml"
95
+ - Gemfile
96
+ - LICENSE.txt
97
+ - README.md
98
+ - Rakefile
99
+ - bin/console
100
+ - bin/setup
101
+ - evil-metrics-sidekiq.gemspec
102
+ - lib/evil/metrics/sidekiq.rb
103
+ - lib/evil/metrics/sidekiq/client_middleware.rb
104
+ - lib/evil/metrics/sidekiq/server_middleware.rb
105
+ - lib/evil/metrics/sidekiq/version.rb
106
+ homepage: https://github.com/evil-metrics/evil-metrics-sidekiq
107
+ licenses:
108
+ - MIT
109
+ metadata: {}
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 2.7.6
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Extensible Prometheus exporter for monitoring your Sidekiq
130
+ test_files: []