librato-metrics 1.6.2 → 2.0.0.beta
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 +13 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -0
- data/.rspec +2 -1
- data/.travis.yml +2 -3
- data/CHANGELOG.md +6 -2
- data/Gemfile +3 -2
- data/README.md +33 -33
- data/Rakefile +3 -4
- data/certs/librato-public.pem +18 -18
- data/examples/simple.rb +5 -5
- data/lib/librato/metrics.rb +9 -12
- data/lib/librato/metrics/aggregator.rb +6 -6
- data/lib/librato/metrics/annotator.rb +11 -11
- data/lib/librato/metrics/client.rb +24 -91
- data/lib/librato/metrics/connection.rb +2 -2
- data/lib/librato/metrics/middleware/retry.rb +1 -1
- data/lib/librato/metrics/processor.rb +3 -3
- data/lib/librato/metrics/queue.rb +1 -1
- data/lib/librato/metrics/smart_json.rb +27 -16
- data/lib/librato/metrics/version.rb +1 -1
- data/librato-metrics.gemspec +2 -2
- data/spec/integration/metrics/annotator_spec.rb +73 -73
- data/spec/integration/metrics/middleware/count_requests_spec.rb +8 -8
- data/spec/integration/metrics/queue_spec.rb +28 -28
- data/spec/integration/metrics_spec.rb +137 -137
- data/spec/spec_helper.rb +6 -10
- data/spec/unit/metrics/aggregator_spec.rb +130 -130
- data/spec/unit/metrics/client_spec.rb +37 -37
- data/spec/unit/metrics/connection_spec.rb +30 -30
- data/spec/unit/metrics/queue/autosubmission_spec.rb +25 -25
- data/spec/unit/metrics/queue_spec.rb +178 -179
- data/spec/unit/metrics/smart_json_spec.rb +79 -0
- data/spec/unit/metrics_spec.rb +21 -21
- metadata +48 -42
- metadata.gz.sig +0 -0
- data/spec/integration/deprecated_methods_spec.rb +0 -85
@@ -7,42 +7,42 @@ module Librato
|
|
7
7
|
|
8
8
|
describe "#api_endpoint" do
|
9
9
|
context "when not provided" do
|
10
|
-
it "
|
11
|
-
subject.api_endpoint.
|
10
|
+
it "uses default" do
|
11
|
+
expect(subject.api_endpoint).to eq('https://metrics-api.librato.com')
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
context "when provided" do
|
16
|
-
it "
|
17
|
-
connection = Connection.new(:
|
18
|
-
connection.api_endpoint.
|
16
|
+
it "uses provided endpoint" do
|
17
|
+
connection = Connection.new(api_endpoint: 'http://test.com/')
|
18
|
+
expect(connection.api_endpoint).to eq('http://test.com/')
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
describe "#user_agent" do
|
24
24
|
context "without an agent_identifier" do
|
25
|
-
it "
|
26
|
-
connection = Connection.new(:
|
27
|
-
connection.user_agent.
|
25
|
+
it "renders standard string" do
|
26
|
+
connection = Connection.new(client: Client.new)
|
27
|
+
expect(connection.user_agent).to start_with('librato-metrics')
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
context "with an agent_identifier" do
|
32
|
-
it "
|
32
|
+
it "renders agent_identifier first" do
|
33
33
|
client = Client.new
|
34
34
|
client.agent_identifier('foo', '0.5', 'bar')
|
35
|
-
connection = Connection.new(:
|
36
|
-
connection.user_agent.
|
35
|
+
connection = Connection.new(client: client)
|
36
|
+
expect(connection.user_agent).to start_with('foo/0.5')
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
40
|
context "with a custom user agent set" do
|
41
|
-
it "
|
41
|
+
it "uses custom user agent" do
|
42
42
|
client = Client.new
|
43
43
|
client.custom_user_agent = 'foo agent'
|
44
|
-
connection = Connection.new(:
|
45
|
-
connection.user_agent.
|
44
|
+
connection = Connection.new(client: client)
|
45
|
+
expect(connection.user_agent).to eq('foo agent')
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -51,8 +51,8 @@ module Librato
|
|
51
51
|
|
52
52
|
describe "network operations" do
|
53
53
|
context "when missing client" do
|
54
|
-
it "
|
55
|
-
|
54
|
+
it "raises exception" do
|
55
|
+
expect { subject.get 'metrics' }.to raise_error(NoClientProvided)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -64,32 +64,32 @@ module Librato
|
|
64
64
|
end
|
65
65
|
|
66
66
|
context "with 400 class errors" do
|
67
|
-
it "
|
67
|
+
it "does not retry" do
|
68
68
|
Middleware::CountRequests.reset
|
69
69
|
with_rackup('status.ru') do
|
70
|
-
|
70
|
+
expect {
|
71
71
|
client.connection.transport.post 'not_found'
|
72
|
-
}.
|
73
|
-
|
72
|
+
}.to raise_error(NotFound)
|
73
|
+
expect {
|
74
74
|
client.connection.transport.post 'forbidden'
|
75
|
-
}.
|
75
|
+
}.to raise_error(ClientError)
|
76
76
|
end
|
77
|
-
Middleware::CountRequests.total_requests.
|
77
|
+
expect(Middleware::CountRequests.total_requests).to eq(2) # no retries
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
81
|
context "with 500 class errors" do
|
82
|
-
it "
|
82
|
+
it "retries" do
|
83
83
|
Middleware::CountRequests.reset
|
84
84
|
with_rackup('status.ru') do
|
85
|
-
|
85
|
+
expect {
|
86
86
|
client.connection.transport.post 'service_unavailable'
|
87
|
-
}.
|
87
|
+
}.to raise_error(ServerError)
|
88
88
|
end
|
89
|
-
Middleware::CountRequests.total_requests.
|
89
|
+
expect(Middleware::CountRequests.total_requests).to eq(4) # did retries
|
90
90
|
end
|
91
91
|
|
92
|
-
it "
|
92
|
+
it "sends consistent body with retries" do
|
93
93
|
Middleware::CountRequests.reset
|
94
94
|
status = 0
|
95
95
|
begin
|
@@ -102,12 +102,12 @@ module Librato
|
|
102
102
|
rescue Exception => error
|
103
103
|
status = error.response[:status].to_i
|
104
104
|
end
|
105
|
-
Middleware::CountRequests.total_requests.
|
106
|
-
status.
|
105
|
+
expect(Middleware::CountRequests.total_requests).to eq(4) # did retries
|
106
|
+
expect(status).to eq(502) # body is sent for retries
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
112
112
|
end
|
113
|
-
end
|
113
|
+
end
|
@@ -8,50 +8,50 @@ module Librato
|
|
8
8
|
let(:client) { Client.new.tap{ |c| c.persistence = :test } }
|
9
9
|
|
10
10
|
context "with an autosubmit count" do
|
11
|
-
it "
|
12
|
-
vol_queue = Queue.new(:
|
13
|
-
vol_queue.add :
|
14
|
-
vol_queue.add :
|
15
|
-
vol_queue.persister.persisted.
|
11
|
+
it "submits when the max is reached" do
|
12
|
+
vol_queue = Queue.new(client: client, autosubmit_count: 2)
|
13
|
+
vol_queue.add foo: 1
|
14
|
+
vol_queue.add bar: 2
|
15
|
+
expect(vol_queue.persister.persisted).not_to be_nil # sent
|
16
16
|
end
|
17
17
|
|
18
|
-
it "
|
19
|
-
vol_queue = Queue.new(:
|
20
|
-
vol_queue.add :
|
21
|
-
vol_queue.add :
|
22
|
-
vol_queue.persister.persisted.
|
18
|
+
it "does not submit if the max has not been reached" do
|
19
|
+
vol_queue = Queue.new(client: client, autosubmit_count: 5)
|
20
|
+
vol_queue.add foo: 1
|
21
|
+
vol_queue.add bar: 2
|
22
|
+
expect(vol_queue.persister.persisted).to be_nil # nothing sent
|
23
23
|
end
|
24
24
|
|
25
|
-
it '
|
26
|
-
queue = Queue.new(:
|
25
|
+
it 'submits when merging' do
|
26
|
+
queue = Queue.new(client: client, autosubmit_count: 5)
|
27
27
|
(1..3).each {|i| queue.add "metric_#{i}" => 1 }
|
28
28
|
|
29
|
-
to_merge = Queue.new(:
|
29
|
+
to_merge = Queue.new(client: client)
|
30
30
|
(1..5).each {|i| to_merge.add "metric_#{i}" => 1 }
|
31
31
|
|
32
32
|
queue.merge!(to_merge)
|
33
33
|
|
34
|
-
queue.persister.persisted[:gauges].length.
|
35
|
-
queue.queued.
|
34
|
+
expect(queue.persister.persisted[:gauges].length).to eq(8)
|
35
|
+
expect(queue.queued).to be_empty
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
39
|
context "with an autosubmit interval" do
|
40
|
-
it "
|
41
|
-
vol_queue = Queue.new(:
|
42
|
-
vol_queue.add :
|
43
|
-
vol_queue.persister.persisted.
|
40
|
+
it "does not submit immediately" do
|
41
|
+
vol_queue = Queue.new(client: client, autosubmit_interval: 1)
|
42
|
+
vol_queue.add foo: 1
|
43
|
+
expect(vol_queue.persister.persisted).to be_nil # nothing sent
|
44
44
|
end
|
45
45
|
|
46
|
-
it "
|
47
|
-
vol_queue = Queue.new(:
|
48
|
-
vol_queue.add :
|
46
|
+
it "submits after interval" do
|
47
|
+
vol_queue = Queue.new(client: client, autosubmit_interval: 1)
|
48
|
+
vol_queue.add foo: 1
|
49
49
|
sleep 1
|
50
|
-
vol_queue.add :
|
51
|
-
vol_queue.persister.persisted.
|
50
|
+
vol_queue.add foo: 2
|
51
|
+
expect(vol_queue.persister.persisted).not_to be_nil # sent
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
55
|
end
|
56
56
|
end
|
57
|
-
end
|
57
|
+
end
|
@@ -7,170 +7,170 @@ module Librato
|
|
7
7
|
|
8
8
|
before(:each) do
|
9
9
|
@time = (Time.now.to_i - 1*60)
|
10
|
-
Queue.
|
10
|
+
allow_any_instance_of(Queue).to receive(:epoch_time).and_return(@time)
|
11
11
|
end
|
12
12
|
|
13
13
|
describe "initialization" do
|
14
14
|
context "with specified client" do
|
15
|
-
it "
|
15
|
+
it "sets to client" do
|
16
16
|
barney = Client
|
17
|
-
queue = Queue.new(:
|
18
|
-
queue.client.
|
17
|
+
queue = Queue.new(client: barney)
|
18
|
+
expect(queue.client).to eq(barney)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
context "without specified client" do
|
23
|
-
it "
|
23
|
+
it "uses Librato::Metrics client" do
|
24
24
|
queue = Queue.new
|
25
|
-
queue.client.
|
25
|
+
expect(queue.client).to eq(Librato::Metrics.client)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
30
|
describe "#add" do
|
31
|
-
it "
|
32
|
-
subject.add(:
|
31
|
+
it "allows chaining" do
|
32
|
+
expect(subject.add(foo: 123)).to eq(subject)
|
33
33
|
end
|
34
34
|
|
35
35
|
context "with single hash argument" do
|
36
|
-
it "
|
37
|
-
expected = {:
|
38
|
-
subject.add :
|
39
|
-
subject.queued.
|
36
|
+
it "records a key-value gauge" do
|
37
|
+
expected = {gauges: [{name: 'foo', value: 3000, measure_time: @time}]}
|
38
|
+
subject.add foo: 3000
|
39
|
+
expect(subject.queued).to equal_unordered(expected)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
context "with specified metric type" do
|
44
|
-
it "
|
45
|
-
subject.add :
|
46
|
-
expected = {:
|
47
|
-
subject.queued.
|
44
|
+
it "records counters" do
|
45
|
+
subject.add total_visits: {type: :counter, value: 4000}
|
46
|
+
expected = {counters: [{name: 'total_visits', value: 4000, measure_time: @time}]}
|
47
|
+
expect(subject.queued).to equal_unordered(expected)
|
48
48
|
end
|
49
49
|
|
50
|
-
it "
|
51
|
-
subject.add :
|
52
|
-
expected = {:
|
53
|
-
subject.queued.
|
50
|
+
it "records gauges" do
|
51
|
+
subject.add temperature: {type: :gauge, value: 34}
|
52
|
+
expected = {gauges: [{name: 'temperature', value: 34, measure_time: @time}]}
|
53
|
+
expect(subject.queued).to equal_unordered(expected)
|
54
54
|
end
|
55
55
|
|
56
|
-
it "
|
57
|
-
subject.add :
|
58
|
-
expected = {:
|
59
|
-
subject.queued.
|
56
|
+
it "accepts type key as string or a symbol" do
|
57
|
+
subject.add total_visits: {type: "counter", value: 4000}
|
58
|
+
expected = {counters: [{name: 'total_visits', value: 4000, measure_time: @time}]}
|
59
|
+
expect(subject.queued).to equal_unordered(expected)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
63
|
context "with extra attributes" do
|
64
|
-
it "
|
64
|
+
it "records" do
|
65
65
|
measure_time = Time.now
|
66
|
-
subject.add :
|
67
|
-
:
|
68
|
-
:
|
69
|
-
expected = {:
|
70
|
-
:
|
71
|
-
:
|
72
|
-
subject.queued.
|
66
|
+
subject.add disk_use: {value: 35.4, period: 2,
|
67
|
+
description: 'current disk utilization', measure_time: measure_time,
|
68
|
+
source: 'db2'}
|
69
|
+
expected = {gauges: [{value: 35.4, name: 'disk_use', period: 2,
|
70
|
+
description: 'current disk utilization', measure_time: measure_time.to_i,
|
71
|
+
source: 'db2'}]}
|
72
|
+
expect(subject.queued).to equal_unordered(expected)
|
73
73
|
end
|
74
74
|
|
75
75
|
context "with a prefix set" do
|
76
|
-
it "
|
77
|
-
subject = Queue.new(:
|
78
|
-
subject.add :
|
79
|
-
subject.add :
|
80
|
-
expected = {:
|
81
|
-
{:
|
82
|
-
subject.queued.
|
76
|
+
it "auto-prepends names" do
|
77
|
+
subject = Queue.new(prefix: 'foo')
|
78
|
+
subject.add bar: 1
|
79
|
+
subject.add baz: {value: 23}
|
80
|
+
expected = {gauges: [{name:'foo.bar', value: 1, measure_time: @time},
|
81
|
+
{name: 'foo.baz', value: 23, measure_time: @time}]}
|
82
|
+
expect(subject.queued).to equal_unordered(expected)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
86
|
context "when dynamically changing prefix" do
|
87
|
-
it "
|
88
|
-
subject.add :
|
87
|
+
it "auto-appends names" do
|
88
|
+
subject.add bar: 12
|
89
89
|
subject.prefix = 'foo' # with string
|
90
|
-
subject.add :
|
90
|
+
subject.add bar: 23
|
91
91
|
subject.prefix = :foo # with symbol
|
92
|
-
subject.add :
|
92
|
+
subject.add bar: 34
|
93
93
|
subject.prefix = nil # unsetting
|
94
|
-
subject.add :
|
95
|
-
expected = {:
|
96
|
-
{:
|
97
|
-
{:
|
98
|
-
{:
|
99
|
-
{:
|
100
|
-
subject.queued.
|
94
|
+
subject.add bar: 45
|
95
|
+
expected = {gauges: [
|
96
|
+
{name: 'bar', value: 12, measure_time: @time},
|
97
|
+
{name: 'foo.bar', value: 23, measure_time: @time},
|
98
|
+
{name: 'foo.bar', value: 34, measure_time: @time},
|
99
|
+
{name: 'bar', value: 45, measure_time: @time}]}
|
100
|
+
expect(subject.queued).to equal_unordered(expected)
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
105
|
context "with multiple metrics" do
|
106
|
-
it "
|
107
|
-
subject.add :
|
108
|
-
expected = {:
|
109
|
-
{:
|
110
|
-
{:
|
111
|
-
subject.queued.
|
106
|
+
it "records" do
|
107
|
+
subject.add foo: 123, bar: 345, baz: 567
|
108
|
+
expected = {gauges:[{name:"foo", value:123, measure_time: @time},
|
109
|
+
{name:"bar", value:345, measure_time: @time},
|
110
|
+
{name:"baz", value:567, measure_time: @time}]}
|
111
|
+
expect(subject.queued).to equal_unordered(expected)
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
115
|
context "with a measure_time" do
|
116
|
-
it "
|
116
|
+
it "accepts time objects" do
|
117
117
|
time = Time.now-5
|
118
|
-
subject.add :
|
119
|
-
subject.queued[:gauges][0][:measure_time].
|
118
|
+
subject.add foo: {measure_time: time, value: 123}
|
119
|
+
expect(subject.queued[:gauges][0][:measure_time]).to eq(time.to_i)
|
120
120
|
end
|
121
121
|
|
122
|
-
it "
|
122
|
+
it "accepts integers" do
|
123
123
|
time = @time.to_i
|
124
|
-
subject.add :
|
125
|
-
subject.queued[:gauges][0][:measure_time].
|
124
|
+
subject.add foo: {measure_time: time, value: 123}
|
125
|
+
expect(subject.queued[:gauges][0][:measure_time]).to eq(time)
|
126
126
|
end
|
127
127
|
|
128
|
-
it "
|
128
|
+
it "accepts strings" do
|
129
129
|
time = @time.to_s
|
130
|
-
subject.add :
|
131
|
-
subject.queued[:gauges][0][:measure_time].
|
130
|
+
subject.add foo: {measure_time: time, value: 123}
|
131
|
+
expect(subject.queued[:gauges][0][:measure_time]).to eq(time.to_i)
|
132
132
|
end
|
133
133
|
|
134
|
-
it "
|
135
|
-
|
136
|
-
subject.add :
|
137
|
-
}.
|
134
|
+
it "raises exception in invalid time" do
|
135
|
+
expect {
|
136
|
+
subject.add foo: {measure_time: '12', value: 123}
|
137
|
+
}.to raise_error(InvalidMeasureTime)
|
138
138
|
end
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
142
|
describe "#counters" do
|
143
|
-
it "
|
144
|
-
subject.add :
|
145
|
-
:
|
146
|
-
subject.counters.
|
143
|
+
it "returns currently queued counters" do
|
144
|
+
subject.add transactions: {type: :counter, value: 12345},
|
145
|
+
register_cents: {type: :gauge, value: 211101}
|
146
|
+
expect(subject.counters).to eq([{name: 'transactions', value: 12345, measure_time: @time}])
|
147
147
|
end
|
148
148
|
|
149
|
-
it "
|
150
|
-
subject.counters.
|
149
|
+
it "returns [] when no queued counters" do
|
150
|
+
expect(subject.counters).to be_empty
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
154
|
describe "#empty?" do
|
155
|
-
it "
|
156
|
-
subject.empty
|
155
|
+
it "returns true when nothing queued" do
|
156
|
+
expect(subject.empty?).to be true
|
157
157
|
end
|
158
158
|
|
159
|
-
it "
|
160
|
-
subject.add :
|
161
|
-
subject.empty
|
159
|
+
it "returns false with queued items" do
|
160
|
+
subject.add foo: {type: :gauge, value: 121212}
|
161
|
+
expect(subject.empty?).to be false
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
165
165
|
describe "#gauges" do
|
166
|
-
it "
|
167
|
-
subject.add :
|
168
|
-
:
|
169
|
-
subject.gauges.
|
166
|
+
it "returns currently queued gauges" do
|
167
|
+
subject.add transactions: {type: :counter, value: 12345},
|
168
|
+
register_cents: {type: :gauge, value: 211101}
|
169
|
+
expect(subject.gauges).to eq([{name: 'register_cents', value: 211101, measure_time: @time}])
|
170
170
|
end
|
171
171
|
|
172
|
-
it "
|
173
|
-
subject.gauges.
|
172
|
+
it "returns [] when no queued gauges" do
|
173
|
+
expect(subject.gauges).to be_empty
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
@@ -180,144 +180,143 @@ module Librato
|
|
180
180
|
Librato::Metrics.persistence = :test
|
181
181
|
end
|
182
182
|
|
183
|
-
it "
|
184
|
-
subject.last_submit_time.
|
183
|
+
it "defaults to nil" do
|
184
|
+
expect(subject.last_submit_time).to be_nil
|
185
185
|
end
|
186
186
|
|
187
|
-
it "
|
187
|
+
it "stores last submission time" do
|
188
188
|
prior = Time.now
|
189
|
-
subject.add :
|
189
|
+
subject.add foo: 123
|
190
190
|
subject.submit
|
191
|
-
subject.last_submit_time.
|
191
|
+
expect(subject.last_submit_time).to be >= prior
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
195
195
|
describe "#merge!" do
|
196
196
|
context "with another queue" do
|
197
|
-
it "
|
197
|
+
it "merges gauges" do
|
198
198
|
q1 = Queue.new
|
199
|
-
q1.add :
|
199
|
+
q1.add foo: 123, bar: 456
|
200
200
|
q2 = Queue.new
|
201
|
-
q2.add :
|
201
|
+
q2.add baz: 678
|
202
202
|
q2.merge!(q1)
|
203
|
-
expected = {:
|
204
|
-
{:
|
205
|
-
{:
|
206
|
-
q2.queued.
|
203
|
+
expected = {gauges:[{name:"foo", value:123, measure_time: @time},
|
204
|
+
{name:"bar", value:456, measure_time: @time},
|
205
|
+
{name:"baz", value:678, measure_time: @time}]}
|
206
|
+
expect(q2.queued).to equal_unordered(expected)
|
207
207
|
end
|
208
208
|
|
209
|
-
it "
|
209
|
+
it "merges counters" do
|
210
210
|
q1 = Queue.new
|
211
|
-
q1.add :
|
212
|
-
q1.add :
|
211
|
+
q1.add users: {type: :counter, value: 1000}
|
212
|
+
q1.add sales: {type: :counter, value: 250}
|
213
213
|
q2 = Queue.new
|
214
|
-
q2.add :
|
214
|
+
q2.add signups: {type: :counter, value: 500}
|
215
215
|
q2.merge!(q1)
|
216
|
-
expected = {:
|
217
|
-
{:
|
218
|
-
{:
|
219
|
-
q2.queued.
|
216
|
+
expected = {counters:[{name:"users", value:1000, measure_time: @time},
|
217
|
+
{name:"sales", value:250, measure_time: @time},
|
218
|
+
{name:"signups", value:500, measure_time: @time}]}
|
219
|
+
expect(q2.queued).to equal_unordered(expected)
|
220
220
|
end
|
221
221
|
|
222
|
-
it "
|
222
|
+
it "maintains specified sources" do
|
223
223
|
q1 = Queue.new
|
224
|
-
q1.add :
|
225
|
-
q2 = Queue.new(:
|
224
|
+
q1.add neo: {source: 'matrix', value: 123}
|
225
|
+
q2 = Queue.new(source: 'red_pill')
|
226
226
|
q2.merge!(q1)
|
227
|
-
q2.queued[:gauges][0][:source].
|
227
|
+
expect(q2.queued[:gauges][0][:source]).to eq('matrix')
|
228
228
|
end
|
229
229
|
|
230
|
-
it "
|
231
|
-
q1 = Queue.new(:
|
232
|
-
q1.add :
|
233
|
-
q2 = Queue.new(:
|
230
|
+
it "does not change default source" do
|
231
|
+
q1 = Queue.new(source: 'matrix')
|
232
|
+
q1.add neo: 456
|
233
|
+
q2 = Queue.new(source: 'red_pill')
|
234
234
|
q2.merge!(q1)
|
235
|
-
q2.queued[:source].
|
235
|
+
expect(q2.queued[:source]).to eq('red_pill')
|
236
236
|
end
|
237
237
|
|
238
|
-
it "
|
239
|
-
q1 = Queue.new(:
|
240
|
-
q1.add :
|
241
|
-
q2 = Queue.new(:
|
242
|
-
q2.add :
|
238
|
+
it "tracks previous default source" do
|
239
|
+
q1 = Queue.new(source: 'matrix')
|
240
|
+
q1.add neo: 456
|
241
|
+
q2 = Queue.new(source: 'red_pill')
|
242
|
+
q2.add morpheus: 678
|
243
243
|
q2.merge!(q1)
|
244
244
|
q2.queued[:gauges].each do |gauge|
|
245
245
|
if gauge[:name] == 'neo'
|
246
|
-
gauge[:source].
|
246
|
+
expect(gauge[:source]).to eq('matrix')
|
247
247
|
end
|
248
248
|
end
|
249
249
|
end
|
250
250
|
|
251
|
-
it "
|
251
|
+
it "handles empty cases" do
|
252
252
|
q1 = Queue.new
|
253
|
-
q1.add :
|
253
|
+
q1.add foo: 123, users: {type: :counter, value: 1000}
|
254
254
|
q2 = Queue.new
|
255
255
|
q2.merge!(q1)
|
256
|
-
expected = {:
|
257
|
-
:
|
258
|
-
q2.queued.
|
256
|
+
expected = {counters: [{name:"users", value:1000, measure_time: @time}],
|
257
|
+
gauges: [{name:"foo", value:123, measure_time: @time}]}
|
258
|
+
expect(q2.queued).to eq(expected)
|
259
259
|
end
|
260
260
|
end
|
261
261
|
|
262
262
|
context "with an aggregator" do
|
263
|
-
it "
|
264
|
-
aggregator = Aggregator.new(:
|
265
|
-
aggregator.add :
|
266
|
-
aggregator.add :
|
267
|
-
queue = Queue.new(:
|
268
|
-
queue.add :
|
263
|
+
it "merges" do
|
264
|
+
aggregator = Aggregator.new(source: 'aggregator')
|
265
|
+
aggregator.add timing: 102
|
266
|
+
aggregator.add timing: 203
|
267
|
+
queue = Queue.new(source: 'queue')
|
268
|
+
queue.add gauge: 42
|
269
269
|
queue.merge!(aggregator)
|
270
|
-
expected = {:
|
271
|
-
{:
|
272
|
-
:
|
273
|
-
queue.queued.
|
274
|
-
|
270
|
+
expected = {gauges:[{name:"gauge", value:42, measure_time:@time},
|
271
|
+
{name:"timing", count:2, sum:305.0, min:102.0, max:203.0, source:"aggregator"}],
|
272
|
+
source:'queue'}
|
273
|
+
expect(queue.queued).to equal_unordered(expected)
|
275
274
|
end
|
276
275
|
end
|
277
276
|
|
278
277
|
context "with a hash" do
|
279
|
-
it "
|
280
|
-
to_merge = {:
|
281
|
-
:
|
278
|
+
it "merges" do
|
279
|
+
to_merge = {gauges:[{name: 'foo', value: 123}],
|
280
|
+
counters:[{name: 'bar', value: 456}]}
|
282
281
|
q = Queue.new
|
283
282
|
q.merge!(to_merge)
|
284
|
-
q.gauges.length.
|
285
|
-
q.counters.length.
|
283
|
+
expect(q.gauges.length).to eq(1)
|
284
|
+
expect(q.counters.length).to eq(1)
|
286
285
|
end
|
287
286
|
end
|
288
287
|
end
|
289
288
|
|
290
289
|
describe "#per_request" do
|
291
|
-
it "
|
292
|
-
subject.per_request.
|
290
|
+
it "defaults to 500" do
|
291
|
+
expect(subject.per_request).to eq(500)
|
293
292
|
end
|
294
293
|
end
|
295
294
|
|
296
295
|
describe "#queued" do
|
297
|
-
it "
|
298
|
-
q = Queue.new(:
|
299
|
-
q.add :
|
300
|
-
q.queued[:source].
|
296
|
+
it "includes global source if set" do
|
297
|
+
q = Queue.new(source: 'blah')
|
298
|
+
q.add foo: 12
|
299
|
+
expect(q.queued[:source]).to eq('blah')
|
301
300
|
end
|
302
301
|
|
303
|
-
it "
|
302
|
+
it "includes global measure_time if set" do
|
304
303
|
measure_time = (Time.now-1000).to_i
|
305
|
-
q = Queue.new(:
|
306
|
-
q.add :
|
307
|
-
q.queued[:measure_time].
|
304
|
+
q = Queue.new(measure_time: measure_time)
|
305
|
+
q.add foo: 12
|
306
|
+
expect(q.queued[:measure_time]).to eq(measure_time)
|
308
307
|
end
|
309
308
|
end
|
310
309
|
|
311
310
|
describe "#size" do
|
312
|
-
it "
|
313
|
-
subject.size.
|
311
|
+
it "returns empty if gauges and counters are emtpy" do
|
312
|
+
expect(subject.size).to be_zero
|
314
313
|
end
|
315
|
-
it "
|
316
|
-
subject.add :
|
317
|
-
:
|
318
|
-
subject.add :
|
319
|
-
:
|
320
|
-
subject.size.
|
314
|
+
it "returns count of gauges and counters if added" do
|
315
|
+
subject.add transactions: {type: :counter, value: 12345},
|
316
|
+
register_cents: {type: :gauge, value: 211101}
|
317
|
+
subject.add transactions: {type: :counter, value: 12345},
|
318
|
+
register_cents: {type: :gauge, value: 211101}
|
319
|
+
expect(subject.size).to eq(4)
|
321
320
|
end
|
322
321
|
end
|
323
322
|
|
@@ -328,47 +327,47 @@ module Librato
|
|
328
327
|
end
|
329
328
|
|
330
329
|
context "when successful" do
|
331
|
-
it "
|
332
|
-
subject.add :
|
333
|
-
subject.submit.
|
334
|
-
subject.queued.
|
330
|
+
it "flushes queued metrics and return true" do
|
331
|
+
subject.add steps: 2042, distance: 1234
|
332
|
+
expect(subject.submit).to be true
|
333
|
+
expect(subject.queued).to be_empty
|
335
334
|
end
|
336
335
|
end
|
337
336
|
|
338
337
|
context "when failed" do
|
339
|
-
it "
|
340
|
-
subject.add :
|
338
|
+
it "preserves queue and return false" do
|
339
|
+
subject.add steps: 2042, distance: 1234
|
341
340
|
subject.persister.return_value(false)
|
342
|
-
subject.submit.
|
343
|
-
subject.queued.
|
341
|
+
expect(subject.submit).to be false
|
342
|
+
expect(subject.queued).not_to be_empty
|
344
343
|
end
|
345
344
|
end
|
346
345
|
end
|
347
346
|
|
348
347
|
describe "#time" do
|
349
348
|
context "with metric name only" do
|
350
|
-
it "
|
349
|
+
it "queues metric with timed value" do
|
351
350
|
subject.time :sleeping do
|
352
351
|
sleep 0.1
|
353
352
|
end
|
354
353
|
queued = subject.queued[:gauges][0]
|
355
|
-
queued[:name].
|
356
|
-
queued[:value].
|
357
|
-
queued[:value].
|
354
|
+
expect(queued[:name]).to eq('sleeping')
|
355
|
+
expect(queued[:value]).to be >= 100
|
356
|
+
expect(queued[:value]).to be_within(30).of(100)
|
358
357
|
end
|
359
358
|
end
|
360
359
|
|
361
360
|
context "with metric and options" do
|
362
|
-
it "
|
363
|
-
subject.time :sleep_two, :
|
361
|
+
it "queues metric with value and options" do
|
362
|
+
subject.time :sleep_two, source: 'app1', period: 2 do
|
364
363
|
sleep 0.05
|
365
364
|
end
|
366
365
|
queued = subject.queued[:gauges][0]
|
367
|
-
queued[:name].
|
368
|
-
queued[:period].
|
369
|
-
queued[:source].
|
370
|
-
queued[:value].
|
371
|
-
queued[:value].
|
366
|
+
expect(queued[:name]).to eq('sleep_two')
|
367
|
+
expect(queued[:period]).to eq(2)
|
368
|
+
expect(queued[:source]).to eq('app1')
|
369
|
+
expect(queued[:value]).to be >= 50
|
370
|
+
expect(queued[:value]).to be_within(30).of(50)
|
372
371
|
end
|
373
372
|
end
|
374
373
|
end
|