fnordmetric 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -75,7 +75,7 @@ Installation
75
75
 
76
76
  or in your Gemfile:
77
77
 
78
- gem 'fnordmetric', '~> 0.5'
78
+ gem 'fnordmetric', '>= 0.6.3'
79
79
 
80
80
 
81
81
  Documentation
@@ -177,6 +177,12 @@ require "fnordmetric"
177
177
 
178
178
  FnordMetric.namespace :myapp do
179
179
 
180
+ # Set a custom namespace title, if you want one
181
+ # set_title "Emails sent"
182
+
183
+ # Hide the "Active Users" tab, if you want
184
+ # hide_active_users
185
+
180
186
  # numeric (delta) gauge, 1-hour tick
181
187
  gauge :messages_sent,
182
188
  :tick => 1.hour.to_i,
@@ -336,19 +342,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
336
342
  Todos
337
343
  -----
338
344
 
339
- * funnel-widget
340
- * combine/calculation gauges via opts_gauge({}, &block) (+calculate ctr)
341
- * timeline_widget: 'compare mode': compate gauge to yesterday
342
- * numbers_widget: handle decreasing vals
343
- * make listen-ports configurable
344
- * referal tracking fu (parse googlequeries)
345
- * trend detection
346
- * opt_event options: :increment => gauge_name
347
- * preconfigured default-dashboard (like google analytics)
348
- * pagview+ref-tracking via js-tracking-pixel
349
- * table/gauge-list-widget (with mini-stats!)
350
- * prune the namespace-sessions-timline (remove event_ids older than x)
351
- * prune the namespace-event-types-list (trim to max items)
352
- * timelinewidget + numberswidget => should use redis hmget
353
- * get multiple metrics in a single http get
354
- * `{ _namespace: myns }` field
345
+ + combine/calculation gauges via opts_gauge({}, &block) (+calculate ctr)
346
+ + timeline_widget: 'compare mode': compare gauge to yesterday
347
+ + numbers_widget: handle decreasing vals
348
+ + opt_event options: :increment => gauge_name
349
+ + prune the namespace-sessions-timline (remove event_ids older than x)
350
+ + prune the namespace-event-types-list (trim to max items)
351
+ + the funnel-widget
352
+ + timelinewidget + numberswidget => should use redis hmget
353
+ + get multiple metrics in a single http get
354
+ + the `{ _namespace: myns }` field
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.2
1
+ 0.6.3
data/fnordmetric.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{fnordmetric}
8
- s.version = "0.6.2"
8
+ s.version = "0.6.3"
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"]
@@ -62,7 +62,6 @@ Gem::Specification.new do |s|
62
62
  "pub/fnordmetric.css",
63
63
  "pub/fnordmetric.js",
64
64
  "pub/loader.gif",
65
- "pub/sprite.png",
66
65
  "pub/vendor/highcharts.js",
67
66
  "pub/vendor/jquery-1.6.1.min.js",
68
67
  "spec/api_spec.rb",
@@ -72,6 +71,7 @@ Gem::Specification.new do |s|
72
71
  "spec/event_spec.rb",
73
72
  "spec/gauge_modifiers_spec.rb",
74
73
  "spec/gauge_spec.rb",
74
+ "spec/inbound_stream_spec.rb",
75
75
  "spec/namespace_spec.rb",
76
76
  "spec/session_spec.rb",
77
77
  "spec/spec_helper.rb",
@@ -91,6 +91,7 @@ Gem::Specification.new do |s|
91
91
  "spec/event_spec.rb",
92
92
  "spec/gauge_modifiers_spec.rb",
93
93
  "spec/gauge_spec.rb",
94
+ "spec/inbound_stream_spec.rb",
94
95
  "spec/namespace_spec.rb",
95
96
  "spec/session_spec.rb",
96
97
  "spec/spec_helper.rb",
data/haml/app.haml CHANGED
@@ -2,7 +2,7 @@
2
2
  %html
3
3
 
4
4
  %head
5
- %title Fnordmetric Dashboard
5
+ %title=current_namespace.title
6
6
 
7
7
  %script(type="text/javascript" src="#{path_prefix}/vendor/jquery-1.6.1.min.js")
8
8
  %script(type="text/javascript" src="#{path_prefix}/vendor/highcharts.js")
@@ -18,14 +18,15 @@
18
18
  %ul
19
19
  -namespaces.each do |key,namespace|
20
20
  %li{:class => namespace.token == current_namespace.token ? 'active' : nil}
21
- %a{:href=>"/#{namespace.token}"}=h namespace.token
21
+ %a{:href=>"/#{namespace.token}"}=h namespace.title
22
22
 
23
23
  #wrap
24
24
  #tabs
25
25
  %ul
26
- %li.active.sessions
27
- .picto.piechart
28
- Active Users
26
+ - if current_namespace.active_users_available
27
+ %li.active.sessions
28
+ .picto.piechart
29
+ Active Users
29
30
 
30
31
  -current_namespace.dashboards.each do |key,dashboard|
31
32
  %li.dashboard{:rel => dashboard.token}
@@ -64,6 +65,10 @@
64
65
  resizeViewport();
65
66
  $(window).resize(resizeViewport);
66
67
 
68
+ if(!#{current_namespace.active_users_available.to_s}) {
69
+ $('#tabs li:first').trigger('click');
70
+ }
71
+
67
72
  if(window.location.hash){
68
73
  $('#tabs li.dashboard[rel="'+window.location.hash.slice(1)+'"]').trigger('click');
69
74
  }
@@ -12,8 +12,17 @@ class FnordMetric::API
12
12
  end
13
13
 
14
14
  def event(event_data)
15
- event_data = event_data.to_json if event_data.is_a?(Hash)
16
- push_event(get_next_uuid, event_data)
15
+ begin
16
+ if event_data.is_a?(Hash)
17
+ event_data = event_data.to_json
18
+ else
19
+ JSON.parse(event_data) # void ;)
20
+ end
21
+ rescue JSON::ParserError
22
+ FnordMetric.log("event_lost: can't parse json")
23
+ else
24
+ push_event(get_next_uuid, event_data)
25
+ end
17
26
  end
18
27
 
19
28
  def disconnect
@@ -23,7 +32,7 @@ class FnordMetric::API
23
32
  private
24
33
 
25
34
  def push_event(event_id, event_data)
26
- prefix = @@opts[:redis_prefix]
35
+ prefix = @@opts[:redis_prefix]
27
36
  @redis.hincrby "#{prefix}-testdata", "events_received", 1
28
37
  @redis.hincrby "#{prefix}-stats", "events_received", 1
29
38
  @redis.set "#{prefix}-event-#{event_id}", event_data
@@ -3,6 +3,12 @@
3
3
  class FnordMetric::App < Sinatra::Base
4
4
 
5
5
  @@sessions = Hash.new
6
+ @@public_files = {
7
+ "fnordmetric.css" => "text/css",
8
+ "fnordmetric.js" => "application/x-javascript",
9
+ "vendor/jquery-1.6.1.min.js" => "application/x-javascript",
10
+ "vendor/highcharts.js" => "application/x-javascript"
11
+ }
6
12
 
7
13
  Encoding.default_external = Encoding::UTF_8
8
14
 
@@ -11,8 +17,7 @@ class FnordMetric::App < Sinatra::Base
11
17
  enable :session
12
18
 
13
19
  set :haml, :format => :html5
14
- set :views, ::File.expand_path('../../../haml', __FILE__)
15
- set :public_folder, ::File.expand_path('../../../pub', __FILE__)
20
+ set :views, ::File.expand_path('../../../haml', __FILE__)
16
21
 
17
22
  def initialize(namespaces, opts)
18
23
  @namespaces = {}
@@ -126,6 +131,12 @@ class FnordMetric::App < Sinatra::Base
126
131
  track_event((8**32).to_s(36), parse_params(params))
127
132
  end
128
133
 
134
+ @@public_files.each do |public_file, public_file_type|
135
+ get "/#{public_file}" do
136
+ content_type(public_file_type)
137
+ ::File.open(::File.expand_path("../../../pub/#{public_file}", __FILE__)).read
138
+ end
139
+ end
129
140
  private
130
141
 
131
142
  def parse_params(hash)
@@ -6,7 +6,11 @@ class FnordMetric::InboundStream < EventMachine::Connection
6
6
  EM.start_server(*opts[:inbound_stream], self)
7
7
  end
8
8
 
9
- def receive_data(chunk)
9
+ def self.options(opts)
10
+ @@opts = opts
11
+ end
12
+
13
+ def receive_data(chunk)
10
14
  @buffer << chunk
11
15
  EM.defer{ next_event }
12
16
  end
@@ -2,12 +2,14 @@ class FnordMetric::Namespace
2
2
 
3
3
  attr_reader :handlers, :gauges, :opts, :key, :dashboards
4
4
 
5
- @@opts = [:event, :gauge, :widget]
5
+ @@opts = [:event, :gauge, :widget, :set_title, :active_users_available]
6
6
 
7
7
  def initialize(key, opts)
8
8
  @gauges = Hash.new
9
9
  @dashboards = Hash.new
10
- @handlers = Hash.new
10
+ @handlers = Hash.new
11
+ @title = key
12
+ @active_users_available = true
11
13
  @opts = opts
12
14
  @key = key
13
15
  end
@@ -63,7 +65,15 @@ class FnordMetric::Namespace
63
65
  def token
64
66
  @key
65
67
  end
66
-
68
+
69
+ def title
70
+ @title
71
+ end
72
+
73
+ def active_users_available
74
+ @active_users_available
75
+ end
76
+
67
77
  def dashboards(name=nil)
68
78
  return @dashboards unless name
69
79
  dash = FnordMetric::Dashboard.new(:title => name)
@@ -85,6 +95,14 @@ class FnordMetric::Namespace
85
95
  send(:"opt_#{m}", *args, &block)
86
96
  end
87
97
 
98
+ def hide_active_users
99
+ @active_users_available = false
100
+ end
101
+
102
+ def set_title(key)
103
+ @title = key
104
+ end
105
+
88
106
  def opt_event(event_type, opts={}, &block)
89
107
  opts.merge!(:redis => @redis, :gauges => @gauges)
90
108
  FnordMetric::Context.new(opts, block).tap do |context|
@@ -22,7 +22,7 @@ class FnordMetric::Worker
22
22
  @redis.blpop(queue_key, 0).callback do |list, event_id|
23
23
  @redis.get(event_key(event_id)).callback do |event_data|
24
24
  process_event(event_id, event_data) if event_data
25
- FnordMetric.log("oops, lost an event :(") unless event_data
25
+ FnordMetric.log("event_lost: event_data not found for event-id '#{event_id}'") unless event_data
26
26
  EM.next_tick(&method(:tick))
27
27
  @redis.hincrby(stats_key, :events_processed, 1)
28
28
  end
data/pub/fnordmetric.css CHANGED
@@ -4,7 +4,7 @@ body{ background:#3b3e45; color:#333; margin:0; padding:0; overflow-y:scroll; fo
4
4
  .shown{ display: block; }
5
5
  .hidden{ display: none; }
6
6
 
7
- .topbar{ height:38px; background:#24272c; position:fixed; top:0px; width:100%; z-index: 1}
7
+ .topbar{ height:38px; background:#24272c; position:fixed; top:0px; width:100%; z-index: 1000;}
8
8
  .topbar ul { list-style-type:none; margin:0; }
9
9
  .topbar ul li { padding: 5px 10px 5px 10px; background-color:#3b3e45; display:inline; height:38px; line-height:38px; border-radius:3px; margin-right:5px;}
10
10
  .topbar ul li a { color:#ccc; font-size:13px; text-decoration:none; }
@@ -21,7 +21,7 @@ body{ background:#3b3e45; color:#333; margin:0; padding:0; overflow-y:scroll; fo
21
21
  #tabs ul li:hover, #tabs ul li:hover:after{ color:#fff; }
22
22
  #tabs ul li:hover .picto{ opacity:1; }
23
23
 
24
- .picto{ display:block; height:14px; width:14px; float:left; background:url('/fnordmetric/sprite.png') no-repeat 14px 14px; opacity:0.7; }
24
+ .picto{ display:block; height:14px; width:14px; float:left; opacity:0.7; }
25
25
  .picto.piechart{ background-position:-42px -173px; width:9px; margin-right:5px; }
26
26
 
27
27
  #viewport{ float:left; margin-left:150px; margin-top:30px; border-radius:3px; min-width:790px; }
@@ -73,7 +73,7 @@ text-shadow: 1px 0px 2px rgba(255, 255, 255, 1);
73
73
  .headbar .button{
74
74
  margin:8px 0px; height:16px; float:right; display:block;
75
75
  margin-right:-1px;
76
- background:url('/fnordmetric/sprite.png') no-repeat 0 -49px #eee;
76
+ background:#eee;
77
77
  border:1px solid #999;
78
78
  border-bottom-color:#888;
79
79
  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, .1);
@@ -0,0 +1,34 @@
1
+ require ::File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe FnordMetric::InboundStream do
4
+
5
+ before(:all) do
6
+ @redis = Redis.new
7
+ @redis_wrap = RedisWrap.new(@redis)
8
+ FnordMetric::InboundStream.options(
9
+ :redis_url => "redis://localhost:6379",
10
+ :redis_prefix => "fnordmetric-test",
11
+ :event_queue_ttl => 120
12
+ )
13
+ @inbound_stream = FnordMetric::InboundStream.new(nil)
14
+ end
15
+
16
+ describe "pushing new events" do
17
+ it "should add parsable event to the queue" do
18
+ data = %Q{{"_type": "started"}\n}
19
+
20
+ lambda {
21
+ @inbound_stream.receive_data data
22
+ }.should change { @redis.llen("fnordmetric-test-queue") }.by +1
23
+ end
24
+
25
+ it "should reject non parsable events" do
26
+ broken_data = %Q{{"_type": \n"started"}\n}
27
+
28
+ lambda {
29
+ @inbound_stream.receive_data broken_data
30
+ }.should_not change { @redis.llen("fnordmetric-test-queue") }
31
+ end
32
+ end
33
+ end
34
+
data/spec/spec_helper.rb CHANGED
@@ -14,6 +14,9 @@ require "fnordmetric"
14
14
  require "eventmachine"
15
15
  require 'em-hiredis'
16
16
 
17
+ def EM.defer; yield; end
18
+ def EM.next_tick; yield; end
19
+
17
20
  class RedisWrap
18
21
 
19
22
  def initialize(redis, callbackable=true)
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: fnordmetric
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.6.2
5
+ version: 0.6.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Asmuth
@@ -266,7 +266,6 @@ files:
266
266
  - pub/fnordmetric.css
267
267
  - pub/fnordmetric.js
268
268
  - pub/loader.gif
269
- - pub/sprite.png
270
269
  - pub/vendor/highcharts.js
271
270
  - pub/vendor/jquery-1.6.1.min.js
272
271
  - spec/api_spec.rb
@@ -276,6 +275,7 @@ files:
276
275
  - spec/event_spec.rb
277
276
  - spec/gauge_modifiers_spec.rb
278
277
  - spec/gauge_spec.rb
278
+ - spec/inbound_stream_spec.rb
279
279
  - spec/namespace_spec.rb
280
280
  - spec/session_spec.rb
281
281
  - spec/spec_helper.rb
@@ -317,6 +317,7 @@ test_files:
317
317
  - spec/event_spec.rb
318
318
  - spec/gauge_modifiers_spec.rb
319
319
  - spec/gauge_spec.rb
320
+ - spec/inbound_stream_spec.rb
320
321
  - spec/namespace_spec.rb
321
322
  - spec/session_spec.rb
322
323
  - spec/spec_helper.rb
data/pub/sprite.png DELETED
Binary file