Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: AudioAddict/fnordmetric
base: 263f429f72
...
head fork: AudioAddict/fnordmetric
compare: 94949a9695
Checking mergeability… Don't worry, you can still create the pull request.
  • 14 commits
  • 17 files changed
  • 0 commit comments
  • 7 contributors
Commits on Jan 05, 2012
@jurriaan jurriaan Use SecureRandom.uuid for uuids 2a4fe0c
Commits on Jan 07, 2012
Kacper Bielecki Server ports are configurable fb14e0a
Commits on Jan 10, 2012
@kazjote kazjote Incoming events can be filtered according to session filter 42fdf20
Commits on Jan 11, 2012
@kazjote kazjote Active user timeline can be displayed 3a49291
Paul Asmuth Merge pull request #32 from kazjote/user_feed
User feed. LOVE IT! :)
1eae778
Paul Asmuth Merge pull request #26 from jurriaan/real-uuids
Use SecureRandom.uuid for uuids
a9f99a6
Paul Asmuth Merge pull request #29 from kazjote/server_configuration
Server ports are configurable
50b5417
@paulasmuth paulasmuth version bump to 0.6.0 82abc1d
Commits on Jan 12, 2012
Paul Asmuth css fixes a6e9aa6
Paul Asmuth readme + proper restart + bump to 0.6.1 4966a6f
John Murray Changed set(:public) to set(:public_folder)
The former was deprecated and throwing warning messages when running the
project.
69826f3
@oleriesenberg oleriesenberg Merge pull request #33 from JohnMurray/master
Changed set(:public, ...) to set(:public_folder, ...)
f62b418
@fd fd Added FnordMetric#embedded
There are still some problems with the CSS with need to be fixed.
See #5
554920f
Commits on Jan 13, 2012
@ianlevesque ianlevesque Allow passing false for some of the config options, expose the namesp…
…aces config for use with custom workers.
94949a9
View
4 Gemfile
@@ -18,6 +18,6 @@ group :development do
gem "delorean", ">= 0"
gem "rspec", "~> 2.6.0"
gem "shoulda", ">= 0"
- gem "bundler", "~> 1.0.0"
- gem "jeweler", "~> 1.5.2"
+ gem "bundler"
+ gem "jeweler"
end
View
45 Gemfile.lock
@@ -1,37 +1,41 @@
GIT
remote: git://github.com/brianmario/yajl-ruby.git
- revision: eef5c48be81b6404af66da3f185ec9301e5214d8
+ revision: b08b3f7ffd2fe5fad051f9d4a78db7ce71d7a5fc
specs:
yajl-ruby (1.1.0)
GEM
remote: http://rubygems.org/
specs:
- activesupport (3.1.1)
+ activesupport (3.1.3)
multi_json (~> 1.0)
- bson_ext (1.4.0)
- chronic (0.6.4)
- daemons (1.1.4)
- delorean (1.1.0)
+ bson (1.5.2)
+ bson_ext (1.5.2)
+ bson (= 1.5.2)
+ chronic (0.6.6)
+ daemons (1.1.5)
+ delorean (1.2.0)
chronic
diff-lcs (1.1.3)
em-hiredis (0.1.0)
hiredis (~> 0.3.0)
eventmachine (0.12.10)
git (1.2.5)
- haml (3.1.2)
+ haml (3.1.4)
hiredis (0.3.2)
i18n (0.6.0)
- jeweler (1.5.2)
- bundler (~> 1.0.0)
+ jeweler (1.6.4)
+ bundler (~> 1.0)
git (>= 1.2.5)
rake
- json (1.6.1)
+ json (1.6.4)
multi_json (1.0.4)
- rack (1.3.0)
- rack-test (0.6.0)
+ rack (1.4.0)
+ rack-protection (1.2.0)
+ rack
+ rack-test (0.6.1)
rack (>= 1.0)
- rake (0.9.2)
+ rake (0.9.2.2)
redis (2.2.2)
rspec (2.6.0)
rspec-core (~> 2.6.0)
@@ -42,14 +46,15 @@ GEM
diff-lcs (~> 1.1.2)
rspec-mocks (2.6.0)
shoulda (2.11.3)
- sinatra (1.2.6)
- rack (~> 1.1)
- tilt (>= 1.2.2, < 2.0)
- thin (1.2.11)
+ sinatra (1.3.2)
+ rack (~> 1.3, >= 1.3.6)
+ rack-protection (~> 1.2)
+ tilt (~> 1.3, >= 1.3.3)
+ thin (1.3.1)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
- tilt (1.3.2)
+ tilt (1.3.3)
PLATFORMS
ruby
@@ -57,13 +62,13 @@ PLATFORMS
DEPENDENCIES
activesupport
bson_ext (>= 1.4.0)
- bundler (~> 1.0.0)
+ bundler
delorean
em-hiredis
eventmachine
haml
i18n
- jeweler (~> 1.5.2)
+ jeweler
json
rack
rack-test
View
23 README.md
@@ -21,7 +21,7 @@ FnordMetric gives you a live dashboard, that shows who is using your app in real
Getting Started
---------------
-Copy `doc/ulm_stats.rb` (that's the configuration from the screenshots and screencast) or the simple example from below to `my_stats_app.rb`.
+Copy `doc/full_example.rb` (that's the configuration from the screenshots and screencast) or the simple example from below to `my_stats_app.rb`.
Simple Example: this will listen for json-events with `type=unicorn_seen` and render a timeline-plot showing the number of received events per hour.
@@ -167,7 +167,7 @@ BarsWidget
Examples
--------
-+ doc/ulm_stats.rb
++ doc/full_example.rb
## Full Example ##
@@ -277,6 +277,23 @@ FnordMetric.namespace :myapp do
end
+FnordMetric.server_configuration = {
+ :redis_url => "redis://localhost:6379",
+ :redis_prefix => "fnordmetric",
+ :inbound_stream => ["0.0.0.0", "1339"],
+ :start_worker => true,
+ :print_stats => 3,
+
+ # events that aren't processed after 2 min get dropped
+ :event_queue_ttl => 120,
+
+ # event data is kept for one month
+ :event_data_ttl => 3600*24*30,
+
+ # session data is kept for one month
+ :session_data_ttl => 3600*24*30
+}
+
FnordMetric.standalone
```
@@ -288,6 +305,8 @@ Contributors
+ Marco Borromeo (http://github.com/mborromeo)
+ Leo Lou (http://github.com/l4u)
+ Andy Lindeman (http://github.com/alindeman)
++ Jurriaan Pruis (http://github.com/jurriaan)
++ Kacper Bielecki (http://github.com/kazjote)
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.
View
2  VERSION
@@ -1 +1 @@
-0.5.9
+0.6.1
View
18 doc/ulm_stats.rb → doc/full_example.rb
@@ -615,6 +615,24 @@
end
+FnordMetric.server_configuration = {
+ :redis_url => "redis://localhost:6379",
+ :redis_prefix => "fnordmetric",
+ :inbound_stream => ["0.0.0.0", "1337"],
+ :web_interface => ["0.0.0.0", "4242"],
+ :start_worker => true,
+ :print_stats => 3,
+
+ # events that aren't processed after 2 min get dropped
+ :event_queue_ttl => 120,
+
+ # event data is kept for one month
+ :event_data_ttl => 3600*24*30,
+
+ # session data is kept for one month
+ :session_data_ttl => 3600*24*30
+}
+
#task :setup do
# @fm_opts = {:web_interface => ["0.0.0.0", "2323"]} if ENV['DEV']
#end
View
18 fnordmetric.gemspec
@@ -4,14 +4,14 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
- s.name = "fnordmetric"
- s.version = "0.5.9"
+ s.name = %q{fnordmetric}
+ s.version = "0.6.1"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Paul Asmuth"]
- s.date = "2012-01-04"
- s.description = "FnordMetric is a Ruby Event-Tracking gem on steroids"
- s.email = "paul@paulasmuth.com"
+ s.date = %q{2012-01-12}
+ s.description = %q{FnordMetric is a Ruby Event-Tracking gem on steroids}
+ s.email = %q{paul@paulasmuth.com}
s.extra_rdoc_files = [
"README.md"
]
@@ -22,9 +22,9 @@ Gem::Specification.new do |s|
"README.md",
"Rakefile",
"VERSION",
+ "doc/full_example.rb",
"doc/preview1.png",
"doc/preview2.png",
- "doc/ulm_stats.rb",
"doc/version",
"fnordmetric.gemspec",
"haml/app.haml",
@@ -76,11 +76,11 @@ Gem::Specification.new do |s|
"spec/widget_spec.rb",
"spec/worker_spec.rb"
]
- s.homepage = "http://github.com/paulasmuth/fnordmetric"
+ s.homepage = %q{http://github.com/paulasmuth/fnordmetric}
s.licenses = ["MIT"]
s.require_paths = ["lib"]
- s.rubygems_version = "1.8.10"
- s.summary = "FnordMetric is a Ruby Event-Tracking gem on steroids"
+ s.rubygems_version = %q{1.5.2}
+ s.summary = %q{FnordMetric is a Ruby Event-Tracking gem on steroids}
s.test_files = [
"spec/app_spec.rb",
"spec/context_spec.rb",
View
106 lib/fnordmetric.rb
@@ -12,20 +12,27 @@ module FnordMetric
@@namespaces = {}
- def self.namespace(key=nil, &block)
- @@namespaces[key] = block
+ def self.namespace(key=nil, &block)
+ @@namespaces[key] = block
end
- def self.default_options(opts)
+ def self.namespaces
+ @@namespaces
+ end
+ def self.server_configuration=(configuration)
+ @@server_configuration = configuration
+ end
+
+ def self.default_options(opts)
opts[:redis_url] ||= "redis://localhost:6379"
- opts[:redis_prefix] ||= "fnordmetric"
+ opts[:redis_prefix] ||= "fnordmetric"
- opts[:inbound_stream] ||= ["0.0.0.0", "1337"]
- opts[:web_interface] ||= ["0.0.0.0", "4242"]
+ opts[:inbound_stream] = ["0.0.0.0", "1337"] if opts[:inbound_stream].nil?
+ opts[:web_interface] = ["0.0.0.0", "4242"] if opts[:web_interface].nil?
- opts[:start_worker] ||= true
- opts[:print_stats] ||= 3
+ opts[:start_worker] = true if opts[:start_worker].nil?
+ opts[:print_stats] = 3 if opts[:print_stats].nil?
# events that aren't processed after 2 min get dropped
opts[:event_queue_ttl] ||= 120
@@ -34,8 +41,8 @@ def self.default_options(opts)
opts[:event_data_ttl] ||= 3600*24*30
# session data is kept for one month
- opts[:session_data_ttl] ||= 3600*24*30
-
+ opts[:session_data_ttl] ||= 3600*24*30
+
opts
end
@@ -45,25 +52,10 @@ def self.start_em(opts)
trap("TERM", &method(:shutdown))
trap("INT", &method(:shutdown))
- opts = default_options(opts)
-
- if opts[:start_worker]
- worker = Worker.new(@@namespaces.clone, opts)
- worker.ready!
- end
-
- if opts[:inbound_stream]
- begin
- inbound_stream = InboundStream.start(opts)
- log "listening on tcp##{opts[:inbound_stream].join(":")}"
- rescue
- log "cant start FnordMetric::InboundStream. port in use?"
- end
- end
+ app = embedded(opts)
if opts[:web_interface]
- begin
- app = FnordMetric::App.new(@@namespaces.clone, opts)
+ begin
Thin::Server.start(*opts[:web_interface], app)
log "listening on http##{opts[:web_interface].join(":")}"
rescue Exception => e
@@ -71,14 +63,7 @@ def self.start_em(opts)
end
end
- if opts[:print_stats]
- redis = connect_redis(opts[:redis_url])
- EM::PeriodicTimer.new(opts[:print_stats]) do
- print_stats(opts, redis)
- end
- end
-
- end
+ end
end
def self.log(msg)
@@ -90,11 +75,12 @@ def self.error!(msg)
puts(msg); exit!
end
- def self.run(opts={})
- start_em(opts)
+ def self.run
+ opts = (defined?(@@server_configuration) && @@server_configuration) || {}
+ start_em(opts)
rescue Exception => e
log "!!! eventmachine died, restarting... #{e.message}"
- sleep(1); run(opts)
+ sleep(1); run
end
def self.shutdown
@@ -108,19 +94,57 @@ def self.connect_redis(redis_url)
def self.print_stats(opts, redis) # FIXME: refactor this mess
keys = [:events_received, :events_processed]
- redis.llen("#{opts[:redis_prefix]}-queue") do |queue_length|
+ redis.llen("#{opts[:redis_prefix]}-queue") do |queue_length|
redis.hmget("#{opts[:redis_prefix]}-stats", *keys) do |data|
data_human = keys.size.times.map{|n|"#{keys[n]}: #{data[n]}"}
log "#{data_human.join(", ")}, queue_length: #{queue_length}"
- end
+ end
end
end
- def self.standalone
+ def self.standalone
require "fnordmetric/logger"
require "fnordmetric/standalone"
end
+ # returns a Rack app which can be mounted under any path.
+ # `:start_worker` starts a worker
+ # `:inbound_stream` starts the TCP interface
+ # `:print_stats` periodicaly prints worker stats
+ def self.embedded(opts={})
+ opts = default_options(opts)
+ app = nil
+
+ if opts[:rack_app] or opts[:web_interface]
+ app = FnordMetric::App.new(@@namespaces.clone, opts)
+ end
+
+ EM.next_tick do
+ if opts[:start_worker]
+ worker = Worker.new(@@namespaces.clone, opts)
+ worker.ready!
+ end
+
+ if opts[:inbound_stream]
+ begin
+ inbound_stream = InboundStream.start(opts)
+ log "listening on tcp##{opts[:inbound_stream].join(":")}"
+ rescue
+ log "cant start FnordMetric::InboundStream. port in use?"
+ end
+ end
+
+ if opts[:print_stats]
+ redis = connect_redis(opts[:redis_url])
+ EM::PeriodicTimer.new(opts[:print_stats]) do
+ print_stats(opts, redis)
+ end
+ end
+ end
+
+ app
+ end
+
end
require "fnordmetric/inbound_stream"
View
4 lib/fnordmetric/app.rb
@@ -12,7 +12,7 @@ class FnordMetric::App < Sinatra::Base
set :haml, :format => :html5
set :views, ::File.expand_path('../../../haml', __FILE__)
- set :public, ::File.expand_path('../../../pub', __FILE__)
+ set :public_folder, ::File.expand_path('../../../pub', __FILE__)
def initialize(namespaces, opts)
@namespaces = {}
@@ -97,6 +97,8 @@ def current_namespace
events = if params[:type]
current_namespace.events(:by_type, :type => params[:type])
+ elsif params[:session_key]
+ current_namespace.events(:by_session_key, :session_key => params[:session_key])
else
find_opts = { :limit => 100 }
find_opts.merge!(:since => params[:since].to_i+1) if params[:since]
View
128 lib/fnordmetric/event.rb
@@ -1,78 +1,86 @@
-class FnordMetric::Event
+module FnordMetric
+ class Event
- attr_accessor :time, :type, :event_id
+ attr_accessor :time, :type, :event_id
- #def self.track!(event_type, event_data)
- #end
+ #def self.track!(event_type, event_data)
+ #end
- def self.all(opts)
- range_opts = { :withscores => true }
- range_opts.merge!(:limit => [0,opts[:limit]]) if opts[:limit]
- opts[:redis].zrevrangebyscore(
- "#{opts[:namespace_prefix]}-timeline",
- '+inf', opts[:since]||'0',
- range_opts
- ).in_groups_of(2).map do |event_id, ts|
- next if event_id.blank?
- find(event_id, opts).tap{ |e| e.time = ts }
+ def self.all(opts)
+ range_opts = { :withscores => true }
+ range_opts.merge!(:limit => [0,opts[:limit]]) if opts[:limit]
+ opts[:redis].zrevrangebyscore(
+ "#{opts[:namespace_prefix]}-timeline",
+ '+inf', opts[:since]||'0',
+ range_opts
+ ).in_groups_of(2).map do |event_id, ts|
+ next if event_id.blank?
+ find(event_id, opts).tap{ |e| e.time = ts }
+ end
end
- end
- def self.by_type(_type, opts)
- opts[:redis].lrange(
- "#{opts[:namespace_prefix]}-type-#{_type}",
- 0, 200).map do |event_id|
- next if event_id.blank?
- find(event_id, opts).tap{ |e| }
+ def self.by_type(_type, opts)
+ opts[:redis].lrange(
+ "#{opts[:namespace_prefix]}-type-#{_type}",
+ 0, 200).map do |event_id|
+ next if event_id.blank?
+ find(event_id, opts).tap{ |e| }
+ end
end
- end
- def self.find(event_id, opts)
- self.new(event_id, opts).tap do |event|
- event.fetch!
+ def self.by_session_key(_session_key, opts)
+ session = Session.find(_session_key, opts)
+ session.fetch_event_ids!(200).reject(&:blank?).map do |event_id|
+ find(event_id, opts)
+ end
end
- end
- def initialize(event_id, opts)
- @opts = opts
- @event_id = event_id
- end
+ def self.find(event_id, opts)
+ self.new(event_id, opts).tap do |event|
+ event.fetch!
+ end
+ end
- def fetch!
- @data = JSON.parse(fetch_json).tap do |event|
- @type = event.delete("_type")
+ def initialize(event_id, opts)
+ @opts = opts
+ @event_id = event_id
end
- end
- def fetch_json
- @opts[:redis].get(redis_key) || "{}"
- end
+ def fetch!
+ @data = JSON.parse(fetch_json).tap do |event|
+ @type = event.delete("_type")
+ end
+ end
- def redis_key
- [@opts[:redis_prefix], :event, @event_id].join("-")
- end
+ def fetch_json
+ @opts[:redis].get(redis_key) || "{}"
+ end
- def session_key
- @data["_session"] ? Digest::MD5.hexdigest(@data["_session"]) : nil
- end
+ def redis_key
+ [@opts[:redis_prefix], :event, @event_id].join("-")
+ end
- def id
- @event_id
- end
-
- def data(key=nil)
- key ? @data[key.to_s] : @data
- end
+ def session_key
+ @data["_session"] ? Digest::MD5.hexdigest(@data["_session"]) : nil
+ end
- alias :[] :data
+ def id
+ @event_id
+ end
+
+ def data(key=nil)
+ key ? @data[key.to_s] : @data
+ end
- def to_json
- @data.merge!(
- :_type => @type,
- :_session_key => session_key,
- :_eid => @event_id,
- :_time => @time
- )
- end
+ alias :[] :data
-end
+ def to_json
+ @data.merge!(
+ :_type => @type,
+ :_session_key => session_key,
+ :_eid => @event_id,
+ :_time => @time
+ )
+ end
+ end
+end
View
3  lib/fnordmetric/inbound_stream.rb
@@ -1,3 +1,4 @@
+require 'securerandom'
class FnordMetric::InboundStream < EventMachine::Connection
@@opts = nil
@@ -43,7 +44,7 @@ def push_next_event
end
def get_next_uuid
- rand(9999999999999999999).to_s # FIXME
+ SecureRandom.uuid
end
def close_connection?
View
1  lib/fnordmetric/namespace.rb
@@ -77,6 +77,7 @@ def sessions(_ids, opts={})
def events(_ids, opts={})
return FnordMetric::Event.all(extend_opts(opts)) if _ids == :all
return FnordMetric::Event.by_type(opts.delete(:type), extend_opts(opts)) if _ids == :by_type
+ return FnordMetric::Event.by_session_key(opts.delete(:session_key), extend_opts(opts)) if _ids == :by_session_key
end
def method_missing(m, *args, &block)
View
5 lib/fnordmetric/session.rb
@@ -89,6 +89,7 @@ def expire(time)
def add_event(event)
@redis.zadd(redis_key(:events), event[:_time], event[:_eid])
+
add_data(:_picture, event[:url]) if event[:_type] == "_set_picture"
add_data(:_name, event[:name]) if event[:_type] == "_set_name"
add_event_data(event) if event[:_type] == "_set_data"
@@ -125,7 +126,7 @@ def fetch_meta_key(key, value)
def fetch_event_ids!(since=-1)
# FIXME: use WITHSCORE to get the timestamps and return event objects
- @event_ids = @redis.zrange(redis_key(:events), 0, since)
+ @event_ids = @redis.zrevrange(redis_key(:events), 0, since)
end
-end
+end
View
11 pub/fnordmetric.css
@@ -107,11 +107,14 @@ text-shadow: 1px 0px 2px rgba(255, 255, 255, 1);
ul.session_list{ list-style-type:none; margin:0; padding:9px 16px 0 11px; }
-ul.session_list li{ color:#0A0A0A; margin-bottom:10px; height:18px; overflow:hidden; line-height:18px; padding:4px; }
+ul.session_list li{ color:#0A0A0A; height:32px; overflow:hidden; line-height:18px; padding:4px; }
ul.session_list li:hover{ background:#eee; cursor:pointer; }
-ul.session_list li .picture{ height:18px; width:18px; float:left; background:#333; overflow:hidden; }
-ul.session_list li .name{ float:left; width:120px; overflow:hidden; margin-left:10px; font-size:12px; }
+ul.session_list li input{ float: left; margin-right: 7px; }
+ul.session_list li .picture{ height:25px; width:25px; float:left; background:#333; overflow:hidden; }
+ul.session_list li .name{ float:left; width:115px; overflow:hidden; margin-left:10px; font-size:12px; }
ul.session_list li .time{ float:right; width:40px; overflow:hidden; text-align:right; font-size:10px; }
+ul.session_list li .history{ float:right; color:#999; font-size:10px; line-height: 12px;}
+ul.session_list li .history:hover{ color:#333; text-decoration:underline; }
.sessions_feed{ min-width:300px; min-height:100px; float:left; }
.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; }
height: 0;
}
-.highcharts-series circle{ stroke-width:1px; }
+.highcharts-series circle{ stroke-width:1px; }
View
79 pub/fnordmetric.js
@@ -739,7 +739,7 @@ var FnordMetric = (function(){
).append(listElem);
var eventsPolledUntil = false;
- var eventsFilter = [];
+ var eventsFilter = {uncheckedTypes: [], checkedSessions: []};
var sessionData = {};
var pollRunning = true;
@@ -777,10 +777,11 @@ var FnordMetric = (function(){
});
};
- function loadEventHistory(event_type){
+ function loadEventHistory(params){
feedInnerElem.html('');
$.ajax({
- url: FnordMetric.p + '/' + currentNamespace+'/events?type='+event_type,
+ url: FnordMetric.p + '/' + currentNamespace+'/events',
+ data: params,
success: function(_data, _status){
var data = JSON.parse(_data).events;
for(var n=data.length; n >= 0; n--){
@@ -813,14 +814,19 @@ var FnordMetric = (function(){
});
};
+ function setCheckboxesCheckedState(types_state, sessions_state) {
+ $('.event_type_list .event_type input').attr('checked', types_state);
+ $('.session_list .session input').attr('checked', sessions_state);
+ }
+
function addEventType(type, display){
typeListElem.append(
$('<li class="event_type"></li>').append(
$('<span class="history"></span>').html('history')
.click(function(){
- $('.event_type_list .event_type input').attr('checked', false);
+ setCheckboxesCheckedState(true, true);
$('input', $(this).parent()).attr('checked', true);
- updateEventFilter(); loadEventHistory(type);
+ updateEventFilter(); loadEventHistory({type: type});
})
).append(
$('<input type="checkbox" />').attr('checked', true)
@@ -838,7 +844,15 @@ var FnordMetric = (function(){
_unchecked_types.push($(v).attr('rel'));
}
});
- eventsFilter = _unchecked_types;
+ eventsFilter.uncheckedTypes = _unchecked_types;
+
+ var _checked_sessions = [];
+ $('ul.session_list li.session').each(function(i,v){
+ if($('input', v).attr('checked')){
+ _checked_sessions.push($(v).data().session);
+ }
+ });
+ eventsFilter.checkedSessions = _checked_sessions;
}
function doEventsPoll(){
@@ -854,18 +868,40 @@ var FnordMetric = (function(){
return (function(_data, _status){
var data = JSON.parse(_data)
var events = data.events;
- var timout = 1000;
+ var timeout = 1000;
var maxevents = 200;
+ var passesFiltering = function(event_data) {
+ var passes_type_filtering = false;
+ var passes_session_filtering = false;
+ if(eventsFilter.uncheckedTypes.indexOf(event_data._type) == -1) {
+ if(parseInt(v._time)<=eventsPolledUntil) {
+ passes_type_filtering = true;
+ }
+ }
+ if(!passes_type_filtering) return false;
+
+ if(eventsFilter.checkedSessions.length == 0){
+ return true; // No filter set - show all events
+ } else {
+ if(event_data._session_key){
+ if(eventsFilter.checkedSessions.indexOf(event_data._session_key) >= 0){
+ return true; // Filter set and match
+ } else {
+ return false; // Filter set but no match
+ }
+ } else {
+ return false; // Filter set but event is not associated with session
+ }
+ }
+ }
+
if(events.length > 0){
- timeout = 200;
eventsPolledUntil = parseInt(events[0]._time)-1;
}
for(var n=events.length-1; n >= 0; n--){
var v = events[n];
- if(eventsFilter.indexOf(v._type) == -1){
- if(parseInt(v._time)<=eventsPolledUntil){
- renderEvent(v);
- }
+ if(passesFiltering(v)) {
+ renderEvent(v);
}
};
var elems = $("p", feedInnerElem);
@@ -873,13 +909,17 @@ var FnordMetric = (function(){
$(elems[n]).remove();
}
if(pollRunning){
- window.setTimeout(doEventsPoll(), timout);
+ window.setTimeout(doEventsPoll(), timeout);
}
});
};
function updateSession(session_data){
- sessionData[session_data.session_key] = session_data;
+ var session_key = session_data.session_key;
+ if(!sessionData[session_key]){
+ updateEventFilter()
+ }
+ sessionData[session_key] = session_data;
renderSession(session_data);
}
@@ -907,7 +947,7 @@ var FnordMetric = (function(){
} else {
- var session_picture = $('<img width="18" />');
+ var session_picture = $('<img width="25" />');
if(!session_name){
session_name = session_data["session_key"].substr(0,15)
@@ -919,11 +959,20 @@ var FnordMetric = (function(){
listElem.append(
$('<li class="session"></li>').append(
+ $('<input type="checkbox" />').click(function(){ updateEventFilter(); })
+ ).append(
$('<div class="picture"></div>').html(session_picture)
).append(
$('<span class="name"></span>').html(session_name)
).append(
$('<span class="time"></span>').html(session_time)
+ ).append(
+ $('<span class="history"></span>').html('history')
+ .click(function(){
+ setCheckboxesCheckedState(true, false);
+ $('input', $(this).parent()).attr('checked', true);
+ updateEventFilter(); loadEventHistory({session_key: session_data["session_key"]});
+ })
).attr('data-session', session_data["session_key"])
);
View
34 spec/app_spec.rb
@@ -334,6 +334,38 @@ def app
JSON.parse(last_response.body)["events"].length.should == 1
end
+ it "should render all events for a single session key" do
+ @namespace.ready!(@redis_wrap).announce(
+ :_time => @now,
+ :_session => "max_session",
+ :_eid => "124234"
+ )
+ @namespace.ready!(@redis_wrap).announce(
+ :_time => @now,
+ :_session => "kate_session",
+ :_eid => "12235234"
+ )
+ @namespace.ready!(@redis_wrap).announce(
+ :_time => @now,
+ :_session => "kate_session",
+ :_eid => "124234234"
+ )
+ @namespace.ready!(@redis_wrap).announce(
+ :_time => @now,
+ :_eid => "124234234"
+ )
+ max_session_key = Digest::MD5.hexdigest "max_session"
+ kate_session_key = Digest::MD5.hexdigest "kate_session"
+
+ get "/foospace/events?session_key=#{max_session_key}"
+ events = JSON.parse(last_response.body)["events"]
+ events.length.should == 1
+
+ get "/foospace/events?session_key=#{kate_session_key}"
+ events = JSON.parse(last_response.body)["events"]
+ events.length.should == 2
+ end
+
it "should render a list of event types" do
@namespace.ready!(@redis_wrap).announce(
:_type => "fn0rd",
@@ -449,4 +481,4 @@ def create_event(event_id, event_data)
end
-end
+end
View
45 spec/event_spec.rb
@@ -1,4 +1,5 @@
require ::File.expand_path('../spec_helper.rb', __FILE__)
+require 'irb'
describe FnordMetric::Event do
@@ -116,6 +117,48 @@
Event.by_type('f00bar', @opts).length.should == 1
end
+ describe "looking by session_key" do
+ let(:namespace) do
+ options = {:redis_prefix => "fnordmetric-test", :session_data_ttl => 1}
+ Namespace.new(:ns123, options)
+ end
+
+ let(:events_data) do
+ [[1, "max_session"], [2, "kate_session"], [3, "kate_session"], [12345678, nil]]
+ end
+
+ let(:kate_session_key) { Digest::MD5.hexdigest "kate_session" }
+ let(:events) { Event.by_session_key kate_session_key, @opts }
+
+ before do
+ created_events_data.each do |(event_id, session)|
+ event_data = { :_time => @now + event_id, :_eid => event_id }
+ event_data[:_session] = session if session
+ namespace.ready!(@redis_wrap).announce event_data
+ end
+ end
+
+ context "when events are added in ascending time order" do
+ let(:created_events_data) { events_data }
+
+ it "should find correct events" do
+ ["2","3"].each {|id| events.map(&:id).should include(id) }
+ end
+
+ it "should have correct order" do
+ events.map(&:id).should == ["3","2"]
+ end
+ end
+
+ context "when events are added in descending time order" do
+ let(:created_events_data) { events_data.reverse }
+
+ it "should have correct order" do
+ events.map(&:id).should == ["3","2"]
+ end
+ end
+ end
+
def create_event(event_id, event_data)
@redis_wrap.zadd(@timeline, event_data.delete(:_time), event_id)
@redis.set("fnordmetric-test-event-#{event_id}", event_data.to_json)
@@ -124,4 +167,4 @@ def create_event(event_id, event_data)
end
-end
+end
View
6 spec/session_spec.rb
@@ -212,8 +212,8 @@
@redis_wrap.zadd("#{@namespace}-session-#{sesshash}-events", @now, "fnord")
sess = Session.find(sesshash, @opts)
sess.fetch_event_ids!
- sess.event_ids[0].should == "fnord"
- sess.event_ids[1].should == "shmoo"
+ sess.event_ids.should include("shmoo")
+ sess.event_ids.should include("fnord")
end
def create_session(sesskey, sesstime, sessdata)
@@ -228,4 +228,4 @@ def create_session(sesskey, sesstime, sessdata)
end
-end
+end

No commit comments for this range

Something went wrong with that request. Please try again.