sidekiq-instrumental 0.2.3 → 0.3.2

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
- SHA1:
3
- metadata.gz: a71199e63e3ff0539ef7e598490f27f0715d30b8
4
- data.tar.gz: bd14c5b122c230a542cbed342e0e1e186eee2bd4
2
+ SHA256:
3
+ metadata.gz: 554f7530d3719b65ba7c9cc9defedaea1cec95adea137a0627ad81b98cee4405
4
+ data.tar.gz: fca6e4182df43e4c1980efe397623248c66c9d6c1510294d01727ef6118ce17f
5
5
  SHA512:
6
- metadata.gz: 509476fe83703bd76e2a4a4129c5236e63877f695125fe0cc5e8695555235781bf401230a31e90ac28d6fb8391d327913645459777c8853a2be1f62e67487498
7
- data.tar.gz: 2f9a3de47b48efa0ee50a410899f5bf59bb6b21af4baec6c73afdb6dbafcb1ddc728a91bd1ce1bd7eee21aafe103642812cf58d89498b105fb7d3ef1de5467a5
6
+ metadata.gz: d04a719ca6409deeacf6cb4ed59acf544521617b75226a4888b2559e94b8bd8ed71132451594d9ef3a2981b9d60760c57b6fb3278b9d0646e0ef44e1286675ba
7
+ data.tar.gz: 3fb5692dc389eb03581a3c0b1ad1dffab4116a410ea21d82887bea2a289657612a9c3deef08b03afdf89335336160db95466ec060e829ed6d38f0bcd8af887bb
@@ -0,0 +1,24 @@
1
+ ## Change description
2
+
3
+ > Please include a summary of the change and which issue is fixed. Please also include
4
+ relevant motivation and context. List any dependencies that are required for this change.
5
+
6
+ ## Related issues
7
+
8
+ - Source: <Issue link or Spec Link>
9
+ - UAT: <UAT Link>
10
+ - QA: <QA Task Link here>
11
+ - Review app: <Link to Heroku>
12
+
13
+ ## Checklists
14
+
15
+ ### Development
16
+
17
+ - [ ] The commit message follows our [guidelines](https://docs.hubstaff.com/hubstaff-docs/latest/great_commit_messages.html)
18
+ - [ ] I have performed a self-review of my own code
19
+ - [ ] I have thoroughly tested the changes
20
+ - [ ] I have added tests that prove my fix is effective or that my feature works
21
+
22
+ ### Security
23
+
24
+ - [ ] Security impact of change has been considered
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: CI PR Builds
3
+ 'on':
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ concurrency:
9
+ group: ci-${{ github.ref }}
10
+ cancel-in-progress: true
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ ruby:
18
+ - '2.5'
19
+ - '2.7'
20
+ sidekiq:
21
+ - '4'
22
+ - '5'
23
+ env:
24
+ BUNDLE_GEMFILE: "${{ github.workspace }}/gemfiles/Gemfile.sidekiq${{ matrix.sidekiq }}"
25
+ steps:
26
+ - uses: actions/checkout@v2
27
+ - name: Set up Ruby
28
+ uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: "${{ matrix.ruby }}"
31
+ bundler-cache: true
32
+ - name: Run bundle update
33
+ run: bundle update
34
+ - name: Run tests
35
+ run: bundle exec rake spec
36
+ - name: Rubocop
37
+ run: bundle exec rubocop
38
+ - name: Build gem
39
+ run: gem build *.gemspec
data/.gitignore CHANGED
@@ -4,6 +4,7 @@
4
4
  /.ruby-version
5
5
  /.ruby-gemset
6
6
  /Gemfile.lock
7
+ /gemfiles/*.lock
7
8
  /_yardoc/
8
9
  /coverage/
9
10
  /doc/
data/.rubocop.yml ADDED
@@ -0,0 +1,8 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+ Layout/MultilineMethodCallIndentation:
4
+ EnforcedStyle: indented_relative_to_receiver
5
+ Layout/LineLength:
6
+ Max: 90
7
+ Metrics:
8
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Next]
8
+ ### Added
9
+ ### Changed
10
+ ### Fixed
11
+
12
+ ## [0.3.2]
13
+ ### Added
14
+ - Implement a custom version of Sidekiq's display\_class\_name that fix an issues with ActiveJob > 6 when the job's class is passed as class not String
15
+ - Limit support up to Sidekiq < 6.
16
+
17
+ ## [0.3.1]
18
+ ### Fixed
19
+ - class name calculation needs to filter out unsupported characters by instrumental
20
+
21
+ ## [0.3.0]
22
+ ### Fixed
23
+ - class name calculation now uses Sidekiq's display\_class\_name to support ActiveJob jobs
24
+
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in sidekiq-instrumental.gemspec
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Gem Version](https://badge.fury.io/rb/sidekiq-instrumental.svg)](https://badge.fury.io/rb/sidekiq-instrumental)
2
+
1
3
  # Sidekiq::Instrumental
2
4
 
3
5
  sidekiq-instrumental is a simple gem to record Sidekiq queue stats into [Instrumental](https://instrumentalapp.com/).
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "sidekiq/instrumental"
4
+ require 'bundler/setup'
5
+ require 'sidekiq/instrumental'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "sidekiq/instrumental"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start
@@ -0,0 +1,3 @@
1
+ mkdir -p ~/.gem
2
+ echo -e "---\n:rubygems_api_key: $RUBYGEMS_API_KEY" > ~/.gem/credentials
3
+ chmod 0600 ~/.gem/credentials
data/bin/tag_check.sh ADDED
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+
3
+ tag=`git describe --tags --exact-match HEAD 2> /dev/null`
4
+
5
+ if [ $? -eq 0 ]; then
6
+ version=`grep VERSION lib/sidekiq/instrumental/version.rb | sed -e "s/.*'\([^']*\)'.*/\1/"`
7
+
8
+ if [ "v$version" = "$tag" ]; then
9
+ echo "Revision $tag Matches $version"
10
+ else
11
+ echo "Revision $tag does not match $version"
12
+ exit 2
13
+ fi
14
+ else
15
+ echo "No tag found"
16
+ exit 1
17
+ fi
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ gemspec path: File.expand_path('..', __FILE__)
3
+
4
+ File.exist?(gemfile_local = File.expand_path('../Gemfile.local', __FILE__)) and eval File.read(gemfile_local), binding, gemfile_local
@@ -0,0 +1,4 @@
1
+ base_gemfile = File.expand_path('../Gemfile.base', __FILE__)
2
+ eval File.read(base_gemfile)
3
+
4
+ gem "sidekiq", ">= 4.0", "< 5.0"
@@ -0,0 +1,4 @@
1
+ base_gemfile = File.expand_path('../Gemfile.base', __FILE__)
2
+ eval File.read(base_gemfile)
3
+
4
+ gem "sidekiq", ">= 5.0", "< 6.0"
@@ -1,17 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sidekiq
2
4
  module Instrumental
5
+ # Configuration for gem
3
6
  class Configuration
4
- ARRAY_OPTIONS = [:whitelist_queues, :blacklist_queues, :whitelist_classes, :blacklist_classes]
7
+ ARRAY_OPTIONS = %i[
8
+ whitelist_queues blacklist_queues
9
+ whitelist_classes blacklist_classes
10
+ ].freeze
5
11
 
6
12
  attr_accessor :instrumental_agent
7
13
  attr_accessor :enabled, *ARRAY_OPTIONS
8
14
 
9
- alias_method :I, :instrumental_agent
15
+ alias I instrumental_agent
10
16
 
11
17
  def initialize
12
18
  @instrumental_agent = nil
13
19
  self.enabled = true
14
- ARRAY_OPTIONS.each {|o| self.send("#{o}=", [])}
20
+ ARRAY_OPTIONS.each { |o| send("#{o}=", []) }
15
21
  end
16
22
 
17
23
  def enabled?
@@ -19,7 +25,9 @@ module Sidekiq
19
25
  end
20
26
 
21
27
  def queue_in_whitelist(queue)
22
- whitelist_queues.nil? || whitelist_queues.empty? || whitelist_queues.include?(queue.to_s)
28
+ whitelist_queues.nil? ||
29
+ whitelist_queues.empty? ||
30
+ whitelist_queues.include?(queue.to_s)
23
31
  end
24
32
 
25
33
  def queue_in_blacklist(queue)
@@ -27,7 +35,9 @@ module Sidekiq
27
35
  end
28
36
 
29
37
  def class_in_whitelist(worker_instance)
30
- whitelist_classes.nil? || whitelist_classes.empty? || whitelist_classes.include?(worker_instance.class.to_s)
38
+ whitelist_classes.nil? ||
39
+ whitelist_classes.empty? ||
40
+ whitelist_classes.include?(worker_instance.class.to_s)
31
41
  end
32
42
 
33
43
  def class_in_blacklist(worker_instance)
@@ -35,8 +45,11 @@ module Sidekiq
35
45
  end
36
46
 
37
47
  def allowed_to_submit(queue, worker_instance)
38
- class_in_whitelist(worker_instance) && !class_in_blacklist(worker_instance) && queue_in_whitelist(queue) && !queue_in_blacklist(queue)
48
+ class_in_whitelist(worker_instance) &&
49
+ !class_in_blacklist(worker_instance) &&
50
+ queue_in_whitelist(queue) &&
51
+ !queue_in_blacklist(queue)
39
52
  end
40
53
  end
41
54
  end
42
- end
55
+ end
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'sidekiq/api'
2
4
 
3
5
  module Sidekiq
4
6
  module Instrumental
5
7
  module Middleware
8
+ # Shared base code for measuring stats for server and client sidekiq
6
9
  class Base
7
10
  attr_reader :config
8
11
 
@@ -10,14 +13,19 @@ module Sidekiq
10
13
  @config = config
11
14
  end
12
15
 
13
- def call(worker_instance, msg, queue, redis_pool = nil)
16
+ def call(worker_instance, msg, queue, _redis_pool = nil)
14
17
  start_time = Time.now
15
18
  result = yield
16
19
  elapsed = (Time.now - start_time).to_f
17
20
 
18
21
  return result unless config.enabled?
19
22
 
20
- track(::Sidekiq::Stats.new, worker_instance, msg, queue, elapsed)
23
+ track(
24
+ ::Sidekiq::Stats.new,
25
+ worker_instance,
26
+ ::Sidekiq::Job.new(msg),
27
+ queue, elapsed
28
+ )
21
29
 
22
30
  result
23
31
  end
@@ -25,11 +33,49 @@ module Sidekiq
25
33
  protected
26
34
 
27
35
  def increment(*args)
28
- config.I.increment *args
36
+ config.I.increment(*args)
29
37
  end
30
38
 
31
39
  def gauge(*args)
32
- config.I.gauge *args
40
+ config.I.gauge(*args)
41
+ end
42
+
43
+ def build_class_key(klass_name)
44
+ key = underscore(klass_name)
45
+ .gsub(/[^\d\w\-_\.]/, '_')
46
+ .gsub(/\.{2,}/, '.')
47
+ key.chomp!('.') while key[-1] == '.'
48
+ key
49
+ end
50
+
51
+ # Borrowed from active support so we do not depend on it.
52
+ def underscore(camel_cased_word)
53
+ return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
54
+
55
+ word = camel_cased_word.to_s.gsub('::', '/')
56
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
57
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
58
+ word.tr!('-', '_')
59
+ word.downcase!
60
+ word
61
+ end
62
+
63
+ # Returns the human-friendly class name, if its a known wrapper we unwrap it.
64
+ # Previously, this was done by the +display_name+ method of Sidekiq::Job,
65
+ # but after this change (https://github.com/rails/rails/commit/0e64348ccaf513de731f403259ec5b49e7b3f028)
66
+ # the method (https://github.com/mperham/sidekiq/blob/main/lib/sidekiq/api.rb#L342)
67
+ # no longer works as expected as it compares a class against a string,
68
+ # returning the wrapped job class not the class behind it as String.
69
+ def unwrap_class_name(job)
70
+ display_class = job.display_class
71
+
72
+ if %w[ActionMailer::DeliveryJob ActionMailer::MailDeliveryJob]
73
+ .include?(display_class.class.name)
74
+ # The class name was not unwrapped correctly by the +display_class+ method
75
+ job.args[0]['arguments'][0..1].join('#')
76
+ else
77
+ display_class
78
+ end
33
79
  end
34
80
  end
35
81
  end
@@ -1,22 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sidekiq
2
4
  module Instrumental
3
5
  module Middleware
6
+ # Client side sidekiq middleware
4
7
  class Client < Base
5
-
6
- def track(stats, worker_instance, msg, queue, elapsed)
7
-
8
+ def track(_stats, worker_instance, msg, queue, _elapsed)
8
9
  increment('sidekiq.queued')
9
10
 
10
11
  return unless config.allowed_to_submit queue, worker_instance
11
12
 
12
- base_key = "sidekiq.#{queue.to_s}."
13
+ base_key = "sidekiq.#{queue}."
13
14
  increment(base_key + 'queued')
14
15
 
15
- base_key += msg['class'].underscore.gsub('/', '_') + '.'
16
+ display_class = unwrap_class_name(msg)
17
+ base_key += build_class_key(display_class) + '.'
16
18
 
17
19
  increment(base_key + 'queued')
18
20
  end
19
21
  end
20
22
  end
21
23
  end
22
- end
24
+ end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sidekiq
2
4
  module Instrumental
3
5
  module Middleware
6
+ # Server side sidekiq middleware
4
7
  class Server < Base
5
8
  protected
6
9
 
@@ -9,26 +12,28 @@ module Sidekiq
9
12
 
10
13
  return unless config.allowed_to_submit queue, worker_instance
11
14
 
12
- base_key = "sidekiq.#{queue.to_s}."
15
+ base_key = "sidekiq.#{queue}."
13
16
 
14
17
  increment(base_key + 'processed')
15
18
  gauge(base_key + 'time', elapsed)
16
19
  gauge(base_key + 'enqueued', stats.queues[queue].to_i)
17
20
  gauge(base_key + 'latency', Sidekiq::Queue.new(queue.to_s).latency)
18
- base_key += msg['class'].underscore.gsub('/', '_') + '.'
21
+
22
+ display_class = unwrap_class_name(msg)
23
+ base_key += build_class_key(display_class) + '.'
19
24
 
20
25
  increment(base_key + 'processed')
21
- increment(base_key + 'time', elapsed)
26
+ gauge(base_key + 'time', elapsed)
22
27
  end
23
28
 
24
29
  def submit_general_stats(stats)
25
- increment("sidekiq.processed")
30
+ increment('sidekiq.processed')
26
31
  {
27
- enqueued: nil,
28
- failed: nil,
29
- scheduled_size: 'scheduled'
32
+ enqueued: nil,
33
+ failed: nil,
34
+ scheduled_size: 'scheduled'
30
35
  }.each do |method, name|
31
- gauge("sidekiq.#{(name || method).to_s}", stats.send(method).to_i)
36
+ gauge("sidekiq.#{(name || method)}", stats.send(method).to_i)
32
37
  end
33
38
  end
34
39
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sidekiq
2
4
  module Instrumental
3
- VERSION = "0.2.3"
5
+ VERSION = '0.3.2'
4
6
  end
5
7
  end
@@ -1,4 +1,6 @@
1
- require "sidekiq/instrumental/version"
1
+ # frozen_string_literal: true
2
+
3
+ require 'sidekiq/instrumental/version'
2
4
  require 'sidekiq/instrumental/configuration'
3
5
  require 'sidekiq/instrumental/middleware/base'
4
6
  require 'sidekiq/instrumental/middleware/client'
@@ -6,18 +8,18 @@ require 'sidekiq/instrumental/middleware/server'
6
8
  require 'sidekiq'
7
9
 
8
10
  module Sidekiq
9
- module Instrumental
11
+ module Instrumental # :nodoc:
10
12
  def self.config
11
13
  @config ||= Sidekiq::Instrumental::Configuration.new
12
14
  end
13
15
 
14
16
  def self.configure
15
- yield self.config if block_given?
16
- self.register
17
+ yield config if block_given?
18
+ register
17
19
  end
18
20
 
19
21
  def self.register
20
- new_config = self.config.dup
22
+ new_config = config.dup
21
23
 
22
24
  ::Sidekiq.configure_server do |config|
23
25
  config.server_middleware do |chain|
@@ -1,28 +1,37 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'sidekiq/instrumental/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "sidekiq-instrumental"
8
- spec.version = Sidekiq::Instrumental::VERSION
9
- spec.authors = ["Edward Rudd"]
10
- spec.email = ["urkle@outoforder.cc"]
11
-
12
- spec.summary = %q{Send Sidekiq status into Instrumental after every job}
13
- spec.homepage = "https://github.com/NetsoftHoldings/sidekiq-instrumental/"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
17
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
- spec.require_paths = ["lib"]
19
- spec.test_files = Dir['spec/**/*']
20
-
21
- spec.add_runtime_dependency 'instrumental_agent', ">= 0.13"
22
- spec.add_runtime_dependency 'sidekiq', '>= 3.5'
23
-
24
- spec.add_development_dependency "bundler", "~> 1.9"
25
- spec.add_development_dependency "simplecov", "~> 0.11"
26
- spec.add_development_dependency "rake", "~> 10.0"
27
- spec.add_development_dependency "rspec", "~> 3.4"
8
+ spec.name = 'sidekiq-instrumental'
9
+ spec.version = Sidekiq::Instrumental::VERSION
10
+ spec.authors = ['Edward Rudd']
11
+ spec.email = ['urkle@outoforder.cc']
12
+
13
+ spec.summary = 'Send Sidekiq status into Instrumental after every job'
14
+ spec.homepage = 'https://github.com/NetsoftHoldings/sidekiq-instrumental/'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`
18
+ .split("\x0")
19
+ .reject { |f| f.match(%r{^(spec)/}) }
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+ spec.test_files = Dir['spec/**/*']
23
+
24
+ spec.required_ruby_version = '>= 2.3'
25
+
26
+ spec.add_runtime_dependency 'instrumental_agent', '>= 0.13'
27
+ spec.add_runtime_dependency 'sidekiq', '>= 4.0', '< 6.0'
28
+
29
+ spec.add_development_dependency 'bundler'
30
+ spec.add_development_dependency 'rake', '>= 10.0'
31
+ spec.add_development_dependency 'rspec', '~> 3.4'
32
+ spec.add_development_dependency 'simplecov', '~> 0.11'
33
+ spec.add_development_dependency 'timecop', '~> 0.9.1'
34
+
35
+ spec.add_development_dependency 'rubocop', '~> 0.79.0'
36
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.37.1'
28
37
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  RSpec.describe Sidekiq::Instrumental::Configuration do
@@ -59,23 +61,38 @@ RSpec.describe Sidekiq::Instrumental::Configuration do
59
61
  expect(subject.send(method, 'other')).to eq(false)
60
62
  end
61
63
  end
62
-
63
64
  end
64
65
 
65
66
  describe '#queue_in_whitelist' do
66
- include_examples 'whitelist checks', :whitelist_queues, :queue_in_whitelist, ['default'], 'default'
67
+ include_examples 'whitelist checks',
68
+ :whitelist_queues,
69
+ :queue_in_whitelist,
70
+ ['default'],
71
+ 'default'
67
72
  end
68
73
 
69
74
  describe '#queue_in_blacklist' do
70
- include_examples 'blacklist checks', :blacklist_queues, :queue_in_blacklist, ['default'], 'default'
75
+ include_examples 'blacklist checks',
76
+ :blacklist_queues,
77
+ :queue_in_blacklist,
78
+ ['default'],
79
+ 'default'
71
80
  end
72
81
 
73
82
  describe '#class_in_whitelist' do
74
- include_examples 'whitelist checks', :whitelist_classes, :class_in_whitelist, ['Array'], []
83
+ include_examples 'whitelist checks',
84
+ :whitelist_classes,
85
+ :class_in_whitelist,
86
+ ['Array'],
87
+ []
75
88
  end
76
89
 
77
90
  describe '#class_in_blacklist' do
78
- include_examples 'blacklist checks', :blacklist_classes, :class_in_blacklist, ['Array'], []
91
+ include_examples 'blacklist checks',
92
+ :blacklist_classes,
93
+ :class_in_blacklist,
94
+ ['Array'],
95
+ []
79
96
  end
80
97
 
81
98
  describe '#allowed_to_submit' do
@@ -83,4 +100,4 @@ RSpec.describe Sidekiq::Instrumental::Configuration do
83
100
  expect(subject.allowed_to_submit('default', [])).to eq(true)
84
101
  end
85
102
  end
86
- end
103
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Sidekiq::Instrumental::Middleware::Client do
6
+ let(:config) { Sidekiq::Instrumental::Configuration.new }
7
+ let(:middleware) { described_class.new(config) }
8
+ let(:sidekiq_stats) { double('Sidekiq::Stats') }
9
+ let(:worker) { {} }
10
+ let(:msg) { { 'class' => 'MyClassName' } }
11
+ let(:queue) { 'default' }
12
+
13
+ before do
14
+ allow(config).to receive(:enabled?).and_return(true)
15
+ allow(middleware).to receive(:increment)
16
+ allow(::Sidekiq::Stats).to receive(:new).and_return(sidekiq_stats)
17
+ end
18
+
19
+ subject { middleware.call(worker, msg, queue) {} }
20
+
21
+ it 'increments the queued metric' do
22
+ expect(middleware).to receive(:increment).with('sidekiq.queued')
23
+
24
+ subject
25
+ end
26
+
27
+ it 'checks if the worker class is allowed to submit detailed metrics' do
28
+ expect(config).to receive(:allowed_to_submit).with(queue, worker)
29
+
30
+ subject
31
+ end
32
+
33
+ it 'increments the queued metric for the queue' do
34
+ expect(middleware).to receive(:increment).with("sidekiq.#{queue}.queued")
35
+
36
+ subject
37
+ end
38
+
39
+ describe 'metric naming' do
40
+ context 'when the class name contains unsupported characters' do
41
+ let(:msg) { { 'class' => 'MyMailer#message/fun' } }
42
+
43
+ it 'changes them to _' do
44
+ expect(middleware).to receive(:increment)
45
+ .with("sidekiq.#{queue}.my_mailer_message_fun.queued")
46
+
47
+ subject
48
+ end
49
+ end
50
+
51
+ context 'when the class name causes more then one . in a row' do
52
+ let(:msg) { { 'class' => 'MyMailer..message' } }
53
+
54
+ it 'combines them to one' do
55
+ expect(middleware).to receive(:increment)
56
+ .with("sidekiq.#{queue}.my_mailer.message.queued")
57
+
58
+ subject
59
+ end
60
+ end
61
+
62
+ context 'trims a trailing .' do
63
+ let(:msg) { { 'class' => 'MyMailer#message.' } }
64
+
65
+ it 'combines them to one' do
66
+ expect(middleware).to receive(:increment)
67
+ .with("sidekiq.#{queue}.my_mailer_message.queued")
68
+
69
+ subject
70
+ end
71
+ end
72
+ end
73
+
74
+ it 'calls display_class to get the class name' do
75
+ expect_any_instance_of(::Sidekiq::Job)
76
+ .to receive(:display_class).and_call_original
77
+
78
+ subject
79
+ end
80
+
81
+ it 'increments the queued metric for the worker class name' do
82
+ expect(middleware).to receive(:increment)
83
+ .with("sidekiq.#{queue}.my_class_name.queued")
84
+
85
+ subject
86
+ end
87
+
88
+ describe 'Unwrap sidekiq job class name' do
89
+ let(:msg) do
90
+ {
91
+ 'class' => 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper',
92
+ 'wrapped' => wrapped_class,
93
+ 'args' => [{ 'arguments' => %w[UserMailer confirm_account deliver_now User] }]
94
+ }
95
+ end
96
+
97
+ context "when sidekiq's wrapped class is set as a String" do
98
+ let(:wrapped_class) { 'ActionMailer::DeliveryJob' }
99
+
100
+ it 'unwraps the class name and increments the metric' do
101
+ expect(middleware)
102
+ .to receive(:increment)
103
+ .with("sidekiq.#{queue}.user_mailer_confirm_account.queued")
104
+
105
+ subject
106
+ end
107
+ end
108
+
109
+ context "when sidekiq's wrapped class is set as a Class" do
110
+ let(:wrapped_class) { stub_const('ActionMailer::DeliveryJob', Class.new).new }
111
+
112
+ it 'unwraps the class name and increments the metric' do
113
+ expect(middleware)
114
+ .to receive(:increment)
115
+ .with("sidekiq.#{queue}.user_mailer_confirm_account.queued")
116
+
117
+ subject
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Sidekiq::Instrumental::Middleware::Server do
6
+ let(:config) { Sidekiq::Instrumental::Configuration.new }
7
+ let(:middleware) { described_class.new(config) }
8
+ let(:sidekiq_stats) do
9
+ instance_double('Sidekiq::Stats',
10
+ enqueued: 1,
11
+ failed: 2,
12
+ scheduled_size: 3,
13
+ queues: { queue => 4 })
14
+ end
15
+ let(:sidekiq_queue) { instance_double('Sidekiq::Queue', latency: 5) }
16
+ let(:worker) { {} }
17
+ let(:msg) { { 'class' => 'MyClassName' } }
18
+ let(:queue) { 'default' }
19
+
20
+ before do
21
+ allow(config).to receive(:enabled?).and_return(true)
22
+ allow(middleware).to receive(:increment)
23
+ allow(middleware).to receive(:gauge)
24
+ allow(::Sidekiq::Stats).to receive(:new).and_return(sidekiq_stats)
25
+ allow(::Sidekiq::Queue).to receive(:new).and_return(sidekiq_queue)
26
+ end
27
+
28
+ subject do
29
+ Timecop.freeze do
30
+ middleware.call(worker, msg, queue) do
31
+ Timecop.travel(0.5)
32
+ end
33
+ end
34
+ end
35
+
36
+ it 'submits general stats' do
37
+ expect(middleware).to receive(:gauge)
38
+ .with('sidekiq.enqueued', 1)
39
+ expect(middleware).to receive(:gauge)
40
+ .with('sidekiq.failed', 2)
41
+ expect(middleware).to receive(:gauge)
42
+ .with('sidekiq.scheduled', 3)
43
+
44
+ subject
45
+ end
46
+
47
+ it 'increments the processed metric' do
48
+ expect(middleware).to receive(:increment)
49
+ .with('sidekiq.processed')
50
+
51
+ subject
52
+ end
53
+
54
+ it 'increments the processed metric for the queue' do
55
+ expect(middleware).to receive(:increment)
56
+ .with("sidekiq.#{queue}.processed")
57
+
58
+ subject
59
+ end
60
+
61
+ it 'gauge the elapsed time metric for the queue' do
62
+ expect(middleware).to receive(:gauge)
63
+ .with(
64
+ "sidekiq.#{queue}.time",
65
+ be_within(0.001).of(0.5)
66
+ )
67
+
68
+ subject
69
+ end
70
+
71
+ it 'gauge the enqueued metric for the queue' do
72
+ expect(middleware).to receive(:gauge)
73
+ .with("sidekiq.#{queue}.enqueued", 4)
74
+
75
+ subject
76
+ end
77
+
78
+ it 'gauge the latency metric for the queue' do
79
+ expect(middleware).to receive(:gauge)
80
+ .with("sidekiq.#{queue}.latency", 5)
81
+
82
+ subject
83
+ end
84
+
85
+ it 'increments processed metric for the class' do
86
+ expect(middleware).to receive(:increment)
87
+ .with("sidekiq.#{queue}.my_class_name.processed")
88
+
89
+ subject
90
+ end
91
+
92
+ describe 'metric naming' do
93
+ context 'when the class name contains unsupported characters' do
94
+ let(:msg) { { 'class' => 'MyMailer#message/fun' } }
95
+
96
+ it 'changes them to _' do
97
+ expect(middleware).to receive(:increment)
98
+ .with("sidekiq.#{queue}.my_mailer_message_fun.processed")
99
+
100
+ subject
101
+ end
102
+ end
103
+
104
+ context 'when the class name causes more then one . in a row' do
105
+ let(:msg) { { 'class' => 'MyMailer..message' } }
106
+
107
+ it 'combines them to one' do
108
+ expect(middleware).to receive(:increment)
109
+ .with("sidekiq.#{queue}.my_mailer.message.processed")
110
+
111
+ subject
112
+ end
113
+ end
114
+
115
+ context 'trims a trailing .' do
116
+ let(:msg) { { 'class' => 'MyMailer#message.' } }
117
+
118
+ it 'combines them to one' do
119
+ expect(middleware).to receive(:increment)
120
+ .with("sidekiq.#{queue}.my_mailer_message.processed")
121
+
122
+ subject
123
+ end
124
+ end
125
+ end
126
+
127
+ it 'gauge elapsed time metric for the class' do
128
+ expect(middleware).to receive(:gauge)
129
+ .with(
130
+ "sidekiq.#{queue}.my_class_name.time",
131
+ be_within(0.001).of(0.5)
132
+ )
133
+
134
+ subject
135
+ end
136
+
137
+ describe 'Unwrap sidekiq job class name' do
138
+ let(:msg) do
139
+ {
140
+ 'class' => 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper',
141
+ 'wrapped' => wrapped_class,
142
+ 'args' => [{ 'arguments' => %w[UserMailer confirm_account deliver_now User] }]
143
+ }
144
+ end
145
+
146
+ context "when sidekiq's wrapped class is set as a String" do
147
+ let(:wrapped_class) { 'ActionMailer::DeliveryJob' }
148
+
149
+ it 'unwraps the class name and increments the metric' do
150
+ expect(middleware)
151
+ .to receive(:increment)
152
+ .with("sidekiq.#{queue}.user_mailer_confirm_account.processed")
153
+
154
+ subject
155
+ end
156
+ end
157
+
158
+ context "when sidekiq's wrapped class is set as a Class" do
159
+ let(:wrapped_class) { stub_const('ActionMailer::DeliveryJob', Class.new).new }
160
+
161
+ it 'unwraps the class name and increments the metric' do
162
+ expect(middleware)
163
+ .to receive(:increment)
164
+ .with("sidekiq.#{queue}.user_mailer_confirm_account.processed")
165
+
166
+ subject
167
+ end
168
+ end
169
+ end
170
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  RSpec.describe Sidekiq::Instrumental do
@@ -8,7 +10,8 @@ RSpec.describe Sidekiq::Instrumental do
8
10
  describe '::config' do
9
11
  describe '::config' do
10
12
  it 'should return a Configuration object' do
11
- expect(described_class.config).to be_an_instance_of(described_class::Configuration)
13
+ expect(described_class.config)
14
+ .to be_an_instance_of(described_class::Configuration)
12
15
  end
13
16
  end
14
17
  end
@@ -22,7 +25,8 @@ RSpec.describe Sidekiq::Instrumental do
22
25
  end
23
26
 
24
27
  it 'should yield the configuration object' do
25
- expect { |b| described_class.configure(&b) }.to yield_with_args(described_class.config)
28
+ expect { |b| described_class.configure(&b) }
29
+ .to yield_with_args(described_class.config)
26
30
  end
27
31
  end
28
32
 
@@ -39,8 +43,13 @@ RSpec.describe Sidekiq::Instrumental do
39
43
  allow(config).to receive(:client_middleware)
40
44
  allow(Sidekiq).to receive(:configure_server).and_yield(config)
41
45
 
42
- expect(server_chain).to receive(:remove).with(described_class::Middleware::Server)
43
- expect(server_chain).to receive(:add).with(described_class::Middleware::Server, an_instance_of(described_class::Configuration))
46
+ expect(server_chain).to receive(:remove)
47
+ .with(described_class::Middleware::Server)
48
+ expect(server_chain).to receive(:add)
49
+ .with(described_class::Middleware::Server,
50
+ an_instance_of(
51
+ described_class::Configuration
52
+ ))
44
53
 
45
54
  described_class.register
46
55
  end
@@ -52,8 +61,13 @@ RSpec.describe Sidekiq::Instrumental do
52
61
  allow(config).to receive(:client_middleware).and_yield(client_chain)
53
62
  allow(Sidekiq).to receive(:configure_server).and_yield(config)
54
63
 
55
- expect(client_chain).to receive(:remove).with(described_class::Middleware::Client)
56
- expect(client_chain).to receive(:add).with(described_class::Middleware::Client, an_instance_of(described_class::Configuration))
64
+ expect(client_chain).to receive(:remove)
65
+ .with(described_class::Middleware::Client)
66
+ expect(client_chain).to receive(:add)
67
+ .with(described_class::Middleware::Client,
68
+ an_instance_of(
69
+ described_class::Configuration
70
+ ))
57
71
 
58
72
  described_class.register
59
73
  end
@@ -66,8 +80,13 @@ RSpec.describe Sidekiq::Instrumental do
66
80
  allow(config).to receive(:client_middleware).and_yield(client_chain)
67
81
  allow(Sidekiq).to receive(:configure_client).and_yield(config)
68
82
 
69
- expect(client_chain).to receive(:remove).with(described_class::Middleware::Client)
70
- expect(client_chain).to receive(:add).with(described_class::Middleware::Client, an_instance_of(described_class::Configuration))
83
+ expect(client_chain).to receive(:remove)
84
+ .with(described_class::Middleware::Client)
85
+ expect(client_chain).to receive(:add)
86
+ .with(described_class::Middleware::Client,
87
+ an_instance_of(
88
+ described_class::Configuration
89
+ ))
71
90
 
72
91
  described_class.register
73
92
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,11 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
2
4
  require 'simplecov'
3
5
  require 'sidekiq/instrumental'
6
+ require 'timecop'
7
+
8
+ Timecop.safe_mode = true
4
9
 
5
10
  RSpec.configure do |config|
6
11
  config.expect_with :rspec do |expectations|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-instrumental
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edward Rudd
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-29 00:00:00.000000000 Z
11
+ date: 2022-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: instrumental_agent
@@ -30,28 +30,62 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '3.5'
33
+ version: '4.0'
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '6.0'
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
41
  - - ">="
39
42
  - !ruby/object:Gem::Version
40
- version: '3.5'
43
+ version: '4.0'
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '6.0'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: bundler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rake
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '10.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '10.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
43
77
  requirement: !ruby/object:Gem::Requirement
44
78
  requirements:
45
79
  - - "~>"
46
80
  - !ruby/object:Gem::Version
47
- version: '1.9'
81
+ version: '3.4'
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.9'
88
+ version: '3.4'
55
89
  - !ruby/object:Gem::Dependency
56
90
  name: simplecov
57
91
  requirement: !ruby/object:Gem::Requirement
@@ -67,50 +101,72 @@ dependencies:
67
101
  - !ruby/object:Gem::Version
68
102
  version: '0.11'
69
103
  - !ruby/object:Gem::Dependency
70
- name: rake
104
+ name: timecop
71
105
  requirement: !ruby/object:Gem::Requirement
72
106
  requirements:
73
107
  - - "~>"
74
108
  - !ruby/object:Gem::Version
75
- version: '10.0'
109
+ version: 0.9.1
76
110
  type: :development
77
111
  prerelease: false
78
112
  version_requirements: !ruby/object:Gem::Requirement
79
113
  requirements:
80
114
  - - "~>"
81
115
  - !ruby/object:Gem::Version
82
- version: '10.0'
116
+ version: 0.9.1
83
117
  - !ruby/object:Gem::Dependency
84
- name: rspec
118
+ name: rubocop
85
119
  requirement: !ruby/object:Gem::Requirement
86
120
  requirements:
87
121
  - - "~>"
88
122
  - !ruby/object:Gem::Version
89
- version: '3.4'
123
+ version: 0.79.0
90
124
  type: :development
91
125
  prerelease: false
92
126
  version_requirements: !ruby/object:Gem::Requirement
93
127
  requirements:
94
128
  - - "~>"
95
129
  - !ruby/object:Gem::Version
96
- version: '3.4'
97
- description:
130
+ version: 0.79.0
131
+ - !ruby/object:Gem::Dependency
132
+ name: rubocop-rspec
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 1.37.1
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: 1.37.1
145
+ description:
98
146
  email:
99
147
  - urkle@outoforder.cc
100
148
  executables: []
101
149
  extensions: []
102
150
  extra_rdoc_files: []
103
151
  files:
152
+ - ".github/PULL_REQUEST_TEMPLATE.md"
153
+ - ".github/workflows/prs.yml"
104
154
  - ".gitignore"
105
155
  - ".rspec"
156
+ - ".rubocop.yml"
106
157
  - ".simplecov"
158
+ - CHANGELOG.md
107
159
  - Gemfile
108
160
  - LICENSE.txt
109
161
  - README.md
110
162
  - Rakefile
111
163
  - bin/console
112
164
  - bin/setup
113
- - circle.yml
165
+ - bin/setup-rubygems.sh
166
+ - bin/tag_check.sh
167
+ - gemfiles/Gemfile.base
168
+ - gemfiles/Gemfile.sidekiq4
169
+ - gemfiles/Gemfile.sidekiq5
114
170
  - lib/sidekiq/instrumental.rb
115
171
  - lib/sidekiq/instrumental/configuration.rb
116
172
  - lib/sidekiq/instrumental/middleware/base.rb
@@ -119,13 +175,15 @@ files:
119
175
  - lib/sidekiq/instrumental/version.rb
120
176
  - sidekiq-instrumental.gemspec
121
177
  - spec/sidekiq/instrumental/configuration_spec.rb
178
+ - spec/sidekiq/instrumental/middleware/client_spec.rb
179
+ - spec/sidekiq/instrumental/middleware/server_spec.rb
122
180
  - spec/sidekiq/instrumental_spec.rb
123
181
  - spec/spec_helper.rb
124
182
  homepage: https://github.com/NetsoftHoldings/sidekiq-instrumental/
125
183
  licenses:
126
184
  - MIT
127
185
  metadata: {}
128
- post_install_message:
186
+ post_install_message:
129
187
  rdoc_options: []
130
188
  require_paths:
131
189
  - lib
@@ -133,19 +191,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
191
  requirements:
134
192
  - - ">="
135
193
  - !ruby/object:Gem::Version
136
- version: '0'
194
+ version: '2.3'
137
195
  required_rubygems_version: !ruby/object:Gem::Requirement
138
196
  requirements:
139
197
  - - ">="
140
198
  - !ruby/object:Gem::Version
141
199
  version: '0'
142
200
  requirements: []
143
- rubyforge_project:
144
- rubygems_version: 2.4.8
145
- signing_key:
201
+ rubygems_version: 3.1.6
202
+ signing_key:
146
203
  specification_version: 4
147
204
  summary: Send Sidekiq status into Instrumental after every job
148
205
  test_files:
149
- - spec/sidekiq/instrumental/configuration_spec.rb
150
- - spec/sidekiq/instrumental_spec.rb
151
206
  - spec/spec_helper.rb
207
+ - spec/sidekiq/instrumental_spec.rb
208
+ - spec/sidekiq/instrumental/middleware/client_spec.rb
209
+ - spec/sidekiq/instrumental/middleware/server_spec.rb
210
+ - spec/sidekiq/instrumental/configuration_spec.rb
data/circle.yml DELETED
@@ -1,17 +0,0 @@
1
- machine:
2
- ruby:
3
- version: 2.2.5
4
- dependencies:
5
- post:
6
- - gem install geminabox
7
- test:
8
- post:
9
- - gem build sidekiq-instrumental.gemspec
10
- - rm -rf pkg
11
- - mkdir -p pkg
12
- - mv *.gem pkg
13
- deployment:
14
- release:
15
- tag: /v[0-9]+(\.[0-9]+)+/
16
- commands:
17
- - gem inabox -g ${HUBSTAFF_GEM_SERVER}