fnordmetric 0.5.9 → 0.6.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.
- data/README.md +19 -0
- data/VERSION +1 -1
- data/doc/ulm_stats.rb +18 -0
- data/fnordmetric.gemspec +2 -2
- data/lib/fnordmetric.rb +6 -1
- data/lib/fnordmetric/app.rb +2 -0
- data/lib/fnordmetric/event.rb +68 -60
- data/lib/fnordmetric/inbound_stream.rb +2 -1
- data/lib/fnordmetric/namespace.rb +1 -0
- data/lib/fnordmetric/session.rb +3 -2
- data/pub/fnordmetric.css +5 -2
- data/pub/fnordmetric.js +69 -14
- data/spec/app_spec.rb +33 -1
- data/spec/event_spec.rb +44 -1
- data/spec/session_spec.rb +3 -3
- metadata +38 -38
data/README.md
CHANGED
@@ -277,6 +277,23 @@ FnordMetric.namespace :myapp do
|
|
277
277
|
|
278
278
|
end
|
279
279
|
|
280
|
+
FnordMetric.server_configuration = {
|
281
|
+
:redis_url => "redis://localhost:6379",
|
282
|
+
:redis_prefix => "fnordmetric",
|
283
|
+
:inbound_stream => ["0.0.0.0", "1339"],
|
284
|
+
:start_worker => true,
|
285
|
+
:print_stats => 3,
|
286
|
+
|
287
|
+
# events that aren't processed after 2 min get dropped
|
288
|
+
:event_queue_ttl => 120,
|
289
|
+
|
290
|
+
# event data is kept for one month
|
291
|
+
:event_data_ttl => 3600*24*30,
|
292
|
+
|
293
|
+
# session data is kept for one month
|
294
|
+
:session_data_ttl => 3600*24*30
|
295
|
+
}
|
296
|
+
|
280
297
|
FnordMetric.standalone
|
281
298
|
```
|
282
299
|
|
@@ -288,6 +305,8 @@ Contributors
|
|
288
305
|
+ Marco Borromeo (http://github.com/mborromeo)
|
289
306
|
+ Leo Lou (http://github.com/l4u)
|
290
307
|
+ Andy Lindeman (http://github.com/alindeman)
|
308
|
+
+ Jurriaan Pruis (http://github.com/jurriaan)
|
309
|
+
+ Kacper Bielecki (http://github.com/kazjote)
|
291
310
|
|
292
311
|
To contribute, please fork this repository, make your changes and run the specs, commit them to your github repository and send me a pull request.
|
293
312
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/doc/ulm_stats.rb
CHANGED
@@ -615,6 +615,24 @@ FnordMetric.namespace :ulm do
|
|
615
615
|
|
616
616
|
end
|
617
617
|
|
618
|
+
FnordMetric.server_configuration = {
|
619
|
+
:redis_url => "redis://localhost:6379",
|
620
|
+
:redis_prefix => "fnordmetric",
|
621
|
+
:inbound_stream => ["0.0.0.0", "1337"],
|
622
|
+
:web_interface => ["0.0.0.0", "4242"],
|
623
|
+
:start_worker => true,
|
624
|
+
:print_stats => 3,
|
625
|
+
|
626
|
+
# events that aren't processed after 2 min get dropped
|
627
|
+
:event_queue_ttl => 120,
|
628
|
+
|
629
|
+
# event data is kept for one month
|
630
|
+
:event_data_ttl => 3600*24*30,
|
631
|
+
|
632
|
+
# session data is kept for one month
|
633
|
+
:session_data_ttl => 3600*24*30
|
634
|
+
}
|
635
|
+
|
618
636
|
#task :setup do
|
619
637
|
# @fm_opts = {:web_interface => ["0.0.0.0", "2323"]} if ENV['DEV']
|
620
638
|
#end
|
data/fnordmetric.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "fnordmetric"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.6.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Paul Asmuth"]
|
12
|
-
s.date = "2012-01-
|
12
|
+
s.date = "2012-01-11"
|
13
13
|
s.description = "FnordMetric is a Ruby Event-Tracking gem on steroids"
|
14
14
|
s.email = "paul@paulasmuth.com"
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/fnordmetric.rb
CHANGED
@@ -15,6 +15,10 @@ module FnordMetric
|
|
15
15
|
def self.namespace(key=nil, &block)
|
16
16
|
@@namespaces[key] = block
|
17
17
|
end
|
18
|
+
|
19
|
+
def self.server_configuration=(configuration)
|
20
|
+
@@server_configuration = configuration
|
21
|
+
end
|
18
22
|
|
19
23
|
def self.default_options(opts)
|
20
24
|
|
@@ -90,7 +94,8 @@ module FnordMetric
|
|
90
94
|
puts(msg); exit!
|
91
95
|
end
|
92
96
|
|
93
|
-
def self.run
|
97
|
+
def self.run
|
98
|
+
opts = (defined?(@@server_configuration) && @@server_configuration) || {}
|
94
99
|
start_em(opts)
|
95
100
|
rescue Exception => e
|
96
101
|
log "!!! eventmachine died, restarting... #{e.message}"
|
data/lib/fnordmetric/app.rb
CHANGED
@@ -97,6 +97,8 @@ class FnordMetric::App < Sinatra::Base
|
|
97
97
|
|
98
98
|
events = if params[:type]
|
99
99
|
current_namespace.events(:by_type, :type => params[:type])
|
100
|
+
elsif params[:session_key]
|
101
|
+
current_namespace.events(:by_session_key, :session_key => params[:session_key])
|
100
102
|
else
|
101
103
|
find_opts = { :limit => 100 }
|
102
104
|
find_opts.merge!(:since => params[:since].to_i+1) if params[:since]
|
data/lib/fnordmetric/event.rb
CHANGED
@@ -1,78 +1,86 @@
|
|
1
|
-
|
1
|
+
module FnordMetric
|
2
|
+
class Event
|
2
3
|
|
3
|
-
|
4
|
+
attr_accessor :time, :type, :event_id
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
#def self.track!(event_type, event_data)
|
7
|
+
#end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
def self.all(opts)
|
10
|
+
range_opts = { :withscores => true }
|
11
|
+
range_opts.merge!(:limit => [0,opts[:limit]]) if opts[:limit]
|
12
|
+
opts[:redis].zrevrangebyscore(
|
13
|
+
"#{opts[:namespace_prefix]}-timeline",
|
14
|
+
'+inf', opts[:since]||'0',
|
15
|
+
range_opts
|
16
|
+
).in_groups_of(2).map do |event_id, ts|
|
17
|
+
next if event_id.blank?
|
18
|
+
find(event_id, opts).tap{ |e| e.time = ts }
|
19
|
+
end
|
18
20
|
end
|
19
|
-
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
def self.by_type(_type, opts)
|
23
|
+
opts[:redis].lrange(
|
24
|
+
"#{opts[:namespace_prefix]}-type-#{_type}",
|
25
|
+
0, 200).map do |event_id|
|
26
|
+
next if event_id.blank?
|
27
|
+
find(event_id, opts).tap{ |e| }
|
28
|
+
end
|
27
29
|
end
|
28
|
-
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
def self.by_session_key(_session_key, opts)
|
32
|
+
session = Session.find(_session_key, opts)
|
33
|
+
session.fetch_event_ids!(200).reject(&:blank?).map do |event_id|
|
34
|
+
find(event_id, opts)
|
35
|
+
end
|
33
36
|
end
|
34
|
-
end
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def self.find(event_id, opts)
|
39
|
+
self.new(event_id, opts).tap do |event|
|
40
|
+
event.fetch!
|
41
|
+
end
|
42
|
+
end
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
@
|
44
|
+
def initialize(event_id, opts)
|
45
|
+
@opts = opts
|
46
|
+
@event_id = event_id
|
44
47
|
end
|
45
|
-
end
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
-
|
49
|
+
def fetch!
|
50
|
+
@data = JSON.parse(fetch_json).tap do |event|
|
51
|
+
@type = event.delete("_type")
|
52
|
+
end
|
53
|
+
end
|
50
54
|
|
51
|
-
|
52
|
-
|
53
|
-
|
55
|
+
def fetch_json
|
56
|
+
@opts[:redis].get(redis_key) || "{}"
|
57
|
+
end
|
54
58
|
|
55
|
-
|
56
|
-
|
57
|
-
|
59
|
+
def redis_key
|
60
|
+
[@opts[:redis_prefix], :event, @event_id].join("-")
|
61
|
+
end
|
58
62
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
def data(key=nil)
|
64
|
-
key ? @data[key.to_s] : @data
|
65
|
-
end
|
63
|
+
def session_key
|
64
|
+
@data["_session"] ? Digest::MD5.hexdigest(@data["_session"]) : nil
|
65
|
+
end
|
66
66
|
|
67
|
-
|
67
|
+
def id
|
68
|
+
@event_id
|
69
|
+
end
|
70
|
+
|
71
|
+
def data(key=nil)
|
72
|
+
key ? @data[key.to_s] : @data
|
73
|
+
end
|
68
74
|
|
69
|
-
|
70
|
-
@data.merge!(
|
71
|
-
:_type => @type,
|
72
|
-
:_session_key => session_key,
|
73
|
-
:_eid => @event_id,
|
74
|
-
:_time => @time
|
75
|
-
)
|
76
|
-
end
|
75
|
+
alias :[] :data
|
77
76
|
|
78
|
-
|
77
|
+
def to_json
|
78
|
+
@data.merge!(
|
79
|
+
:_type => @type,
|
80
|
+
:_session_key => session_key,
|
81
|
+
:_eid => @event_id,
|
82
|
+
:_time => @time
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'securerandom'
|
1
2
|
class FnordMetric::InboundStream < EventMachine::Connection
|
2
3
|
|
3
4
|
@@opts = nil
|
@@ -43,7 +44,7 @@ class FnordMetric::InboundStream < EventMachine::Connection
|
|
43
44
|
end
|
44
45
|
|
45
46
|
def get_next_uuid
|
46
|
-
|
47
|
+
SecureRandom.uuid
|
47
48
|
end
|
48
49
|
|
49
50
|
def close_connection?
|
@@ -77,6 +77,7 @@ class FnordMetric::Namespace
|
|
77
77
|
def events(_ids, opts={})
|
78
78
|
return FnordMetric::Event.all(extend_opts(opts)) if _ids == :all
|
79
79
|
return FnordMetric::Event.by_type(opts.delete(:type), extend_opts(opts)) if _ids == :by_type
|
80
|
+
return FnordMetric::Event.by_session_key(opts.delete(:session_key), extend_opts(opts)) if _ids == :by_session_key
|
80
81
|
end
|
81
82
|
|
82
83
|
def method_missing(m, *args, &block)
|
data/lib/fnordmetric/session.rb
CHANGED
@@ -89,6 +89,7 @@ class FnordMetric::Session
|
|
89
89
|
|
90
90
|
def add_event(event)
|
91
91
|
@redis.zadd(redis_key(:events), event[:_time], event[:_eid])
|
92
|
+
|
92
93
|
add_data(:_picture, event[:url]) if event[:_type] == "_set_picture"
|
93
94
|
add_data(:_name, event[:name]) if event[:_type] == "_set_name"
|
94
95
|
add_event_data(event) if event[:_type] == "_set_data"
|
@@ -125,7 +126,7 @@ class FnordMetric::Session
|
|
125
126
|
|
126
127
|
def fetch_event_ids!(since=-1)
|
127
128
|
# FIXME: use WITHSCORE to get the timestamps and return event objects
|
128
|
-
@event_ids = @redis.
|
129
|
+
@event_ids = @redis.zrevrange(redis_key(:events), 0, since)
|
129
130
|
end
|
130
131
|
|
131
|
-
end
|
132
|
+
end
|
data/pub/fnordmetric.css
CHANGED
@@ -107,11 +107,14 @@ text-shadow: 1px 0px 2px rgba(255, 255, 255, 1);
|
|
107
107
|
|
108
108
|
|
109
109
|
ul.session_list{ list-style-type:none; margin:0; padding:9px 16px 0 11px; }
|
110
|
-
ul.session_list li{ color:#0A0A0A;
|
110
|
+
ul.session_list li{ color:#0A0A0A; height:32px; overflow:hidden; line-height:18px; padding:4px; }
|
111
111
|
ul.session_list li:hover{ background:#eee; cursor:pointer; }
|
112
|
+
ul.session_list li input{ float: left; margin-right: 7px; }
|
112
113
|
ul.session_list li .picture{ height:18px; width:18px; float:left; background:#333; overflow:hidden; }
|
113
114
|
ul.session_list li .name{ float:left; width:120px; overflow:hidden; margin-left:10px; font-size:12px; }
|
114
115
|
ul.session_list li .time{ float:right; width:40px; overflow:hidden; text-align:right; font-size:10px; }
|
116
|
+
ul.session_list li .history{ float:right; color:#999; font-size:10px; line-height: 12px;}
|
117
|
+
ul.session_list li .history:hover{ color:#333; text-decoration:underline; }
|
115
118
|
|
116
119
|
.sessions_feed{ min-width:300px; min-height:100px; float:left; }
|
117
120
|
.sessions_feed ul.feed_inner{ margin:5px 15px; min-height:100px; padding:0px; }
|
@@ -139,4 +142,4 @@ ul.event_type_list li .history:hover{ color:#333; text-decoration:underline; }
|
|
139
142
|
height: 0;
|
140
143
|
}
|
141
144
|
|
142
|
-
.highcharts-series circle{ stroke-width:1px; }
|
145
|
+
.highcharts-series circle{ stroke-width:1px; }
|
data/pub/fnordmetric.js
CHANGED
@@ -78,9 +78,15 @@ var FnordMetric = (function(){
|
|
78
78
|
}
|
79
79
|
}
|
80
80
|
|
81
|
+
function formatPercentValue(value){
|
82
|
+
return value + '%';
|
83
|
+
}
|
84
|
+
|
81
85
|
function formatGaugeValue(gauge_key, value){
|
82
86
|
if(gauge_key.slice(0,8) === '__time__'){
|
83
87
|
return formatTimeValue(value);
|
88
|
+
} else if(gauge_key.slice(0,11) === '__percent__'){
|
89
|
+
return formatPercentValue(value);
|
84
90
|
} else {
|
85
91
|
return formatValue(value);
|
86
92
|
}
|
@@ -733,7 +739,7 @@ var FnordMetric = (function(){
|
|
733
739
|
).append(listElem);
|
734
740
|
|
735
741
|
var eventsPolledUntil = false;
|
736
|
-
var eventsFilter = [];
|
742
|
+
var eventsFilter = {uncheckedTypes: [], checkedSessions: []};
|
737
743
|
var sessionData = {};
|
738
744
|
var pollRunning = true;
|
739
745
|
|
@@ -771,10 +777,11 @@ var FnordMetric = (function(){
|
|
771
777
|
});
|
772
778
|
};
|
773
779
|
|
774
|
-
function loadEventHistory(
|
780
|
+
function loadEventHistory(params){
|
775
781
|
feedInnerElem.html('');
|
776
782
|
$.ajax({
|
777
|
-
url: FnordMetric.p + '/' + currentNamespace+'/events
|
783
|
+
url: FnordMetric.p + '/' + currentNamespace+'/events',
|
784
|
+
data: params,
|
778
785
|
success: function(_data, _status){
|
779
786
|
var data = JSON.parse(_data).events;
|
780
787
|
for(var n=data.length; n >= 0; n--){
|
@@ -807,14 +814,19 @@ var FnordMetric = (function(){
|
|
807
814
|
});
|
808
815
|
};
|
809
816
|
|
817
|
+
function setCheckboxesCheckedState(types_state, sessions_state) {
|
818
|
+
$('.event_type_list .event_type input').attr('checked', types_state);
|
819
|
+
$('.session_list .session input').attr('checked', sessions_state);
|
820
|
+
}
|
821
|
+
|
810
822
|
function addEventType(type, display){
|
811
823
|
typeListElem.append(
|
812
824
|
$('<li class="event_type"></li>').append(
|
813
825
|
$('<span class="history"></span>').html('history')
|
814
826
|
.click(function(){
|
815
|
-
|
827
|
+
setCheckboxesCheckedState(true, true);
|
816
828
|
$('input', $(this).parent()).attr('checked', true);
|
817
|
-
updateEventFilter(); loadEventHistory(type);
|
829
|
+
updateEventFilter(); loadEventHistory({type: type});
|
818
830
|
})
|
819
831
|
).append(
|
820
832
|
$('<input type="checkbox" />').attr('checked', true)
|
@@ -832,7 +844,15 @@ var FnordMetric = (function(){
|
|
832
844
|
_unchecked_types.push($(v).attr('rel'));
|
833
845
|
}
|
834
846
|
});
|
835
|
-
eventsFilter = _unchecked_types;
|
847
|
+
eventsFilter.uncheckedTypes = _unchecked_types;
|
848
|
+
|
849
|
+
var _checked_sessions = [];
|
850
|
+
$('ul.session_list li.session').each(function(i,v){
|
851
|
+
if($('input', v).attr('checked')){
|
852
|
+
_checked_sessions.push($(v).data().session);
|
853
|
+
}
|
854
|
+
});
|
855
|
+
eventsFilter.checkedSessions = _checked_sessions;
|
836
856
|
}
|
837
857
|
|
838
858
|
function doEventsPoll(){
|
@@ -848,18 +868,40 @@ var FnordMetric = (function(){
|
|
848
868
|
return (function(_data, _status){
|
849
869
|
var data = JSON.parse(_data)
|
850
870
|
var events = data.events;
|
851
|
-
var
|
871
|
+
var timeout = 1000;
|
852
872
|
var maxevents = 200;
|
873
|
+
var passesFiltering = function(event_data) {
|
874
|
+
var passes_type_filtering = false;
|
875
|
+
var passes_session_filtering = false;
|
876
|
+
if(eventsFilter.uncheckedTypes.indexOf(event_data._type) == -1) {
|
877
|
+
if(parseInt(v._time)<=eventsPolledUntil) {
|
878
|
+
passes_type_filtering = true;
|
879
|
+
}
|
880
|
+
}
|
881
|
+
if(!passes_type_filtering) return false;
|
882
|
+
|
883
|
+
if(eventsFilter.checkedSessions.length == 0){
|
884
|
+
return true; // No filter set - show all events
|
885
|
+
} else {
|
886
|
+
if(event_data._session_key){
|
887
|
+
if(eventsFilter.checkedSessions.indexOf(event_data._session_key) >= 0){
|
888
|
+
return true; // Filter set and match
|
889
|
+
} else {
|
890
|
+
return false; // Filter set but no match
|
891
|
+
}
|
892
|
+
} else {
|
893
|
+
return false; // Filter set but event is not associated with session
|
894
|
+
}
|
895
|
+
}
|
896
|
+
}
|
897
|
+
|
853
898
|
if(events.length > 0){
|
854
|
-
timeout = 200;
|
855
899
|
eventsPolledUntil = parseInt(events[0]._time)-1;
|
856
900
|
}
|
857
901
|
for(var n=events.length-1; n >= 0; n--){
|
858
902
|
var v = events[n];
|
859
|
-
if(
|
860
|
-
|
861
|
-
renderEvent(v);
|
862
|
-
}
|
903
|
+
if(passesFiltering(v)) {
|
904
|
+
renderEvent(v);
|
863
905
|
}
|
864
906
|
};
|
865
907
|
var elems = $("p", feedInnerElem);
|
@@ -867,13 +909,17 @@ var FnordMetric = (function(){
|
|
867
909
|
$(elems[n]).remove();
|
868
910
|
}
|
869
911
|
if(pollRunning){
|
870
|
-
window.setTimeout(doEventsPoll(),
|
912
|
+
window.setTimeout(doEventsPoll(), timeout);
|
871
913
|
}
|
872
914
|
});
|
873
915
|
};
|
874
916
|
|
875
917
|
function updateSession(session_data){
|
876
|
-
|
918
|
+
var session_key = session_data.session_key;
|
919
|
+
if(!sessionData[session_key]){
|
920
|
+
updateEventFilter()
|
921
|
+
}
|
922
|
+
sessionData[session_key] = session_data;
|
877
923
|
renderSession(session_data);
|
878
924
|
}
|
879
925
|
|
@@ -913,11 +959,20 @@ var FnordMetric = (function(){
|
|
913
959
|
|
914
960
|
listElem.append(
|
915
961
|
$('<li class="session"></li>').append(
|
962
|
+
$('<input type="checkbox" />').click(function(){ updateEventFilter(); })
|
963
|
+
).append(
|
916
964
|
$('<div class="picture"></div>').html(session_picture)
|
917
965
|
).append(
|
918
966
|
$('<span class="name"></span>').html(session_name)
|
919
967
|
).append(
|
920
968
|
$('<span class="time"></span>').html(session_time)
|
969
|
+
).append(
|
970
|
+
$('<span class="history"></span>').html('history')
|
971
|
+
.click(function(){
|
972
|
+
setCheckboxesCheckedState(true, false);
|
973
|
+
$('input', $(this).parent()).attr('checked', true);
|
974
|
+
updateEventFilter(); loadEventHistory({session_key: session_data["session_key"]});
|
975
|
+
})
|
921
976
|
).attr('data-session', session_data["session_key"])
|
922
977
|
);
|
923
978
|
|
data/spec/app_spec.rb
CHANGED
@@ -334,6 +334,38 @@ describe "app" do
|
|
334
334
|
JSON.parse(last_response.body)["events"].length.should == 1
|
335
335
|
end
|
336
336
|
|
337
|
+
it "should render all events for a single session key" do
|
338
|
+
@namespace.ready!(@redis_wrap).announce(
|
339
|
+
:_time => @now,
|
340
|
+
:_session => "max_session",
|
341
|
+
:_eid => "124234"
|
342
|
+
)
|
343
|
+
@namespace.ready!(@redis_wrap).announce(
|
344
|
+
:_time => @now,
|
345
|
+
:_session => "kate_session",
|
346
|
+
:_eid => "12235234"
|
347
|
+
)
|
348
|
+
@namespace.ready!(@redis_wrap).announce(
|
349
|
+
:_time => @now,
|
350
|
+
:_session => "kate_session",
|
351
|
+
:_eid => "124234234"
|
352
|
+
)
|
353
|
+
@namespace.ready!(@redis_wrap).announce(
|
354
|
+
:_time => @now,
|
355
|
+
:_eid => "124234234"
|
356
|
+
)
|
357
|
+
max_session_key = Digest::MD5.hexdigest "max_session"
|
358
|
+
kate_session_key = Digest::MD5.hexdigest "kate_session"
|
359
|
+
|
360
|
+
get "/foospace/events?session_key=#{max_session_key}"
|
361
|
+
events = JSON.parse(last_response.body)["events"]
|
362
|
+
events.length.should == 1
|
363
|
+
|
364
|
+
get "/foospace/events?session_key=#{kate_session_key}"
|
365
|
+
events = JSON.parse(last_response.body)["events"]
|
366
|
+
events.length.should == 2
|
367
|
+
end
|
368
|
+
|
337
369
|
it "should render a list of event types" do
|
338
370
|
@namespace.ready!(@redis_wrap).announce(
|
339
371
|
:_type => "fn0rd",
|
@@ -449,4 +481,4 @@ describe "app" do
|
|
449
481
|
|
450
482
|
end
|
451
483
|
|
452
|
-
end
|
484
|
+
end
|
data/spec/event_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require ::File.expand_path('../spec_helper.rb', __FILE__)
|
2
|
+
require 'irb'
|
2
3
|
|
3
4
|
describe FnordMetric::Event do
|
4
5
|
|
@@ -116,6 +117,48 @@ describe FnordMetric::Event do
|
|
116
117
|
Event.by_type('f00bar', @opts).length.should == 1
|
117
118
|
end
|
118
119
|
|
120
|
+
describe "looking by session_key" do
|
121
|
+
let(:namespace) do
|
122
|
+
options = {:redis_prefix => "fnordmetric-test", :session_data_ttl => 1}
|
123
|
+
Namespace.new(:ns123, options)
|
124
|
+
end
|
125
|
+
|
126
|
+
let(:events_data) do
|
127
|
+
[[1, "max_session"], [2, "kate_session"], [3, "kate_session"], [12345678, nil]]
|
128
|
+
end
|
129
|
+
|
130
|
+
let(:kate_session_key) { Digest::MD5.hexdigest "kate_session" }
|
131
|
+
let(:events) { Event.by_session_key kate_session_key, @opts }
|
132
|
+
|
133
|
+
before do
|
134
|
+
created_events_data.each do |(event_id, session)|
|
135
|
+
event_data = { :_time => @now + event_id, :_eid => event_id }
|
136
|
+
event_data[:_session] = session if session
|
137
|
+
namespace.ready!(@redis_wrap).announce event_data
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context "when events are added in ascending time order" do
|
142
|
+
let(:created_events_data) { events_data }
|
143
|
+
|
144
|
+
it "should find correct events" do
|
145
|
+
["2","3"].each {|id| events.map(&:id).should include(id) }
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should have correct order" do
|
149
|
+
events.map(&:id).should == ["3","2"]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "when events are added in descending time order" do
|
154
|
+
let(:created_events_data) { events_data.reverse }
|
155
|
+
|
156
|
+
it "should have correct order" do
|
157
|
+
events.map(&:id).should == ["3","2"]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
119
162
|
def create_event(event_id, event_data)
|
120
163
|
@redis_wrap.zadd(@timeline, event_data.delete(:_time), event_id)
|
121
164
|
@redis.set("fnordmetric-test-event-#{event_id}", event_data.to_json)
|
@@ -124,4 +167,4 @@ describe FnordMetric::Event do
|
|
124
167
|
end
|
125
168
|
|
126
169
|
|
127
|
-
end
|
170
|
+
end
|
data/spec/session_spec.rb
CHANGED
@@ -212,8 +212,8 @@ describe FnordMetric::Session do
|
|
212
212
|
@redis_wrap.zadd("#{@namespace}-session-#{sesshash}-events", @now, "fnord")
|
213
213
|
sess = Session.find(sesshash, @opts)
|
214
214
|
sess.fetch_event_ids!
|
215
|
-
sess.event_ids
|
216
|
-
sess.event_ids
|
215
|
+
sess.event_ids.should include("shmoo")
|
216
|
+
sess.event_ids.should include("fnord")
|
217
217
|
end
|
218
218
|
|
219
219
|
def create_session(sesskey, sesstime, sessdata)
|
@@ -228,4 +228,4 @@ describe FnordMetric::Session do
|
|
228
228
|
end
|
229
229
|
|
230
230
|
|
231
|
-
end
|
231
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fnordmetric
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-01-
|
12
|
+
date: 2012-01-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bson_ext
|
16
|
-
requirement: &
|
16
|
+
requirement: &70186955498840 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 1.4.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70186955498840
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: sinatra
|
27
|
-
requirement: &
|
27
|
+
requirement: &70186955498360 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.2.6
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70186955498360
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: redis
|
38
|
-
requirement: &
|
38
|
+
requirement: &70186955497820 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 2.2.2
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70186955497820
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: eventmachine
|
49
|
-
requirement: &
|
49
|
+
requirement: &70186955497320 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70186955497320
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: em-hiredis
|
60
|
-
requirement: &
|
60
|
+
requirement: &70186955496720 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70186955496720
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: json
|
71
|
-
requirement: &
|
71
|
+
requirement: &70186955496080 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70186955496080
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: i18n
|
82
|
-
requirement: &
|
82
|
+
requirement: &70186955495200 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70186955495200
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: haml
|
93
|
-
requirement: &
|
93
|
+
requirement: &70186955494700 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70186955494700
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: rack
|
104
|
-
requirement: &
|
104
|
+
requirement: &70186955494200 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :runtime
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70186955494200
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: rack-test
|
115
|
-
requirement: &
|
115
|
+
requirement: &70186955490620 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: '0'
|
121
121
|
type: :runtime
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70186955490620
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: yajl-ruby
|
126
|
-
requirement: &
|
126
|
+
requirement: &70186955490140 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ! '>='
|
@@ -131,10 +131,10 @@ dependencies:
|
|
131
131
|
version: '0'
|
132
132
|
type: :runtime
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *70186955490140
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: thin
|
137
|
-
requirement: &
|
137
|
+
requirement: &70186955489620 !ruby/object:Gem::Requirement
|
138
138
|
none: false
|
139
139
|
requirements:
|
140
140
|
- - ! '>='
|
@@ -142,10 +142,10 @@ dependencies:
|
|
142
142
|
version: '0'
|
143
143
|
type: :runtime
|
144
144
|
prerelease: false
|
145
|
-
version_requirements: *
|
145
|
+
version_requirements: *70186955489620
|
146
146
|
- !ruby/object:Gem::Dependency
|
147
147
|
name: activesupport
|
148
|
-
requirement: &
|
148
|
+
requirement: &70186955489120 !ruby/object:Gem::Requirement
|
149
149
|
none: false
|
150
150
|
requirements:
|
151
151
|
- - ! '>='
|
@@ -153,10 +153,10 @@ dependencies:
|
|
153
153
|
version: '0'
|
154
154
|
type: :runtime
|
155
155
|
prerelease: false
|
156
|
-
version_requirements: *
|
156
|
+
version_requirements: *70186955489120
|
157
157
|
- !ruby/object:Gem::Dependency
|
158
158
|
name: delorean
|
159
|
-
requirement: &
|
159
|
+
requirement: &70186955488640 !ruby/object:Gem::Requirement
|
160
160
|
none: false
|
161
161
|
requirements:
|
162
162
|
- - ! '>='
|
@@ -164,10 +164,10 @@ dependencies:
|
|
164
164
|
version: '0'
|
165
165
|
type: :development
|
166
166
|
prerelease: false
|
167
|
-
version_requirements: *
|
167
|
+
version_requirements: *70186955488640
|
168
168
|
- !ruby/object:Gem::Dependency
|
169
169
|
name: rspec
|
170
|
-
requirement: &
|
170
|
+
requirement: &70186955488160 !ruby/object:Gem::Requirement
|
171
171
|
none: false
|
172
172
|
requirements:
|
173
173
|
- - ~>
|
@@ -175,10 +175,10 @@ dependencies:
|
|
175
175
|
version: 2.6.0
|
176
176
|
type: :development
|
177
177
|
prerelease: false
|
178
|
-
version_requirements: *
|
178
|
+
version_requirements: *70186955488160
|
179
179
|
- !ruby/object:Gem::Dependency
|
180
180
|
name: shoulda
|
181
|
-
requirement: &
|
181
|
+
requirement: &70186955487680 !ruby/object:Gem::Requirement
|
182
182
|
none: false
|
183
183
|
requirements:
|
184
184
|
- - ! '>='
|
@@ -186,10 +186,10 @@ dependencies:
|
|
186
186
|
version: '0'
|
187
187
|
type: :development
|
188
188
|
prerelease: false
|
189
|
-
version_requirements: *
|
189
|
+
version_requirements: *70186955487680
|
190
190
|
- !ruby/object:Gem::Dependency
|
191
191
|
name: bundler
|
192
|
-
requirement: &
|
192
|
+
requirement: &70186955487140 !ruby/object:Gem::Requirement
|
193
193
|
none: false
|
194
194
|
requirements:
|
195
195
|
- - ~>
|
@@ -197,10 +197,10 @@ dependencies:
|
|
197
197
|
version: 1.0.0
|
198
198
|
type: :development
|
199
199
|
prerelease: false
|
200
|
-
version_requirements: *
|
200
|
+
version_requirements: *70186955487140
|
201
201
|
- !ruby/object:Gem::Dependency
|
202
202
|
name: jeweler
|
203
|
-
requirement: &
|
203
|
+
requirement: &70186955486600 !ruby/object:Gem::Requirement
|
204
204
|
none: false
|
205
205
|
requirements:
|
206
206
|
- - ~>
|
@@ -208,7 +208,7 @@ dependencies:
|
|
208
208
|
version: 1.5.2
|
209
209
|
type: :development
|
210
210
|
prerelease: false
|
211
|
-
version_requirements: *
|
211
|
+
version_requirements: *70186955486600
|
212
212
|
description: FnordMetric is a Ruby Event-Tracking gem on steroids
|
213
213
|
email: paul@paulasmuth.com
|
214
214
|
executables: []
|