nightfury 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,80 @@
1
+ .sass-cache/
2
+ .bundle
3
+ public/javascripts/app_error_handler.js
4
+ supportbeeapp_production.sql
5
+ solr/data
6
+ db/*.qlite3
7
+ log/*.log
8
+ tmp/**/*
9
+ config/database.yml
10
+ config/sb_config.yml
11
+ config/secret_config.yml
12
+ tmp/*
13
+ public/javascripts/backbone/**/**/*.js
14
+ public/javascripts/backbone/*.js
15
+ public/javascripts/backbone/collections/
16
+ public/javascripts/backbone/models/
17
+ doc/api
18
+ doc/app
19
+ *.swp
20
+ *.swo
21
+ *.swm
22
+ *.un~
23
+
24
+ .DS_Store
25
+ schema.rb
26
+ .tags
27
+ emails/*
28
+ public/uploads/*
29
+ public/images/twitter_auth.png
30
+ public/assets
31
+ public/javascripts/backbone/libs/
32
+ public/javascripts/spin.js
33
+ public/javascripts/utility.js
34
+ public/javascripts/admin/
35
+ public/javascripts/backbone-rails.js
36
+ public/javascripts/payments.js
37
+ public/javascripts/widget/script_coffee.js
38
+ public/javascripts/app_error_handler.js
39
+ public/javascripts/sb.apps.js
40
+ public/stylesheets/admin/ie.css
41
+ public/stylesheets/admin/ie6.css
42
+ public/stylesheets/admin/print.css
43
+ public/stylesheets/admin/screen.css
44
+ public/stylesheets/admin/theme.css
45
+ public/stylesheets/app/ie.css
46
+ public/stylesheets/app/ie6.css
47
+ public/stylesheets/app/layout.css
48
+ public/stylesheets/app/screen.css
49
+ public/stylesheets/app/theme.css
50
+ public/stylesheets/app/account.css
51
+ public/stylesheets/app/screen_responsive.css
52
+ public/stylesheets/embed_form.css
53
+ public/stylesheets/formtastic_changes.css
54
+ public/stylesheets/app/email.css
55
+ public/stylesheets/common/marketing.css
56
+ public/stylesheets/common/sprite.css
57
+ public/stylesheets/common/blueprint_tabs.css
58
+ public/stylesheets/widget/
59
+ spec/javascripts/backbone/
60
+ spec/javascripts/admin
61
+ spec/javascripts/UtilitySpec.js
62
+ spec/javascripts/BackboneRailsSpec.js
63
+ spec/javascripts/helpers/SpecHelper.js
64
+ *.swn
65
+ uploads/
66
+ bin/
67
+ lib/daemons/log
68
+ log/
69
+ .sass-cache/
70
+ tags
71
+ .rvmrc
72
+ bundler_stubs/
73
+ *.swg
74
+ *.swh
75
+ *.swi
76
+ *.swj
77
+ *.swk
78
+ *.swl
79
+ public/stylesheets/common/tinymce.css
80
+ public/stylesheets/common/tinymce_ui.css
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'redis', '~> 3.0.0'
4
+ gem 'redis-namespace', '~> 1.2'
5
+ gem 'activesupport', '~> 3.0.0'
6
+ gem 'i18n'
7
+ gem 'json'
8
+
9
+ gemspec
10
+
11
+ gem 'rspec'
12
+ gem 'flexmock'
13
+ gem 'mock_redis'
14
+ gem 'timecop'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Avinasha Shastry
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Nightfury
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'nightfury'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install nightfury
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/example.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'nightfury'
4
+
5
+ REDIS_CLIENT = Redis.new(:db => 15)
6
+ Redis.current = REDIS_CLIENT
7
+
8
+ # Defining Identity
9
+ class CompanyIdentity < Nightfury::Identity::Base
10
+ # Defining metric:
11
+ # #metric(name, type)
12
+ # type defaults to :value
13
+ metric :first_response_time, :time_series
14
+ metric :ticket_count
15
+ end
16
+
17
+
18
+ time_now = Time.now
19
+
20
+ # Identity object requires an unique ID
21
+ c = CompanyIdentity.new(1)
22
+
23
+ # Working with time series
24
+ # #set(value, timestamp)
25
+ # timestamp defaults to current time
26
+ c.first_response_time.set(1)
27
+ c.first_response_time.set(2,time_now - 10)
28
+
29
+ # #get([timestamp])
30
+ # without a timestamp get returns the latest value
31
+ # return value is a hash with a key value pair (unix_timestamp, value)
32
+ # all return values are strings regardless of their data type at the time of insertion
33
+ puts "#get; latest value: \n #{c.first_response_time.get}"
34
+ puts "#get(timestamp); value at the timestamp: \n #{c.first_response_time.get(time_now - 10)}"
35
+ puts "#get_range(start_time, end_time); returns values with condition start_time >= value <= end_time \n #{c.first_response_time.get_range(time_now - 15, time_now - 5)}"
36
+ puts "#get_all; returns all values \n #{c.first_response_time.get_all}"
37
+
38
+
39
+ # Working with values
40
+ c.ticket_count.set(0)
41
+ # increment by 1
42
+ c.ticket_count.incr
43
+ # increment by 10
44
+ c.ticket_count.incr(10)
45
+ # decrement by 1
46
+ c.ticket_count.decr
47
+ # decrement by 5
48
+ c.ticket_count.decr(5)
49
+ puts "Ticket Count; should be 5 \n #{c.ticket_count.get}"
@@ -0,0 +1,42 @@
1
+ module Nightfury
2
+ module Identity
3
+ class Base
4
+
5
+ METRIC_MAPPINGS = {
6
+ :value => Nightfury::Metric::Value,
7
+ :time_series => Nightfury::Metric::TimeSeries
8
+ }
9
+
10
+ class << self
11
+
12
+ attr_reader :metrics
13
+
14
+ def name
15
+ self.to_s.demodulize.underscore
16
+ end
17
+
18
+ def metric(name, type = :value)
19
+ @metrics ||= {}
20
+ @metrics[name] = {type: type}
21
+
22
+ class_eval <<-ENDOFMETHOD
23
+ def #{name}
24
+ @_#{name} ||= METRIC_MAPPINGS[:#{type}].new(:#{name}, redis_key_prefix: key_prefix)
25
+ end
26
+ ENDOFMETHOD
27
+ end
28
+
29
+ end
30
+
31
+ attr_accessor :id
32
+
33
+ def initialize(id)
34
+ @id = id
35
+ end
36
+
37
+ def key_prefix
38
+ "#{self.class.name}:#{id}"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,91 @@
1
+ module Nightfury
2
+ module Metric
3
+ class TimeSeries < Base
4
+
5
+ def initialize(name, options={})
6
+ super(name, options={})
7
+ init_time_series unless redis.exists(redis_key)
8
+ end
9
+
10
+ def set(value, time=Time.now)
11
+ value = before_set(value)
12
+ # make sure the time_series is initialized.
13
+ # It will not if the metric is removed and
14
+ # set is called on the smae object
15
+ init_time_series unless redis.exists(redis_key)
16
+ add_value_to_timeline(value, time)
17
+ end
18
+
19
+ def get(timestamp=nil)
20
+ return nil unless redis.exists(redis_key)
21
+ data_point = ''
22
+ if timestamp
23
+ timestamp = timestamp.to_i
24
+ data_point = redis.zrangebyscore(redis_key, timestamp, timestamp).first
25
+ else
26
+ data_point = redis.zrevrange(redis_key, 0, 0).first
27
+ end
28
+
29
+ time, data = decode_data_point(data_point)
30
+ {time => data}
31
+ end
32
+
33
+ def get_range(start_time, end_time)
34
+ return nil unless redis.exists(redis_key)
35
+ start_time = start_time.to_i
36
+ end_time = end_time.to_i
37
+ data_points = redis.zrangebyscore(redis_key, start_time, end_time)
38
+ decode_many_data_points(data_points)
39
+ end
40
+
41
+ def get_all
42
+ return nil unless redis.exists(redis_key)
43
+ data_points = redis.zrange(redis_key,1,-1)
44
+ decode_many_data_points(data_points)
45
+ end
46
+
47
+ def meta
48
+ json = redis.zrange(redis_key, 0, 0).first
49
+ JSON.parse(json)
50
+ end
51
+
52
+ def default_meta
53
+ {}
54
+ end
55
+
56
+ private
57
+
58
+ def add_value_to_timeline(value, time)
59
+ time = time.to_i
60
+ value = "#{time}:#{value}"
61
+ redis.zadd redis_key, time, value
62
+ end
63
+
64
+ def decode_many_data_points(data_points)
65
+ result = {}
66
+ data_points.each do |data_point|
67
+ time, data = decode_data_point(data_point)
68
+ result[time] = data
69
+ end
70
+ result
71
+ end
72
+
73
+ def decode_data_point(data_point)
74
+ colon_index = data_point.index(':')
75
+
76
+ [
77
+ data_point[0...colon_index],
78
+ data_point[colon_index+1..-1]
79
+ ]
80
+ end
81
+
82
+ def before_set(value)
83
+ value
84
+ end
85
+
86
+ def init_time_series
87
+ redis.zadd redis_key, 0, default_meta.to_json
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,28 @@
1
+ module Nightfury
2
+ module Metric
3
+ class Value < Base
4
+ def set(value)
5
+ value = before_set(value)
6
+ redis.set(redis_key, value)
7
+ end
8
+
9
+ def get
10
+ redis.get(redis_key)
11
+ end
12
+
13
+ def incr(step=1)
14
+ redis.incrby(redis_key, step)
15
+ end
16
+
17
+ def decr(step=1)
18
+ redis.decrby(redis_key, step)
19
+ end
20
+
21
+ private
22
+
23
+ def before_set(value)
24
+ value
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ module Nightfury
2
+ module Metric
3
+ class Base
4
+ attr_reader :name, :redis, :redis_key_prefix
5
+
6
+ def initialize(name, options={})
7
+ @name = name
8
+ @redis = Nightfury.redis
9
+ @redis_key_prefix = options[:redis_key_prefix]
10
+ end
11
+
12
+ def redis_key
13
+ prefix = redis_key_prefix.blank? ? '' : "#{redis_key_prefix}:"
14
+ "#{prefix}metric:#{name}"
15
+ end
16
+
17
+ def delete
18
+ redis.del redis_key
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+
@@ -0,0 +1,3 @@
1
+ module Nightfury
2
+ VERSION = "0.0.1"
3
+ end
data/lib/nightfury.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'redis'
2
+ require 'redis-namespace'
3
+ require 'json'
4
+ require 'active_support/core_ext/object/blank'
5
+ require 'active_support/core_ext/class/attribute'
6
+ require 'active_support/core_ext/string/inflections'
7
+ require 'active_support/concern'
8
+
9
+ module Nightfury
10
+ class << self
11
+ attr_accessor :redis, :namespace
12
+
13
+ def redis
14
+ @redis ||= set_namespace(Redis.current)
15
+ end
16
+
17
+ def redis=(redis_instance)
18
+ @redis = set_namespace(redis_instance)
19
+ end
20
+
21
+ def namespace
22
+ @namespace ||= :nf
23
+ end
24
+
25
+ def namespace=(namespace_symbol)
26
+ @namespace = namespace_symbol
27
+ @redis = set_namespace(redis)
28
+ end
29
+
30
+ private
31
+
32
+ def set_namespace(redis_instance)
33
+ Redis::Namespace.new(namespace, redis: redis_instance)
34
+ end
35
+ end
36
+ end
37
+
38
+ require "nightfury/version"
39
+ require "nightfury/metric"
40
+ require "nightfury/metric/value"
41
+ require "nightfury/metric/time_series"
42
+ require "nightfury/identity"
43
+
data/nightfury.gemspec ADDED
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/nightfury/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Avinasha Shastry", "Prateek Dayal"]
6
+ gem.email = ["me@avinasha.com", "prateek@supportbee.com"]
7
+ gem.description = %q{Nightfury is a reporting/analytics backend written on Redis}
8
+ gem.summary = %q{Nightfury is a reporting/analytics backend written on Redis}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "nightfury"
15
+ gem.require_paths = ["lib"]
16
+ gem.requirements = ["redis, v3.0.0 or greater"]
17
+ gem.version = Nightfury::VERSION
18
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nightfury::Identity::Base do
4
+
5
+ class Dummy < Nightfury::Identity::Base
6
+ end
7
+
8
+ describe "ClassMethods" do
9
+ it "should have a name" do
10
+ Dummy.name.should == 'dummy'
11
+ end
12
+
13
+ describe "metric" do
14
+ it "should add to metrics" do
15
+ Dummy.metric(:count)
16
+ Dummy.metrics[:count].should == {type: :value}
17
+ end
18
+
19
+ it "should add a instance method" do
20
+ Dummy.metric(:another_count)
21
+ Dummy.instance_methods.should include(:another_count)
22
+ end
23
+ end
24
+ end
25
+
26
+ describe "InstanceMethods" do
27
+ it "should have an id" do
28
+ d = Dummy.new(1)
29
+ d.id.should == 1
30
+ end
31
+
32
+ it "should generates a key prefix" do
33
+ d = Dummy.new(1)
34
+ d.key_prefix.should == 'dummy:1'
35
+ end
36
+
37
+ describe "Dynamically generated metric" do
38
+ it "should instantiate the right metric class" do
39
+ Dummy.metric(:third_count)
40
+ d = Dummy.new(1)
41
+ metric_object = d.third_count
42
+ metric_object.should be_kind_of(Nightfury::Metric::Value)
43
+ metric_object.name.should == :third_count
44
+ metric_object.redis_key_prefix.should == 'dummy:1'
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,141 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nightfury::Metric::TimeSeries do
4
+ describe "Initialization" do
5
+ it "should initialize a time series (setup meta data)" do
6
+ ts_metric = Nightfury::Metric::TimeSeries.new(:avg_time)
7
+ ts_metric.meta.should == {}
8
+ end
9
+ end
10
+
11
+ describe "Getter" do
12
+ describe "#get" do
13
+ it "should retrun nil if metric key on redis is empty" do
14
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
15
+ # delete redis key
16
+ ts_metric.redis.del ts_metric.redis_key
17
+ ts_metric.get.should be_nil
18
+ end
19
+
20
+ context "without timestamp" do
21
+ it "should get the most recent data point" do
22
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
23
+ time_now = Time.now
24
+ time_later = time_now + 10
25
+ ts_metric.set(1, time_now)
26
+ ts_metric.set(2, time_later)
27
+ result = ts_metric.get
28
+ result[time_later.to_i.to_s].should == '2'
29
+ end
30
+ end
31
+
32
+ context "with timestamp" do
33
+ it "should get the data point at the time stamp" do
34
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
35
+ time_now = Time.now
36
+ time_later = time_now + 10
37
+ ts_metric.set(1, time_now)
38
+ ts_metric.set(2, time_later)
39
+ result = ts_metric.get(time_now)
40
+ result[time_now.to_i.to_s].should == '1'
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "#get_range" do
46
+ it "should retrun nil if metric key on redis is empty" do
47
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
48
+ # delete redis key
49
+ ts_metric.redis.del ts_metric.redis_key
50
+ ts_metric.get_range(Time.now, Time.now).should be_nil
51
+ end
52
+
53
+ it "should get all data points between the specified ranges" do
54
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
55
+ time = Time.now
56
+ loop_time = time.dup
57
+
58
+ 10.times do |i|
59
+ ts_metric.set(i, loop_time)
60
+ loop_time = loop_time + 1
61
+ end
62
+
63
+ start_time = time + 3
64
+ end_time = time + 5
65
+
66
+ result = ts_metric.get_range(start_time, end_time)
67
+ result[start_time.to_i.to_s].should == '3'
68
+ result[(start_time.to_i + 1).to_s].should == '4'
69
+ result[end_time.to_i.to_s].should == '5'
70
+ end
71
+ end
72
+
73
+ describe "#get_all" do
74
+ it "should retrun nil if metric key on redis is empty" do
75
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
76
+ # delete redis key
77
+ ts_metric.redis.del ts_metric.redis_key
78
+ ts_metric.get_all.should be_nil
79
+ end
80
+
81
+ it "should get all the data points in the series" do
82
+ ts_metric = Nightfury::Metric::TimeSeries.new(:time)
83
+ time = Time.now
84
+ loop_time = time.dup
85
+
86
+ 10.times do |i|
87
+ ts_metric.set(i, loop_time)
88
+ loop_time = loop_time + 1
89
+ end
90
+
91
+ result = ts_metric.get_all
92
+ result.length.should == 10
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "Setter" do
98
+ describe "add the value to timeline" do
99
+ it "should default time to current time" do
100
+ time_now = Time.now
101
+ ts_metric = Nightfury::Metric::TimeSeries.new(:avg_time)
102
+
103
+ flexmock(ts_metric.redis).should_receive(:zadd)
104
+ .with(ts_metric.redis_key,
105
+ time_now.to_i,
106
+ FlexMock.any)
107
+ .once
108
+
109
+ Timecop.freeze(time_now) do
110
+ ts_metric.set(1)
111
+ end
112
+ Timecop.return
113
+ end
114
+
115
+ it "should add at specified time" do
116
+ time = Time.now - 60
117
+ ts_metric = Nightfury::Metric::TimeSeries.new(:avg_time)
118
+
119
+ flexmock(ts_metric.redis).should_receive(:zadd)
120
+ .with(ts_metric.redis_key,
121
+ time.to_i,
122
+ FlexMock.any)
123
+ .once
124
+
125
+ ts_metric.set(1, time)
126
+ end
127
+
128
+ it "should add the time to the value to avoid duplicate value in the set" do
129
+ time = Time.now
130
+ ts_metric = Nightfury::Metric::TimeSeries.new(:avg_time)
131
+
132
+ flexmock(ts_metric.redis).should_receive(:zadd)
133
+ .with(FlexMock.any,
134
+ FlexMock.any,
135
+ "#{time.to_i}:1")
136
+ .once
137
+ ts_metric.set(1, time)
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,25 @@
1
+ describe Nightfury::Metric::Value do
2
+ it "should get a value by delegating to redis" do
3
+ value_metric = Nightfury::Metric::Value.new(:tickets_count)
4
+ flexmock(value_metric.redis).should_receive(:get).with('metric:tickets_count').once
5
+ value_metric.get
6
+ end
7
+
8
+ it "should set a value by delegating to redis" do
9
+ value_metric = Nightfury::Metric::Value.new(:tickets_count)
10
+ flexmock(value_metric.redis).should_receive(:set).with('metric:tickets_count', 1).once
11
+ value_metric.set(1)
12
+ end
13
+
14
+ it "should increment a value by delegating to redis" do
15
+ value_metric = Nightfury::Metric::Value.new(:tickets_count)
16
+ flexmock(value_metric.redis).should_receive(:incrby).with('metric:tickets_count', 1).once
17
+ value_metric.incr
18
+ end
19
+
20
+ it "should decrement a value by delegating to redis" do
21
+ value_metric = Nightfury::Metric::Value.new(:tickets_count)
22
+ flexmock(value_metric.redis).should_receive(:decrby).with('metric:tickets_count', 2).once
23
+ value_metric.decr(2)
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nightfury::Metric::Base do
4
+ it "should have a name" do
5
+ metric = Nightfury::Metric::Base.new(:tickets_count)
6
+ metric.name.should == :tickets_count
7
+ end
8
+
9
+ it "should have a redis key" do
10
+ metric = Nightfury::Metric::Base.new(:tickets_count)
11
+ metric.redis_key.should == "metric:tickets_count"
12
+ end
13
+
14
+ it "should accept a redis key prefix" do
15
+ metric = Nightfury::Metric::Base.new(:tickets_count, redis_key_prefix: 'prefix')
16
+ metric.redis_key.should == "prefix:metric:tickets_count"
17
+ end
18
+
19
+ it "should have nightfury's redis connection" do
20
+ metric = Nightfury::Metric::Base.new(:tickets_count)
21
+ metric.redis.should == Nightfury.redis
22
+ end
23
+
24
+ it "should be able to remove itself" do
25
+ metric = Nightfury::Metric::Base.new(:tickets_count)
26
+ flexmock(metric.redis).should_receive(:del).with('metric:tickets_count').once
27
+ metric.delete
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nightfury do
4
+ describe "redis setup" do
5
+ it "should default redis connection to Redis.current" do
6
+ Nightfury.redis.client.host.should == "localhost"
7
+ Nightfury.redis.client.port.should == 9212
8
+ Nightfury.redis.client.db.should == 0
9
+ end
10
+
11
+ it "should accept a redis connection" do
12
+ redis = Redis.new
13
+ Nightfury.redis = redis
14
+
15
+ Nightfury.redis.client.host.should == "127.0.0.1"
16
+ Nightfury.redis.client.port.should == 6379
17
+ Nightfury.redis.client.db.should == 0
18
+ end
19
+
20
+ it "should default redis namespace to 'nf'" do
21
+ Nightfury.redis.namespace.should == :nf
22
+ end
23
+
24
+ it "should set redis namespace to the specified namespace" do
25
+ Nightfury.namespace = :new_nf
26
+ Nightfury.redis.namespace.should == :new_nf
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'nightfury'
5
+ require 'timecop'
6
+
7
+ # Start our own redis-server to avoid corrupting any others
8
+ REDIS_BIN = 'redis-server'
9
+ REDIS_PORT = ENV['REDIS_PORT'] || 9212
10
+ REDIS_HOST = ENV['REDIS_HOST'] || 'localhost'
11
+ REDIS_PID = File.expand_path 'redis.pid', File.dirname(__FILE__)
12
+ REDIS_DUMP = File.expand_path 'redis.rdb', File.dirname(__FILE__)
13
+ puts "=> Starting redis-server on #{REDIS_HOST}:#{REDIS_PORT}"
14
+ fork_pid = fork do
15
+ system "(echo port #{REDIS_PORT}; echo logfile /dev/null; echo daemonize yes; echo pidfile #{REDIS_PID}; echo dbfilename #{REDIS_DUMP}) | #{REDIS_BIN} -"
16
+ end
17
+ at_exit do
18
+ pid = File.read(REDIS_PID).to_i
19
+ puts "=> Killing #{REDIS_BIN} with pid #{pid}"
20
+ Process.kill "TERM", pid
21
+ Process.kill "KILL", pid
22
+ File.unlink REDIS_PID
23
+ File.unlink REDIS_DUMP if File.exists? REDIS_DUMP
24
+ end
25
+
26
+ REDIS_CLIENT = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT)
27
+ Redis.current = REDIS_CLIENT
28
+
29
+ RSpec.configure do |config|
30
+ config.mock_with :flexmock
31
+
32
+ config.before(:each) do
33
+ REDIS_CLIENT.flushdb
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nightfury
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Avinasha Shastry
9
+ - Prateek Dayal
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-12-17 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: Nightfury is a reporting/analytics backend written on Redis
16
+ email:
17
+ - me@avinasha.com
18
+ - prateek@supportbee.com
19
+ executables: []
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - .gitignore
24
+ - Gemfile
25
+ - LICENSE
26
+ - README.md
27
+ - Rakefile
28
+ - example.rb
29
+ - lib/nightfury.rb
30
+ - lib/nightfury/identity.rb
31
+ - lib/nightfury/metric.rb
32
+ - lib/nightfury/metric/time_series.rb
33
+ - lib/nightfury/metric/value.rb
34
+ - lib/nightfury/version.rb
35
+ - nightfury.gemspec
36
+ - spec/nightfury/identity_spec.rb
37
+ - spec/nightfury/metric/time_series_spec.rb
38
+ - spec/nightfury/metric/value_spec.rb
39
+ - spec/nightfury/metric_spec.rb
40
+ - spec/nightfury_spec.rb
41
+ - spec/spec_helper.rb
42
+ homepage: ''
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements:
61
+ - redis, v3.0.0 or greater
62
+ rubyforge_project:
63
+ rubygems_version: 1.8.24
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Nightfury is a reporting/analytics backend written on Redis
67
+ test_files:
68
+ - spec/nightfury/identity_spec.rb
69
+ - spec/nightfury/metric/time_series_spec.rb
70
+ - spec/nightfury/metric/value_spec.rb
71
+ - spec/nightfury/metric_spec.rb
72
+ - spec/nightfury_spec.rb
73
+ - spec/spec_helper.rb