appoptics-api-ruby 2.1.3
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 +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/.travis.yml +25 -0
- data/CHANGELOG.md +184 -0
- data/Gemfile +36 -0
- data/LICENSE +24 -0
- data/README.md +271 -0
- data/Rakefile +63 -0
- data/appoptics-api-ruby.gemspec +31 -0
- data/benchmarks/array_vs_set.rb +29 -0
- data/certs/librato-public.pem +20 -0
- data/examples/simple.rb +24 -0
- data/examples/submit_every.rb +27 -0
- data/lib/appoptics/metrics.rb +95 -0
- data/lib/appoptics/metrics/aggregator.rb +138 -0
- data/lib/appoptics/metrics/annotator.rb +145 -0
- data/lib/appoptics/metrics/client.rb +361 -0
- data/lib/appoptics/metrics/collection.rb +43 -0
- data/lib/appoptics/metrics/connection.rb +101 -0
- data/lib/appoptics/metrics/errors.rb +32 -0
- data/lib/appoptics/metrics/middleware/count_requests.rb +28 -0
- data/lib/appoptics/metrics/middleware/expects_status.rb +38 -0
- data/lib/appoptics/metrics/middleware/request_body.rb +18 -0
- data/lib/appoptics/metrics/middleware/retry.rb +31 -0
- data/lib/appoptics/metrics/persistence.rb +2 -0
- data/lib/appoptics/metrics/persistence/direct.rb +73 -0
- data/lib/appoptics/metrics/persistence/test.rb +27 -0
- data/lib/appoptics/metrics/processor.rb +130 -0
- data/lib/appoptics/metrics/queue.rb +191 -0
- data/lib/appoptics/metrics/smart_json.rb +43 -0
- data/lib/appoptics/metrics/util.rb +25 -0
- data/lib/appoptics/metrics/version.rb +5 -0
- data/spec/integration/metrics/annotator_spec.rb +190 -0
- data/spec/integration/metrics/connection_spec.rb +14 -0
- data/spec/integration/metrics/middleware/count_requests_spec.rb +28 -0
- data/spec/integration/metrics/queue_spec.rb +96 -0
- data/spec/integration/metrics_spec.rb +375 -0
- data/spec/rackups/status.ru +30 -0
- data/spec/spec_helper.rb +88 -0
- data/spec/unit/metrics/aggregator_spec.rb +417 -0
- data/spec/unit/metrics/client_spec.rb +127 -0
- data/spec/unit/metrics/connection_spec.rb +113 -0
- data/spec/unit/metrics/queue/autosubmission_spec.rb +57 -0
- data/spec/unit/metrics/queue_spec.rb +593 -0
- data/spec/unit/metrics/smart_json_spec.rb +79 -0
- data/spec/unit/metrics/util_spec.rb +23 -0
- data/spec/unit/metrics_spec.rb +63 -0
- metadata +135 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'sinatra'
|
|
2
|
+
|
|
3
|
+
class App < Sinatra::Base
|
|
4
|
+
get('/v1/success') do
|
|
5
|
+
status 200
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
post('/v1/forbidden') do
|
|
9
|
+
status 403
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
get('/v1/not_found') do
|
|
13
|
+
status 404
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
post('/v1/service_unavailable') do
|
|
17
|
+
status 503
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
post('/v1/retry_body') do
|
|
21
|
+
body = request.env["rack.input"].read
|
|
22
|
+
if body.empty?
|
|
23
|
+
status 504 # body not sent
|
|
24
|
+
else
|
|
25
|
+
status 502 # body sent
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
run App
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
2
|
+
|
|
3
|
+
# only load pry for MRI > 1.8
|
|
4
|
+
require 'pry' if RUBY_ENGINE == 'ruby' rescue nil
|
|
5
|
+
require 'popen4'
|
|
6
|
+
require 'rspec'
|
|
7
|
+
require 'rspec/mocks/standalone'
|
|
8
|
+
require 'set'
|
|
9
|
+
|
|
10
|
+
require 'appoptics-api-ruby'
|
|
11
|
+
|
|
12
|
+
RSpec.configure do |config|
|
|
13
|
+
|
|
14
|
+
# only accept expect syntax instead of should
|
|
15
|
+
config.expect_with :rspec do |c|
|
|
16
|
+
c.syntax = :expect
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# purge all metrics from test account
|
|
20
|
+
def delete_all_metrics
|
|
21
|
+
connection = Appoptics::Metrics.client.connection
|
|
22
|
+
Appoptics::Metrics.metrics.each do |metric|
|
|
23
|
+
#puts "deleting #{metric['name']}..."
|
|
24
|
+
# expects 204
|
|
25
|
+
connection.delete("metrics/#{metric['name']}")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# purge all annotations from test account
|
|
30
|
+
def delete_all_annotations
|
|
31
|
+
annotator = Appoptics::Metrics::Annotator.new
|
|
32
|
+
streams = annotator.list
|
|
33
|
+
if streams['annotations']
|
|
34
|
+
names = streams['annotations'].map{|s| s['name']}
|
|
35
|
+
names.each { |name| annotator.delete name}
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# set up test account credentials for integration tests
|
|
40
|
+
def prep_integration_tests
|
|
41
|
+
raise 'no TEST_API_USER specified in environment' unless ENV['TEST_API_USER']
|
|
42
|
+
raise 'no TEST_API_KEY specified in environment' unless ENV['TEST_API_KEY']
|
|
43
|
+
if ENV['TEST_API_ENDPOINT']
|
|
44
|
+
Appoptics::Metrics.api_endpoint = ENV['TEST_API_ENDPOINT']
|
|
45
|
+
end
|
|
46
|
+
Appoptics::Metrics.authenticate ENV['TEST_API_USER'], ENV['TEST_API_KEY']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def rackup_path(*parts)
|
|
50
|
+
File.expand_path(File.join(File.dirname(__FILE__), 'rackups', *parts))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# fire up a given rackup file for the enclosed tests
|
|
54
|
+
def with_rackup(name)
|
|
55
|
+
if RUBY_PLATFORM == 'java'
|
|
56
|
+
pid, w, r, e = IO.popen4("rackup", rackup_path(name), '-p 9296')
|
|
57
|
+
else
|
|
58
|
+
GC.disable
|
|
59
|
+
pid, w, r, e = Open4.popen4("rackup", rackup_path(name), '-p 9296')
|
|
60
|
+
end
|
|
61
|
+
until e.gets =~ /HTTPServer#start:/; end
|
|
62
|
+
yield
|
|
63
|
+
ensure
|
|
64
|
+
Process.kill(9, pid)
|
|
65
|
+
if RUBY_PLATFORM != 'java'
|
|
66
|
+
GC.enable
|
|
67
|
+
Process.wait(pid)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Compares hashes of arrays by converting the arrays to
|
|
74
|
+
# sets before comparision
|
|
75
|
+
#
|
|
76
|
+
# @example
|
|
77
|
+
# {foo: [1,3,2]}.should equal_unordered({foo: [1,2,3]})
|
|
78
|
+
RSpec::Matchers.define :equal_unordered do |result|
|
|
79
|
+
result.each do |key, value|
|
|
80
|
+
result[key] = value.to_set if value.respond_to?(:to_set)
|
|
81
|
+
end
|
|
82
|
+
match do |target|
|
|
83
|
+
target.each do |key, value|
|
|
84
|
+
target[key] = value.to_set if value.respond_to?(:to_set)
|
|
85
|
+
end
|
|
86
|
+
target == result
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
require "spec_helper.rb"
|
|
2
|
+
module Appoptics
|
|
3
|
+
module Metrics
|
|
4
|
+
|
|
5
|
+
describe Aggregator do
|
|
6
|
+
|
|
7
|
+
before(:all) do
|
|
8
|
+
@time = 1354720160 #Time.now.to_i
|
|
9
|
+
allow_any_instance_of(Aggregator).to receive(:epoch_time).and_return(@time)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "initialization" do
|
|
13
|
+
context "with specified client" do
|
|
14
|
+
it "sets to client" do
|
|
15
|
+
barney = Client.new
|
|
16
|
+
a = Aggregator.new(client: barney)
|
|
17
|
+
expect(a.client).to eq(barney)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context "without specified client" do
|
|
22
|
+
it "uses Appoptics::Metrics client" do
|
|
23
|
+
a = Aggregator.new
|
|
24
|
+
expect(a.client).to eq(Appoptics::Metrics.client)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "with specified source" do
|
|
29
|
+
it "sets to source" do
|
|
30
|
+
a = Aggregator.new(source: 'rubble')
|
|
31
|
+
expect(a.source).to eq('rubble')
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "without specified source" do
|
|
36
|
+
it "does not have a source" do
|
|
37
|
+
a = Aggregator.new
|
|
38
|
+
expect(a.source).to be_nil
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context "with valid arguments" do
|
|
43
|
+
it "initializes Aggregator" do
|
|
44
|
+
expect { Aggregator.new }.not_to raise_error
|
|
45
|
+
expect { Aggregator.new(source: "metrics-web-stg-1") }.not_to raise_error
|
|
46
|
+
expect { Aggregator.new(tags: { hostname: "metrics-web-stg-1" }) }.not_to raise_error
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "with invalid arguments" do
|
|
51
|
+
it "raises exception" do
|
|
52
|
+
expect {
|
|
53
|
+
Aggregator.new(
|
|
54
|
+
source: "metrics-web-stg-1",
|
|
55
|
+
tags: { hostname: "metrics-web-stg-1" }
|
|
56
|
+
)
|
|
57
|
+
}.to raise_error(InvalidParameters)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "#tags" do
|
|
63
|
+
context "when set" do
|
|
64
|
+
let(:aggregator) { Aggregator.new(tags: { instance_id: "i-1234567a" }) }
|
|
65
|
+
it "gets @tags" do
|
|
66
|
+
expect(aggregator.tags).to be_a(Hash)
|
|
67
|
+
expect(aggregator.tags.keys).to include(:instance_id)
|
|
68
|
+
expect(aggregator.tags[:instance_id]).to eq("i-1234567a")
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context "when not set" do
|
|
73
|
+
let(:aggregator) { Aggregator.new }
|
|
74
|
+
it "defaults to empty hash" do
|
|
75
|
+
expect(aggregator.tags).to be_a(Hash)
|
|
76
|
+
expect(aggregator.tags).to be_empty
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe "#tags=" do
|
|
82
|
+
it "sets @tags" do
|
|
83
|
+
expected_tags = { instance_id: "i-1234567b" }
|
|
84
|
+
expect{subject.tags = expected_tags}.to change{subject.tags}.from({}).to(expected_tags)
|
|
85
|
+
expect(subject.tags).to be_a(Hash)
|
|
86
|
+
expect(subject.tags).to eq(expected_tags)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe "#has_tags?" do
|
|
91
|
+
context "when tags are set" do
|
|
92
|
+
it "returns true" do
|
|
93
|
+
subject.tags = { instance_id: "i-1234567f" }
|
|
94
|
+
|
|
95
|
+
expect(subject.has_tags?).to eq(true)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context "when tags are not set" do
|
|
100
|
+
it "returns false" do
|
|
101
|
+
expect(subject.has_tags?).to eq(false)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe "#add" do
|
|
107
|
+
it "allows chaining" do
|
|
108
|
+
expect(subject.add(foo: 1234)).to eq(subject)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context "with invalid arguments" do
|
|
112
|
+
it "raises exception" do
|
|
113
|
+
expect {
|
|
114
|
+
subject.add test: { source: "metrics-web-stg-1", tags: { hostname: "metrics-web-stg-1" }, value: 123 }
|
|
115
|
+
}.to raise_error(InvalidParameters)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context "with single hash argument" do
|
|
120
|
+
it "records a single aggregate" do
|
|
121
|
+
subject.add foo: 3000
|
|
122
|
+
expected = { #measure_time: @time, TODO: support specific time
|
|
123
|
+
gauges: [
|
|
124
|
+
{ name: 'foo',
|
|
125
|
+
count: 1,
|
|
126
|
+
sum: 3000.0,
|
|
127
|
+
min: 3000.0,
|
|
128
|
+
max: 3000.0}
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
expect(subject.queued).to equal_unordered(expected)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "aggregates multiple measurements" do
|
|
135
|
+
subject.add foo: 1
|
|
136
|
+
subject.add foo: 2
|
|
137
|
+
subject.add foo: 3
|
|
138
|
+
subject.add foo: 4
|
|
139
|
+
subject.add foo: 5
|
|
140
|
+
expected = { gauges: [
|
|
141
|
+
{ name: 'foo',
|
|
142
|
+
count: 5,
|
|
143
|
+
sum: 15.0,
|
|
144
|
+
min: 1.0,
|
|
145
|
+
max: 5.0}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
expect(subject.queued).to equal_unordered(expected)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "respects source argument" do
|
|
152
|
+
subject.add foo: {source: 'alpha', value: 1}
|
|
153
|
+
subject.add foo: 5
|
|
154
|
+
subject.add foo: {source: :alpha, value: 6}
|
|
155
|
+
subject.add foo: 10
|
|
156
|
+
expected = { gauges: [
|
|
157
|
+
{ name: 'foo', source: 'alpha', count: 2,
|
|
158
|
+
sum: 7.0, min: 1.0, max: 6.0 },
|
|
159
|
+
{ name: 'foo', count: 2,
|
|
160
|
+
sum: 15.0, min: 5.0, max: 10.0 }
|
|
161
|
+
]}
|
|
162
|
+
expect(subject.queued).to equal_unordered(expected)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
context "when per-measurement tags" do
|
|
166
|
+
it "maintains specified tags" do
|
|
167
|
+
subject.add test: { tags: { hostname: "metrics-web-stg-1" }, value: 1 }
|
|
168
|
+
subject.add test: 5
|
|
169
|
+
subject.add test: { tags: { hostname: "metrics-web-stg-1" }, value: 6 }
|
|
170
|
+
subject.add test: 10
|
|
171
|
+
expected = [
|
|
172
|
+
{ name: "test", tags: { hostname: "metrics-web-stg-1" }, count: 2, sum: 7.0, min: 1.0, max: 6.0 },
|
|
173
|
+
{ name: "test", count: 2, sum: 15.0, min: 5.0, max: 10.0 }
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
expect(subject.queued[:measurements]).to equal_unordered(expected)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
context "with a prefix set" do
|
|
181
|
+
it "auto-prepends names" do
|
|
182
|
+
subject = Aggregator.new(prefix: 'foo')
|
|
183
|
+
subject.add bar: 1
|
|
184
|
+
subject.add bar: 12
|
|
185
|
+
expected = {gauges: [
|
|
186
|
+
{ name:'foo.bar',
|
|
187
|
+
count: 2,
|
|
188
|
+
sum: 13.0,
|
|
189
|
+
min: 1.0,
|
|
190
|
+
max: 12.0
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
expect(subject.queued).to equal_unordered(expected)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
context "with multiple hash arguments" do
|
|
200
|
+
it "records a single aggregate" do
|
|
201
|
+
subject.add foo: 3000
|
|
202
|
+
subject.add bar: 30
|
|
203
|
+
expected = {
|
|
204
|
+
#measure_time: @time, TODO: support specific time
|
|
205
|
+
gauges: [
|
|
206
|
+
{ name: 'foo',
|
|
207
|
+
count: 1,
|
|
208
|
+
sum: 3000.0,
|
|
209
|
+
min: 3000.0,
|
|
210
|
+
max: 3000.0},
|
|
211
|
+
{ name: 'bar',
|
|
212
|
+
count: 1,
|
|
213
|
+
sum: 30.0,
|
|
214
|
+
min: 30.0,
|
|
215
|
+
max: 30.0},
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
expect(subject.queued).to equal_unordered(expected)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "aggregates multiple measurements" do
|
|
222
|
+
subject.add foo: 1
|
|
223
|
+
subject.add foo: 2
|
|
224
|
+
subject.add foo: 3
|
|
225
|
+
subject.add foo: 4
|
|
226
|
+
subject.add foo: 5
|
|
227
|
+
|
|
228
|
+
subject.add bar: 6
|
|
229
|
+
subject.add bar: 7
|
|
230
|
+
subject.add bar: 8
|
|
231
|
+
subject.add bar: 9
|
|
232
|
+
subject.add bar: 10
|
|
233
|
+
expected = { gauges: [
|
|
234
|
+
{ name: 'foo',
|
|
235
|
+
count: 5,
|
|
236
|
+
sum: 15.0,
|
|
237
|
+
min: 1.0,
|
|
238
|
+
max: 5.0},
|
|
239
|
+
{ name: 'bar',
|
|
240
|
+
count: 5,
|
|
241
|
+
sum: 40.0,
|
|
242
|
+
min: 6.0,
|
|
243
|
+
max: 10.0}
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
expect(subject.queued).to equal_unordered(expected)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
context "with tags" do
|
|
251
|
+
context "when Aggregator is initialized with tags" do
|
|
252
|
+
let(:aggregator) { Aggregator.new(tags: { region: "us-east-1" }) }
|
|
253
|
+
|
|
254
|
+
it "applies top-level tags" do
|
|
255
|
+
expected = { name: "test", count: 2, sum: 3, min: 1, max: 2 }
|
|
256
|
+
aggregator.add test: 1
|
|
257
|
+
aggregator.add test: 2
|
|
258
|
+
|
|
259
|
+
expect(aggregator.queued[:tags]).to eq({ region: "us-east-1" })
|
|
260
|
+
expect(aggregator.queued[:measurements].first).to eq(expected)
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
context "when tags are used as arguments" do
|
|
265
|
+
let(:aggregator) { Aggregator.new }
|
|
266
|
+
|
|
267
|
+
it "applies per-measurement tags" do
|
|
268
|
+
expected = { name: "test", count: 2, sum: 3, min: 1, max: 2, tags: { hostname: "metrics-web-stg-1" } }
|
|
269
|
+
aggregator.add test: { value: 1, tags: { hostname: "metrics-web-stg-1" } }
|
|
270
|
+
aggregator.add test: { value: 2, tags: { hostname: "metrics-web-stg-1" } }
|
|
271
|
+
|
|
272
|
+
expect(aggregator.queued[:tags]).to be_nil
|
|
273
|
+
expect(aggregator.queued[:measurements].first).to eq(expected)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
context "when tags arguments are not sorted" do
|
|
277
|
+
let(:aggregator) { Aggregator.new }
|
|
278
|
+
|
|
279
|
+
it "uses sorted tags hash key" do
|
|
280
|
+
expected = { name: "test", count: 2, sum: 3, min: 1, max: 2, tags: { a: 1, b: 2, c: 3 } }
|
|
281
|
+
aggregator.add test: { value: 1, tags: { c: 3, b: 2, a: 1 } }
|
|
282
|
+
aggregator.add test: { value: 2, tags: { b: 2, a: 1, c: 3 } }
|
|
283
|
+
|
|
284
|
+
expect(aggregator.queued[:tags]).to be_nil
|
|
285
|
+
expect(aggregator.queued[:measurements].first).to eq(expected)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
context "when Aggregator is initialized with tags and when tags are used as arguments" do
|
|
291
|
+
let(:aggregator) { Aggregator.new(tags: { region: "us-east-1" }) }
|
|
292
|
+
|
|
293
|
+
it "applies top-level tags and per-measurement tags" do
|
|
294
|
+
expected = { name: "test", count: 3, sum: 12, min: 3, max: 5, tags: { hostname: "metrics-web-stg-1" } }
|
|
295
|
+
aggregator.add test: { value: 3, tags: { hostname: "metrics-web-stg-1" } }
|
|
296
|
+
aggregator.add test: { value: 4, tags: { hostname: "metrics-web-stg-1" } }
|
|
297
|
+
aggregator.add test: { value: 5, tags: { hostname: "metrics-web-stg-1" } }
|
|
298
|
+
aggregator.add test: { value: 1, tags: { hostname: "metrics-web-stg-2" } }
|
|
299
|
+
aggregator.add test: { value: 2, tags: { region: "us-tirefire-1" } }
|
|
300
|
+
|
|
301
|
+
expect(aggregator.queued[:tags]).to eq({ region: "us-east-1" })
|
|
302
|
+
expect(aggregator.queued[:measurements].first).to eq(expected)
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
describe "#queued" do
|
|
309
|
+
it "includes global source if set" do
|
|
310
|
+
a = Aggregator.new(source: 'blah')
|
|
311
|
+
a.add foo: 12
|
|
312
|
+
expect(a.queued[:source]).to eq('blah')
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it "includes global measure_time if set" do
|
|
316
|
+
measure_time = (Time.now-1000).to_i
|
|
317
|
+
a = Aggregator.new(source: "foo", measure_time: measure_time)
|
|
318
|
+
a.add foo: 12
|
|
319
|
+
expect(a.queued[:measure_time]).to eq(measure_time)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
context "when tags are set" do
|
|
323
|
+
it "includes global tags" do
|
|
324
|
+
expected_tags = { region: "us-east-1" }
|
|
325
|
+
subject = Aggregator.new(tags: expected_tags)
|
|
326
|
+
subject.add test: 5
|
|
327
|
+
|
|
328
|
+
expect(subject.queued[:tags]).to eq(expected_tags)
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
context "when time is set" do
|
|
333
|
+
it "includes global time" do
|
|
334
|
+
expected_time = (Time.now-1000).to_i
|
|
335
|
+
subject = Aggregator.new(tags: { foo: "bar" }, time: expected_time)
|
|
336
|
+
subject.add test: 10
|
|
337
|
+
|
|
338
|
+
expect(subject.queued[:time]).to eq(expected_time)
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
describe "#submit" do
|
|
344
|
+
before(:all) do
|
|
345
|
+
Appoptics::Metrics.authenticate 'me@AppOptics.com', 'foo'
|
|
346
|
+
Appoptics::Metrics.persistence = :test
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context "when successful" do
|
|
350
|
+
it "flushes queued metrics and return true" do
|
|
351
|
+
subject.add steps: 2042, distance: 1234
|
|
352
|
+
expect(subject.submit).to be true
|
|
353
|
+
expect(subject.empty?).to be true
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
context "when failed" do
|
|
358
|
+
it "preserves queue and return false" do
|
|
359
|
+
subject.add steps: 2042, distance: 1234
|
|
360
|
+
subject.persister.return_value(false)
|
|
361
|
+
expect(subject.submit).to be false
|
|
362
|
+
expect(subject.empty?).to be false
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
describe "#time" do
|
|
368
|
+
context "with metric name only" do
|
|
369
|
+
it "queues metric with timed value" do
|
|
370
|
+
1.upto(5) do
|
|
371
|
+
subject.time :sleeping do
|
|
372
|
+
sleep 0.1
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
queued = subject.queued[:gauges][0]
|
|
376
|
+
expect(queued[:name]).to eq('sleeping')
|
|
377
|
+
expect(queued[:count]).to eq(5)
|
|
378
|
+
expect(queued[:sum]).to be >= 500.0
|
|
379
|
+
expect(queued[:sum]).to be_within(150).of(500)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
it "returns the result of the block" do
|
|
383
|
+
result = subject.time :returning do
|
|
384
|
+
:hi_there
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
expect(result).to eq(:hi_there)
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
context "with an autosubmit interval" do
|
|
393
|
+
let(:client) do
|
|
394
|
+
client = Client.new
|
|
395
|
+
client.persistence = :test
|
|
396
|
+
client
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
it "does not submit immediately" do
|
|
400
|
+
timed_agg = Aggregator.new(client: client, autosubmit_interval: 1)
|
|
401
|
+
timed_agg.add foo: 1
|
|
402
|
+
expect(timed_agg.persister.persisted).to be_nil # nothing sent
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
it "submits after interval" do
|
|
406
|
+
timed_agg = Aggregator.new(client: client, autosubmit_interval: 1)
|
|
407
|
+
timed_agg.add foo: 1
|
|
408
|
+
sleep 1
|
|
409
|
+
timed_agg.add foo: 2
|
|
410
|
+
expect(timed_agg.persister.persisted).not_to be_nil # sent
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
end
|
|
417
|
+
end
|