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 +4 -4
- data/.travis.yml +8 -0
- data/CHANGELOG.md +14 -1
- data/README.md +2 -0
- data/bin/rake +18 -5
- data/lib/statue/sidekiq_statistics.rb +73 -0
- data/lib/statue/version.rb +1 -1
- data/statue.gemspec +1 -0
- data/test/sidekiq_statistics_test.rb +89 -0
- metadata +21 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1e8d8ac15844fcc7be73f711dbef4dd68f674f4
|
4
|
+
data.tar.gz: bb8f101f7b34197ef55c1ae9a1b796117fe73948
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df3750b4897fa143ec1f3c7eebf519e5f2d9fe698979843b3ec400d353dd5d85e2fcd5587af94d38bce454bfd1fae166e3e3234c5a7ae74465a7a22d19456b44
|
7
|
+
data.tar.gz: d91000f02e854e6619666adfa9ea12c04685bc32463c8a7ebc694ce5722a95c310bafc95b310175b37a0d98b8f28a5c86fcd5f42618eb653f650dcfe2182af08
|
data/.travis.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,17 @@
|
|
1
|
-
## [0.
|
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
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
|
10
|
-
ENV[
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
11
13
|
Pathname.new(__FILE__).realpath)
|
12
14
|
|
13
|
-
|
14
|
-
|
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(
|
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
|
data/lib/statue/version.rb
CHANGED
data/statue.gemspec
CHANGED
@@ -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.
|
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:
|
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
|
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:
|