simple_metrics 0.2.3 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +3 -0
- data/README.markdown +16 -53
- data/Rakefile +17 -0
- data/bin/populate +26 -13
- data/bin/simple_metrics_server +4 -3
- data/bin/simple_metrics_web +11 -0
- data/config.ru +6 -0
- data/default_config.yml +34 -0
- data/lib/simple_metrics/app.rb +136 -0
- data/lib/simple_metrics/array_aggregation.rb +84 -0
- data/lib/simple_metrics/bucket.rb +74 -63
- data/lib/simple_metrics/configuration.rb +79 -0
- data/lib/simple_metrics/data_point/base.rb +59 -0
- data/lib/simple_metrics/data_point/counter.rb +13 -0
- data/lib/simple_metrics/data_point/event.rb +12 -0
- data/lib/simple_metrics/data_point/gauge.rb +13 -0
- data/lib/simple_metrics/data_point/timing.rb +12 -0
- data/lib/simple_metrics/data_point.rb +32 -136
- data/lib/simple_metrics/data_point_repository.rb +131 -0
- data/lib/simple_metrics/functions.rb +5 -5
- data/lib/simple_metrics/graph.rb +10 -14
- data/lib/simple_metrics/metric.rb +28 -0
- data/lib/simple_metrics/metric_repository.rb +54 -0
- data/lib/simple_metrics/public/css/bootstrap-responsive.min.css +12 -0
- data/lib/simple_metrics/public/css/bootstrap.min.css +689 -0
- data/lib/simple_metrics/public/css/graph.css +45 -0
- data/lib/simple_metrics/public/css/rickshaw.min.css +1 -0
- data/lib/simple_metrics/public/img/glyphicons-halflings-white.png +0 -0
- data/lib/simple_metrics/public/img/glyphicons-halflings.png +0 -0
- data/lib/simple_metrics/public/js/application.js +278 -0
- data/lib/simple_metrics/public/js/backbone-0.9.2.min.js +38 -0
- data/lib/simple_metrics/public/js/bootstrap.min.js +6 -0
- data/lib/simple_metrics/public/js/d3.v2.min.js +4 -0
- data/lib/simple_metrics/public/js/handlebars-1.0.0.beta.6.js +1550 -0
- data/lib/simple_metrics/public/js/jquery-1.7.1.min.js +4 -0
- data/lib/simple_metrics/public/js/rickshaw.min.js +1 -0
- data/lib/simple_metrics/public/js/underscore-1.3.1.min.js +31 -0
- data/lib/simple_metrics/repository.rb +34 -0
- data/lib/simple_metrics/udp_server.rb +81 -0
- data/lib/simple_metrics/update_aggregation.rb +62 -0
- data/lib/simple_metrics/value_aggregation.rb +63 -0
- data/lib/simple_metrics/version.rb +1 -1
- data/lib/simple_metrics/views/graph.erb +93 -0
- data/lib/simple_metrics/views/index.erb +0 -0
- data/lib/simple_metrics/views/layout.erb +119 -0
- data/lib/simple_metrics/views/show.erb +31 -0
- data/lib/simple_metrics.rb +19 -76
- data/simple_metrics.gemspec +6 -0
- data/spec/array_aggregation_spec.rb +51 -0
- data/spec/bucket_spec.rb +24 -62
- data/spec/data_point_repository_spec.rb +114 -0
- data/spec/data_point_spec.rb +1 -70
- data/spec/graph_spec.rb +2 -20
- data/spec/metric_repository_spec.rb +53 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/value_aggregation_spec.rb +52 -0
- metadata +131 -24
- data/bin/simple_metrics_client +0 -64
- data/lib/simple_metrics/client.rb +0 -83
- data/lib/simple_metrics/mongo.rb +0 -48
- data/lib/simple_metrics/server.rb +0 -66
@@ -5,7 +5,7 @@ module SimpleMetrics
|
|
5
5
|
class << self
|
6
6
|
|
7
7
|
def all
|
8
|
-
@@all ||= SimpleMetrics.
|
8
|
+
@@all ||= SimpleMetrics.config.buckets.map { |r| Bucket.new(r) }
|
9
9
|
end
|
10
10
|
|
11
11
|
def first
|
@@ -17,44 +17,62 @@ module SimpleMetrics
|
|
17
17
|
all[index]
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
20
|
+
def flush_raw_data(data)
|
21
|
+
data_points = []
|
22
|
+
data.each do |str|
|
23
|
+
begin
|
24
|
+
data_points << DataPoint.parse(str)
|
25
|
+
rescue DataPoint::ParserError => e
|
26
|
+
SimpleMetrics.logger.debug "Invalid Data skipped: #{str}, #{e}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
flush_data_points(data_points, Time.now.utc.to_i)
|
22
30
|
end
|
23
31
|
|
24
|
-
def flush_data_points(data_points)
|
32
|
+
def flush_data_points(data_points, ts = nil)
|
25
33
|
return if data_points.empty?
|
26
34
|
SimpleMetrics.logger.info "#{Time.now} Flushing #{data_points.count} counters to MongoDB"
|
27
35
|
|
28
|
-
ts
|
36
|
+
ts ||= Time.now.utc.to_i
|
29
37
|
bucket = Bucket.first
|
30
|
-
data_points.group_by { |data| data.name }.each_pair do |name,dps|
|
31
|
-
data = DataPoint.aggregate(dps)
|
32
|
-
bucket.save(data, ts)
|
33
|
-
end
|
34
38
|
|
35
|
-
|
39
|
+
data_points.group_by { |dp| dp.name }.each_pair do |name,dps|
|
40
|
+
dp = ValueAggregation.aggregate(dps)
|
41
|
+
bucket.save(dp, ts)
|
42
|
+
update_metric(dp)
|
43
|
+
aggregate(dp)
|
44
|
+
end
|
36
45
|
end
|
37
46
|
|
38
|
-
def
|
39
|
-
ts_bucket = self.first.ts_bucket(ts)
|
40
|
-
|
47
|
+
def aggregate(dp)
|
41
48
|
coarse_buckets.each do |bucket|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
bucket.save(data, previous_ts)
|
51
|
-
end
|
49
|
+
existing_dp = bucket.find_data_point_at_ts(dp.ts, dp.name)
|
50
|
+
if existing_dp
|
51
|
+
UpdateAggregation.aggregate(existing_dp, dp)
|
52
|
+
bucket.update(existing_dp, existing_dp.ts)
|
53
|
+
else
|
54
|
+
dp.sum = dp.value
|
55
|
+
dp.total = 1
|
56
|
+
bucket.save(dp, dp.ts)
|
52
57
|
end
|
53
58
|
end
|
54
59
|
end
|
55
60
|
|
56
61
|
private
|
57
62
|
|
63
|
+
def update_metric(dp)
|
64
|
+
metric = MetricRepository.find_one_by_name(dp.name)
|
65
|
+
if metric
|
66
|
+
MetricRepository.update(Metric.new(:name => dp.name, :total => metric.total + 1))
|
67
|
+
else
|
68
|
+
MetricRepository.save(Metric.new(:name => dp.name, :total => 1))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def coarse_buckets
|
73
|
+
Bucket.all.sort_by! { |r| r.seconds }[1..-1]
|
74
|
+
end
|
75
|
+
|
58
76
|
def humanized_timestamp(ts)
|
59
77
|
Time.at(ts).utc
|
60
78
|
end
|
@@ -63,10 +81,10 @@ module SimpleMetrics
|
|
63
81
|
attr_reader :name, :capped
|
64
82
|
|
65
83
|
def initialize(attributes)
|
66
|
-
@name = attributes[
|
67
|
-
@seconds = attributes[
|
68
|
-
@capped = attributes[
|
69
|
-
@size = attributes[
|
84
|
+
@name = attributes['name']
|
85
|
+
@seconds = attributes['seconds']
|
86
|
+
@capped = attributes['capped']
|
87
|
+
@size = attributes['size']
|
70
88
|
end
|
71
89
|
|
72
90
|
def seconds
|
@@ -78,7 +96,7 @@ module SimpleMetrics
|
|
78
96
|
end
|
79
97
|
|
80
98
|
def ts_bucket(ts)
|
81
|
-
ts / seconds * seconds
|
99
|
+
(ts / seconds) * seconds
|
82
100
|
end
|
83
101
|
|
84
102
|
def next_ts_bucket(ts)
|
@@ -89,70 +107,59 @@ module SimpleMetrics
|
|
89
107
|
ts_bucket(ts) - seconds
|
90
108
|
end
|
91
109
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
|
97
|
-
def find_all_by_name(name)
|
98
|
-
mongo_result = mongo_coll.find({ :name => name }).to_a
|
99
|
-
mongo_result.inject([]) { |result, a| result << DataPoint.create_from_db(a) }
|
100
|
-
end
|
101
|
-
|
102
|
-
def find_all_in_ts(ts)
|
103
|
-
mongo_result = mongo_coll.find({ :ts => ts_bucket(ts) }).to_a
|
104
|
-
mongo_result.inject([]) { |result, a| result << DataPoint.create_from_db(a) }
|
110
|
+
# TODO: only used in tests, do we need it?
|
111
|
+
def find_all_at_ts(ts)
|
112
|
+
repository.find_all_at_ts(ts_bucket(ts))
|
105
113
|
end
|
106
114
|
|
107
|
-
def
|
108
|
-
|
109
|
-
mongo_result.inject([]) { |result, a| result << DataPoint.create_from_db(a) }
|
115
|
+
def find_data_point_at_ts(ts, name)
|
116
|
+
repository.find_data_point_at_ts(ts_bucket(ts), name)
|
110
117
|
end
|
111
118
|
|
119
|
+
# TODO: only used in tests, do we need it?
|
112
120
|
def find_all_in_ts_range(from, to)
|
113
|
-
|
114
|
-
mongo_result.inject([]) { |result, a| result << DataPoint.create_from_db(a) }
|
121
|
+
repository.find_all_in_ts_range(from, to)
|
115
122
|
end
|
116
123
|
|
117
124
|
def find_all_in_ts_range_by_name(from, to, name)
|
118
|
-
|
119
|
-
mongo_result.inject([]) { |result, a| result << DataPoint.create_from_db(a) }
|
125
|
+
repository.find_all_in_ts_range_by_name(from, to, name)
|
120
126
|
end
|
121
127
|
|
122
128
|
def find_all_in_ts_range_by_wildcard(from, to, target)
|
123
|
-
|
124
|
-
target = target.gsub('*', '.*')
|
125
|
-
mongo_result = mongo_coll.find({ :name => /#{target}/, :ts => { "$gte" => from, "$lte" => to } }).to_a
|
126
|
-
mongo_result.inject([]) { |result, a| result << DataPoint.create_from_db(a) }
|
129
|
+
repository.find_all_in_ts_range_by_wildcard(from, to, target)
|
127
130
|
end
|
128
131
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
+
# TODO: only used in tests, do we need it?
|
133
|
+
def data_points_exist_at_ts?(ts, name)
|
134
|
+
repository.count_for_name_at(ts, name) > 0
|
132
135
|
end
|
133
136
|
|
137
|
+
# TODO: only used in tests, do we need it?
|
134
138
|
def stats_exist_in_previous_ts?(ts)
|
135
|
-
|
139
|
+
repository.count_at(ts) > 0
|
136
140
|
end
|
137
141
|
|
138
142
|
def find_all_distinct_names
|
139
|
-
|
143
|
+
repository.find_all_distinct_names
|
140
144
|
end
|
141
145
|
|
142
|
-
def save(
|
143
|
-
|
144
|
-
|
145
|
-
SimpleMetrics.logger.debug "SERVER: MongoDB - insert in #{name}: #{
|
146
|
+
def save(dp, ts)
|
147
|
+
dp.ts = ts_bucket(ts)
|
148
|
+
repository.save(dp)
|
149
|
+
SimpleMetrics.logger.debug "SERVER: MongoDB - insert in #{name}: #{dp.inspect}"
|
146
150
|
end
|
147
151
|
|
148
|
-
def
|
149
|
-
|
152
|
+
def update(dp, ts)
|
153
|
+
dp.ts = ts_bucket(ts)
|
154
|
+
repository.update(dp, ts)
|
155
|
+
SimpleMetrics.logger.debug "SERVER: MongoDB - update in #{name}: #{dp.inspect}"
|
150
156
|
end
|
151
157
|
|
152
158
|
def capped?
|
153
159
|
@capped == true
|
154
160
|
end
|
155
161
|
|
162
|
+
# TODO refactor, move to graph.rb
|
156
163
|
def fill_gaps(from, to, query_result)
|
157
164
|
return query_result if query_result.nil? || query_result.size == 0
|
158
165
|
|
@@ -176,6 +183,10 @@ module SimpleMetrics
|
|
176
183
|
|
177
184
|
private
|
178
185
|
|
186
|
+
def repository
|
187
|
+
DataPointRepository.for_retention(name)
|
188
|
+
end
|
189
|
+
|
179
190
|
def each_ts(from, to)
|
180
191
|
current_bucket_ts = ts_bucket(from)
|
181
192
|
while (current_bucket_ts <= ts_bucket(to))
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module SimpleMetrics
|
4
|
+
class Configuration
|
5
|
+
|
6
|
+
attr_reader :config
|
7
|
+
|
8
|
+
def initialize(hash = {}, &block)
|
9
|
+
@config = load_defaults.merge(hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure(hash = {}, &block)
|
13
|
+
yield self if block_given?
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def db
|
18
|
+
@db ||= config['db']
|
19
|
+
end
|
20
|
+
|
21
|
+
def db=(db)
|
22
|
+
@db = db
|
23
|
+
end
|
24
|
+
|
25
|
+
def buckets
|
26
|
+
@buckets ||= config['buckets']
|
27
|
+
end
|
28
|
+
|
29
|
+
def buckets=(buckets)
|
30
|
+
@buckets = buckets
|
31
|
+
end
|
32
|
+
|
33
|
+
def server
|
34
|
+
@server ||= config['server']
|
35
|
+
end
|
36
|
+
|
37
|
+
def server=(server)
|
38
|
+
@server = server
|
39
|
+
end
|
40
|
+
|
41
|
+
def web
|
42
|
+
@web ||= config['web']
|
43
|
+
end
|
44
|
+
|
45
|
+
def web=(web)
|
46
|
+
@web = web
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def load_defaults
|
52
|
+
@config = load_config
|
53
|
+
rescue Errno::ENOENT # not found error
|
54
|
+
logger.info "Creating initial config file: #{config_file}"
|
55
|
+
FileUtils.cp(default_config_file, config_file)
|
56
|
+
@config = load_config
|
57
|
+
end
|
58
|
+
|
59
|
+
def config_file
|
60
|
+
File.expand_path('~/.simple_metrics.conf')
|
61
|
+
end
|
62
|
+
|
63
|
+
def default_config_file
|
64
|
+
File.expand_path('../../../default_config.yml', __FILE__)
|
65
|
+
end
|
66
|
+
|
67
|
+
def load_config
|
68
|
+
YAML.load_file(config_file)
|
69
|
+
rescue ArgumentError => e
|
70
|
+
logger.error "Error parsing config file: #{e}"
|
71
|
+
rescue IOError => e
|
72
|
+
logger.error "Error reading config file: #{e}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def logger
|
76
|
+
SimpleMetrics.logger
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module SimpleMetrics
|
3
|
+
module DataPoint
|
4
|
+
class Base
|
5
|
+
|
6
|
+
attr_accessor :name, :ts, :type, :value, :total, :sum
|
7
|
+
attr_reader :id
|
8
|
+
|
9
|
+
def initialize(attributes)
|
10
|
+
@id = attributes[:id]
|
11
|
+
@name = attributes[:name]
|
12
|
+
@value = attributes[:value]
|
13
|
+
@ts = attributes[:ts]
|
14
|
+
@sample_rate = attributes[:sample_rate]
|
15
|
+
@sum = attributes[:sum]
|
16
|
+
@total = attributes[:total]
|
17
|
+
end
|
18
|
+
|
19
|
+
def counter?
|
20
|
+
@type == 'c'
|
21
|
+
end
|
22
|
+
|
23
|
+
def gauge?
|
24
|
+
@type == 'g'
|
25
|
+
end
|
26
|
+
|
27
|
+
def timing?
|
28
|
+
@type == 'ms'
|
29
|
+
end
|
30
|
+
|
31
|
+
def event?
|
32
|
+
@type == 'ev'
|
33
|
+
end
|
34
|
+
|
35
|
+
def timestamp
|
36
|
+
ts
|
37
|
+
end
|
38
|
+
|
39
|
+
def value
|
40
|
+
@value.to_i if @value
|
41
|
+
end
|
42
|
+
|
43
|
+
def attributes
|
44
|
+
{
|
45
|
+
:name => @name,
|
46
|
+
:value => @value,
|
47
|
+
:ts => @ts,
|
48
|
+
:type => @type,
|
49
|
+
:total => @total,
|
50
|
+
:sum => @sum
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
attributes.to_s
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
module SimpleMetrics
|
3
|
-
|
4
|
-
|
2
|
+
module DataPoint
|
3
|
+
extend self
|
5
4
|
|
6
5
|
class NonMatchingTypesError < Exception; end
|
7
6
|
class ParserError < Exception; end
|
7
|
+
class UnknownTypeError < Exception; end
|
8
8
|
|
9
9
|
# examples:
|
10
10
|
# com.example.test1:1|c
|
@@ -14,149 +14,45 @@ module SimpleMetrics
|
|
14
14
|
# com.example.test4:44|ms
|
15
15
|
REGEXP = /^([\d\w_.]*):(-?[\d]*)\|(c|g|ms){1}(\|@([.\d]+))?$/i
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# TODO: implement sample_rate handling
|
24
|
-
create_timing(:name => name, :value => value)
|
25
|
-
elsif type == "g"
|
26
|
-
create_gauge(:name => name, :value => (value.to_i || 1) * (1.0 / (sample_rate || 1).to_f) )
|
27
|
-
elsif type == "c"
|
28
|
-
create_counter(:name => name, :value => (value.to_i || 1) * (1.0 / (sample_rate || 1).to_f) )
|
29
|
-
end
|
30
|
-
else
|
31
|
-
raise ParserError, "Parser Error - Invalid Stat: #{str}"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def create_counter(attributes)
|
36
|
-
self.new(attributes.merge(:type => 'c'))
|
37
|
-
end
|
38
|
-
|
39
|
-
def create_gauge(attributes)
|
40
|
-
self.new(attributes.merge(:type => 'g'))
|
41
|
-
end
|
42
|
-
|
43
|
-
def create_timing(attributes)
|
44
|
-
self.new(attributes.merge(:type => 'ms'))
|
45
|
-
end
|
46
|
-
|
47
|
-
def aggregate(stats_array, name = nil)
|
48
|
-
raise NonMatchingTypesError unless stats_array.group_by { |stats| stats.type }.size == 1
|
49
|
-
|
50
|
-
result_stat = stats_array.first.dup
|
51
|
-
result_stat.name = name if name
|
52
|
-
if stats_array.first.counter?
|
53
|
-
result_stat.value = stats_array.map { |stats| stats.value }.inject(0) { |result, value| result += value }
|
54
|
-
result_stat
|
55
|
-
elsif stats_array.first.gauge?
|
56
|
-
total_value = stats_array.map { |stats| stats.value }.inject(0) { |result, value| result += value }
|
57
|
-
result_stat.value = total_value / stats_array.size
|
58
|
-
result_stat
|
59
|
-
elsif stats_array.first.timing?
|
60
|
-
# TODO implement timing aggregation
|
61
|
-
elsif stats_array.first.event?
|
62
|
-
# TODO implement event aggregation
|
63
|
-
else
|
64
|
-
raise ArgumentError, "Unknown data point type"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def aggregate_array(stats_array, name = nil)
|
69
|
-
raise NonMatchingTypesError unless stats_array.group_by { |stats| stats.type }.size == 1
|
70
|
-
|
71
|
-
if stats_array.first.counter?
|
72
|
-
tmp_hash = ts_hash_aggregated(stats_array) do |value1, value2|
|
73
|
-
value1 + value2
|
74
|
-
end
|
75
|
-
|
76
|
-
result = []
|
77
|
-
tmp_hash.each_pair do |key, value|
|
78
|
-
result << self.new(:name => name, :ts => key, :value => value, :type => 'c')
|
79
|
-
end
|
80
|
-
result
|
81
|
-
elsif stats_array.first.gauge?
|
82
|
-
tmp_hash = ts_hash_aggregated(stats_array) do |value1, value2|
|
83
|
-
(value1 + value2)/2
|
84
|
-
end
|
85
|
-
|
86
|
-
result = []
|
87
|
-
tmp_hash.each_pair do |key, value|
|
88
|
-
result << self.new(:name => name, :ts => key, :value => value, :type => 'g')
|
89
|
-
end
|
90
|
-
result
|
91
|
-
elsif stats_array.first.timing?
|
92
|
-
# TODO implement timing aggregation
|
93
|
-
elsif stats_array.first.event?
|
94
|
-
# TODO implement event aggregation
|
95
|
-
else
|
96
|
-
raise ArgumentError, "Unknown data point type"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def create_from_db(attributes)
|
101
|
-
self.new(:name => attributes["name"], :value => attributes["value"], :ts => attributes["ts"], :type => attributes["type"])
|
102
|
-
end
|
103
|
-
|
104
|
-
def ts_hash(query_result)
|
105
|
-
query_result.inject({}) { |result, dp| result[dp.ts] = dp; result }
|
106
|
-
end
|
107
|
-
|
108
|
-
private
|
109
|
-
|
110
|
-
def ts_hash_aggregated(data_points, &block)
|
111
|
-
tmp = {}
|
112
|
-
data_points.each do |dp|
|
113
|
-
if tmp.key?(dp.ts)
|
114
|
-
tmp[dp.ts] = block.call(tmp[dp.ts], dp.value)
|
115
|
-
else
|
116
|
-
tmp[dp.ts] = dp.value
|
117
|
-
end
|
118
|
-
end
|
119
|
-
tmp
|
17
|
+
def parse(str)
|
18
|
+
if str =~ REGEXP
|
19
|
+
name, value, type, sample_rate = $1, $2, $3, $5
|
20
|
+
build(:name => name, :value => value, :type => type, :sample_rate => sample_rate)
|
21
|
+
else
|
22
|
+
raise ParserError, "Parser Error - Invalid data point: #{str}"
|
120
23
|
end
|
121
24
|
end
|
122
25
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
def gauge?
|
137
|
-
type == 'g'
|
26
|
+
def build(attributes)
|
27
|
+
case attributes[:type]
|
28
|
+
when 'c'
|
29
|
+
DataPoint.create_counter(attributes)
|
30
|
+
when 'g'
|
31
|
+
Gauge.new(attributes)
|
32
|
+
when 'ms'
|
33
|
+
Timing.new(attributes)
|
34
|
+
when 'ev'
|
35
|
+
Event.new(attributes)
|
36
|
+
else
|
37
|
+
raise UnknownTypeError, "Unknown Type Error: #{attributes[:type]}"
|
38
|
+
end
|
138
39
|
end
|
139
40
|
|
140
|
-
def
|
141
|
-
|
41
|
+
def create_counter(attributes)
|
42
|
+
Counter.new(attributes)
|
142
43
|
end
|
143
44
|
|
144
|
-
def
|
145
|
-
|
45
|
+
def create_gauge(attributes)
|
46
|
+
Gauge.new(attributes)
|
146
47
|
end
|
147
48
|
|
148
|
-
def
|
149
|
-
|
49
|
+
def create_timing(attributes)
|
50
|
+
Timing.new(attributes)
|
150
51
|
end
|
151
52
|
|
152
|
-
def
|
153
|
-
{
|
154
|
-
:name => name,
|
155
|
-
:value => value,
|
156
|
-
:ts => ts,
|
157
|
-
:type => type
|
158
|
-
}
|
53
|
+
def ts_hash(query_result)
|
54
|
+
query_result.inject({}) { |result, dp| result[dp.ts] = dp; result }
|
159
55
|
end
|
160
|
-
|
56
|
+
|
161
57
|
end
|
162
|
-
end
|
58
|
+
end
|