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