statue 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4babeecc571be33fbda04a81c3eabc6455368aff
4
- data.tar.gz: 6bced52052f52e3611df23562825e570a548d1d1
3
+ metadata.gz: c1e8d8ac15844fcc7be73f711dbef4dd68f674f4
4
+ data.tar.gz: bb8f101f7b34197ef55c1ae9a1b796117fe73948
5
5
  SHA512:
6
- metadata.gz: b73f850044ca23086c8f837fc3f969d94121390139292ab94ac28956a686567e27784b066ad000151629ba0f76492746dc127cb310f84a95609b5f8fe9f70087
7
- data.tar.gz: bde0b2df82abc4ccc570bd87254cb176c435dbb3799cc24484622a502134b48351806be9ae3333e43b77d52940faddae1265d5c889543b56017948853d7024ad
6
+ metadata.gz: df3750b4897fa143ec1f3c7eebf519e5f2d9fe698979843b3ec400d353dd5d85e2fcd5587af94d38bce454bfd1fae166e3e3234c5a7ae74465a7a22d19456b44
7
+ data.tar.gz: d91000f02e854e6619666adfa9ea12c04685bc32463c8a7ebc694ce5722a95c310bafc95b310175b37a0d98b8f28a5c86fcd5f42618eb653f650dcfe2182af08
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.2.0
5
+ - 2.1.6
6
+ - jruby-9.1.8.0
7
+ bundler_args: --binstubs
8
+ script: bin/rake test
data/CHANGELOG.md CHANGED
@@ -1,4 +1,17 @@
1
- ## [0.3.0] - Unreleased
1
+ ## [0.4.0] - 2017-03-13
2
+
3
+ ### Feature
4
+
5
+ - Added `SidekiqStatistics` middleware support
6
+ - To integrate it with your middleware, just add it to your sidekiq's initializer like follows:
7
+
8
+ ```ruby
9
+ config.server_middleware do |chain|
10
+ chain.add Statue::SidekiqStatistics::SidekiqMiddleware
11
+ end
12
+ ```
13
+
14
+ ## [0.3.0] - 2017-03-13
2
15
 
3
16
  ### Feature
4
17
 
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Statue
2
2
 
3
+ ![Build Status](https://travis-ci.org/restorando/statue.svg?branch=master)
4
+
3
5
  / ___)(_ _)/ _\(_ _)/ )( \( __)
4
6
  \___ \ )( / \ )( ) \/ ( ) _)
5
7
  (____/ (__)\_/\_/(__) \____/(____)
data/bin/rake CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  #
3
5
  # This file was generated by Bundler.
4
6
  #
@@ -6,11 +8,22 @@
6
8
  # this file is here to facilitate running it.
7
9
  #
8
10
 
9
- require 'pathname'
10
- ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
13
  Pathname.new(__FILE__).realpath)
12
14
 
13
- require 'rubygems'
14
- require 'bundler/setup'
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
15
28
 
16
- load Gem.bin_path('rake', 'rake')
29
+ load Gem.bin_path("rake", "rake")
@@ -0,0 +1,73 @@
1
+ require 'statue'
2
+
3
+ module Statue
4
+ # This module simplifies the job statistics tracking using Statue
5
+ # * Provides a SidekiqMiddleware (to track performance and latency)
6
+ # * Provides a method for tracking other middleware events (eg. throttling, deadline)
7
+ #
8
+ # The current set of metrics are:
9
+ #
10
+ # * count job.<queue>.<job_name>.(success|failure):
11
+ # depending if the job succeeded or failed
12
+ # * count job.<queue>.<job_name>.throttled:
13
+ # only if the job was throttled by sidekiq-throttler
14
+ # * count job.<queue>.<job_name>.overdue:
15
+ # only if the deadline from run_deadline_middleware was reached
16
+ # * count job.<queue>.<job_name>.retry:
17
+ # only if the job corresponds to a retry for a previously failed job
18
+ # * duration job.<queue>.<job_name>.latency:
19
+ # time difference between now and when the job last entered the queue
20
+ # * duration job.<queue>.<job_name>:
21
+ # job run duration (reported only if the job doesn't fail)
22
+ module SidekiqStatistics
23
+ def self.count_event(event, worker, message)
24
+ Statue.report_increment("#{job_metric_name(worker, message)}.#{event}")
25
+ end
26
+
27
+ def self.job_metric_name(worker, message)
28
+ job_name = if worker.respond_to?(:job_name)
29
+ worker.job_name(*message["args"])
30
+ elsif message.dig("args", 0, "job_class")
31
+ # search for the class name that resides in the message received
32
+ message.dig("args", 0, "job_class")
33
+ else
34
+ worker.class.name.gsub(/::/, "-")
35
+ end
36
+ "job.#{message["queue"]}.#{job_name}"
37
+ end
38
+
39
+ # Middleware for tracking common job run metrics
40
+ class SidekiqMiddleware
41
+ def call(worker, message, _queue)
42
+ job_metric_name = Statue::SidekiqStatistics.job_metric_name(worker, message)
43
+
44
+ if message["retry_count"]
45
+ # Count retried jobs
46
+ Statue.report_increment("#{job_metric_name}.retry")
47
+ else
48
+ # Track latency for new jobs only (we can't know since when the failed job is waiting)
49
+ enqueued_at = Time.at(message["enqueued_at"])
50
+ Statue.report_duration("#{job_metric_name}.latency", Time.now - enqueued_at)
51
+ end
52
+
53
+ Statue.report_duration(job_metric_name) do
54
+ Statue.report_success_or_failure(job_metric_name) do
55
+ yield
56
+ true # We only count exceptions as failure
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ # This module is prepended in sidekiq-throttler rate_limit class
63
+ # Wraps the exceeded block with a block that also counts the job as beeing throttled
64
+ module ThrottlingExceeded
65
+ def exceeded(&block)
66
+ super do |*args|
67
+ yield(*args)
68
+ Statue::SidekiqStatistics.count_event("throttled", worker, "queue" => queue, "args" => payload)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -1,3 +1,3 @@
1
1
  module Statue
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
data/statue.gemspec CHANGED
@@ -22,4 +22,5 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "rack", "~> 1.6"
23
23
  spec.add_development_dependency "rack-test", "~> 0.6.3"
24
24
  spec.add_development_dependency "minitest"
25
+ spec.add_development_dependency "sidekiq", "~> 3.2"
25
26
  end
@@ -0,0 +1,89 @@
1
+ require 'test_helper'
2
+ require 'statue/sidekiq_statistics'
3
+ require 'sidekiq/testing'
4
+
5
+ describe Statue::SidekiqStatistics do
6
+ let(:metrics) { Statue.backend.captures }
7
+
8
+ Sidekiq::Testing.inline!
9
+
10
+ after do
11
+ Statue.backend.captures.clear
12
+ end
13
+
14
+ class FooJob
15
+ include Sidekiq::Worker
16
+
17
+ def job_name(*_args)
18
+ self.class.name.gsub(/::/, "-")
19
+ end
20
+
21
+ attr_accessor :should_fail
22
+
23
+ def perform
24
+ raise "fail" if should_fail
25
+ end
26
+ end
27
+
28
+ it "allows arbitrary event counting" do
29
+ Statue::SidekiqStatistics.count_event("test", FooJob.new, "queue" => "queue")
30
+
31
+ assert_equal(metrics.size, 1)
32
+ assert_equal(metrics.first.name, "job.queue.FooJob.test")
33
+ assert_equal(metrics.first.type, :c)
34
+ end
35
+
36
+ describe "Sidekiq Middleware" do
37
+ let(:worker) { FooJob.new }
38
+ let(:middleware) { Statue::SidekiqStatistics::SidekiqMiddleware.new }
39
+ let(:msg) { { "enqueued_at" => Time.now.to_f, "queue" => "default" } }
40
+
41
+ it "tracks job performance" do
42
+ Statue::Clock.stub :duration_in_ms, 5 do
43
+ middleware.call(worker, msg, msg["queue"]) { nil }
44
+
45
+ performance = metrics.find { |m| m.name == "job.default.FooJob" }
46
+ assert_equal(performance.type, :ms)
47
+ assert_equal(performance.value, 5)
48
+ end
49
+ end
50
+
51
+ it "counts block call always as a success" do
52
+ middleware.call(worker, msg, msg["queue"]) { false }
53
+
54
+ success = metrics.find { |m| m.name == "job.default.FooJob.success" }
55
+ assert_equal(success.type, :c)
56
+ end
57
+
58
+ it "counts exceptions as job failure" do
59
+ assert_raises("a") {
60
+ middleware.call(worker, msg, msg["queue"]) { raise "a" }
61
+ }
62
+
63
+ success = metrics.find { |m| m.name == "job.default.FooJob.success" }
64
+ assert_nil(success)
65
+
66
+ failure = metrics.find { |m| m.name == "job.default.FooJob.failure" }
67
+ assert_equal(failure.type, :c)
68
+ end
69
+
70
+ it "counts retries as job failure" do
71
+ msg["retry_count"] = 1
72
+ middleware.call(worker, msg, msg["queue"]) { true }
73
+
74
+ retry_metric = metrics.find { |m| m.name == "job.default.FooJob.retry" }
75
+ assert_equal(retry_metric.type, :c)
76
+ end
77
+
78
+ it "tracks queue latency" do
79
+ # Time.now - 1 minute
80
+ msg["enqueued_at"] = Time.now - 60
81
+
82
+ middleware.call(worker, msg, msg["queue"]) { nil }
83
+
84
+ latency = metrics.find { |m| m.name == "job.default.FooJob.latency" }
85
+ assert_equal(latency.type, :ms)
86
+ assert_in_delta(latency.value, 60, delta = 0.001)
87
+ end
88
+ end
89
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Barreneche
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-13 00:00:00.000000000 Z
11
+ date: 2018-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sidekiq
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.2'
83
97
  description: Track application metrics to Statsie
84
98
  email:
85
99
  - devs@restorando.com
@@ -88,6 +102,7 @@ extensions: []
88
102
  extra_rdoc_files: []
89
103
  files:
90
104
  - ".gitignore"
105
+ - ".travis.yml"
91
106
  - CHANGELOG.md
92
107
  - Gemfile
93
108
  - LICENSE.txt
@@ -103,10 +118,12 @@ files:
103
118
  - lib/statue/clock.rb
104
119
  - lib/statue/metric.rb
105
120
  - lib/statue/rack_statistics.rb
121
+ - lib/statue/sidekiq_statistics.rb
106
122
  - lib/statue/stopwatch.rb
107
123
  - lib/statue/version.rb
108
124
  - statue.gemspec
109
125
  - test/rack_statistics_test.rb
126
+ - test/sidekiq_statistics_test.rb
110
127
  - test/statue_test.rb
111
128
  - test/stopwatch_test.rb
112
129
  - test/test_helper.rb
@@ -130,13 +147,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
147
  version: '0'
131
148
  requirements: []
132
149
  rubyforge_project:
133
- rubygems_version: 2.5.2
150
+ rubygems_version: 2.4.5
134
151
  signing_key:
135
152
  specification_version: 4
136
153
  summary: Easily track application metrics into Statsie
137
154
  test_files:
138
155
  - test/rack_statistics_test.rb
156
+ - test/sidekiq_statistics_test.rb
139
157
  - test/statue_test.rb
140
158
  - test/stopwatch_test.rb
141
159
  - test/test_helper.rb
142
- has_rdoc: