simple_metrics 0.4.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.travis.yml +3 -0
  2. data/README.markdown +7 -59
  3. data/Rakefile +17 -0
  4. data/bin/populate +25 -12
  5. data/bin/populate_for_demo +65 -0
  6. data/bin/simple_metrics_server +4 -3
  7. data/config.ru +13 -0
  8. data/default_config.yml +34 -0
  9. data/lib/simple_metrics/bucket.rb +43 -106
  10. data/lib/simple_metrics/configuration.rb +82 -0
  11. data/lib/simple_metrics/dashboard.rb +29 -0
  12. data/lib/simple_metrics/dashboard_repository.rb +59 -0
  13. data/lib/simple_metrics/data_point/base.rb +59 -0
  14. data/lib/simple_metrics/data_point/counter.rb +20 -0
  15. data/lib/simple_metrics/data_point/event.rb +16 -0
  16. data/lib/simple_metrics/data_point/gauge.rb +19 -0
  17. data/lib/simple_metrics/data_point/timing.rb +15 -0
  18. data/lib/simple_metrics/data_point.rb +45 -137
  19. data/lib/simple_metrics/data_point_repository.rb +115 -0
  20. data/lib/simple_metrics/functions.rb +5 -5
  21. data/lib/simple_metrics/graph.rb +69 -32
  22. data/lib/simple_metrics/importer.rb +64 -0
  23. data/lib/simple_metrics/instrument.rb +28 -0
  24. data/lib/simple_metrics/instrument_repository.rb +64 -0
  25. data/lib/simple_metrics/metric.rb +29 -0
  26. data/lib/simple_metrics/metric_repository.rb +54 -0
  27. data/lib/simple_metrics/repository.rb +34 -0
  28. data/lib/simple_metrics/udp_server.rb +81 -0
  29. data/lib/simple_metrics/version.rb +1 -1
  30. data/lib/simple_metrics.rb +21 -76
  31. data/simple_metrics.gemspec +4 -0
  32. data/spec/bucket_spec.rb +17 -152
  33. data/spec/dashboard_repository_spec.rb +52 -0
  34. data/spec/data_point_repository_spec.rb +77 -0
  35. data/spec/data_point_spec.rb +14 -64
  36. data/spec/graph_spec.rb +30 -19
  37. data/spec/importer_spec.rb +126 -0
  38. data/spec/instrument_repository_spec.rb +52 -0
  39. data/spec/metric_repository_spec.rb +53 -0
  40. data/spec/spec_helper.rb +4 -3
  41. metadata +93 -23
  42. data/bin/simple_metrics_client +0 -64
  43. data/lib/simple_metrics/client.rb +0 -83
  44. data/lib/simple_metrics/mongo.rb +0 -48
  45. data/lib/simple_metrics/server.rb +0 -66
data/spec/bucket_spec.rb CHANGED
@@ -37,17 +37,17 @@ module SimpleMetrics
37
37
 
38
38
  describe "#save" do
39
39
  before do
40
- Mongo.truncate_collections
41
- Mongo.ensure_collections_exist
40
+ DataPointRepository.truncate_collections
41
+ DataPointRepository.ensure_collections_exist
42
42
  bucket.save(stats, ts)
43
43
  end
44
44
 
45
45
  let(:stats) do
46
- DataPoint.create_counter(:name => "key1", :value => 5)
46
+ DataPoint::Counter.new(:name => "key1", :value => 5)
47
47
  end
48
48
 
49
49
  it "saves given data in bucket" do
50
- results = bucket.find_all_by_name("key1")
50
+ results = bucket.find_all_at_ts(ts)
51
51
  results.should have(1).item
52
52
  result = results.first
53
53
  result.name.should == stats.name
@@ -56,7 +56,7 @@ module SimpleMetrics
56
56
  end
57
57
 
58
58
  it "saves data in correct timestamp" do
59
- result = bucket.find_all_by_name("key1").first
59
+ result = bucket.find_all_at_ts(ts).first
60
60
  result.ts.should == ts/sec*sec
61
61
  end
62
62
 
@@ -65,68 +65,33 @@ module SimpleMetrics
65
65
  describe "finder methods" do
66
66
 
67
67
  before do
68
- Mongo.truncate_collections
69
- Mongo.ensure_collections_exist
68
+ DataPointRepository.truncate_collections
69
+ DataPointRepository.ensure_collections_exist
70
70
  end
71
71
 
72
- describe "#find_all_by_name" do
73
- it "returns all stats for given name" do
74
- stats_same1 = DataPoint.create_counter(:name => "key1", :value => 5)
75
- stats_same2 = DataPoint.create_counter(:name => "key1", :value => 3)
76
- stats_different = DataPoint.create_counter(:name => "key2", :value => 3)
77
-
78
- bucket.save(stats_same1, ts)
79
- bucket.save(stats_same2, ts)
80
- bucket.save(stats_different, ts)
81
-
82
- results = bucket.find_all_by_name("key1")
83
- results.should have(2).items
84
- results.first.name.should == stats_same1.name
85
- end
86
- end
87
-
88
- describe "#find_all_in_ts" do
72
+ describe "#find_all_at_ts" do
89
73
  it "returns all stats in given timestamp" do
90
- stats1 = DataPoint.create_counter(:name => "key1", :value => 5)
91
- stats2 = DataPoint.create_counter(:name => "key2", :value => 3)
74
+ stats1 = DataPoint::Counter.new(:name => "key1", :value => 5)
75
+ stats2 = DataPoint::Counter.new(:name => "key2", :value => 3)
92
76
 
93
77
  bucket.save(stats1, ts)
94
78
  bucket.save(stats2, bucket.next_ts_bucket(ts))
95
79
 
96
- result1 = bucket.find_all_in_ts(ts).first
80
+ result1 = bucket.find_all_at_ts(ts).first
97
81
  result1.name.should == stats1.name
98
82
  result1.value.should == stats1.value
99
83
 
100
- result2 = bucket.find_all_in_ts(bucket.next_ts_bucket(ts)).first
84
+ result2 = bucket.find_all_at_ts(bucket.next_ts_bucket(ts)).first
101
85
  result2.name.should == stats2.name
102
86
  result2.value.should == stats2.value
103
87
  end
104
88
  end
105
89
 
106
- describe "#find_all_in_ts_by_name" do
107
- it "returns all stats for given name and timestamp" do
108
- stats1a = DataPoint.create_counter(:name => "key1", :value => 5)
109
- stats1b = DataPoint.create_counter(:name => "key1", :value => 7)
110
- stats2 = DataPoint.create_counter(:name => "key2", :value => 7)
111
- stats1_different_ts = DataPoint.create_counter(:name => "key1", :value => 3)
112
-
113
- bucket.save(stats1a, ts)
114
- bucket.save(stats1b, ts)
115
- bucket.save(stats2, ts)
116
- bucket.save(stats1_different_ts, bucket.next_ts_bucket(ts))
117
-
118
- results = bucket.find_all_in_ts_by_name(ts, "key1")
119
- results.should have(2).items
120
- results.first.name.should == "key1"
121
- results.last.name.should == "key1"
122
- end
123
- end
124
-
125
- describe "#find_all_in_ts_by_wildcard" do
90
+ describe "#find_all_in_ts_range_by_wildcard" do
126
91
  it "returns all stats for given name and timestamp" do
127
- stats1 = DataPoint.create_counter(:name => "com.test.key1", :value => 5)
128
- stats2 = DataPoint.create_counter(:name => "com.test.key2", :value => 7)
129
- stats_different = DataPoint.create_counter(:name => "com.test2.key1", :value => 3)
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)
130
95
 
131
96
  from = bucket.ts_bucket(ts)
132
97
  to = from
@@ -144,7 +109,7 @@ module SimpleMetrics
144
109
 
145
110
  describe "#fill_gaps" do
146
111
  it "returns stats and fills missing gaps with null entries" do
147
- stats = DataPoint.create_counter(:name => "com.test.key1", :value => 5)
112
+ stats = DataPoint::Counter.new(:name => "com.test.key1", :value => 5)
148
113
 
149
114
  from = ts - 10
150
115
  to = ts + 10
@@ -169,105 +134,5 @@ module SimpleMetrics
169
134
  end
170
135
  end # describe "finder methods"
171
136
 
172
- describe "#aggregate_all" do
173
- before do
174
- Mongo.truncate_collections
175
- Mongo.ensure_collections_exist
176
- end
177
-
178
- it "aggregates all counter data points" do
179
- stats1a = DataPoint.create_counter(:name => "key1", :value => 5)
180
- stats1b = DataPoint.create_counter(:name => "key1", :value => 7)
181
- stats2 = DataPoint.create_counter(:name => "key2", :value => 3)
182
-
183
- bucket2 = Bucket[1]
184
- ts_at_insert = bucket2.previous_ts_bucket(ts)
185
- bucket.save(stats1a, ts_at_insert)
186
- bucket.save(stats1b, ts_at_insert)
187
- bucket.save(stats2, ts_at_insert)
188
-
189
- Bucket.aggregate_all(ts)
190
-
191
- results = bucket2.find_all_in_ts(ts_at_insert)
192
- results.should have(2).items
193
-
194
- key1_result = results.find {|stat| stat.name == "key1"}
195
- key1_result.value.should == 12
196
- key1_result.should be_counter
197
-
198
- key2_result = results.find {|stat| stat.name == "key2"}
199
- key2_result.value.should == 3
200
- key2_result.should be_counter
201
- end
202
-
203
- it "aggregates all gauge data points" do
204
- stats1a = DataPoint.create_gauge(:name => "key1", :value => 5)
205
- stats1b = DataPoint.create_gauge(:name => "key1", :value => 7)
206
- stats2 = DataPoint.create_gauge(:name => "key2", :value => 3)
207
-
208
- bucket2 = Bucket[1]
209
- ts_at_insert = bucket2.previous_ts_bucket(ts)
210
- bucket.save(stats1a, ts_at_insert)
211
- bucket.save(stats1b, ts_at_insert)
212
- bucket.save(stats2, ts_at_insert)
213
-
214
- Bucket.aggregate_all(ts)
215
-
216
- results = bucket2.find_all_in_ts(ts_at_insert)
217
- results.should have(2).items
218
-
219
- key1_result = results.find {|stat| stat.name == "key1"}
220
- key1_result.value.should == 6
221
- key1_result.should be_gauge
222
-
223
- key2_result = results.find {|stat| stat.name == "key2"}
224
- key2_result.value.should == 3
225
- key2_result.should be_gauge
226
- end
227
-
228
- end # describe "#aggregate_all"
229
-
230
- describe "#flush_data_points" do
231
- before do
232
- Mongo.truncate_collections
233
- Mongo.ensure_collections_exist
234
-
235
- stats1 = DataPoint.create_counter(:name => "key1", :value => 5)
236
- stats2 = DataPoint.create_counter(:name => "key1", :value => 7)
237
- stats3 = DataPoint.create_counter(:name => "key2", :value => 3)
238
- @stats = [stats1, stats2, stats3]
239
- end
240
-
241
- it "saves all stats in finest/first bucket" do
242
- Bucket.flush_data_points(@stats)
243
-
244
- results = bucket.find_all_in_ts(ts)
245
- results.should have(2).items
246
- end
247
-
248
- it "calls aggregate_all afterwards" do
249
- mock(Bucket).aggregate_all(ts)
250
- Bucket.flush_data_points(@stats)
251
- end
252
-
253
- it "saves all stats and aggregate if duplicates found" do
254
- Bucket.flush_data_points(@stats)
255
-
256
- results = bucket.find_all_in_ts(ts)
257
- results.should have(2).items
258
- results.first.name.should == "key1"
259
- results.last.name.should == "key2"
260
- results.first.value == 12
261
- results.last.value == 3
262
- end
263
-
264
- it "raises error if name matches but type does not" do
265
- stats4 = DataPoint.create_gauge(:name => "key1", :value => 3)
266
- input = @stats + [stats4]
267
- expect { Bucket.flush_data_points(input) }.to raise_error(SimpleMetrics::DataPoint::NonMatchingTypesError)
268
- end
269
-
270
- end # describe "#flush_data_points"
271
-
272
137
  end
273
138
  end
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ module SimpleMetrics
5
+
6
+ describe DashboardRepository do
7
+
8
+ before do
9
+ DashboardRepository.truncate_collections
10
+ end
11
+
12
+ let(:ts) do
13
+ Time.now.utc.to_i
14
+ end
15
+
16
+ describe "#save" do
17
+ it "saves dashboard correctly" do
18
+ dashboard = Dashboard.new(:name => "test")
19
+ DashboardRepository.save(dashboard)
20
+
21
+ results = DashboardRepository.find_all
22
+ results.should have(1).dashboard
23
+ results.first.name.should == "test"
24
+ end
25
+ end
26
+
27
+ describe "#find_all" do
28
+ it "returns all dashboards" do
29
+ dashboard1 = Dashboard.new(:name => "test")
30
+ dashboard2 = Dashboard.new(:name => "test2")
31
+ DashboardRepository.save(dashboard1)
32
+ DashboardRepository.save(dashboard2)
33
+
34
+ results = DashboardRepository.find_all
35
+ results.should have(2).dashboards
36
+ end
37
+ end
38
+
39
+ describe "#find_one_by_name" do
40
+ it "returns all dashboards" do
41
+ dashboard1 = Dashboard.new(:name => "test")
42
+ dashboard2 = Dashboard.new(:name => "test2")
43
+ DashboardRepository.save(dashboard1)
44
+ DashboardRepository.save(dashboard2)
45
+
46
+ result = DashboardRepository.find_one_by_name("test")
47
+ result.name.should == "test"
48
+ end
49
+ end
50
+ end # describe DashboardRepository
51
+
52
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ module SimpleMetrics
5
+
6
+ describe DataPointRepository do
7
+
8
+ before do
9
+ DataPointRepository.truncate_collections
10
+ DataPointRepository.ensure_collections_exist
11
+ end
12
+
13
+ let(:ts) do
14
+ Time.now.utc.to_i
15
+ end
16
+
17
+ let(:repository) do
18
+ DataPointRepository.for_retention('stats_per_10s')
19
+ end
20
+
21
+ describe "#save" do
22
+ it "saves data point correctly" do
23
+ dp = DataPoint::Counter.new(:name => "key", :ts => ts)
24
+ repository.save(dp)
25
+
26
+ results = repository.find_all_at_ts(ts)
27
+ results.should have(1).data_point
28
+ end
29
+ end
30
+
31
+ describe "#find_all_at_ts" do
32
+ it "returns all data points at given time stamp" do
33
+ dp1 = DataPoint::Counter.new(:name => "key1", :ts => ts)
34
+ dp2 = DataPoint::Counter.new(:name => "key1", :ts => ts + 10)
35
+ repository.save(dp1)
36
+ repository.save(dp2)
37
+
38
+ results = repository.find_all_at_ts(ts)
39
+ results.should have(1).data_point
40
+ results.first.name.should == "key1"
41
+ end
42
+ end
43
+
44
+ describe "#find_all_in_ts_range_by_name" do
45
+ it "returns all data points in given time stamp range by name" do
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)
49
+ repository.save(dp1)
50
+ repository.save(dp2)
51
+ repository.save(dp3)
52
+
53
+ results = repository.find_all_in_ts_range_by_name(ts, ts+10, "key1")
54
+ results.should have(1).data_point
55
+ results.first.name.should == "key1"
56
+ end
57
+ end
58
+
59
+ describe "#find_all_in_ts_range_by_wildcard" do
60
+ it "returns all data points in given time stamp range by wildcard" do
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)
64
+ repository.save(dp1)
65
+ repository.save(dp2)
66
+ repository.save(dp3)
67
+
68
+ results = repository.find_all_in_ts_range_by_wildcard(ts, ts+10, "test.*")
69
+ results.should have(2).data_point2
70
+ results.first.name.should == "test.key1"
71
+ results.last.name.should == "test.key2"
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -54,78 +54,28 @@ module SimpleMetrics
54
54
  end
55
55
 
56
56
  it "parses increment timing with sample rate" do
57
+ # TODO
57
58
  end
58
- end
59
-
59
+ end # describe
60
60
 
61
61
  describe "#aggregate" do
62
- it "aggregates counter data points" do
63
- stats1 = DataPoint.create_counter(:name => "key1", :value => 5)
64
- stats2 = DataPoint.create_counter(:name => "key1", :value => 7)
65
- result = DataPoint.aggregate([stats1, stats2])
66
- result.value.should == 12
67
- result.name.should == "key1"
68
- result.should be_counter
69
- end
70
62
 
71
- it "aggregates counter data points with custom name" do
72
- stats1 = DataPoint.create_counter(:name => "key1", :value => 5)
73
- stats2 = DataPoint.create_counter(:name => "key1", :value => 7)
74
- result = DataPoint.aggregate([stats1, stats2], "new_name")
75
- result.value.should == 12
76
- result.name.should == "new_name"
77
- result.should be_counter
78
- end
79
-
80
- it "aggregates gauge data points" do
81
- stats1 = DataPoint.create_gauge(:name => "key1", :value => 5)
82
- stats2 = DataPoint.create_gauge(:name => "key1", :value => 7)
83
- result = DataPoint.aggregate([stats1, stats2])
84
- result.value.should == 6
63
+ it "aggregate counters" do
64
+ key1 = DataPoint::Counter.new(:name => "key1", :value => 1)
65
+ key2 = DataPoint::Counter.new(:name => "key1", :value => 3)
66
+ result = DataPoint.aggregate_values([key1, key2])
85
67
  result.name.should == "key1"
86
- result.should be_gauge
68
+ result.value.should == 4
87
69
  end
88
70
 
89
- it "aggregates timing data points" do
90
- end
91
-
92
- it "aggregates event data points" do
93
- end
94
- end
95
-
96
- describe "#aggregate_array" do
97
- it "aggregates counter data points" do
98
- stats1 = DataPoint.create_counter(:name => "com.test.key1", :value => 5, :ts => ts)
99
- stats2 = DataPoint.create_counter(:name => "com.test.key1", :value => 7, :ts => ts)
100
- stats3 = DataPoint.create_counter(:name => "com.test.key1", :value => 9, :ts => (ts + 60) )
101
-
102
- results = DataPoint.aggregate_array([stats1, stats2, stats3], "com.test.*")
103
- results.should have(2).data_points
104
- results.first.name.should == "com.test.*"
105
- results.last.name.should == "com.test.*"
106
- results.first.value.should == 12
107
- results.last.value.should == 9
71
+ it "aggregate gauges" do
72
+ key1 = DataPoint::Gauge.new(:name => "key1", :value => 1)
73
+ key2 = DataPoint::Gauge.new(:name => "key1", :value => 3)
74
+ result = DataPoint.aggregate_values([key1, key2])
75
+ result.name.should == "key1"
76
+ result.value.should == 2
108
77
  end
109
78
 
110
- it "aggregates gauge data points" do
111
- stats1 = DataPoint.create_gauge(:name => "com.test.key1", :value => 5, :ts => ts)
112
- stats2 = DataPoint.create_gauge(:name => "com.test.key1", :value => 7, :ts => ts)
113
- stats3 = DataPoint.create_gauge(:name => "com.test.key1", :value => 9, :ts => (ts + 60) )
114
-
115
- results = DataPoint.aggregate_array([stats1, stats2, stats3], "com.test.*")
116
- results.should have(2).data_points
117
- results.first.name.should == "com.test.*"
118
- results.last.name.should == "com.test.*"
119
- results.first.value.should == 6
120
- results.last.value.should == 9
121
- end
122
-
123
- it "raises NonMatchingTypesError if types are different" do
124
- stats1 = DataPoint.create_counter(:name => "com.test.key1", :value => 5, :ts => ts)
125
- stats2 = DataPoint.create_gauge(:name => "com.test.key1", :value => 5, :ts => ts)
126
- expect { DataPoint.aggregate_array([stats1, stats2], "com.test.*") }.to raise_error(SimpleMetrics::DataPoint::NonMatchingTypesError)
127
- end
128
- end
79
+ end # describe
129
80
  end
130
-
131
81
  end
data/spec/graph_spec.rb CHANGED
@@ -14,14 +14,14 @@ module SimpleMetrics
14
14
  end
15
15
 
16
16
  before do
17
- Mongo.truncate_collections
18
- Mongo.ensure_collections_exist
17
+ DataPointRepository.truncate_collections
18
+ DataPointRepository.ensure_collections_exist
19
19
  end
20
20
 
21
21
  describe "#query" do
22
22
 
23
23
  it "returns string request data points as is" do
24
- dp1 = DataPoint.create_counter(:name => "key1", :value => 5)
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.create_counter(:name => "key1", :value => 5)
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.create_counter(:name => "com.test.key1", :value => 5)
53
- dp2 = DataPoint.create_counter(:name => "com.test.key2", :value => 7)
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,24 +66,35 @@ module SimpleMetrics
66
66
  result.should be_counter
67
67
  end
68
68
 
69
- it "returns regexp request data points with aggregate gauge" do
70
- dp1 = DataPoint.create_gauge(:name => "com.test.key1", :value => 5)
71
- dp2 = DataPoint.create_gauge(:name => "com.test.key2", :value => 7)
69
+ end # descibe
72
70
 
73
- bucket.save(dp1, ts)
74
- bucket.save(dp2, ts)
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)
75
80
 
76
81
  current_ts = bucket.ts_bucket(ts)
77
- from = current_ts
82
+ from = current_ts - 10
78
83
  to = current_ts
79
-
80
- results = Graph.query(bucket, from, to, /com\.test(.*)/)
81
- results.should have(1).data_point
82
- result = results.first
83
- result.name.should == "/com\\.test(.*)/"
84
- result.value.should == 6
85
- result.should be_gauge
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
86
96
  end
97
+
87
98
  end
88
99
  end
89
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