statue 0.3.0 → 0.4.0

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
  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: