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.
- data/.travis.yml +3 -0
- data/README.markdown +7 -59
- data/Rakefile +17 -0
- data/bin/populate +25 -12
- data/bin/populate_for_demo +65 -0
- data/bin/simple_metrics_server +4 -3
- data/config.ru +13 -0
- data/default_config.yml +34 -0
- data/lib/simple_metrics/bucket.rb +43 -106
- data/lib/simple_metrics/configuration.rb +82 -0
- data/lib/simple_metrics/dashboard.rb +29 -0
- data/lib/simple_metrics/dashboard_repository.rb +59 -0
- data/lib/simple_metrics/data_point/base.rb +59 -0
- data/lib/simple_metrics/data_point/counter.rb +20 -0
- data/lib/simple_metrics/data_point/event.rb +16 -0
- data/lib/simple_metrics/data_point/gauge.rb +19 -0
- data/lib/simple_metrics/data_point/timing.rb +15 -0
- data/lib/simple_metrics/data_point.rb +45 -137
- data/lib/simple_metrics/data_point_repository.rb +115 -0
- data/lib/simple_metrics/functions.rb +5 -5
- data/lib/simple_metrics/graph.rb +69 -32
- data/lib/simple_metrics/importer.rb +64 -0
- data/lib/simple_metrics/instrument.rb +28 -0
- data/lib/simple_metrics/instrument_repository.rb +64 -0
- data/lib/simple_metrics/metric.rb +29 -0
- data/lib/simple_metrics/metric_repository.rb +54 -0
- data/lib/simple_metrics/repository.rb +34 -0
- data/lib/simple_metrics/udp_server.rb +81 -0
- data/lib/simple_metrics/version.rb +1 -1
- data/lib/simple_metrics.rb +21 -76
- data/simple_metrics.gemspec +4 -0
- data/spec/bucket_spec.rb +17 -152
- data/spec/dashboard_repository_spec.rb +52 -0
- data/spec/data_point_repository_spec.rb +77 -0
- data/spec/data_point_spec.rb +14 -64
- data/spec/graph_spec.rb +30 -19
- data/spec/importer_spec.rb +126 -0
- data/spec/instrument_repository_spec.rb +52 -0
- data/spec/metric_repository_spec.rb +53 -0
- data/spec/spec_helper.rb +4 -3
- metadata +93 -23
- 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
data/.travis.yml
ADDED
data/README.markdown
CHANGED
@@ -9,78 +9,26 @@ Technically speaking it provides a simple UDP interface to send data to an Event
|
|
9
9
|
|
10
10
|
SimpleMetrics is written in Ruby and packaged as a gem.
|
11
11
|
|
12
|
-
The current version is considered ALPHA.
|
12
|
+
The current version is considered ALPHA.
|
13
13
|
|
14
|
-
|
15
|
-
--------------------
|
16
|
-
|
17
|
-
Commandline client:
|
18
|
-
|
19
|
-
Send a count of 5 for data point "module.test1":
|
20
|
-
|
21
|
-
simple_metrics_client module.test1 -counter 5
|
22
|
-
|
23
|
-
Send a timing of 100ms:
|
24
|
-
|
25
|
-
simple_metrics_client module.test1 -timing 100
|
26
|
-
|
27
|
-
doing the same, but since we expect a lot of calls we sample the data (10%):
|
28
|
-
|
29
|
-
simple_metrics_client module.test1 -timing 100 --sample_rate 0.1
|
30
|
-
|
31
|
-
more info:
|
32
|
-
|
33
|
-
simple_metrics_client --help
|
34
|
-
|
35
|
-
Ruby client API
|
36
|
-
---------------
|
37
|
-
|
38
|
-
Initialize client:
|
39
|
-
|
40
|
-
client = SimpleMetrics::Client.new("localhost")
|
41
|
-
|
42
|
-
sends "com.example.test1:1|c" via UDP:
|
43
|
-
|
44
|
-
client.increment("com.example.test1")
|
45
|
-
|
46
|
-
sends "com.example.test1:-1|c":
|
47
|
-
|
48
|
-
client.decrement("com.example.test1")
|
49
|
-
|
50
|
-
sends "com.example.test1:5|c" (a counter with a relative value of 5):
|
51
|
-
|
52
|
-
client.count("com.example.test1", 5)
|
53
|
-
|
54
|
-
sends "com.example.test1:5|c|@0.1" with a sample rate of 10%:
|
55
|
-
|
56
|
-
client.count("com.example.test1", 5, 0.1)
|
57
|
-
|
58
|
-
sends "com.example.test1:5|g" (meaning gauge, an absolute value of 5):
|
59
|
-
|
60
|
-
client.count("com.example.test1", 5)
|
61
|
-
|
62
|
-
sends "com.example.test1:100|ms":
|
63
|
-
|
64
|
-
client.timing("com.example.test1")
|
65
|
-
|
66
|
-
More examples in the examples/ directory.
|
14
|
+
There is a rails app provided to visualize the graphs in dashboards.
|
67
15
|
|
68
16
|
SimpleMetrics Server
|
69
17
|
--------------------
|
70
18
|
|
71
19
|
We provide a simple commandline wrapper using daemons gem (http://daemons.rubyforge.org/).
|
72
20
|
|
73
|
-
Start Server as background
|
21
|
+
Start Server as background daemon:
|
74
22
|
|
75
|
-
|
23
|
+
simple_metrics_server start
|
76
24
|
|
77
25
|
Start in foreground:
|
78
26
|
|
79
|
-
|
27
|
+
simple_metrics_server start -t
|
80
28
|
|
81
29
|
Show Help:
|
82
30
|
|
83
|
-
|
31
|
+
simple_metrics_server --help
|
84
32
|
|
85
33
|
Round Robin Database Principles in MongoDB
|
86
34
|
------------------------------------------
|
@@ -91,7 +39,7 @@ We use 4 collections in MongoDB each with more coarse timestamp buckets:
|
|
91
39
|
* 10 min
|
92
40
|
* 1 day
|
93
41
|
|
94
|
-
The
|
42
|
+
The 10sec and 1min collections are capped collections and have a fixed size. The others will store the data as long as there is sufficient disc space.
|
95
43
|
|
96
44
|
How can we map these times to graphs?
|
97
45
|
|
data/Rakefile
CHANGED
@@ -2,7 +2,24 @@ require "bundler/gem_tasks"
|
|
2
2
|
require 'rake'
|
3
3
|
require 'rspec/core/rake_task'
|
4
4
|
|
5
|
+
require 'simple_metrics'
|
6
|
+
|
5
7
|
RSpec::Core::RakeTask.new
|
6
8
|
task :default => :spec
|
7
9
|
task :test => :spec
|
8
10
|
|
11
|
+
namespace :simple_metrics do
|
12
|
+
|
13
|
+
desc "Ensure collections and index exist"
|
14
|
+
task :ensure_collections_exist do
|
15
|
+
SimpleMetrics.logger = Logger.new($stdout)
|
16
|
+
SimpleMetrics::DataPointRepository.ensure_collections_exist
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Truncate all collections"
|
20
|
+
task :truncate_collections do
|
21
|
+
SimpleMetrics.logger = Logger.new($stdout)
|
22
|
+
SimpleMetrics::DataPointRepository.truncate_collections
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/bin/populate
CHANGED
@@ -6,20 +6,33 @@ require "bundler/setup"
|
|
6
6
|
require 'optparse'
|
7
7
|
require "simple_metrics"
|
8
8
|
|
9
|
-
|
9
|
+
SimpleMetrics.logger = Logger.new("/dev/null")
|
10
|
+
SimpleMetrics::DataPointRepository.truncate_collections
|
11
|
+
SimpleMetrics::DataPointRepository.ensure_collections_exist
|
10
12
|
|
11
|
-
|
13
|
+
bucket = SimpleMetrics::Bucket.first
|
12
14
|
|
13
|
-
|
15
|
+
name = ENV['NAME'] || "test.page.visits.1"
|
16
|
+
now = Time.now.to_i
|
17
|
+
minute = 60
|
18
|
+
hour = minute * 60
|
14
19
|
|
15
|
-
|
16
|
-
|
20
|
+
def create_dps(name)
|
21
|
+
previous_value = 20
|
22
|
+
(1..1).inject([]) do |result, index|
|
23
|
+
value = previous_value+rand(20)
|
24
|
+
result << SimpleMetrics::DataPoint::Counter.new(:name => name, :value => value)
|
25
|
+
previous_value = value
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
17
29
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
30
|
+
counter = 1
|
31
|
+
current = now - 1 * hour
|
32
|
+
while (current < now)
|
33
|
+
dps = create_dps(name)
|
34
|
+
puts "flush data for #{Time.at(current)}, #{counter}"
|
35
|
+
SimpleMetrics::Importer.flush_data_points(dps, current)
|
36
|
+
current += 10
|
37
|
+
counter += 1
|
25
38
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler/setup"
|
5
|
+
|
6
|
+
require 'optparse'
|
7
|
+
require "simple_metrics"
|
8
|
+
|
9
|
+
SimpleMetrics.logger = Logger.new("/dev/null")
|
10
|
+
SimpleMetrics::DataPointRepository.truncate_collections
|
11
|
+
SimpleMetrics::DataPointRepository.ensure_collections_exist
|
12
|
+
SimpleMetrics::MetricRepository.truncate_collections
|
13
|
+
|
14
|
+
def create_dps(name)
|
15
|
+
previous_value = 20
|
16
|
+
(1..1).inject([]) do |result, index|
|
17
|
+
value = previous_value+rand(20)
|
18
|
+
result << SimpleMetrics::DataPoint::Counter.new(:name => name, :value => value)
|
19
|
+
previous_value = value
|
20
|
+
result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def flush_data_points(name)
|
25
|
+
#bucket = SimpleMetrics::Bucket.first
|
26
|
+
now = Time.now.to_i
|
27
|
+
minute = 60
|
28
|
+
hour = minute * 60
|
29
|
+
|
30
|
+
counter = 1
|
31
|
+
current = now - 1 * hour
|
32
|
+
while (current < now)
|
33
|
+
dps = create_dps(name)
|
34
|
+
puts "flush data for #{Time.at(current)}, #{counter}"
|
35
|
+
SimpleMetrics::Importer.flush_data_points(dps, current)
|
36
|
+
current += 10
|
37
|
+
counter += 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
name1 = "test.page.visits"
|
43
|
+
flush_data_points(name1)
|
44
|
+
name2 = "test.invoices.send"
|
45
|
+
flush_data_points(name2)
|
46
|
+
|
47
|
+
metric1 = SimpleMetrics::MetricRepository.find_one_by_name(name1)
|
48
|
+
metric2 = SimpleMetrics::MetricRepository.find_one_by_name(name2)
|
49
|
+
|
50
|
+
SimpleMetrics::InstrumentRepository.truncate_collections
|
51
|
+
instrument1 = SimpleMetrics::Instrument.new(:name => "Example Instrument 1", :metrics => [{ :name => metric1.name }, { :name => metric2.name}])
|
52
|
+
instrument2 = SimpleMetrics::Instrument.new(:name => "Example Instrument 2", :metrics => [{ :name => metric1.name} ])
|
53
|
+
instrument1.id = SimpleMetrics::InstrumentRepository.save(instrument1)
|
54
|
+
instrument2.id = SimpleMetrics::InstrumentRepository.save(instrument2)
|
55
|
+
|
56
|
+
puts instrument1.inspect
|
57
|
+
puts instrument2.inspect
|
58
|
+
10.times do |i|
|
59
|
+
instrument = SimpleMetrics::Instrument.new(:name => "Example Instrument Randmon #{i}", :metrics => [{ :name => metric1.name}])
|
60
|
+
SimpleMetrics::InstrumentRepository.save(instrument)
|
61
|
+
end
|
62
|
+
|
63
|
+
SimpleMetrics::DashboardRepository.truncate_collections
|
64
|
+
SimpleMetrics::DashboardRepository.save(SimpleMetrics::Dashboard.new(:name => "Example Dashboard 1", :instruments => [instrument1.id.to_s, instrument2.id.to_s]))
|
65
|
+
SimpleMetrics::DashboardRepository.save(SimpleMetrics::Dashboard.new(:name => "Example Dashboard 2", :instruments => [instrument1.id.to_s]))
|
data/bin/simple_metrics_server
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
|
3
5
|
require "rubygems"
|
4
|
-
require "bundler/setup"
|
5
6
|
require "simple_metrics"
|
6
7
|
require "daemons"
|
7
8
|
|
8
9
|
options = {
|
9
10
|
:backtrace => true,
|
10
11
|
:log_output => true,
|
11
|
-
:dir_mode => :script
|
12
|
+
:dir_mode => :script,
|
12
13
|
}
|
13
14
|
|
14
15
|
Daemons.run_proc("simple_metrics", options) do
|
15
|
-
SimpleMetrics::
|
16
|
+
SimpleMetrics::UDPServer.new.start
|
16
17
|
end
|
17
18
|
|
18
19
|
|
data/config.ru
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$LOAD_PATH.unshift ::File.expand_path(::File.dirname(__FILE__) + '/lib')
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "simple_metrics"
|
5
|
+
require "simple_metrics/app"
|
6
|
+
|
7
|
+
map "/assets" do
|
8
|
+
run SimpleMetrics::App.sprockets
|
9
|
+
end
|
10
|
+
|
11
|
+
map "/" do
|
12
|
+
run SimpleMetrics::App
|
13
|
+
end
|
data/default_config.yml
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
server:
|
2
|
+
host: 'localhost'
|
3
|
+
port: 8125
|
4
|
+
flush_interval: 10
|
5
|
+
|
6
|
+
db:
|
7
|
+
host: 'localhost'
|
8
|
+
port: 27017
|
9
|
+
prefix: 'development'
|
10
|
+
options:
|
11
|
+
pool_size: 5
|
12
|
+
timeout: 5
|
13
|
+
|
14
|
+
web:
|
15
|
+
host: 'localhost'
|
16
|
+
port: 5678
|
17
|
+
|
18
|
+
buckets:
|
19
|
+
- name: 'stats_per_10s'
|
20
|
+
seconds: 10
|
21
|
+
capped: true
|
22
|
+
size: 180_000 # 6*30 = 180 (30 min ttl), 180 * 100 = 18.000 (100 data points), 18.000 * 10 (bytes each) = 180.000
|
23
|
+
- name: 'stats_per_1min'
|
24
|
+
seconds: 60
|
25
|
+
capped: true
|
26
|
+
size: 120_000 # 60*3 = 180 (3h ttl), 120 * 100 = 18.000 (100 data points), 18.000 * 10 (bytes each) = 180.000
|
27
|
+
- name: 'stats_per_10min'
|
28
|
+
seconds: 600
|
29
|
+
size: 0
|
30
|
+
capped: false
|
31
|
+
- name: 'stats_per_day'
|
32
|
+
seconds: 86400 # 600*6*24
|
33
|
+
size: 0
|
34
|
+
capped: false
|
@@ -5,68 +5,39 @@ 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
|
12
12
|
all.first
|
13
13
|
end
|
14
|
-
alias :finest :first
|
15
14
|
|
16
15
|
def [](index)
|
17
16
|
all[index]
|
18
17
|
end
|
19
18
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
35
|
-
self.aggregate_all(ts)
|
36
|
-
end
|
37
|
-
|
38
|
-
def aggregate_all(ts)
|
39
|
-
ts_bucket = self.first.ts_bucket(ts)
|
40
|
-
|
41
|
-
coarse_buckets.each do |bucket|
|
42
|
-
current_ts = bucket.ts_bucket(ts_bucket)
|
43
|
-
previous_ts = bucket.previous_ts_bucket(ts_bucket)
|
44
|
-
SimpleMetrics.logger.debug "Aggregating #{bucket.name} #{previous_ts}....#{current_ts} (#{humanized_timestamp(previous_ts)}..#{humanized_timestamp(current_ts)})"
|
45
|
-
|
46
|
-
unless bucket.stats_exist_in_previous_ts?(previous_ts)
|
47
|
-
data_points = self.first.find_all_in_ts_range(previous_ts, current_ts)
|
48
|
-
data_points.group_by { |data| data.name }.each_pair do |name,dps|
|
49
|
-
data = DataPoint.aggregate(dps)
|
50
|
-
bucket.save(data, previous_ts)
|
51
|
-
end
|
52
|
-
end
|
19
|
+
def for_time(time)
|
20
|
+
case time
|
21
|
+
when 'minute'
|
22
|
+
self[0]
|
23
|
+
when 'hour'
|
24
|
+
self[1]
|
25
|
+
when 'day'
|
26
|
+
self[2]
|
27
|
+
when 'week'
|
28
|
+
self[3]
|
53
29
|
end
|
54
30
|
end
|
55
31
|
|
56
|
-
private
|
57
|
-
|
58
|
-
def humanized_timestamp(ts)
|
59
|
-
Time.at(ts).utc
|
60
|
-
end
|
61
32
|
end
|
62
33
|
|
63
34
|
attr_reader :name, :capped
|
64
35
|
|
65
36
|
def initialize(attributes)
|
66
|
-
@name = attributes
|
67
|
-
@seconds = attributes
|
68
|
-
@capped = attributes
|
69
|
-
@size = attributes
|
37
|
+
@name = attributes.fetch(:name)
|
38
|
+
@seconds = attributes.fetch(:seconds)
|
39
|
+
@capped = attributes.fetch(:capped)
|
40
|
+
@size = attributes.fetch(:size)
|
70
41
|
end
|
71
42
|
|
72
43
|
def seconds
|
@@ -78,7 +49,7 @@ module SimpleMetrics
|
|
78
49
|
end
|
79
50
|
|
80
51
|
def ts_bucket(ts)
|
81
|
-
ts / seconds * seconds
|
52
|
+
(ts / seconds) * seconds
|
82
53
|
end
|
83
54
|
|
84
55
|
def next_ts_bucket(ts)
|
@@ -89,64 +60,33 @@ module SimpleMetrics
|
|
89
60
|
ts_bucket(ts) - seconds
|
90
61
|
end
|
91
62
|
|
92
|
-
|
93
|
-
|
94
|
-
|
63
|
+
# TODO: only used in tests, do we need it?
|
64
|
+
def find_all_at_ts(ts)
|
65
|
+
repository.find_all_at_ts(ts_bucket(ts))
|
95
66
|
end
|
96
67
|
|
97
|
-
def
|
98
|
-
|
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) }
|
105
|
-
end
|
106
|
-
|
107
|
-
def find_all_in_ts_by_name(ts, name)
|
108
|
-
mongo_result = mongo_coll.find({ :ts => ts_bucket(ts), :name => name }).to_a
|
109
|
-
mongo_result.inject([]) { |result, a| result << DataPoint.create_from_db(a) }
|
110
|
-
end
|
111
|
-
|
112
|
-
def find_all_in_ts_range(from, to)
|
113
|
-
mongo_result = mongo_coll.find({ :ts => { "$gte" => from, "$lte" => to }}).to_a
|
114
|
-
mongo_result.inject([]) { |result, a| result << DataPoint.create_from_db(a) }
|
68
|
+
def find_data_point_at_ts(ts, name)
|
69
|
+
repository.find_data_point_at_ts(ts_bucket(ts), name)
|
115
70
|
end
|
116
71
|
|
117
72
|
def find_all_in_ts_range_by_name(from, to, name)
|
118
|
-
|
119
|
-
mongo_result.inject([]) { |result, a| result << DataPoint.create_from_db(a) }
|
73
|
+
repository.find_all_in_ts_range_by_name(from, to, name)
|
120
74
|
end
|
121
75
|
|
122
76
|
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) }
|
77
|
+
repository.find_all_in_ts_range_by_wildcard(from, to, target)
|
127
78
|
end
|
128
79
|
|
129
|
-
def
|
130
|
-
|
131
|
-
|
80
|
+
def save(dp, ts)
|
81
|
+
dp.ts = ts_bucket(ts)
|
82
|
+
dp.sum = dp.value
|
83
|
+
dp.total = 1
|
84
|
+
repository.save(dp)
|
132
85
|
end
|
133
86
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
def find_all_distinct_names
|
139
|
-
mongo_coll.distinct(:name).to_a
|
140
|
-
end
|
141
|
-
|
142
|
-
def save(stats, ts)
|
143
|
-
stats.ts = ts_bucket(ts)
|
144
|
-
result = mongo_coll.insert(stats.attributes)
|
145
|
-
SimpleMetrics.logger.debug "SERVER: MongoDB - insert in #{name}: #{stats.inspect}, result: #{result}"
|
146
|
-
end
|
147
|
-
|
148
|
-
def mongo_coll
|
149
|
-
Mongo.collection(name)
|
87
|
+
def update(dp, ts)
|
88
|
+
dp.ts = ts_bucket(ts)
|
89
|
+
repository.update(dp, ts)
|
150
90
|
end
|
151
91
|
|
152
92
|
def capped?
|
@@ -156,31 +96,28 @@ module SimpleMetrics
|
|
156
96
|
def fill_gaps(from, to, query_result)
|
157
97
|
return query_result if query_result.nil? || query_result.size == 0
|
158
98
|
|
159
|
-
|
99
|
+
existing_ts_entries = query_result.inject({}) { |result, dp| result[dp.ts] = dp; result }
|
160
100
|
dp_template = query_result.first
|
161
101
|
|
162
102
|
result = []
|
163
|
-
each_ts(from, to) do |
|
164
|
-
|
165
|
-
|
166
|
-
tmp_hash[current_bucket_ts]
|
167
|
-
else
|
168
|
-
dp = dp_template.dup
|
169
|
-
dp.value = nil
|
170
|
-
dp.ts = current_bucket_ts
|
171
|
-
dp
|
172
|
-
end
|
103
|
+
each_ts(from, to) do |ts_bucket|
|
104
|
+
dp = existing_ts_entries[ts_bucket] || DataPoint::Base.new(:name => dp_template.name, :ts => ts_bucket)
|
105
|
+
result << dp
|
173
106
|
end
|
174
107
|
result
|
175
108
|
end
|
176
109
|
|
177
110
|
private
|
178
111
|
|
112
|
+
def repository
|
113
|
+
DataPointRepository.for_retention(name)
|
114
|
+
end
|
115
|
+
|
179
116
|
def each_ts(from, to)
|
180
|
-
|
181
|
-
while (
|
182
|
-
yield(
|
183
|
-
|
117
|
+
ts_bucket = ts_bucket(from)
|
118
|
+
while (ts_bucket <= ts_bucket(to))
|
119
|
+
yield(ts_bucket)
|
120
|
+
ts_bucket = ts_bucket + seconds
|
184
121
|
end
|
185
122
|
end
|
186
123
|
|
@@ -0,0 +1,82 @@
|
|
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.symbolize_keys)
|
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.fetch(:db).symbolize_keys
|
19
|
+
end
|
20
|
+
|
21
|
+
def db=(db)
|
22
|
+
@db = db
|
23
|
+
end
|
24
|
+
|
25
|
+
def buckets
|
26
|
+
@buckets ||= begin
|
27
|
+
tmp = config.fetch(:buckets)
|
28
|
+
tmp.map { |b| b.symbolize_keys }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def buckets=(buckets)
|
33
|
+
@buckets = buckets
|
34
|
+
end
|
35
|
+
|
36
|
+
def server
|
37
|
+
@server ||= config.fetch(:server).symbolize_keys
|
38
|
+
end
|
39
|
+
|
40
|
+
def server=(server)
|
41
|
+
@server = server
|
42
|
+
end
|
43
|
+
|
44
|
+
def web
|
45
|
+
@web ||= config.fetch(:web).symbolize_keys
|
46
|
+
end
|
47
|
+
|
48
|
+
def web=(web)
|
49
|
+
@web = web
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def load_defaults
|
55
|
+
@config = load_config
|
56
|
+
rescue Errno::ENOENT # not found error
|
57
|
+
logger.info "Creating initial config file: #{config_file}"
|
58
|
+
FileUtils.cp(default_config_file, config_file)
|
59
|
+
@config = load_config
|
60
|
+
end
|
61
|
+
|
62
|
+
def config_file
|
63
|
+
File.expand_path('~/.simple_metrics.conf')
|
64
|
+
end
|
65
|
+
|
66
|
+
def default_config_file
|
67
|
+
File.expand_path('../../../default_config.yml', __FILE__)
|
68
|
+
end
|
69
|
+
|
70
|
+
def load_config
|
71
|
+
YAML.load_file(config_file).symbolize_keys
|
72
|
+
rescue ArgumentError => e
|
73
|
+
logger.error "Error parsing config file: #{e}"
|
74
|
+
rescue IOError => e
|
75
|
+
logger.error "Error reading config file: #{e}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def logger
|
79
|
+
SimpleMetrics.logger
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module SimpleMetrics
|
2
|
+
class Dashboard
|
3
|
+
|
4
|
+
attr_reader :id, :created_at, :updated_at
|
5
|
+
attr_accessor :name, :instruments
|
6
|
+
|
7
|
+
def initialize(attributes)
|
8
|
+
@id = attributes[:id]
|
9
|
+
@name = attributes[:name]
|
10
|
+
@created_at = attributes[:created_at]
|
11
|
+
@updated_at = attributes[:updated_at]
|
12
|
+
@instruments = attributes[:instruments] || []
|
13
|
+
end
|
14
|
+
|
15
|
+
def attributes
|
16
|
+
{
|
17
|
+
:id => @id.to_s, # convert bson id to str
|
18
|
+
:name => @name,
|
19
|
+
:instruments => @instruments,
|
20
|
+
:created_at => @created_at,
|
21
|
+
:updated_at => @updated_at
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
attributes.to_s
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|