simple_metrics 0.2.3 → 0.3.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.
- 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
|