simple_metrics 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -1,7 +1,8 @@
1
1
  module SimpleMetrics
2
2
  class Metric
3
3
 
4
- attr_reader :id, :name, :total, :created_at, :updated_at
4
+ attr_reader :id, :name, :created_at, :updated_at
5
+ attr_accessor :total
5
6
 
6
7
  def initialize(attributes)
7
8
  @id = attributes[:id]
@@ -237,7 +237,7 @@ $(function(){
237
237
  routes: {
238
238
  "": "home",
239
239
  "metrics": "metrics",
240
- "metrics/:id": "metric_details",
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(id) {
254
- console.log("ROUTER: metric details:", id);
253
+ metric_details: function(name) {
254
+ console.log("ROUTER: metric details:", name);
255
255
 
256
- metric = new Metric({ id: id});
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['options'])
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['prefix'] || 'development'
18
+ config[:prefix] || 'development'
19
19
  end
20
20
 
21
21
  def host
22
- config['host'] || 'localhost'
22
+ config[:host] || 'localhost'
23
23
  end
24
24
 
25
25
  def port
26
- config['port'] || 27017
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.flush_raw_data(ClientHandler.get_and_clear_data) }
47
+ EM.defer { Bucket.flush_raw(ClientHandler.get_and_clear_data) }
48
48
  end
49
49
  end
50
50
  end
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module SimpleMetrics
3
- VERSION = "0.3.2"
3
+ VERSION = "0.3.3"
4
4
  end
@@ -56,7 +56,7 @@
56
56
  <tbody>
57
57
  {{#each metrics}}
58
58
  <tr>
59
- <td><a href="#metrics/{{id}}">{{name}}</a></td>
59
+ <td><a href="#metrics/{{name}}">{{name}}</a></td>
60
60
  <td>{{total}}</td>
61
61
  <td>{{updated_at}}</td>
62
62
  </tr>
@@ -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/update_aggregation"
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.create_counter(:name => "com.test.key1", :value => 5, :ts => ts)
20
- stats2 = DataPoint.create_counter(:name => "com.test.key1", :value => 7, :ts => ts)
21
- stats3 = DataPoint.create_counter(:name => "com.test.key1", :value => 9, :ts => (ts + 60) )
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.create_gauge(:name => "com.test.key1", :value => 5, :ts => ts)
33
- stats2 = DataPoint.create_gauge(:name => "com.test.key1", :value => 7, :ts => ts)
34
- stats3 = DataPoint.create_gauge(:name => "com.test.key1", :value => 9, :ts => (ts + 60) )
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.create_counter(:name => "com.test.key1", :value => 5, :ts => ts)
46
- stats2 = DataPoint.create_gauge(:name => "com.test.key1", :value => 5, :ts => ts)
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.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
@@ -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.create_counter(:name => "key1", :value => 5)
75
- 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)
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.create_counter(:name => "com.test.key1", :value => 5)
93
- stats2 = DataPoint.create_counter(:name => "com.test.key2", :value => 7)
94
- 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)
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.create_counter(:name => "com.test.key1", :value => 5)
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.create_counter(:name => "key", :ts => ts)
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.create_counter(:name => "key1", :ts => ts)
34
- dp2 = DataPoint.create_counter(:name => "key1", :ts => ts + 10)
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.create_counter(:name => "key1", :ts => ts)
63
- dp2 = DataPoint.create_counter(:name => "key2", :ts => ts + 10)
64
- dp3 = DataPoint.create_counter(:name => "key3", :ts => ts + 20)
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.create_counter(:name => "test.key1", :ts => ts)
78
- dp2 = DataPoint.create_counter(:name => "test.key2", :ts => ts + 10)
79
- dp3 = DataPoint.create_counter(:name => "test.key3", :ts => ts + 20)
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.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,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
@@ -6,5 +6,5 @@ end
6
6
 
7
7
  SimpleMetrics.logger = Logger.new('/dev/null')
8
8
  SimpleMetrics.configure do |config|
9
- config.db = { 'host' => 'localhost', 'prefix' => 'test', 'options' => {} }
9
+ config.db = { :host => 'localhost', :prefix => 'test', :options => {} }
10
10
  end