pulse-meter 0.2.7 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/pulse-meter/extensions/enumerable.rb +24 -0
- data/lib/pulse-meter/mixins/cmd.rb +2 -28
- data/lib/pulse-meter/sensor/configuration.rb +14 -0
- data/lib/pulse-meter/sensor/hashed_counter.rb +4 -1
- data/lib/pulse-meter/sensor/timeline.rb +22 -20
- data/lib/pulse-meter/sensor/timelined/hashed_counter.rb +4 -1
- data/lib/pulse-meter/version.rb +1 -1
- data/spec/pulse_meter/extensions/enumerable_spec.rb +58 -0
- data/spec/pulse_meter/mixins/cmd_spec.rb +112 -0
- data/spec/pulse_meter/sensor/hashed_counter_spec.rb +6 -2
- data/spec/pulse_meter/sensor/timelined/hashed_counter_spec.rb +3 -3
- data/spec/shared_examples/timeline_sensor.rb +25 -5
- metadata +8 -3
@@ -0,0 +1,24 @@
|
|
1
|
+
module Enumerable
|
2
|
+
require 'csv'
|
3
|
+
require 'terminal-table'
|
4
|
+
|
5
|
+
def convert_time
|
6
|
+
map {|el| el.is_a?(Time) ? el.to_i : el}
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_table(format = nil)
|
10
|
+
if "csv" == format.to_s
|
11
|
+
CSV.generate(:col_sep => ';') do |csv|
|
12
|
+
self.each {|row| csv << row.convert_time}
|
13
|
+
end
|
14
|
+
else
|
15
|
+
self.each_with_object(Terminal::Table.new) do |row, table|
|
16
|
+
table << if row.respond_to?(:map)
|
17
|
+
row.map(&:to_s)
|
18
|
+
else
|
19
|
+
row
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,30 +1,4 @@
|
|
1
|
-
|
2
|
-
def convert_time
|
3
|
-
map do |el|
|
4
|
-
if el.is_a?(Time)
|
5
|
-
el.to_i
|
6
|
-
else
|
7
|
-
el
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_table(format = nil)
|
13
|
-
if "csv" == format
|
14
|
-
CSV.generate(:col_sep => ';') do |csv|
|
15
|
-
self.each {|row| csv << row.convert_time}
|
16
|
-
end
|
17
|
-
else
|
18
|
-
self.each_with_object(Terminal::Table.new) do |row, table|
|
19
|
-
table << if row.respond_to?(:map)
|
20
|
-
row.map(&:to_s)
|
21
|
-
else
|
22
|
-
row
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
1
|
+
require 'pulse-meter/extensions/enumerable'
|
28
2
|
|
29
3
|
module PulseMeter
|
30
4
|
module Mixins
|
@@ -52,7 +26,7 @@ module PulseMeter
|
|
52
26
|
data = [
|
53
27
|
["Name", "Class", "ttl", "raw data ttl", "interval", "reduce delay"],
|
54
28
|
]
|
55
|
-
data << :separator unless
|
29
|
+
data << :separator unless 'csv' == format.to_s
|
56
30
|
all_sensors.each do |s|
|
57
31
|
if s.kind_of? PulseMeter::Sensor::Timeline
|
58
32
|
data << [s.name, s.class, s.ttl, s.raw_data_ttl, s.interval, s.reduce_delay]
|
@@ -1,11 +1,16 @@
|
|
1
1
|
module PulseMeter
|
2
2
|
module Sensor
|
3
|
+
# Constructs multiple sensors from configuration passed
|
3
4
|
class Configuration
|
4
5
|
include PulseMeter::Mixins::Utils
|
5
6
|
include Enumerable
|
6
7
|
|
8
|
+
# @!attribute [r] sensors
|
9
|
+
# @return [Hash] hash of sensors with names as keys and sensors as values
|
7
10
|
attr_reader :sensors
|
8
11
|
|
12
|
+
# Initializes sensors
|
13
|
+
# @param opts [Hash] sensors' configuration
|
9
14
|
def initialize(opts = {})
|
10
15
|
@sensors = {}
|
11
16
|
opts.each do |name, opts|
|
@@ -13,6 +18,9 @@ module PulseMeter
|
|
13
18
|
end
|
14
19
|
end
|
15
20
|
|
21
|
+
# Adds sensor
|
22
|
+
# @param name [Symbol] sensor name
|
23
|
+
# @param opts [Hash] sensor options
|
16
24
|
def add_sensor(name, opts)
|
17
25
|
sensor_type = opts.respond_to?(:sensor_type) ? opts.sensor_type : opts[:sensor_type]
|
18
26
|
klass_s = sensor_class(sensor_type)
|
@@ -22,16 +30,22 @@ module PulseMeter
|
|
22
30
|
@sensors[name.to_s] = klass.new(name, symbolize_keys(args.to_hash))
|
23
31
|
end
|
24
32
|
|
33
|
+
# Returns previously initialized sensor by name
|
34
|
+
# @param name [Symbol] sensor name
|
35
|
+
# @return [Sensor] sensor
|
25
36
|
def sensor(name)
|
26
37
|
@sensors[name.to_s]
|
27
38
|
end
|
28
39
|
|
40
|
+
# Iterates over each sensor
|
29
41
|
def each
|
30
42
|
@sensors.each_value do |sensor|
|
31
43
|
yield(sensor)
|
32
44
|
end
|
33
45
|
end
|
34
46
|
|
47
|
+
# Invokes event for any sensor
|
48
|
+
# @raise [ArgumentError] unless sensor exists
|
35
49
|
def method_missing(name, *args)
|
36
50
|
name = name.to_s
|
37
51
|
if @sensors.has_key?(name)
|
@@ -25,7 +25,10 @@ module PulseMeter
|
|
25
25
|
# @param data [Hash] hash where keys represent counter keys
|
26
26
|
# and values are increments for their keys
|
27
27
|
def process_event(data)
|
28
|
-
data.each_pair
|
28
|
+
data.each_pair do |k, v|
|
29
|
+
redis.hincrby(value_key, k, v.to_i)
|
30
|
+
redis.hincrby(value_key, :total, v.to_i)
|
31
|
+
end
|
29
32
|
end
|
30
33
|
|
31
34
|
end
|
@@ -108,12 +108,17 @@ module PulseMeter
|
|
108
108
|
# Returts sensor data within given time
|
109
109
|
# @param from [Time] lower bound
|
110
110
|
# @param till [Time] upper bound
|
111
|
+
# @param skip_optimization [Boolean] must be set to true to skip interval optimization
|
111
112
|
# @return [Array<SensorData>]
|
112
113
|
# @raise ArgumentError if argumets are not valid time objects
|
113
|
-
def timeline_within(from, till)
|
114
|
+
def timeline_within(from, till, skip_optimization = false)
|
114
115
|
raise ArgumentError unless from.kind_of?(Time) && till.kind_of?(Time)
|
115
116
|
start_time, end_time = from.to_i, till.to_i
|
116
|
-
actual_interval =
|
117
|
+
actual_interval = if skip_optimization
|
118
|
+
interval
|
119
|
+
else
|
120
|
+
optimized_interval(start_time, end_time)
|
121
|
+
end
|
117
122
|
current_interval_id = get_interval_id(start_time) + actual_interval
|
118
123
|
keys = []
|
119
124
|
ids = []
|
@@ -134,19 +139,6 @@ module PulseMeter
|
|
134
139
|
res
|
135
140
|
end
|
136
141
|
|
137
|
-
# Makes interval optimization so that the requested timespan contains less than MAX_TIMESPAN_POINTS values
|
138
|
-
# @param start_time [Fixnum] unix timestamp of timespan start
|
139
|
-
# @param end_time [Fixnum] unix timestamp of timespan start
|
140
|
-
# @return [Fixnum] optimized interval in seconds.
|
141
|
-
def optimized_inteval(start_time, end_time)
|
142
|
-
res_interval = interval
|
143
|
-
timespan = end_time - start_time
|
144
|
-
while timespan / res_interval > MAX_TIMESPAN_POINTS - 1
|
145
|
-
res_interval *= 2
|
146
|
-
end
|
147
|
-
res_interval
|
148
|
-
end
|
149
|
-
|
150
142
|
# Returns sensor data for given interval making in-memory summarization
|
151
143
|
# and returns calculated value
|
152
144
|
# @param interval_id [Fixnum]
|
@@ -174,11 +166,7 @@ module PulseMeter
|
|
174
166
|
keys << raw_data_key(current_interval_id)
|
175
167
|
current_interval_id += interval
|
176
168
|
end
|
177
|
-
|
178
|
-
0
|
179
|
-
else
|
180
|
-
redis.del(*keys)
|
181
|
-
end
|
169
|
+
keys.empty? ? 0 : redis.del(*keys)
|
182
170
|
end
|
183
171
|
|
184
172
|
# Returns Redis key by which raw data for current interval is stored
|
@@ -255,6 +243,20 @@ module PulseMeter
|
|
255
243
|
end
|
256
244
|
end
|
257
245
|
|
246
|
+
# Makes interval optimization so that the requested timespan contains less than MAX_TIMESPAN_POINTS values
|
247
|
+
# @param start_time [Fixnum] unix timestamp of timespan start
|
248
|
+
# @param end_time [Fixnum] unix timestamp of timespan start
|
249
|
+
# @return [Fixnum] optimized interval in seconds.
|
250
|
+
def optimized_interval(start_time, end_time)
|
251
|
+
res_interval = interval
|
252
|
+
timespan = end_time - start_time
|
253
|
+
while timespan / res_interval > MAX_TIMESPAN_POINTS - 1
|
254
|
+
res_interval *= 2
|
255
|
+
end
|
256
|
+
res_interval
|
257
|
+
end
|
258
|
+
|
259
|
+
|
258
260
|
end
|
259
261
|
end
|
260
262
|
end
|
@@ -7,7 +7,10 @@ module PulseMeter
|
|
7
7
|
# Good replacement for multiple counters to be visualized together
|
8
8
|
class HashedCounter < Timeline
|
9
9
|
def aggregate_event(key, data)
|
10
|
-
data.each_pair
|
10
|
+
data.each_pair do |k, v|
|
11
|
+
redis.hincrby(key, k, v)
|
12
|
+
redis.hincrby(key, :total, v)
|
13
|
+
end
|
11
14
|
end
|
12
15
|
|
13
16
|
def summarize(key)
|
data/lib/pulse-meter/version.rb
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pulse-meter/extensions/enumerable'
|
3
|
+
|
4
|
+
describe Enumerable do
|
5
|
+
let!(:time) {Time.new}
|
6
|
+
describe "#convert_time" do
|
7
|
+
it "converts Time objects to unixtime" do
|
8
|
+
[time].convert_time.should == [time.to_i]
|
9
|
+
end
|
10
|
+
|
11
|
+
it "does not change other members" do
|
12
|
+
[1, 2, 3].convert_time.should == [1, 2 ,3]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#to_table" do
|
17
|
+
context "when format is csv" do
|
18
|
+
it "returns csv as string" do
|
19
|
+
[].to_table(:csv).should be_instance_of(String)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns csv containing each subarray as a row" do
|
23
|
+
[[:a, :b], [:c, :d]].to_table(:csv).should == "a;b\nc;d\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "converts Time objects to unixtime" do
|
27
|
+
[[time]].to_table(:csv).should == "#{time.to_i}\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "takes format argument both as string and as symbol" do
|
31
|
+
[[:foo]].to_table("csv").should == "foo\n"
|
32
|
+
[[:foo]].to_table(:csv).should == "foo\n"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when format is table" do
|
37
|
+
it "return Terminal::Table instance" do
|
38
|
+
[].to_table.should be_instance_of(Terminal::Table)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns table containing each subarray as a row" do
|
42
|
+
data = [[:a, :b], [:c, :d]]
|
43
|
+
table = [[:a, :b], [:c, :d]].to_table
|
44
|
+
table.rows.map do |row|
|
45
|
+
row.cells.map(&:to_s).map(&:strip).map(&:to_sym)
|
46
|
+
end.should == data
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "uses table format as default" do
|
51
|
+
[].to_table.should be_instance_of(Terminal::Table)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "uses table format unless it is :csv or 'csv'" do
|
55
|
+
[].to_table(:unknown_format).should be_instance_of(Terminal::Table)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PulseMeter::Mixins::Cmd do
|
4
|
+
class Dummy
|
5
|
+
extend PulseMeter::Mixins::Cmd
|
6
|
+
|
7
|
+
def self.options
|
8
|
+
{host: :localhost, port: 6379, db: 0}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:dummy){ Dummy }
|
13
|
+
before {PulseMeter.redis = Redis.new}
|
14
|
+
|
15
|
+
describe "#fail!" do
|
16
|
+
it "prints given message and exits" do
|
17
|
+
STDOUT.should_receive(:puts).with(:msg)
|
18
|
+
lambda {dummy.fail!(:msg)}.should raise_error(SystemExit)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#with_redis' do
|
23
|
+
it "initializes redies and yields a block" do
|
24
|
+
PulseMeter.redis = nil
|
25
|
+
dummy.with_redis do
|
26
|
+
PulseMeter.redis.should_not be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#with_safe_restore_of" do
|
32
|
+
it "restores sensor by name and passes it to block" do
|
33
|
+
sensor = PulseMeter::Sensor::Counter.new(:foo)
|
34
|
+
dummy.with_safe_restore_of(:foo) do |s|
|
35
|
+
s.should be_instance_of(sensor.class)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "prints error and exits if sensor cannot be restored" do
|
40
|
+
STDOUT.should_receive(:puts).with("Sensor nonexistant is unknown or cannot be restored")
|
41
|
+
lambda {dummy.with_safe_restore_of(:nonexistant) {|s| s}}.should raise_error(SystemExit)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#all_sensors" do
|
46
|
+
it "is just an alias to PulseMeter::Sensor::Timeline.list_objects" do
|
47
|
+
PulseMeter::Sensor::Timeline.should_receive(:list_objects)
|
48
|
+
dummy.all_sensors
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#all_sensors_table" do
|
53
|
+
before {PulseMeter.redis.flushall}
|
54
|
+
let(:init_values){ {:ttl => 1, :raw_data_ttl => 2, :interval => 3, :reduce_delay => 4} }
|
55
|
+
let!(:s1) {PulseMeter::Sensor::Counter.new(:s1)}
|
56
|
+
let!(:s2) {PulseMeter::Sensor::Timelined::Counter.new(:s2, init_values)}
|
57
|
+
let!(:table) {dummy.all_sensors_table}
|
58
|
+
let!(:csv) {dummy.all_sensors_table(:csv)}
|
59
|
+
let!(:parsed_csv) {CSV.parse(csv, col_sep: ";")}
|
60
|
+
|
61
|
+
def rows(format)
|
62
|
+
if "csv" == format.to_s
|
63
|
+
parsed_csv
|
64
|
+
else
|
65
|
+
table.rows.map do |row|
|
66
|
+
row.cells.map(&:to_s).map(&:strip)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def sensor_row(name, format)
|
72
|
+
rows(format).select {|row| row[0] == name}.first
|
73
|
+
end
|
74
|
+
|
75
|
+
[:csv, :table].each do |format|
|
76
|
+
context "when format is #{format}" do
|
77
|
+
|
78
|
+
if "csv" == format.to_s
|
79
|
+
it "returns csv as string" do
|
80
|
+
csv.should be_instance_of(String)
|
81
|
+
end
|
82
|
+
else
|
83
|
+
it "returns Terminal::Table instance" do
|
84
|
+
table.should be_instance_of(Terminal::Table)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
it "has title row" do
|
89
|
+
rows(format)[0].should == ["Name", "Class", "ttl", "raw data ttl", "interval", "reduce delay"]
|
90
|
+
end
|
91
|
+
|
92
|
+
it "has one row for each sensor (and a title)" do
|
93
|
+
rows(format).count.should == 3
|
94
|
+
end
|
95
|
+
|
96
|
+
it "can display timelined sensors" do
|
97
|
+
sensor_row("s2", format).should == [
|
98
|
+
s2.name, s2.class, s2.ttl, s2.raw_data_ttl, s2.interval, s2.reduce_delay
|
99
|
+
].map(&:to_s)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "can display static sensors" do
|
103
|
+
sensor_row("s1", format).should == [
|
104
|
+
s1.name, s1.class, "", "", "", ""
|
105
|
+
].map(&:to_s)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -15,6 +15,10 @@ describe PulseMeter::Sensor::HashedCounter do
|
|
15
15
|
expect{ sensor.event({"foo" => 10.4}) }.to change{ sensor.value["foo"] }.from(0).to(10)
|
16
16
|
expect{ sensor.event({"foo" => 15.1}) }.to change{ sensor.value["foo"] }.from(10).to(25)
|
17
17
|
end
|
18
|
+
|
19
|
+
it "should increment total value" do
|
20
|
+
expect{ sensor.event({"foo" => 1, "bar" => 2}) }.to change{sensor.value["total"]}.from(0).to(3)
|
21
|
+
end
|
18
22
|
end
|
19
23
|
|
20
24
|
describe "#value" do
|
@@ -24,8 +28,8 @@ describe PulseMeter::Sensor::HashedCounter do
|
|
24
28
|
|
25
29
|
it "should store redis hash by value_key" do
|
26
30
|
sensor.event({"foo" => 1})
|
27
|
-
sensor.value.should == {"foo" => 1}
|
28
|
-
redis.hgetall(sensor.value_key).should == {"foo" => "1"}
|
31
|
+
sensor.value.should == {"foo" => 1, "total" => 1}
|
32
|
+
redis.hgetall(sensor.value_key).should == {"foo" => "1", "total" => "1"}
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe PulseMeter::Sensor::Timelined::HashedCounter do
|
4
4
|
it_should_behave_like "timeline sensor", {}, {:foo => 1}
|
5
|
-
it_should_behave_like "timelined subclass", [{:foo => 1}, {:foo => 2}], {:foo => 3}.to_json
|
6
|
-
it_should_behave_like "timelined subclass", [{:foo => 1}, {:foo => :bad_value}], {:foo => 1}.to_json
|
7
|
-
it_should_behave_like "timelined subclass", [{:foo => 1}, {:boo => 2}], {:foo => 1, :boo => 2}.to_json
|
5
|
+
it_should_behave_like "timelined subclass", [{:foo => 1}, {:foo => 2}], {:foo => 3, :total => 3}.to_json
|
6
|
+
it_should_behave_like "timelined subclass", [{:foo => 1}, {:foo => :bad_value}], {:foo => 1, :total => 1}.to_json
|
7
|
+
it_should_behave_like "timelined subclass", [{:foo => 1}, {:boo => 2}], {:foo => 1, :boo => 2, :total => 3}.to_json
|
8
8
|
end
|
@@ -242,12 +242,32 @@ shared_examples_for "timeline sensor" do |extra_init_values, default_event|
|
|
242
242
|
end
|
243
243
|
end
|
244
244
|
|
245
|
-
|
246
|
-
max
|
247
|
-
(1..10).each do |i|
|
248
|
-
timespan = sensor.interval * max * (2**i)
|
249
|
-
sensor.timeline_within(Time.now, Time.now - timespan).size.should < max
|
245
|
+
context "to avoid getting to much data" do
|
246
|
+
let(:max) {PulseMeter::Sensor::Timeline::MAX_TIMESPAN_POINTS}
|
250
247
|
|
248
|
+
it "should skip some points not to exceed MAX_TIMESPAN_POINTS" do
|
249
|
+
count = max * 2
|
250
|
+
sensor.timeline_within(
|
251
|
+
Time.at(@start_of_interval - 1),
|
252
|
+
Time.at(@start_of_interval + count * interval)
|
253
|
+
).size.should < max
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should not skip any points when timeline orginal size is less then MAX_TIMESPAN_POINTS" do
|
257
|
+
count = max - 1
|
258
|
+
sensor.timeline_within(
|
259
|
+
Time.at(@start_of_interval - 1),
|
260
|
+
Time.at(@start_of_interval + count * interval)
|
261
|
+
).size.should == count
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should give full data in case skip_optimization parameter set to true" do
|
265
|
+
count = max * 2
|
266
|
+
sensor.timeline_within(
|
267
|
+
Time.at(@start_of_interval - 1),
|
268
|
+
Time.at(@start_of_interval + count * interval),
|
269
|
+
true
|
270
|
+
).size.should == count
|
251
271
|
end
|
252
272
|
end
|
253
273
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pulse-meter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-08-02 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: gon-sinatra
|
@@ -333,6 +333,7 @@ files:
|
|
333
333
|
- examples/server_config.yml
|
334
334
|
- lib/cmd.rb
|
335
335
|
- lib/pulse-meter.rb
|
336
|
+
- lib/pulse-meter/extensions/enumerable.rb
|
336
337
|
- lib/pulse-meter/mixins/cmd.rb
|
337
338
|
- lib/pulse-meter/mixins/dumper.rb
|
338
339
|
- lib/pulse-meter/mixins/utils.rb
|
@@ -405,6 +406,8 @@ files:
|
|
405
406
|
- lib/pulse-meter/visualize/widgets/timeline.rb
|
406
407
|
- lib/pulse-meter/visualizer.rb
|
407
408
|
- pulse-meter.gemspec
|
409
|
+
- spec/pulse_meter/extensions/enumerable_spec.rb
|
410
|
+
- spec/pulse_meter/mixins/cmd_spec.rb
|
408
411
|
- spec/pulse_meter/mixins/dumper_spec.rb
|
409
412
|
- spec/pulse_meter/mixins/utils_spec.rb
|
410
413
|
- spec/pulse_meter/sensor/base_spec.rb
|
@@ -472,7 +475,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
472
475
|
version: '0'
|
473
476
|
segments:
|
474
477
|
- 0
|
475
|
-
hash: -
|
478
|
+
hash: -2299028715226414900
|
476
479
|
requirements: []
|
477
480
|
rubyforge_project:
|
478
481
|
rubygems_version: 1.8.24
|
@@ -481,6 +484,8 @@ specification_version: 3
|
|
481
484
|
summary: Lightweight Redis-based metrics aggregator and processor with CLI and simple
|
482
485
|
and customizable WEB interfaces
|
483
486
|
test_files:
|
487
|
+
- spec/pulse_meter/extensions/enumerable_spec.rb
|
488
|
+
- spec/pulse_meter/mixins/cmd_spec.rb
|
484
489
|
- spec/pulse_meter/mixins/dumper_spec.rb
|
485
490
|
- spec/pulse_meter/mixins/utils_spec.rb
|
486
491
|
- spec/pulse_meter/sensor/base_spec.rb
|