yabeda-sidekiq 0.5.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56cc207100137641a1ba2cd7151f411473a003623f4316f470c9cab2734b0c46
4
- data.tar.gz: ab292a2728a35ab4ed163f9d77e4260d33944052fb384c93895fceddcdd63876
3
+ metadata.gz: 7ca3b88de76f5fc2ebb1e495445d25ad5b5de0c9f053bb8ca9dcbb5940ef4d41
4
+ data.tar.gz: 7be84caa2d3463a41d59606493e7739377ebfa908476b15b60bb16330067b99b
5
5
  SHA512:
6
- metadata.gz: 225fdd8793b40a5efc4ae7a476e90e142cf2a1b8b790d395262d76f7a7ad8f73d7f9969f7cfe7dcb87359eee272bfa9ab5dac08b7ff477961814f70daa81f676
7
- data.tar.gz: 7673942008c4c0b83d57fa681016f6b4238107f3c355165fa616191a9a6f8d339828830d3e7fff03d9f3d80e67a1f657756459d87aecd0681547ba6060b2fe7e
6
+ metadata.gz: 1f7fc13c744da0aa66ffabd9882b24a43c60038e4b966cc557412c80687ed92848d508e179221e93b15e610f9021415e8a7494dc7cfade3f851d617f304ef4ee
7
+ data.tar.gz: e026f095d1ba62dd75da0c29d0069c89223bc3cf357ea912c0d1d137cb9b1e7ae7e5223ee7967c2dcd68dd706212553f2840718f52af05240846e965d0be239d
@@ -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-sidekiq-${{ steps.tag.outputs.version }}.gem > SHA256SUM
42
+ - name: Check version
43
+ run: ls -l yabeda-sidekiq-${{ 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-sidekiq-${{ steps.tag.outputs.version }}.gem
62
+ asset_name: yabeda-sidekiq-${{ 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-sidekiq-${{ 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-sidekiq-${{ steps.tag.outputs.version }}.gem
@@ -0,0 +1,47 @@
1
+ name: Run tests
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - '**'
8
+ tags-ignore:
9
+ - 'v*'
10
+
11
+ jobs:
12
+ test:
13
+ name: "Run tests"
14
+ if: "!contains(github.event.head_commit.message, '[ci skip]')"
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ include:
20
+ - ruby: 3.0
21
+ - ruby: 2.7
22
+ - ruby: 2.6
23
+ - ruby: 2.5
24
+ container:
25
+ image: ruby:${{ matrix.ruby }}
26
+ env:
27
+ CI: true
28
+ steps:
29
+ - uses: actions/checkout@v2
30
+ - uses: actions/cache@v2
31
+ with:
32
+ path: vendor/bundle
33
+ key: bundle-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}-${{ hashFiles('**/Gemfile') }}
34
+ restore-keys: |
35
+ bundle-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}-${{ hashFiles('**/Gemfile') }}
36
+ bundle-${{ matrix.ruby }}-
37
+ - name: Upgrade Bundler to 2.0 (for older Rubies)
38
+ run: gem install bundler -v '~> 2.0'
39
+ - name: Bundle install
40
+ run: |
41
+ bundle config path vendor/bundle
42
+ bundle install
43
+ bundle update
44
+ - name: Run Rubocop
45
+ run: bundle exec rubocop
46
+ - name: Run RSpec
47
+ run: bundle exec rspec
data/.rubocop.yml CHANGED
@@ -1,17 +1,18 @@
1
1
  ---
2
2
  require:
3
- - rubocop-rspec
3
+ - rubocop-rspec
4
4
 
5
5
  AllCops:
6
6
  TargetRubyVersion: 2.3
7
7
 
8
8
  Metrics/BlockLength:
9
+ Enabled: false
9
10
  Exclude:
10
11
  - "Gemfile"
11
12
  - "spec/**/*"
12
13
 
13
- Style/BracesAroundHashParameters:
14
- EnforcedStyle: context_dependent
14
+ Layout/LineLength:
15
+ Max: 160
15
16
 
16
17
  Style/StringLiterals:
17
18
  EnforcedStyle: double_quotes
@@ -44,3 +45,23 @@ Style/TrailingCommaInHashLiteral:
44
45
  Enabled: true
45
46
  EnforcedStyleForMultiline: consistent_comma
46
47
 
48
+ Style/HashEachMethods:
49
+ Enabled: true
50
+
51
+ Style/HashTransformKeys:
52
+ Enabled: true
53
+
54
+ Style/HashTransformValues:
55
+ Enabled: true
56
+
57
+ RSpec/ExampleLength:
58
+ Enabled: false
59
+
60
+ Style/Documentation:
61
+ Enabled: false
62
+
63
+ Metrics/MethodLength:
64
+ Max: 15
65
+
66
+ Metrics/AbcSize:
67
+ Max: 17
data/CHANGELOG.md CHANGED
@@ -5,6 +5,41 @@ 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.8.1 - 2021-08-24
11
+
12
+ ### Fixed
13
+
14
+ - Compatibility with Sidekiq 6.2.2+ due to renamings in Sidekiq's undocumented API that yabeda-sidekiq uses. See [mperham/sidekiq#4971](https://github.com/mperham/sidekiq/discussions/4971). [@Envek]
15
+
16
+ ## 0.8.0 - 2021-05-12
17
+
18
+ ### Added
19
+
20
+ - `sidekiq_running_job_runtime` metric that tracks maximum runtime of currently running jobs. It may be useful for detection of hung jobs. See [#17](https://github.com/yabeda-rb/yabeda-sidekiq/pull/17). [@dsalahutdinov], [@Envek]
21
+
22
+ - Setting `collect_cluster_metrics` allowing to force enable or disable collection of global (whole Sidekiq installaction-wide) metrics. See [#20](https://github.com/yabeda-rb/yabeda-sidekiq/pull/20). [@mrexox]
23
+
24
+ By default all sidekiq worker processes (servers) collects global metrics about whole Sidekiq installation.
25
+ Client processes (everything else that is not Sidekiq worker) by default doesn't.
26
+
27
+ With this config you can override this behavior:
28
+ - force disable if you don't want multiple Sidekiq workers to report the same numbers (that causes excess load to both Redis and monitoring)
29
+ - force enable if you want non-Sidekiq process to collect them (like dedicated metric exporter process)
30
+
31
+ ## 0.7.0 - 2020-07-15
32
+
33
+ ### Changed
34
+
35
+ - Tags from `yabeda_tags` method are applied to all metrics collected inside a job, not only sidekiq-specific. See [#14](https://github.com/yabeda-rb/yabeda-sidekiq/issues/14). @Envek
36
+
37
+ ## 0.6.0 - 2020-07-15
38
+
39
+ ### Added
40
+
41
+ - Ability to override or add tags for every job via `yabeda_tags` method. @Envek
42
+
8
43
  ## 0.5.0 - 2020-02-20
9
44
 
10
45
  ### Added
@@ -49,5 +84,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
49
84
 
50
85
  - Initial release of evil-metrics-sidekiq gem. @Envek
51
86
 
87
+ [@Envek]: https://github.com/Envek "Andrey Novikov"
52
88
  [@dsalahutdinov]: https://github.com/dsalahutdinov "Salahutdinov Dmitry"
53
89
  [@asusikov]: https://github.com/asusikov "Alexander Susikov"
90
+ [@mrexox]: https://github.com/mrexox "Valentine Kiselev"
data/Gemfile CHANGED
@@ -11,6 +11,6 @@ group :development, :test do
11
11
  gem "pry"
12
12
  gem "pry-byebug", platform: :mri
13
13
 
14
- gem "rubocop"
14
+ gem "rubocop", "~> 0.80.0"
15
15
  gem "rubocop-rspec"
16
16
  end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Yabeda::[Sidekiq]
1
+ # ![Yabeda::Sidekiq](./yabeda-sidekiq-logo.png)
2
2
 
3
3
  Built-in metrics for [Sidekiq] monitoring out of the box! Part of the [yabeda] suite.
4
4
 
@@ -16,6 +16,14 @@ And then execute:
16
16
 
17
17
  $ bundle
18
18
 
19
+ If you're not on Rails then configure Yabeda after your application was initialized:
20
+
21
+ ```ruby
22
+ Yabeda.configure!
23
+ ```
24
+
25
+ _If you're using Ruby on Rails then Yabeda will configure itself automatically!_
26
+
19
27
  **And that is it!** Sidekiq metrics are being collected!
20
28
 
21
29
  Additionally, depending on your adapter, you may want to setup metrics export. E.g. for [yabeda-prometheus]:
@@ -29,18 +37,61 @@ end
29
37
 
30
38
  ## Metrics
31
39
 
40
+ ### Local per-process metrics
41
+
42
+ Metrics representing state of current Sidekiq worker process and stats of executed or executing jobs:
43
+
32
44
  - Total number of executed jobs: `sidekiq_jobs_executed_total` - (segmented by queue and class name)
33
45
  - Number of jobs have been finished successfully: `sidekiq_jobs_success_total` (segmented by queue and class name)
34
46
  - Number of jobs have been failed: `sidekiq_jobs_failed_total` (segmented by queue and class name)
35
47
  - Time of job run: `sidekiq_job_runtime` (seconds per job execution, segmented by queue and class name)
36
- - Time of the queue latency `sidekiq_queue_latency` (the difference in seconds since the oldest job in the queue was enqueued)
37
48
  - Time of the job latency `sidekiq_job_latency` (the difference in seconds since the enqueuing until running job)
49
+ - Maximum runtime of currently executing jobs: `sidekiq_running_job_runtime` (useful for detection of hung jobs, segmented by queue and class name)
50
+
51
+ ### Global cluster-wide metrics
52
+
53
+ Metrics representing state of the whole Sidekiq installation (queues, processes, etc):
54
+
38
55
  - Number of jobs in queues: `sidekiq_jobs_waiting_count` (segmented by queue)
56
+ - Time of the queue latency `sidekiq_queue_latency` (the difference in seconds since the oldest job in the queue was enqueued)
39
57
  - Number of scheduled jobs:`sidekiq_jobs_scheduled_count`
40
58
  - Number of jobs in retry set: `sidekiq_jobs_retry_count`
41
59
  - Number of jobs in dead set (“morgue”): `sidekiq_jobs_dead_count`
42
- - Active workers count: `sidekiq_active_processes`
43
- - Active processes count: `sidekiq_active_workers_count`
60
+ - Active processes count: `sidekiq_active_processes`
61
+ - Active servers count: `sidekiq_active_workers_count`
62
+
63
+ By default all sidekiq worker processes (servers) collects global metrics about whole Sidekiq installation. This can be overridden by setting `collect_cluster_metrics` config key to `true` for non-Sidekiq processes or to `false` for Sidekiq processes (e.g. by setting `YABEDA_SIDEKIQ_COLLECT_CLUSTER_METRICS` env variable to `no`, see other methods in [anyway_config] docs).
64
+
65
+ ## Custom tags
66
+
67
+ You can add additional tags to these metrics by declaring `yabeda_tags` method in your worker.
68
+
69
+ ```ruby
70
+ # This block is optional but some adapters (like Prometheus) requires that all tags should be declared in advance
71
+ Yabeda.configure do
72
+ default_tag :importance, nil
73
+ end
74
+
75
+ class MyWorker
76
+ include Sidekiq::Worker
77
+
78
+ def yabeda_tags(*params) # This method will be called first, before +perform+
79
+ { importance: extract_importance(params) }
80
+ end
81
+
82
+ def perform(*params)
83
+ # Your logic here
84
+ end
85
+ end
86
+ ```
87
+
88
+ ## Configuration
89
+
90
+ Configuration is handled by [anyway_config] gem. With it you can load settings from environment variables (upcased and prefixed with `YABEDA_SIDEKIQ_`), YAML files, and other sources. See [anyway_config] docs for details.
91
+
92
+ Config key | Type | Default | Description |
93
+ ------------------------- | -------- | ------------------------------------------------------- | ----------- |
94
+ `collect_cluster_metrics` | boolean | Enabled in Sidekiq worker processes, disabled otherwise | Defines whether this Ruby process should collect and expose metrics representing state of the whole Sidekiq installation (queues, processes, etc). |
44
95
 
45
96
  # Roadmap (TODO or Help wanted)
46
97
 
@@ -60,6 +111,38 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
60
111
 
61
112
  Bug reports and pull requests are welcome on GitHub at https://github.com/yabeda-rb/yabeda-sidekiq.
62
113
 
114
+ ### Releasing
115
+
116
+ 1. Bump version number in `lib/yabeda/sidekiq/version.rb`
117
+
118
+ 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::Sidekiq::VERSION).to_s`
119
+
120
+ 2. Fill `CHANGELOG.md` with missing changes, add header with version and date.
121
+
122
+ 3. Make a commit:
123
+
124
+ ```sh
125
+ git add lib/yabeda/sidekiq/version.rb CHANGELOG.md
126
+ version=$(ruby -r ./lib/yabeda/sidekiq/version.rb -e "puts Gem::Version.new(Yabeda::Sidekiq::VERSION)")
127
+ git commit --message="${version}: " --edit
128
+ ```
129
+
130
+ 4. Create annotated tag:
131
+
132
+ ```sh
133
+ git tag v${version} --annotate --message="${version}: " --edit --sign
134
+ ```
135
+
136
+ 5. Fill version name into subject line and (optionally) some description (list of changes will be taken from changelog and appended automatically)
137
+
138
+ 6. Push it:
139
+
140
+ ```sh
141
+ git push --follow-tags
142
+ ```
143
+
144
+ 7. GitHub Actions will create a new release, build and push gem into RubyGems! You're done!
145
+
63
146
  ## License
64
147
 
65
148
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -67,3 +150,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
67
150
  [Sidekiq]: https://github.com/mperham/sidekiq/ "Simple, efficient background processing for Ruby"
68
151
  [yabeda]: https://github.com/yabeda-rb/yabeda
69
152
  [yabeda-prometheus]: https://github.com/yabeda-rb/yabeda-prometheus
153
+ [anyway_config]: https://github.com/palkan/anyway_config "Configuration library for Ruby gems and applications"
data/Rakefile CHANGED
@@ -2,7 +2,10 @@
2
2
 
3
3
  require "bundler/gem_tasks"
4
4
  require "rspec/core/rake_task"
5
+ require "rubocop/rake_task"
6
+
7
+ RuboCop::RakeTask.new
5
8
 
6
9
  RSpec::Core::RakeTask.new(:spec)
7
10
 
8
- task default: :spec
11
+ task default: %i[rubocop spec]
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "anyway"
4
+
5
+ module Yabeda
6
+ module Sidekiq
7
+ class Config < ::Anyway::Config
8
+ config_name :yabeda_sidekiq
9
+
10
+ # By default all sidekiq worker processes (servers) collects global metrics about whole Sidekiq installation.
11
+ # Client processes (everything else that is not Sidekiq worker) by default doesn't.
12
+ # With this config you can override this behavior:
13
+ # - force disable if you don't want multiple Sidekiq workers to report the same numbers (that causes excess load to both Redis and monitoring)
14
+ # - force enable if you want non-Sidekiq process to collect them (like dedicated metric exporter process)
15
+ attr_config collect_cluster_metrics: ::Sidekiq.server?
16
+ end
17
+ end
18
+ end
@@ -4,13 +4,21 @@ module Yabeda
4
4
  module Sidekiq
5
5
  # Sidekiq worker middleware
6
6
  class ServerMiddleware
7
+ # See https://github.com/mperham/sidekiq/discussions/4971
8
+ JOB_RECORD_CLASS = defined?(::Sidekiq::JobRecord) ? ::Sidekiq::JobRecord : ::Sidekiq::Job
9
+
10
+ # rubocop: disable Metrics/AbcSize, Metrics/MethodLength:
7
11
  def call(worker, job, queue)
8
- labels = Yabeda::Sidekiq.labelize(worker, job, queue)
9
- start = Time.now
12
+ custom_tags = Yabeda::Sidekiq.custom_tags(worker, job).to_h
13
+ labels = Yabeda::Sidekiq.labelize(worker, job, queue).merge(custom_tags)
14
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
10
15
  begin
11
- job_instance = ::Sidekiq::Job.new(job)
16
+ job_instance = JOB_RECORD_CLASS.new(job)
12
17
  Yabeda.sidekiq_job_latency.measure(labels, job_instance.latency)
13
- yield
18
+ Yabeda::Sidekiq.jobs_started_at[labels][job["jid"]] = start
19
+ Yabeda.with_tags(**custom_tags) do
20
+ yield
21
+ end
14
22
  Yabeda.sidekiq_jobs_success_total.increment(labels)
15
23
  rescue Exception # rubocop: disable Lint/RescueException
16
24
  Yabeda.sidekiq_jobs_failed_total.increment(labels)
@@ -18,13 +26,15 @@ module Yabeda
18
26
  ensure
19
27
  Yabeda.sidekiq_job_runtime.measure(labels, elapsed(start))
20
28
  Yabeda.sidekiq_jobs_executed_total.increment(labels)
29
+ Yabeda::Sidekiq.jobs_started_at[labels].delete(job["jid"])
21
30
  end
22
31
  end
32
+ # rubocop: enable Metrics/AbcSize, Metrics/MethodLength:
23
33
 
24
34
  private
25
35
 
26
36
  def elapsed(start)
27
- (Time.now - start).round(3)
37
+ (Process.clock_gettime(Process::CLOCK_MONOTONIC) - start).round(3)
28
38
  end
29
39
  end
30
40
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Yabeda
4
4
  module Sidekiq
5
- VERSION = "0.5.0"
5
+ VERSION = "0.8.1"
6
6
  end
7
7
  end
@@ -7,43 +7,57 @@ require "yabeda"
7
7
  require "yabeda/sidekiq/version"
8
8
  require "yabeda/sidekiq/client_middleware"
9
9
  require "yabeda/sidekiq/server_middleware"
10
+ require "yabeda/sidekiq/config"
10
11
 
11
12
  module Yabeda
12
13
  module Sidekiq
13
14
  LONG_RUNNING_JOB_RUNTIME_BUCKETS = [
14
15
  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
+ 30, 60, 120, 300, 1800, 3600, 21_600, # Sidekiq tasks may be very long-running
16
17
  ].freeze
17
18
 
18
19
  Yabeda.configure do
20
+ config = Config.new
21
+
19
22
  group :sidekiq
20
23
 
21
24
  counter :jobs_enqueued_total, tags: %i[queue worker], comment: "A counter of the total number of jobs sidekiq enqueued."
22
25
 
23
- next unless ::Sidekiq.server?
24
-
25
- counter :jobs_executed_total, tags: %i[queue worker], comment: "A counter of the total number of jobs sidekiq executed."
26
- counter :jobs_success_total, tags: %i[queue worker], comment: "A counter of the total number of jobs successfully processed by sidekiq."
27
- counter :jobs_failed_total, tags: %i[queue worker], comment: "A counter of the total number of jobs failed in sidekiq."
28
-
29
- gauge :jobs_waiting_count, tags: %i[queue], comment: "The number of jobs waiting to process in sidekiq."
30
- gauge :active_workers_count, tags: [], comment: "The number of currently running machines with sidekiq workers."
31
- gauge :jobs_scheduled_count, tags: [], comment: "The number of jobs scheduled for later execution."
32
- gauge :jobs_retry_count, tags: [], comment: "The number of failed jobs waiting to be retried"
33
- gauge :jobs_dead_count, tags: [], comment: "The number of jobs exceeded their retry count."
34
- gauge :active_processes, tags: [], comment: "The number of active Sidekiq worker processes."
35
- gauge :queue_latency, tags: %i[queue], comment: "The queue latency, the difference in seconds since the oldest job in the queue was enqueued"
36
-
37
- histogram :job_latency, comment: "The job latency, the difference in seconds between enqueued and running time",
38
- unit: :seconds, per: :job,
39
- tags: %i[queue worker],
40
- buckets: LONG_RUNNING_JOB_RUNTIME_BUCKETS
41
- histogram :job_runtime, comment: "A histogram of the job execution time.",
42
- unit: :seconds, per: :job,
43
- tags: %i[queue worker],
44
- buckets: LONG_RUNNING_JOB_RUNTIME_BUCKETS
26
+ if ::Sidekiq.server?
27
+ counter :jobs_executed_total, tags: %i[queue worker], comment: "A counter of the total number of jobs sidekiq executed."
28
+ counter :jobs_success_total, tags: %i[queue worker], comment: "A counter of the total number of jobs successfully processed by sidekiq."
29
+ counter :jobs_failed_total, tags: %i[queue worker], comment: "A counter of the total number of jobs failed in sidekiq."
30
+
31
+ gauge :running_job_runtime, tags: %i[queue worker], aggregation: :max, unit: :seconds,
32
+ comment: "How long currently running jobs are running (useful for detection of hung jobs)"
33
+
34
+ histogram :job_latency, comment: "The job latency, the difference in seconds between enqueued and running time",
35
+ unit: :seconds, per: :job,
36
+ tags: %i[queue worker],
37
+ buckets: LONG_RUNNING_JOB_RUNTIME_BUCKETS
38
+ histogram :job_runtime, comment: "A histogram of the job execution time.",
39
+ unit: :seconds, per: :job,
40
+ tags: %i[queue worker],
41
+ buckets: LONG_RUNNING_JOB_RUNTIME_BUCKETS
42
+ end
43
+
44
+ # Metrics not specific for current Sidekiq process, but representing state of the whole Sidekiq installation (queues, processes, etc)
45
+ # You can opt-out from collecting these by setting YABEDA_SIDEKIQ_COLLECT_CLUSTER_METRICS to falsy value (+no+ or +false+)
46
+ if config.collect_cluster_metrics # defaults to +::Sidekiq.server?+
47
+ gauge :jobs_waiting_count, tags: %i[queue], comment: "The number of jobs waiting to process in sidekiq."
48
+ gauge :active_workers_count, tags: [], comment: "The number of currently running machines with sidekiq workers."
49
+ gauge :jobs_scheduled_count, tags: [], comment: "The number of jobs scheduled for later execution."
50
+ gauge :jobs_retry_count, tags: [], comment: "The number of failed jobs waiting to be retried"
51
+ gauge :jobs_dead_count, tags: [], comment: "The number of jobs exceeded their retry count."
52
+ gauge :active_processes, tags: [], comment: "The number of active Sidekiq worker processes."
53
+ gauge :queue_latency, tags: %i[queue], comment: "The queue latency, the difference in seconds since the oldest job in the queue was enqueued"
54
+ end
45
55
 
46
56
  collect do
57
+ Yabeda::Sidekiq.track_max_job_runtime if ::Sidekiq.server?
58
+
59
+ next unless config.collect_cluster_metrics
60
+
47
61
  stats = ::Sidekiq::Stats.new
48
62
 
49
63
  stats.queues.each do |k, v|
@@ -93,10 +107,34 @@ module Yabeda
93
107
 
94
108
  def worker_class(worker, job)
95
109
  if defined?(ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper)
96
- return job["wrapped"] if worker.is_a?(ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper)
110
+ if worker.is_a?(ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper) || worker == ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper
111
+ return job["wrapped"].to_s
112
+ end
113
+ end
114
+ (worker.is_a?(String) || worker.is_a?(Class) ? worker : worker.class).to_s
115
+ end
116
+
117
+ def custom_tags(worker, job)
118
+ return {} unless worker.respond_to?(:yabeda_tags)
119
+
120
+ worker.method(:yabeda_tags).arity.zero? ? worker.yabeda_tags : worker.yabeda_tags(*job["args"])
121
+ end
122
+
123
+ # Hash of hashes containing all currently running jobs' start timestamps
124
+ # to calculate maximum durations of currently running not yet completed jobs
125
+ # { { queue: "default", worker: "SomeJob" } => { "jid1" => 100500, "jid2" => 424242 } }
126
+ attr_accessor :jobs_started_at
127
+
128
+ def track_max_job_runtime
129
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
130
+ ::Yabeda::Sidekiq.jobs_started_at.each do |labels, jobs|
131
+ oldest_job_started_at = jobs.values.min
132
+ oldest_job_duration = oldest_job_started_at ? (now - oldest_job_started_at).round(3) : 0
133
+ Yabeda.sidekiq.running_job_runtime.set(labels, oldest_job_duration)
97
134
  end
98
- (worker.is_a?(String) ? worker : worker.class).to_s
99
135
  end
100
136
  end
137
+
138
+ self.jobs_started_at = Concurrent::Hash.new { |hash, key| hash[key] = Concurrent::Hash.new }
101
139
  end
102
140
  end
Binary file
@@ -22,10 +22,12 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- spec.add_dependency "yabeda", "~> 0.2"
25
+ spec.add_dependency "anyway_config", ">= 1.3", "< 3"
26
26
  spec.add_dependency "sidekiq"
27
+ spec.add_dependency "yabeda", "~> 0.6"
27
28
 
28
- spec.add_development_dependency "bundler", "~> 1.16"
29
- spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "activejob", ">= 6.0"
30
+ spec.add_development_dependency "bundler", "~> 2.0"
31
+ spec.add_development_dependency "rake", "~> 13.0"
30
32
  spec.add_development_dependency "rspec", "~> 3.0"
31
33
  end
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yabeda-sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.8.1
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-02-20 00:00:00.000000000 Z
11
+ date: 2021-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: yabeda
14
+ name: anyway_config
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ - - "<"
18
21
  - !ruby/object:Gem::Version
19
- version: '0.2'
22
+ version: '3'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: '0.2'
29
+ version: '1.3'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: sidekiq
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -38,34 +44,62 @@ dependencies:
38
44
  - - ">="
39
45
  - !ruby/object:Gem::Version
40
46
  version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: yabeda
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.6'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.6'
61
+ - !ruby/object:Gem::Dependency
62
+ name: activejob
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '6.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '6.0'
41
75
  - !ruby/object:Gem::Dependency
42
76
  name: bundler
43
77
  requirement: !ruby/object:Gem::Requirement
44
78
  requirements:
45
79
  - - "~>"
46
80
  - !ruby/object:Gem::Version
47
- version: '1.16'
81
+ version: '2.0'
48
82
  type: :development
49
83
  prerelease: false
50
84
  version_requirements: !ruby/object:Gem::Requirement
51
85
  requirements:
52
86
  - - "~>"
53
87
  - !ruby/object:Gem::Version
54
- version: '1.16'
88
+ version: '2.0'
55
89
  - !ruby/object:Gem::Dependency
56
90
  name: rake
57
91
  requirement: !ruby/object:Gem::Requirement
58
92
  requirements:
59
93
  - - "~>"
60
94
  - !ruby/object:Gem::Version
61
- version: '10.0'
95
+ version: '13.0'
62
96
  type: :development
63
97
  prerelease: false
64
98
  version_requirements: !ruby/object:Gem::Requirement
65
99
  requirements:
66
100
  - - "~>"
67
101
  - !ruby/object:Gem::Version
68
- version: '10.0'
102
+ version: '13.0'
69
103
  - !ruby/object:Gem::Dependency
70
104
  name: rspec
71
105
  requirement: !ruby/object:Gem::Requirement
@@ -88,10 +122,11 @@ executables: []
88
122
  extensions: []
89
123
  extra_rdoc_files: []
90
124
  files:
125
+ - ".github/workflows/build-release.yml"
126
+ - ".github/workflows/test.yml"
91
127
  - ".gitignore"
92
128
  - ".rspec"
93
129
  - ".rubocop.yml"
94
- - ".travis.yml"
95
130
  - CHANGELOG.md
96
131
  - Gemfile
97
132
  - LICENSE.txt
@@ -101,8 +136,10 @@ files:
101
136
  - bin/setup
102
137
  - lib/yabeda/sidekiq.rb
103
138
  - lib/yabeda/sidekiq/client_middleware.rb
139
+ - lib/yabeda/sidekiq/config.rb
104
140
  - lib/yabeda/sidekiq/server_middleware.rb
105
141
  - lib/yabeda/sidekiq/version.rb
142
+ - yabeda-sidekiq-logo.png
106
143
  - yabeda-sidekiq.gemspec
107
144
  homepage: https://github.com/yabeda-rb/yabeda-sidekiq
108
145
  licenses:
@@ -123,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
160
  - !ruby/object:Gem::Version
124
161
  version: '0'
125
162
  requirements: []
126
- rubygems_version: 3.0.3
163
+ rubygems_version: 3.1.6
127
164
  signing_key:
128
165
  specification_version: 4
129
166
  summary: Extensible Prometheus exporter for monitoring your Sidekiq
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5.1
5
- before_install: gem install bundler -v 1.16.1