simple_metrics 0.4.0 → 0.4.2

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.
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