nightfury 0.6.3 → 0.7.0

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.
@@ -2,20 +2,26 @@ module Nightfury
2
2
  module Metric
3
3
  class AvgTimeSeries < TimeSeries
4
4
 
5
- def default_meta
6
- {'count' => 0.0, 'total' => 0.0}
7
- end
8
-
9
5
  protected
10
6
 
11
- def before_set(value)
12
- updated_count = meta['count'].to_f + 1.0
13
- updated_total = meta['total'].to_f + value
7
+ def before_set(value, time)
8
+ step_time = get_step_time(time).to_i
9
+ data_point, meta_value = get_exact(step_time, true)
10
+ current_count = current_total = 0.0
11
+ unless data_point.nil?
12
+ current_count = meta_value[:current_count].to_f
13
+ current_total = meta_value[:current_total].to_f
14
+ end
15
+ updated_count = current_count + 1.0
16
+ updated_total = current_total + value
14
17
  result = updated_total / updated_count
15
- meta['count'] = updated_count
16
- meta['total'] = updated_total
17
- save_meta
18
- result
18
+ result = "#{updated_count},#{updated_total},#{result}"
19
+ [result, time]
20
+ end
21
+
22
+ def decode_data_point(data_point)
23
+ current_count, current_total, data = data_point[0].split(',')
24
+ [data_point[1], data, {current_count: current_count, current_total: current_total}]
19
25
  end
20
26
  end
21
27
  end
@@ -12,7 +12,7 @@ module Nightfury
12
12
  end
13
13
 
14
14
  def set(value, time=Time.now, options={})
15
- value = before_set(value) unless options[:skip_before_set]
15
+ value, time = before_set(value, time) unless options[:skip_before_set]
16
16
  # make sure the time_series is initialized.
17
17
  # It will not if the metric is removed and
18
18
  # set is called on the smae object
@@ -20,7 +20,7 @@ module Nightfury
20
20
  add_value_to_timeline(value, time)
21
21
  end
22
22
 
23
- def get(timestamp=nil)
23
+ def get(timestamp=nil, get_meta=false)
24
24
  return nil unless redis.exists(redis_key)
25
25
  data_point = ''
26
26
  if timestamp
@@ -32,11 +32,21 @@ module Nightfury
32
32
  data_point = data_point.each_slice(2).map {|pair| pair }.last
33
33
  end
34
34
 
35
- return nil if data_point.nil?
36
- return nil if data_point[1] == "0"
35
+ return get_meta ? [nil, {}] : nil if data_point.nil?
36
+ return get_meta ? [nil, {}] : nil if data_point[1] == "0"
37
37
 
38
- time, data = decode_data_point(data_point)
39
- {time => data}
38
+ time, data, meta_value = decode_data_point(data_point)
39
+ get_meta ? [{time => data}, meta_value] : {time => data}
40
+ end
41
+
42
+ def get_exact(timestamp, get_meta=false)
43
+ return nil unless redis.exists(redis_key)
44
+ timestamp = get_step_time(timestamp).to_i
45
+ data_point = redis.zrangebyscore(redis_key, timestamp, timestamp, withscores: true)
46
+ data_point = data_point.each_slice(2).map {|pair| pair }.last
47
+ return get_meta ? [nil, {}] : nil if data_point.nil?
48
+ time, data, meta_value = decode_data_point(data_point)
49
+ result = get_meta ? [{time => data}, meta_value] : {time => data}
40
50
  end
41
51
 
42
52
  def get_range(start_time, end_time)
@@ -72,8 +82,26 @@ module Nightfury
72
82
 
73
83
  protected
74
84
 
75
- def before_set(value)
76
- value
85
+ def before_set(value, time)
86
+ [value, time]
87
+ end
88
+
89
+ def decode_data_point(data_point)
90
+ [data_point[1], data_point[0], {}]
91
+ end
92
+
93
+ def round_time(time, seconds=60)
94
+ self.class.round_time(time, seconds)
95
+ end
96
+
97
+ def get_step_time(time)
98
+ case step
99
+ when :minute then round_time(time, 60)
100
+ when :hour then round_time(time, 1.hour)
101
+ when :day then round_time(time, 1.day)
102
+ when :week then round_time(time, 1.week)
103
+ when :month then round_time(time, Time.days_in_month(time.month, time.year))
104
+ end
77
105
  end
78
106
 
79
107
  private
@@ -91,11 +119,7 @@ module Nightfury
91
119
  result[time] = data
92
120
  end
93
121
  result
94
- end
95
-
96
- def decode_data_point(data_point)
97
- [data_point[1], data_point[0]]
98
- end
122
+ end
99
123
 
100
124
  def save_meta
101
125
  redis.zremrangebyscore redis_key, 0, 0
@@ -106,19 +130,6 @@ module Nightfury
106
130
  redis.zadd redis_key, 0, default_meta.to_json
107
131
  end
108
132
 
109
- def round_time(time, seconds=60)
110
- self.class.round_time(time, seconds)
111
- end
112
-
113
- def get_step_time(time)
114
- case step
115
- when :minute then round_time(time, 60)
116
- when :hour then round_time(time, 1.hour)
117
- when :day then round_time(time, 1.day)
118
- when :week then round_time(time, 1.week)
119
- when :month then round_time(time, Time.days_in_month(time.month, time.year))
120
- end
121
- end
122
133
  end
123
134
  end
124
135
  end
@@ -1,3 +1,3 @@
1
1
  module Nightfury
2
- VERSION = "0.6.3"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -1,24 +1,22 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Nightfury::Metric::AvgTimeSeries do
4
- it "should have the right default meta" do
4
+ it "should calculate avg in buckets defined by step" do
5
5
  avg_metric = Nightfury::Metric::AvgTimeSeries.new(:avg)
6
- avg_metric.default_meta.should == { 'count' => 0.0, 'total' => 0.0 }
7
- end
6
+ first_bucket_time = Time.now
7
+ next_bucket_time = first_bucket_time + 61 # step is 60 seconds by default
8
+
9
+ # Add to first bucket
10
+ avg_metric.set(3, first_bucket_time)
11
+ avg_metric.set(2, first_bucket_time)
12
+ avg_metric.set(4, first_bucket_time)
13
+ avg_metric.set(11, first_bucket_time)
8
14
 
9
- it "should calculate avg before saving" do
10
- avg_metric = Nightfury::Metric::AvgTimeSeries.new(:avg)
11
- avg_metric.set(3)
12
- avg_metric.set(2)
13
- avg_metric.set(4)
14
- avg_metric.set(11)
15
- avg_metric.get.values.first.should == "5.0"
16
- end
15
+ # Add to next bucket
16
+ avg_metric.set(3, next_bucket_time)
17
+ avg_metric.set(2, next_bucket_time)
17
18
 
18
- it "should update meta update count" do
19
- avg_metric = Nightfury::Metric::AvgTimeSeries.new(:avg)
20
- avg_metric.set(1)
21
- avg_metric.set(2)
22
- avg_metric.meta['count'].should == 2
19
+ avg_metric.get(first_bucket_time).values.first.should == "5.0"
20
+ avg_metric.get(next_bucket_time).values.first.should == "2.5"
23
21
  end
24
22
  end
@@ -27,6 +27,15 @@ describe Nightfury::Metric::TimeSeries do
27
27
  ts_metric.get.should be_nil
28
28
  end
29
29
 
30
+ context "with meta" do
31
+ it "should also return the meta part of the data point" do
32
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
33
+ time_now = Time.now
34
+ ts_metric.set(1, time_now)
35
+ ts_metric.get(time_now, true)[1].should == {}
36
+ end
37
+ end
38
+
30
39
  context "without timestamp" do
31
40
  it "should get the most recent data point" do
32
41
  ts_metric = Nightfury::Metric::TimeSeries.new(:time)
@@ -72,6 +81,39 @@ describe Nightfury::Metric::TimeSeries do
72
81
  end
73
82
  end
74
83
 
84
+ describe "#get_exact" do
85
+ it "should get the data_point at the timestamp" do
86
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
87
+ time = Time.now
88
+ ts_metric.set(1, time)
89
+ result = ts_metric.get_exact(time)
90
+ result.values.first.should == '1'
91
+ end
92
+
93
+ it "should return data point's meta if specified" do
94
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
95
+ time = Time.now
96
+ ts_metric.set(1, time)
97
+ result = ts_metric.get_exact(time, true)
98
+ result[1].should == {}
99
+ end
100
+
101
+ it "should return nil if there is no data_point at the timestamp" do
102
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
103
+ time = Time.now
104
+ ts_metric.set(1, time)
105
+ result = ts_metric.get_exact(time+61)
106
+ result.should be_nil
107
+ end
108
+
109
+ it "should retrun nil if metric key on redis is empty" do
110
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
111
+ # delete redis key
112
+ ts_metric.redis.del ts_metric.redis_key
113
+ ts_metric.get_exact(Time.now).should be_nil
114
+ end
115
+ end
116
+
75
117
  describe "#get_range" do
76
118
  it "should retrun nil if metric key on redis is empty" do
77
119
  ts_metric = Nightfury::Metric::TimeSeries.new(:time)
@@ -136,8 +178,9 @@ describe Nightfury::Metric::TimeSeries do
136
178
  describe "before set" do
137
179
  it "should call before_set, before adding the value to the timeline" do
138
180
  ts_metric = Nightfury::Metric::TimeSeries.new(:avg_time)
139
- flexmock(ts_metric).should_receive(:before_set).with(1).once
140
- ts_metric.set(1)
181
+ time = Time.now
182
+ flexmock(ts_metric).should_receive(:before_set).with(1, time).once
183
+ ts_metric.set(1, time)
141
184
  end
142
185
 
143
186
  it "should not call before_set, before adding the value to the timeline if optiond ':skip_before_set' is provided" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nightfury
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: