nexia_worker_roulette 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/worker_roulette/batch_size.rb +18 -0
- data/lib/worker_roulette/monkey_patches.rb +9 -0
- data/lib/worker_roulette/queue_depth.rb +15 -0
- data/lib/worker_roulette/queue_latency.rb +32 -0
- data/lib/worker_roulette/queue_metric_tracker.rb +71 -0
- data/lib/worker_roulette/stat_calculator.rb +24 -0
- data/lib/worker_roulette/tradesman.rb +2 -0
- data/lib/worker_roulette/version.rb +1 -1
- data/lib/worker_roulette.rb +7 -10
- data/spec/integration/evented_worker_roulette_spec.rb +4 -4
- data/spec/integration/worker_roulette_spec.rb +5 -5
- data/spec/unit/{queue_latency_tracker_spec.rb → queue_latency_spec.rb} +9 -25
- data/spec/unit/queue_metric_tracker_spec.rb +71 -0
- data/spec/unit/readlock_spec.rb +4 -4
- data/spec/unit/stat_calculator_spec.rb +32 -0
- metadata +15 -6
- data/lib/worker_roulette/queue_latency_tracker.rb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53d36e15910ce2db5cd63152496ee34dfa5c9b0f
|
4
|
+
data.tar.gz: 28376e7730e8e6fbe960f53a9936897307bc1bc8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aef9594153c398471a13a261e673a442d085c670c3782a17c673112ec4ffbfe55cf309fbfce5e746af8a66bbdb8ed629e71ca836d1fb160f6cc9b49b1088761e
|
7
|
+
data.tar.gz: 79cfc9c99a374508c56b2783d180f170671723530eccea31f6de1a8bd8dc7e19160e6b87dd1708b8eb3b68e96e03f32df40d9efa7d8052ca6e5a79ee21e0ec8f
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "queue_metric_tracker"
|
2
|
+
|
3
|
+
module WorkerRoulette
|
4
|
+
class BatchSize
|
5
|
+
include ::QueueMetricTracker
|
6
|
+
|
7
|
+
def track(sender, work_orders, _remaining)
|
8
|
+
return unless enabled?
|
9
|
+
|
10
|
+
batch_size = work_orders.length
|
11
|
+
return if batch_size == 0
|
12
|
+
|
13
|
+
if value = calculate_stats(:batch_size, batch_size)
|
14
|
+
tracker_send(message("batch_size", channel(sender), value))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative "queue_metric_tracker"
|
2
|
+
|
3
|
+
module WorkerRoulette
|
4
|
+
class QueueDepth
|
5
|
+
include ::QueueMetricTracker
|
6
|
+
|
7
|
+
def track(sender, work_orders, remaining)
|
8
|
+
return unless enabled?
|
9
|
+
|
10
|
+
if value = calculate_stats(:queue_depth, remaining)
|
11
|
+
tracker_send(message("queue_depth", channel(sender), value))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module WorkerRoulette
|
2
|
+
module QueueLatency
|
3
|
+
GRANULARITY = 1_000_000
|
4
|
+
|
5
|
+
class Foreman
|
6
|
+
def process(work_order, _channel)
|
7
|
+
work_order['headers'].merge!(
|
8
|
+
"queued_at" => (Time.now.to_f * GRANULARITY).to_i) if work_order.is_a?(Hash) && work_order["headers"]
|
9
|
+
work_order
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Tradesman
|
14
|
+
include QueueMetricTracker
|
15
|
+
|
16
|
+
def process(work_order, channel)
|
17
|
+
send_latency(work_order["headers"]["queued_at"], channel)
|
18
|
+
work_order
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_latency(queued_at, channel)
|
22
|
+
return unless queued_at
|
23
|
+
|
24
|
+
latency_ns = (Time.now.to_f * GRANULARITY).to_i - queued_at
|
25
|
+
|
26
|
+
if value = calculate_stats(:queue_latency, latency_ns / 1000.0)
|
27
|
+
tracker_send(message("queue_latency(ms)", channel, value))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module QueueMetricTracker
|
2
|
+
def tracker_send(msg)
|
3
|
+
UDPSocket.new.send(msg, 0, config[:metric_host][:host_ip], config[:metric_host][:host_port])
|
4
|
+
end
|
5
|
+
|
6
|
+
def granularity
|
7
|
+
config[:granularity] || 100
|
8
|
+
end
|
9
|
+
|
10
|
+
def calculate_stats(stat_name, value)
|
11
|
+
calculator(stat_name).add(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def calculator(stat_name)
|
15
|
+
QueueMetricTracker.calculators[stat_name] ||= QueueMetricTracker::StatCalculator.new(granularity)
|
16
|
+
end
|
17
|
+
|
18
|
+
def channel(sender)
|
19
|
+
(sender.split ":").first
|
20
|
+
end
|
21
|
+
|
22
|
+
def config
|
23
|
+
QueueMetricTracker.config
|
24
|
+
end
|
25
|
+
|
26
|
+
def message(label, channel, value)
|
27
|
+
"#{label},server_name=#{config[:server_name]},channel=#{channel} value=#{value} #{(Time.now.to_f * 1_000_000_000).to_i}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def enabled?
|
31
|
+
return false unless config && config[:metrics]
|
32
|
+
|
33
|
+
klass = self.class.to_s.split("::").last.underscore.to_sym
|
34
|
+
config[:metrics][klass] rescue false
|
35
|
+
end
|
36
|
+
|
37
|
+
class << self
|
38
|
+
attr_reader :config, :calculators
|
39
|
+
def configure(options)
|
40
|
+
@calculators = {}
|
41
|
+
@config = {
|
42
|
+
server_name: options[:server_name],
|
43
|
+
granularity: options[:granularity],
|
44
|
+
metric_host: {
|
45
|
+
host_ip: ip_address(options[:metric_host]),
|
46
|
+
host_port: options[:metric_host_port]
|
47
|
+
}
|
48
|
+
}
|
49
|
+
@config.merge!({
|
50
|
+
metrics: options[:metrics]
|
51
|
+
}) if options[:metrics]
|
52
|
+
end
|
53
|
+
|
54
|
+
def included(tracker)
|
55
|
+
@trackers ||= []
|
56
|
+
@trackers << tracker
|
57
|
+
end
|
58
|
+
|
59
|
+
def track_all(options)
|
60
|
+
@trackers.each do |tracker_class|
|
61
|
+
tracker = tracker_class.new
|
62
|
+
tracker.track(*options) if tracker.respond_to?(:track)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def ip_address(server_name)
|
67
|
+
server_name == "localhost" ? "127.0.0.1" : Resolv.new.getaddress(server_name).to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module QueueMetricTracker
|
2
|
+
class StatCalculator
|
3
|
+
attr_accessor :count, :sum, :granularity
|
4
|
+
|
5
|
+
def initialize(granularity = 100)
|
6
|
+
@granularity = granularity
|
7
|
+
@sum = 0
|
8
|
+
@count = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(value)
|
12
|
+
@sum += value
|
13
|
+
@count += 1
|
14
|
+
|
15
|
+
if @count == granularity
|
16
|
+
value = @sum / granularity
|
17
|
+
@sum = @count = 0
|
18
|
+
return value
|
19
|
+
end
|
20
|
+
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -134,6 +134,8 @@ module WorkerRoulette
|
|
134
134
|
work_orders = results[1]
|
135
135
|
@remaining_jobs = results[2]
|
136
136
|
@last_sender = sender_key.split(':').last
|
137
|
+
|
138
|
+
QueueMetricTracker.track_all(results) if work_orders.any?
|
137
139
|
work = work_orders.map { |wo| preprocess(WorkerRoulette.load(wo), channel) }
|
138
140
|
callback.call work if callback
|
139
141
|
work
|
data/lib/worker_roulette.rb
CHANGED
@@ -67,21 +67,22 @@ module WorkerRoulette
|
|
67
67
|
|
68
68
|
@preprocessors = []
|
69
69
|
|
70
|
-
|
70
|
+
configure_queue_tracker(config.delete(:metric_tracker))
|
71
71
|
end
|
72
72
|
|
73
|
-
def
|
73
|
+
def configure_queue_tracker(config)
|
74
74
|
return unless config
|
75
75
|
|
76
|
-
|
76
|
+
QueueMetricTracker.configure(
|
77
77
|
{
|
78
78
|
server_name: `hostname`.chomp,
|
79
|
-
|
80
|
-
|
79
|
+
metric_host: config[:metric_host],
|
80
|
+
metric_host_port: config[:metric_host_port],
|
81
|
+
metrics: config[:metrics]
|
81
82
|
}
|
82
83
|
)
|
83
84
|
|
84
|
-
preprocessors <<
|
85
|
+
preprocessors << QueueLatency
|
85
86
|
end
|
86
87
|
|
87
88
|
def foreman(sender, namespace = nil)
|
@@ -112,10 +113,6 @@ module WorkerRoulette
|
|
112
113
|
|
113
114
|
private
|
114
115
|
|
115
|
-
def ip_address(server_name)
|
116
|
-
server_name == "localhost" ? "127.0.0.1" : Resolv::DNS.new.getaddress(server_name).to_s
|
117
|
-
end
|
118
|
-
|
119
116
|
def new_redis
|
120
117
|
if @evented
|
121
118
|
require 'eventmachine'
|
@@ -12,13 +12,13 @@ module WorkerRoulette
|
|
12
12
|
let(:foreman_work_order) { Hash["payload" => "foreman"] }
|
13
13
|
let(:work_orders_with_headers) { default_headers.merge({ "payload" => work_orders }) }
|
14
14
|
let(:jsonized_work_orders_with_headers) { [WorkerRoulette.dump(work_orders_with_headers)] }
|
15
|
-
let(:
|
15
|
+
let(:metric_tracker) {
|
16
16
|
{
|
17
|
-
|
18
|
-
|
17
|
+
metric_host: "localhost",
|
18
|
+
metric_host_port: 7777
|
19
19
|
}
|
20
20
|
}
|
21
|
-
let(:worker_roulette) { WorkerRoulette.start(evented: true,
|
21
|
+
let(:worker_roulette) { WorkerRoulette.start(evented: true, metric_tracker: metric_tracker) }
|
22
22
|
let(:redis) { Redis.new(worker_roulette.redis_config) }
|
23
23
|
|
24
24
|
before do
|
@@ -14,8 +14,8 @@ module WorkerRoulette
|
|
14
14
|
let(:foreman_work_order) { Hash['payload' => "foreman"] }
|
15
15
|
let(:work_orders_with_headers) { default_headers.merge({ 'payload' => work_orders }) }
|
16
16
|
let(:jsonized_work_orders_with_headers) { [WorkerRoulette.dump(work_orders_with_headers)] }
|
17
|
-
let(:worker_roulette) { WorkerRoulette.start(evented: false,
|
18
|
-
let(:
|
17
|
+
let(:worker_roulette) { WorkerRoulette.start(evented: false, metric_tracker: metric_tracker) }
|
18
|
+
let(:metric_tracker) { nil }
|
19
19
|
|
20
20
|
let(:redis) { Redis.new(worker_roulette.redis_config) }
|
21
21
|
|
@@ -153,10 +153,10 @@ module WorkerRoulette
|
|
153
153
|
context "when latency tracker is enabled" do
|
154
154
|
let(:default_headers) { Hash["headers" => { "sender" => sender, "queued_at" => (queued_at.to_f * 1_000_000).to_i }] }
|
155
155
|
let(:queued_at) { 1234567 }
|
156
|
-
let(:
|
156
|
+
let(:metric_tracker) {
|
157
157
|
{
|
158
|
-
|
159
|
-
|
158
|
+
metric_host: "localhost",
|
159
|
+
metric_host_port: 7777
|
160
160
|
}
|
161
161
|
}
|
162
162
|
|
@@ -1,25 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
module
|
4
|
-
describe ".configure" do
|
5
|
-
let(:source_config) { { logstash_server_ip: ip, logstash_port: port, server_name: server_name } }
|
6
|
-
let(:ip) { "1.2.3.4" }
|
7
|
-
let(:port) { 123 }
|
8
|
-
let(:server_name) { "server.example" }
|
9
|
-
|
10
|
-
|
11
|
-
it "stores the configuration" do
|
12
|
-
QueueLatencyTracker.configure(source_config)
|
13
|
-
|
14
|
-
expect(QueueLatencyTracker.config).to eq({
|
15
|
-
logstash: {
|
16
|
-
server_ip: ip,
|
17
|
-
port: port },
|
18
|
-
server_name: server_name
|
19
|
-
})
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
3
|
+
module WorkerRoulette::QueueLatency
|
23
4
|
describe Foreman do
|
24
5
|
describe "#process" do
|
25
6
|
let(:channel) { "a_channel" }
|
@@ -39,7 +20,7 @@ module QueueLatencyTracker
|
|
39
20
|
describe Tradesman do
|
40
21
|
describe "#process" do
|
41
22
|
let(:queued_at) { 1234567 * GRANULARITY }
|
42
|
-
let(:
|
23
|
+
let(:host) { "a_metric_host" }
|
43
24
|
let(:ip) { "1.2.3.4" }
|
44
25
|
let(:port) { 123 }
|
45
26
|
let(:latency) { 123.432 }
|
@@ -47,15 +28,18 @@ module QueueLatencyTracker
|
|
47
28
|
let(:channel) { "a_channel" }
|
48
29
|
let(:headers) { { "queued_at" => queued_at } }
|
49
30
|
let(:raw_work_order) { { "headers" => headers, "payload" => "aPayload" } }
|
50
|
-
let(:
|
51
|
-
let(:config) { {
|
31
|
+
let(:metric_config) { { host_ip: ip, host_port: port } }
|
32
|
+
let(:config) { { metric_host: metric_config, server_name: server_name } }
|
33
|
+
let(:expected_msg) { "queue_latency(ms),server_name=server.example,channel=a_channel value=123.432 1234690432000000" }
|
52
34
|
|
53
|
-
before { allow(
|
35
|
+
before { allow(QueueMetricTracker).to receive(:config).and_return(config) }
|
54
36
|
before { allow(Time).to receive(:now).and_return(queued_at / GRANULARITY + latency) }
|
55
37
|
before { allow_any_instance_of(UDPSocket).to receive(:send) }
|
38
|
+
before { allow_any_instance_of(QueueMetricTracker).to receive(:calculate_stats).and_return(latency) }
|
39
|
+
before { allow(QueueMetricTracker).to receive(:ipaddress).and_return(ip) }
|
56
40
|
|
57
41
|
it "passes the right json to logstash_send" do
|
58
|
-
expect_any_instance_of(UDPSocket).to receive(:send).with(
|
42
|
+
expect_any_instance_of(UDPSocket).to receive(:send).with(expected_msg, 0, ip, port)
|
59
43
|
|
60
44
|
subject.process(raw_work_order, channel)
|
61
45
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module QueueMetricTracker
|
4
|
+
describe QueueMetricTracker do
|
5
|
+
let(:host) { "localhost" }
|
6
|
+
let(:port) { 123 }
|
7
|
+
let(:granularity) { 3 }
|
8
|
+
let(:ip) { "1.2.3.4" }
|
9
|
+
let(:server_name) { "server.example" }
|
10
|
+
let(:source_config) { {
|
11
|
+
metric_host: host,
|
12
|
+
metric_host_port: port,
|
13
|
+
server_name: server_name,
|
14
|
+
granularity: granularity
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
describe ".configure" do
|
19
|
+
it "stores the configuration" do
|
20
|
+
allow(QueueMetricTracker).to receive(:ip_address).and_return(ip)
|
21
|
+
QueueMetricTracker.configure(source_config)
|
22
|
+
|
23
|
+
expect(QueueMetricTracker.config).to eq({
|
24
|
+
metric_host: {
|
25
|
+
host_ip: ip,
|
26
|
+
host_port: port },
|
27
|
+
server_name: server_name,
|
28
|
+
granularity: granularity
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#enabled?" do
|
34
|
+
let(:config) { {} }
|
35
|
+
subject(:metric) { WorkerRoulette::BatchSize }
|
36
|
+
subject(:metric_object) { metric.new }
|
37
|
+
|
38
|
+
before { QueueMetricTracker.configure(source_config.merge(config)) }
|
39
|
+
|
40
|
+
context "when the config is nil" do
|
41
|
+
it "returns false" do
|
42
|
+
expect(metric_object.enabled?).to be_falsey
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when the config has no metrics defined" do
|
47
|
+
let(:config) { { metrics: {}} }
|
48
|
+
|
49
|
+
it "returns false" do
|
50
|
+
expect(metric_object.enabled?).to be_falsey
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when the metric is false" do
|
55
|
+
let(:config) { { metrics: { :batch_size => false } } }
|
56
|
+
|
57
|
+
it "returns false" do
|
58
|
+
expect(metric_object.enabled?).to be_falsey
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when the metric is true" do
|
63
|
+
let(:config) { { metrics: { :batch_size => true }} }
|
64
|
+
|
65
|
+
it "returns true" do
|
66
|
+
expect(metric_object.enabled?).to be_truthy
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/spec/unit/readlock_spec.rb
CHANGED
@@ -2,13 +2,13 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
module WorkerRoulette
|
4
4
|
describe "Read Lock" do
|
5
|
-
let(:
|
5
|
+
let(:metric_tracker) {
|
6
6
|
{
|
7
|
-
|
8
|
-
|
7
|
+
metric_host: "localhost",
|
8
|
+
metric_host_port: 7777
|
9
9
|
}
|
10
10
|
}
|
11
|
-
let(:worker_roulette) { WorkerRoulette.start(evented: false,
|
11
|
+
let(:worker_roulette) { WorkerRoulette.start(evented: false, metric_tracker: metric_tracker) }
|
12
12
|
let(:redis) { Redis.new(worker_roulette.redis_config) }
|
13
13
|
let(:sender) { "katie_80" }
|
14
14
|
let(:work_orders) { "hello" }
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module QueueMetricTracker
|
4
|
+
describe StatCalculator do
|
5
|
+
let(:granularity) { 10 }
|
6
|
+
let(:default_granularity) { 100 }
|
7
|
+
subject(:calculator) { described_class }
|
8
|
+
|
9
|
+
it "responds to new with a granularity" do
|
10
|
+
expect(calculator.new(granularity).granularity).to eq(granularity)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "granularity defaults to a value" do
|
14
|
+
expect(calculator.new().granularity).to eq(default_granularity)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#add" do
|
18
|
+
let(:granularity) { 3 }
|
19
|
+
let(:value1) { 4 }
|
20
|
+
let(:value2) { 3 }
|
21
|
+
let(:value3) { 8 }
|
22
|
+
let(:average) { 5 }
|
23
|
+
subject(:calculator) { described_class.new(granularity) }
|
24
|
+
|
25
|
+
it "calculates average of N values" do
|
26
|
+
expect(subject.add(value1)).to be_nil
|
27
|
+
expect(subject.add(value2)).to be_nil
|
28
|
+
expect(subject.add(value3)).to eq(average)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nexia_worker_roulette
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Saieg
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-
|
13
|
+
date: 2015-08-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: oj
|
@@ -211,10 +211,15 @@ files:
|
|
211
211
|
- README.md
|
212
212
|
- Rakefile
|
213
213
|
- lib/worker_roulette.rb
|
214
|
+
- lib/worker_roulette/batch_size.rb
|
214
215
|
- lib/worker_roulette/foreman.rb
|
215
216
|
- lib/worker_roulette/lua.rb
|
217
|
+
- lib/worker_roulette/monkey_patches.rb
|
216
218
|
- lib/worker_roulette/preprocessor.rb
|
217
|
-
- lib/worker_roulette/
|
219
|
+
- lib/worker_roulette/queue_depth.rb
|
220
|
+
- lib/worker_roulette/queue_latency.rb
|
221
|
+
- lib/worker_roulette/queue_metric_tracker.rb
|
222
|
+
- lib/worker_roulette/stat_calculator.rb
|
218
223
|
- lib/worker_roulette/tradesman.rb
|
219
224
|
- lib/worker_roulette/version.rb
|
220
225
|
- spec/benchmark/irb_demo_runner.rb
|
@@ -226,8 +231,10 @@ files:
|
|
226
231
|
- spec/unit/evented_readlock_spec.rb
|
227
232
|
- spec/unit/lua_spec.rb
|
228
233
|
- spec/unit/preprocessor_spec.rb
|
229
|
-
- spec/unit/
|
234
|
+
- spec/unit/queue_latency_spec.rb
|
235
|
+
- spec/unit/queue_metric_tracker_spec.rb
|
230
236
|
- spec/unit/readlock_spec.rb
|
237
|
+
- spec/unit/stat_calculator_spec.rb
|
231
238
|
- worker_roulette.gemspec
|
232
239
|
homepage: https://github.com/nexiahome/worker_roulette
|
233
240
|
licenses: []
|
@@ -248,7 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
248
255
|
version: '0'
|
249
256
|
requirements: []
|
250
257
|
rubyforge_project:
|
251
|
-
rubygems_version: 2.4.
|
258
|
+
rubygems_version: 2.4.5
|
252
259
|
signing_key:
|
253
260
|
specification_version: 4
|
254
261
|
summary: Pub Sub Queue for Redis that ensures ordered processing
|
@@ -262,5 +269,7 @@ test_files:
|
|
262
269
|
- spec/unit/evented_readlock_spec.rb
|
263
270
|
- spec/unit/lua_spec.rb
|
264
271
|
- spec/unit/preprocessor_spec.rb
|
265
|
-
- spec/unit/
|
272
|
+
- spec/unit/queue_latency_spec.rb
|
273
|
+
- spec/unit/queue_metric_tracker_spec.rb
|
266
274
|
- spec/unit/readlock_spec.rb
|
275
|
+
- spec/unit/stat_calculator_spec.rb
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module QueueLatencyTracker
|
2
|
-
GRANULARITY = 1_000_000
|
3
|
-
|
4
|
-
class Foreman
|
5
|
-
def process(work_order, _channel)
|
6
|
-
work_order['headers'].merge!(
|
7
|
-
"queued_at" => (Time.now.to_f * GRANULARITY).to_i) if work_order.is_a?(Hash) && work_order["headers"]
|
8
|
-
work_order
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class Tradesman
|
13
|
-
def process(work_order, channel)
|
14
|
-
send_latency(work_order["headers"]["queued_at"], channel)
|
15
|
-
work_order
|
16
|
-
end
|
17
|
-
|
18
|
-
def send_latency(queued_at, channel)
|
19
|
-
latency_ns = (Time.now.to_f * GRANULARITY).to_i - queued_at
|
20
|
-
logstash_send(latency_json(latency_ns / 1000.0, channel))
|
21
|
-
end
|
22
|
-
|
23
|
-
def logstash_send(json)
|
24
|
-
UDPSocket.new.send(json, 0, config[:logstash][:server_ip], config[:logstash][:port])
|
25
|
-
end
|
26
|
-
|
27
|
-
def latency_json(latency_ms, channel)
|
28
|
-
%({"server_name":"#{config[:server_name]}","queue_latency (ms)":#{latency_ms},"channel":"#{channel}"})
|
29
|
-
end
|
30
|
-
|
31
|
-
def config
|
32
|
-
QueueLatencyTracker.config
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
class << self
|
37
|
-
attr_reader :config
|
38
|
-
def configure(config)
|
39
|
-
@config = {
|
40
|
-
logstash: {
|
41
|
-
server_ip: config[:logstash_server_ip],
|
42
|
-
port: config[:logstash_port] },
|
43
|
-
server_name: config[:server_name]
|
44
|
-
}
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|