simple_metrics 0.3.2 → 0.3.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.
- data/bin/populate +2 -2
- data/lib/simple_metrics/app.rb +5 -89
- data/lib/simple_metrics/bucket.rb +25 -99
- data/lib/simple_metrics/configuration.rb +24 -6
- data/lib/simple_metrics/data_point/counter.rb +7 -0
- data/lib/simple_metrics/data_point/event.rb +4 -0
- data/lib/simple_metrics/data_point/gauge.rb +6 -0
- data/lib/simple_metrics/data_point/timing.rb +3 -0
- data/lib/simple_metrics/data_point.rb +1 -17
- data/lib/simple_metrics/data_point_repository.rb +11 -28
- data/lib/simple_metrics/graph.rb +37 -21
- data/lib/simple_metrics/importer.rb +90 -0
- data/lib/simple_metrics/metric.rb +2 -1
- data/lib/simple_metrics/public/js/application.js +4 -4
- data/lib/simple_metrics/repository.rb +4 -4
- data/lib/simple_metrics/udp_server.rb +1 -1
- data/lib/simple_metrics/version.rb +1 -1
- data/lib/simple_metrics/views/layout.erb +1 -1
- data/lib/simple_metrics.rb +1 -2
- data/spec/array_aggregation_spec.rb +8 -8
- data/spec/bucket_spec.rb +7 -104
- data/spec/data_point_repository_spec.rb +9 -46
- data/spec/graph_spec.rb +33 -4
- data/spec/importer_spec.rb +126 -0
- data/spec/spec_helper.rb +1 -1
- metadata +33 -34
- data/lib/simple_metrics/update_aggregation.rb +0 -62
- data/lib/simple_metrics/value_aggregation.rb +0 -63
- data/spec/value_aggregation_spec.rb +0 -52
@@ -0,0 +1,90 @@
|
|
1
|
+
module SimpleMetrics
|
2
|
+
module Importer
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def flush_raw(data)
|
6
|
+
data_points = []
|
7
|
+
data.each do |str|
|
8
|
+
begin
|
9
|
+
data_points << DataPoint.parse(str)
|
10
|
+
rescue DataPoint::ParserError => e
|
11
|
+
SimpleMetrics.logger.debug "Invalid Data skipped: #{str}, #{e}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
flush_data_points(data_points, Time.now.utc.to_i)
|
15
|
+
end
|
16
|
+
|
17
|
+
def flush_data_points(data_points, ts = nil)
|
18
|
+
return if data_points.empty?
|
19
|
+
SimpleMetrics.logger.info "#{Time.now} Flushing #{data_points.count} to MongoDB"
|
20
|
+
|
21
|
+
ts ||= Time.now.utc.to_i
|
22
|
+
bucket = Bucket.first
|
23
|
+
|
24
|
+
group_by_name(data_points) do |name, dps|
|
25
|
+
dp = aggregate_values(dps)
|
26
|
+
bucket.save(dp, ts)
|
27
|
+
update_metric(dp, dps.size)
|
28
|
+
aggregate_coarse_buckets(dp)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def aggregate_coarse_buckets(dp)
|
33
|
+
coarse_buckets.each do |bucket|
|
34
|
+
if existing_dp = bucket.find_data_point_at_ts(dp.ts, dp.name)
|
35
|
+
bucket.update(existing_dp.combine(dp), existing_dp.ts)
|
36
|
+
else
|
37
|
+
bucket.save(dp, dp.ts)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def group_by_name(dps, &block)
|
45
|
+
dps.group_by { |dp| dp.name }.each_pair do |name,dps|
|
46
|
+
block.call(name, dps)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def aggregate_values(dps)
|
51
|
+
raise SimpleMetrics::DataPoint::NonMatchingTypesError if has_non_matching_types?(dps)
|
52
|
+
|
53
|
+
dp = dps.first.dup
|
54
|
+
dp.value = if dp.counter?
|
55
|
+
sum(dps) / dps.size
|
56
|
+
elsif dp.gauge?
|
57
|
+
sum(dps)
|
58
|
+
elsif dp.event?
|
59
|
+
raise "Implement me!"
|
60
|
+
elsif dp.timing?
|
61
|
+
raise "Implement me!"
|
62
|
+
else
|
63
|
+
raise ArgumentError("Unknown data point type: #{dp}")
|
64
|
+
end
|
65
|
+
dp
|
66
|
+
end
|
67
|
+
|
68
|
+
def sum(dps)
|
69
|
+
dps.map { |dp| dp.value }.inject(0) { |result, value| result += value }
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_non_matching_types?(dps)
|
73
|
+
dps.group_by { |dp| dp.type }.size != 1
|
74
|
+
end
|
75
|
+
|
76
|
+
def update_metric(dp, total)
|
77
|
+
if metric = MetricRepository.find_one_by_name(dp.name)
|
78
|
+
metric.total += total
|
79
|
+
MetricRepository.update(metric)
|
80
|
+
else
|
81
|
+
MetricRepository.save(Metric.new(:name => dp.name, :total => total))
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def coarse_buckets
|
86
|
+
Bucket.all.sort_by! { |r| r.seconds }[1..-1]
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -237,7 +237,7 @@ $(function(){
|
|
237
237
|
routes: {
|
238
238
|
"": "home",
|
239
239
|
"metrics": "metrics",
|
240
|
-
"metrics/:
|
240
|
+
"metrics/:name": "metric_details",
|
241
241
|
"dashboard": "dashboard",
|
242
242
|
"about": "about"
|
243
243
|
},
|
@@ -250,10 +250,10 @@ $(function(){
|
|
250
250
|
console.log("ROUTER: metrics");
|
251
251
|
new AppView({ el: "#main", collection: metricList }).render();
|
252
252
|
},
|
253
|
-
metric_details: function(
|
254
|
-
console.log("ROUTER: metric details:",
|
253
|
+
metric_details: function(name) {
|
254
|
+
console.log("ROUTER: metric details:", name);
|
255
255
|
|
256
|
-
metric = new Metric({
|
256
|
+
metric = new Metric({ name: name});
|
257
257
|
metric.fetch({
|
258
258
|
success: function(model, resp) {
|
259
259
|
new MetricDetailView({ el: "#main", model: model}).render();
|
@@ -7,7 +7,7 @@ module SimpleMetrics
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def db
|
10
|
-
@@db ||= connection.db(db_name, config
|
10
|
+
@@db ||= connection.db(db_name, config.fetch(:options))
|
11
11
|
end
|
12
12
|
|
13
13
|
def db_name
|
@@ -15,15 +15,15 @@ module SimpleMetrics
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def prefix
|
18
|
-
config[
|
18
|
+
config[:prefix] || 'development'
|
19
19
|
end
|
20
20
|
|
21
21
|
def host
|
22
|
-
config[
|
22
|
+
config[:host] || 'localhost'
|
23
23
|
end
|
24
24
|
|
25
25
|
def port
|
26
|
-
config[
|
26
|
+
config[:port] || 27017
|
27
27
|
end
|
28
28
|
|
29
29
|
def config
|
@@ -44,7 +44,7 @@ module SimpleMetrics
|
|
44
44
|
EventMachine::add_periodic_timer(flush_interval) do
|
45
45
|
SimpleMetrics.logger.debug "SERVER: period timer triggered after #{flush_interval} seconds"
|
46
46
|
|
47
|
-
EM.defer { Bucket.
|
47
|
+
EM.defer { Bucket.flush_raw(ClientHandler.get_and_clear_data) }
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
data/lib/simple_metrics.rb
CHANGED
@@ -12,9 +12,8 @@ require "simple_metrics/data_point/counter"
|
|
12
12
|
require "simple_metrics/data_point/event"
|
13
13
|
require "simple_metrics/data_point/gauge"
|
14
14
|
require "simple_metrics/data_point/timing"
|
15
|
-
require "simple_metrics/value_aggregation"
|
16
15
|
require "simple_metrics/array_aggregation"
|
17
|
-
require "simple_metrics/
|
16
|
+
require "simple_metrics/importer"
|
18
17
|
require "simple_metrics/bucket"
|
19
18
|
require "simple_metrics/graph"
|
20
19
|
require "simple_metrics/functions"
|
@@ -16,9 +16,9 @@ module SimpleMetrics
|
|
16
16
|
|
17
17
|
describe "#aggregate" do
|
18
18
|
it "aggregates counter data points" do
|
19
|
-
stats1 = DataPoint.
|
20
|
-
stats2 = DataPoint.
|
21
|
-
stats3 = DataPoint.
|
19
|
+
stats1 = DataPoint::Counter.new(:name => "com.test.key1", :value => 5, :ts => ts)
|
20
|
+
stats2 = DataPoint::Counter.new(:name => "com.test.key1", :value => 7, :ts => ts)
|
21
|
+
stats3 = DataPoint::Counter.new(:name => "com.test.key1", :value => 9, :ts => (ts + 60) )
|
22
22
|
|
23
23
|
results = ArrayAggregation.aggregate([stats1, stats2, stats3], "com.test.*")
|
24
24
|
results.should have(2).data_points
|
@@ -29,9 +29,9 @@ module SimpleMetrics
|
|
29
29
|
end
|
30
30
|
|
31
31
|
it "aggregates gauge data points" do
|
32
|
-
stats1 = DataPoint.
|
33
|
-
stats2 = DataPoint.
|
34
|
-
stats3 = DataPoint.
|
32
|
+
stats1 = DataPoint::Gauge.new(:name => "com.test.key1", :value => 5, :ts => ts)
|
33
|
+
stats2 = DataPoint::Gauge.new(:name => "com.test.key1", :value => 7, :ts => ts)
|
34
|
+
stats3 = DataPoint::Gauge.new(:name => "com.test.key1", :value => 9, :ts => (ts + 60) )
|
35
35
|
|
36
36
|
results = ArrayAggregation.aggregate([stats1, stats2, stats3], "com.test.*")
|
37
37
|
results.should have(2).data_points
|
@@ -42,8 +42,8 @@ module SimpleMetrics
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it "raises NonMatchingTypesError if types are different" do
|
45
|
-
stats1 = DataPoint.
|
46
|
-
stats2 = DataPoint.
|
45
|
+
stats1 = DataPoint::Counter.new(:name => "com.test.key1", :value => 5, :ts => ts)
|
46
|
+
stats2 = DataPoint::Gauge.new(:name => "com.test.key1", :value => 5, :ts => ts)
|
47
47
|
expect { ArrayAggregation.aggregate([stats1, stats2], "com.test.*") }.to raise_error(SimpleMetrics::DataPoint::NonMatchingTypesError)
|
48
48
|
end
|
49
49
|
end
|
data/spec/bucket_spec.rb
CHANGED
@@ -43,7 +43,7 @@ module SimpleMetrics
|
|
43
43
|
end
|
44
44
|
|
45
45
|
let(:stats) do
|
46
|
-
DataPoint.
|
46
|
+
DataPoint::Counter.new(:name => "key1", :value => 5)
|
47
47
|
end
|
48
48
|
|
49
49
|
it "saves given data in bucket" do
|
@@ -71,8 +71,8 @@ module SimpleMetrics
|
|
71
71
|
|
72
72
|
describe "#find_all_at_ts" do
|
73
73
|
it "returns all stats in given timestamp" do
|
74
|
-
stats1 = DataPoint.
|
75
|
-
stats2 = DataPoint.
|
74
|
+
stats1 = DataPoint::Counter.new(:name => "key1", :value => 5)
|
75
|
+
stats2 = DataPoint::Counter.new(:name => "key2", :value => 3)
|
76
76
|
|
77
77
|
bucket.save(stats1, ts)
|
78
78
|
bucket.save(stats2, bucket.next_ts_bucket(ts))
|
@@ -89,9 +89,9 @@ module SimpleMetrics
|
|
89
89
|
|
90
90
|
describe "#find_all_in_ts_range_by_wildcard" do
|
91
91
|
it "returns all stats for given name and timestamp" do
|
92
|
-
stats1 = DataPoint.
|
93
|
-
stats2 = DataPoint.
|
94
|
-
stats_different = DataPoint.
|
92
|
+
stats1 = DataPoint::Counter.new(:name => "com.test.key1", :value => 5)
|
93
|
+
stats2 = DataPoint::Counter.new(:name => "com.test.key2", :value => 7)
|
94
|
+
stats_different = DataPoint::Counter.new(:name => "com.test2.key1", :value => 3)
|
95
95
|
|
96
96
|
from = bucket.ts_bucket(ts)
|
97
97
|
to = from
|
@@ -109,7 +109,7 @@ module SimpleMetrics
|
|
109
109
|
|
110
110
|
describe "#fill_gaps" do
|
111
111
|
it "returns stats and fills missing gaps with null entries" do
|
112
|
-
stats = DataPoint.
|
112
|
+
stats = DataPoint::Counter.new(:name => "com.test.key1", :value => 5)
|
113
113
|
|
114
114
|
from = ts - 10
|
115
115
|
to = ts + 10
|
@@ -134,102 +134,5 @@ module SimpleMetrics
|
|
134
134
|
end
|
135
135
|
end # describe "finder methods"
|
136
136
|
|
137
|
-
describe "#aggregate_all" do
|
138
|
-
before do
|
139
|
-
DataPointRepository.truncate_collections
|
140
|
-
DataPointRepository.ensure_collections_exist
|
141
|
-
end
|
142
|
-
|
143
|
-
it "aggregates all counter data points" do
|
144
|
-
stats1a = DataPoint.create_counter(:name => "key1", :value => 5)
|
145
|
-
stats1b = DataPoint.create_counter(:name => "key1", :value => 7)
|
146
|
-
stats2 = DataPoint.create_counter(:name => "key2", :value => 3)
|
147
|
-
|
148
|
-
bucket2 = Bucket[1]
|
149
|
-
ts_at_insert = bucket2.previous_ts_bucket(ts)
|
150
|
-
bucket.save(stats1a, ts_at_insert)
|
151
|
-
Bucket.aggregate(stats1a)
|
152
|
-
bucket.save(stats1b, ts_at_insert)
|
153
|
-
Bucket.aggregate(stats1b)
|
154
|
-
bucket.save(stats2, ts_at_insert)
|
155
|
-
Bucket.aggregate(stats2)
|
156
|
-
|
157
|
-
results = bucket2.find_all_at_ts(ts_at_insert)
|
158
|
-
results.should have(2).items
|
159
|
-
|
160
|
-
key1_result = results.find {|stat| stat.name == "key1"}
|
161
|
-
key1_result.value.should == 12
|
162
|
-
key1_result.should be_counter
|
163
|
-
|
164
|
-
key2_result = results.find {|stat| stat.name == "key2"}
|
165
|
-
key2_result.value.should == 3
|
166
|
-
key2_result.should be_counter
|
167
|
-
end
|
168
|
-
|
169
|
-
it "aggregates all gauge data points" do
|
170
|
-
stats1a = DataPoint.create_gauge(:name => "key1", :value => 5)
|
171
|
-
stats1b = DataPoint.create_gauge(:name => "key1", :value => 7)
|
172
|
-
stats2 = DataPoint.create_gauge(:name => "key2", :value => 3)
|
173
|
-
|
174
|
-
bucket2 = Bucket[1]
|
175
|
-
ts_at_insert = bucket2.previous_ts_bucket(ts)
|
176
|
-
bucket.save(stats1a, ts_at_insert)
|
177
|
-
Bucket.aggregate(stats1a)
|
178
|
-
bucket.save(stats1b, ts_at_insert)
|
179
|
-
Bucket.aggregate(stats1b)
|
180
|
-
bucket.save(stats2, ts_at_insert)
|
181
|
-
Bucket.aggregate(stats2)
|
182
|
-
|
183
|
-
results = bucket2.find_all_at_ts(ts_at_insert)
|
184
|
-
results.should have(2).items
|
185
|
-
|
186
|
-
key1_result = results.find {|stat| stat.name == "key1"}
|
187
|
-
key1_result.value.should == 6
|
188
|
-
key1_result.should be_gauge
|
189
|
-
|
190
|
-
key2_result = results.find {|stat| stat.name == "key2"}
|
191
|
-
key2_result.value.should == 3
|
192
|
-
key2_result.should be_gauge
|
193
|
-
end
|
194
|
-
|
195
|
-
end # describe "#aggregate_all"
|
196
|
-
|
197
|
-
describe "#flush_data_points" do
|
198
|
-
before do
|
199
|
-
DataPointRepository.truncate_collections
|
200
|
-
DataPointRepository.ensure_collections_exist
|
201
|
-
|
202
|
-
stats1 = DataPoint.create_counter(:name => "key1", :value => 5)
|
203
|
-
stats2 = DataPoint.create_counter(:name => "key1", :value => 7)
|
204
|
-
stats3 = DataPoint.create_counter(:name => "key2", :value => 3)
|
205
|
-
@stats = [stats1, stats2, stats3]
|
206
|
-
end
|
207
|
-
|
208
|
-
it "saves all stats in finest/first bucket" do
|
209
|
-
Bucket.flush_data_points(@stats)
|
210
|
-
|
211
|
-
results = bucket.find_all_at_ts(ts)
|
212
|
-
results.should have(2).items
|
213
|
-
end
|
214
|
-
|
215
|
-
it "saves all stats and aggregate if duplicates found" do
|
216
|
-
Bucket.flush_data_points(@stats)
|
217
|
-
|
218
|
-
results = bucket.find_all_at_ts(ts)
|
219
|
-
results.should have(2).items
|
220
|
-
results.first.name.should == "key1"
|
221
|
-
results.last.name.should == "key2"
|
222
|
-
results.first.value == 12
|
223
|
-
results.last.value == 3
|
224
|
-
end
|
225
|
-
|
226
|
-
it "raises error if name matches but type does not" do
|
227
|
-
stats4 = DataPoint.create_gauge(:name => "key1", :value => 3)
|
228
|
-
input = @stats + [stats4]
|
229
|
-
expect { Bucket.flush_data_points(input) }.to raise_error(SimpleMetrics::DataPoint::NonMatchingTypesError)
|
230
|
-
end
|
231
|
-
|
232
|
-
end # describe "#flush_data_points"
|
233
|
-
|
234
137
|
end
|
235
138
|
end
|
@@ -20,7 +20,7 @@ module SimpleMetrics
|
|
20
20
|
|
21
21
|
describe "#save" do
|
22
22
|
it "saves data point correctly" do
|
23
|
-
dp = DataPoint.
|
23
|
+
dp = DataPoint::Counter.new(:name => "key", :ts => ts)
|
24
24
|
repository.save(dp)
|
25
25
|
|
26
26
|
results = repository.find_all_at_ts(ts)
|
@@ -30,8 +30,8 @@ module SimpleMetrics
|
|
30
30
|
|
31
31
|
describe "#find_all_at_ts" do
|
32
32
|
it "returns all data points at given time stamp" do
|
33
|
-
dp1 = DataPoint.
|
34
|
-
dp2 = DataPoint.
|
33
|
+
dp1 = DataPoint::Counter.new(:name => "key1", :ts => ts)
|
34
|
+
dp2 = DataPoint::Counter.new(:name => "key1", :ts => ts + 10)
|
35
35
|
repository.save(dp1)
|
36
36
|
repository.save(dp2)
|
37
37
|
|
@@ -41,27 +41,11 @@ module SimpleMetrics
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
describe "#find_all_in_ts_range" do
|
45
|
-
it "returns all data points in given time stamp range" do
|
46
|
-
dp1 = DataPoint.create_counter(:name => "key1", :ts => ts)
|
47
|
-
dp2 = DataPoint.create_counter(:name => "key2", :ts => ts + 10)
|
48
|
-
dp3 = DataPoint.create_counter(:name => "key3", :ts => ts + 20)
|
49
|
-
repository.save(dp1)
|
50
|
-
repository.save(dp2)
|
51
|
-
repository.save(dp3)
|
52
|
-
|
53
|
-
results = repository.find_all_in_ts_range(ts, ts+10)
|
54
|
-
results.should have(2).data_points
|
55
|
-
results.first.name.should == "key1"
|
56
|
-
results.last.name.should == "key2"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
44
|
describe "#find_all_in_ts_range_by_name" do
|
61
45
|
it "returns all data points in given time stamp range by name" do
|
62
|
-
dp1 = DataPoint.
|
63
|
-
dp2 = DataPoint.
|
64
|
-
dp3 = DataPoint.
|
46
|
+
dp1 = DataPoint::Counter.new(:name => "key1", :ts => ts)
|
47
|
+
dp2 = DataPoint::Counter.new(:name => "key2", :ts => ts + 10)
|
48
|
+
dp3 = DataPoint::Counter.new(:name => "key3", :ts => ts + 20)
|
65
49
|
repository.save(dp1)
|
66
50
|
repository.save(dp2)
|
67
51
|
repository.save(dp3)
|
@@ -74,9 +58,9 @@ module SimpleMetrics
|
|
74
58
|
|
75
59
|
describe "#find_all_in_ts_range_by_wildcard" do
|
76
60
|
it "returns all data points in given time stamp range by wildcard" do
|
77
|
-
dp1 = DataPoint.
|
78
|
-
dp2 = DataPoint.
|
79
|
-
dp3 = DataPoint.
|
61
|
+
dp1 = DataPoint::Counter.new(:name => "test.key1", :ts => ts)
|
62
|
+
dp2 = DataPoint::Counter.new(:name => "test.key2", :ts => ts + 10)
|
63
|
+
dp3 = DataPoint::Counter.new(:name => "test.key3", :ts => ts + 20)
|
80
64
|
repository.save(dp1)
|
81
65
|
repository.save(dp2)
|
82
66
|
repository.save(dp3)
|
@@ -88,27 +72,6 @@ module SimpleMetrics
|
|
88
72
|
end
|
89
73
|
end
|
90
74
|
|
91
|
-
describe "#count_at" do
|
92
|
-
it "returns the total count of entries for given time stamp" do
|
93
|
-
dp1 = DataPoint.create_counter(:name => "test.key1", :ts => ts)
|
94
|
-
dp2 = DataPoint.create_counter(:name => "test.key2", :ts => ts + 10)
|
95
|
-
repository.save(dp1)
|
96
|
-
repository.save(dp2)
|
97
|
-
repository.count_at(ts).should == 1
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
describe "#find_all_distinct_names" do
|
102
|
-
it "returns all distinct names of data points" do
|
103
|
-
dp1 = DataPoint.create_counter(:name => "test.key1", :ts => ts)
|
104
|
-
dp2 = DataPoint.create_counter(:name => "test.key2", :ts => ts + 10)
|
105
|
-
repository.save(dp1)
|
106
|
-
repository.save(dp2)
|
107
|
-
results = repository.find_all_distinct_names
|
108
|
-
results.should include("test.key1")
|
109
|
-
results.should include("test.key2")
|
110
|
-
end
|
111
|
-
end
|
112
75
|
end
|
113
76
|
|
114
77
|
end
|
data/spec/graph_spec.rb
CHANGED
@@ -21,7 +21,7 @@ module SimpleMetrics
|
|
21
21
|
describe "#query" do
|
22
22
|
|
23
23
|
it "returns string request data points as is" do
|
24
|
-
dp1 = DataPoint.
|
24
|
+
dp1 = DataPoint::Counter.new(:name => "key1", :value => 5)
|
25
25
|
|
26
26
|
bucket.save(dp1, ts)
|
27
27
|
|
@@ -34,7 +34,7 @@ module SimpleMetrics
|
|
34
34
|
end
|
35
35
|
|
36
36
|
it "returns string request data points and fill graps" do
|
37
|
-
dp1 = DataPoint.
|
37
|
+
dp1 = DataPoint::Counter.new(:name => "key1", :value => 5)
|
38
38
|
|
39
39
|
bucket.save(dp1, ts)
|
40
40
|
|
@@ -49,8 +49,8 @@ module SimpleMetrics
|
|
49
49
|
end
|
50
50
|
|
51
51
|
it "returns wildcard request data points with aggregate counter" do
|
52
|
-
dp1 = DataPoint.
|
53
|
-
dp2 = DataPoint.
|
52
|
+
dp1 = DataPoint::Counter.new(:name => "com.test.key1", :value => 5)
|
53
|
+
dp2 = DataPoint::Counter.new(:name => "com.test.key2", :value => 7)
|
54
54
|
|
55
55
|
bucket.save(dp1, ts)
|
56
56
|
bucket.save(dp2, ts)
|
@@ -66,6 +66,35 @@ module SimpleMetrics
|
|
66
66
|
result.should be_counter
|
67
67
|
end
|
68
68
|
|
69
|
+
end # descibe
|
70
|
+
|
71
|
+
describe "#query_all" do
|
72
|
+
|
73
|
+
it "returns request data points as is" do
|
74
|
+
dp1 = DataPoint::Counter.new(:name => "com.test.key1", :value => 5)
|
75
|
+
dp2 = DataPoint::Counter.new(:name => "com.test.key2", :value => 7)
|
76
|
+
dp3 = DataPoint::Counter.new(:name => "com.test.key2", :value => 3)
|
77
|
+
bucket.save(dp1, ts)
|
78
|
+
bucket.save(dp2, ts - 10)
|
79
|
+
bucket.save(dp3, ts)
|
80
|
+
|
81
|
+
current_ts = bucket.ts_bucket(ts)
|
82
|
+
from = current_ts - 10
|
83
|
+
to = current_ts
|
84
|
+
results = Graph.query_all(bucket, from, to, "com.test.key1", "com.test.key2")
|
85
|
+
key1 = results.first
|
86
|
+
key1[:name].should == "com.test.key1"
|
87
|
+
key1[:data].should have(2).entry
|
88
|
+
key1[:data].first[:y].should == 0
|
89
|
+
key1[:data].last[:y].should == 5
|
90
|
+
|
91
|
+
key2 = results.last
|
92
|
+
key2[:name].should == "com.test.key2"
|
93
|
+
key2[:data].should have(2).entry
|
94
|
+
key2[:data].first[:y].should == 7
|
95
|
+
key2[:data].last[:y].should == 3
|
96
|
+
end
|
97
|
+
|
69
98
|
end
|
70
99
|
end
|
71
100
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
module SimpleMetrics
|
5
|
+
|
6
|
+
describe Importer do
|
7
|
+
|
8
|
+
let(:bucket) do
|
9
|
+
Bucket.first
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:ts) do
|
13
|
+
Time.now.utc.to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#aggregate_coarse_buckets" do
|
17
|
+
before do
|
18
|
+
DataPointRepository.truncate_collections
|
19
|
+
DataPointRepository.ensure_collections_exist
|
20
|
+
end
|
21
|
+
|
22
|
+
it "aggregates all counter data points" do
|
23
|
+
stats1a = DataPoint::Counter.new(:name => "key1", :value => 5)
|
24
|
+
stats1b = DataPoint::Counter.new(:name => "key1", :value => 7)
|
25
|
+
stats2 = DataPoint::Counter.new(:name => "key2", :value => 3)
|
26
|
+
|
27
|
+
bucket2 = Bucket[1]
|
28
|
+
ts_at_insert = bucket2.previous_ts_bucket(ts)
|
29
|
+
bucket.save(stats1a, ts_at_insert)
|
30
|
+
Importer.aggregate_coarse_buckets(stats1a)
|
31
|
+
bucket.save(stats1b, ts_at_insert)
|
32
|
+
Importer.aggregate_coarse_buckets(stats1b)
|
33
|
+
bucket.save(stats2, ts_at_insert)
|
34
|
+
Importer.aggregate_coarse_buckets(stats2)
|
35
|
+
|
36
|
+
results = bucket2.find_all_at_ts(ts_at_insert)
|
37
|
+
results.should have(2).items
|
38
|
+
|
39
|
+
key1_result = results.find {|stat| stat.name == "key1"}
|
40
|
+
key1_result.value.should == 12
|
41
|
+
key1_result.should be_counter
|
42
|
+
|
43
|
+
key2_result = results.find {|stat| stat.name == "key2"}
|
44
|
+
key2_result.value.should == 3
|
45
|
+
key2_result.should be_counter
|
46
|
+
end
|
47
|
+
|
48
|
+
it "aggregates all gauge data points" do
|
49
|
+
stats1a = DataPoint::Gauge.new(:name => "key1", :value => 5)
|
50
|
+
stats1b = DataPoint::Gauge.new(:name => "key1", :value => 7)
|
51
|
+
stats2 = DataPoint::Gauge.new(:name => "key2", :value => 3)
|
52
|
+
|
53
|
+
bucket2 = Bucket[1]
|
54
|
+
ts_at_insert = bucket2.previous_ts_bucket(ts)
|
55
|
+
bucket.save(stats1a, ts_at_insert)
|
56
|
+
Importer.aggregate_coarse_buckets(stats1a)
|
57
|
+
bucket.save(stats1b, ts_at_insert)
|
58
|
+
Importer.aggregate_coarse_buckets(stats1b)
|
59
|
+
bucket.save(stats2, ts_at_insert)
|
60
|
+
Importer.aggregate_coarse_buckets(stats2)
|
61
|
+
|
62
|
+
results = bucket2.find_all_at_ts(ts_at_insert)
|
63
|
+
results.should have(2).items
|
64
|
+
|
65
|
+
key1_result = results.find {|stat| stat.name == "key1"}
|
66
|
+
key1_result.value.should == 6
|
67
|
+
key1_result.should be_gauge
|
68
|
+
|
69
|
+
key2_result = results.find {|stat| stat.name == "key2"}
|
70
|
+
key2_result.value.should == 3
|
71
|
+
key2_result.should be_gauge
|
72
|
+
end
|
73
|
+
|
74
|
+
end # describe "#aggregate_all"
|
75
|
+
|
76
|
+
describe "#flush_data_points" do
|
77
|
+
before do
|
78
|
+
DataPointRepository.truncate_collections
|
79
|
+
DataPointRepository.ensure_collections_exist
|
80
|
+
MetricRepository.truncate_collections
|
81
|
+
|
82
|
+
stats1 = DataPoint::Counter.new(:name => "key1", :value => 5)
|
83
|
+
stats2 = DataPoint::Counter.new(:name => "key1", :value => 7)
|
84
|
+
stats3 = DataPoint::Counter.new(:name => "key2", :value => 3)
|
85
|
+
@stats = [stats1, stats2, stats3]
|
86
|
+
end
|
87
|
+
|
88
|
+
it "saves all stats in finest/first bucket" do
|
89
|
+
Importer.flush_data_points(@stats)
|
90
|
+
|
91
|
+
results = bucket.find_all_at_ts(ts)
|
92
|
+
results.should have(2).items
|
93
|
+
end
|
94
|
+
|
95
|
+
it "saves all stats and aggregate if duplicates found" do
|
96
|
+
Importer.flush_data_points(@stats)
|
97
|
+
|
98
|
+
results = bucket.find_all_at_ts(ts)
|
99
|
+
results.should have(2).items
|
100
|
+
results.first.name.should == "key1"
|
101
|
+
results.last.name.should == "key2"
|
102
|
+
results.first.value == 12
|
103
|
+
results.last.value == 3
|
104
|
+
end
|
105
|
+
|
106
|
+
it "raises error if name matches but type does not" do
|
107
|
+
stats4 = DataPoint::Gauge.new(:name => "key1", :value => 3)
|
108
|
+
input = @stats + [stats4]
|
109
|
+
expect { Importer.flush_data_points(input) }.to raise_error(SimpleMetrics::DataPoint::NonMatchingTypesError)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "increments metrics counter" do
|
113
|
+
Importer.flush_data_points(@stats)
|
114
|
+
key1 = MetricRepository.find_one_by_name("key1")
|
115
|
+
key1.name.should == "key1"
|
116
|
+
key1.total.should == 2
|
117
|
+
key2 = MetricRepository.find_one_by_name("key2")
|
118
|
+
key2.name.should == "key2"
|
119
|
+
key2.total.should == 1
|
120
|
+
end
|
121
|
+
|
122
|
+
end # describe "#flush_data_points"
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
data/spec/spec_helper.rb
CHANGED