fnordmetric 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.travis.yml +1 -0
  2. data/VERSION +1 -1
  3. data/doc/preview1.png +0 -0
  4. data/doc/preview2.png +0 -0
  5. data/doc/ulm_stats.rb +622 -0
  6. data/doc/version +1 -0
  7. data/fnordmetric.gemspec +16 -38
  8. data/haml/app.haml +12 -5
  9. data/lib/fnordmetric.rb +3 -0
  10. data/lib/fnordmetric/app.rb +19 -10
  11. data/lib/fnordmetric/bars_widget.rb +26 -0
  12. data/lib/fnordmetric/context.rb +3 -3
  13. data/lib/fnordmetric/gauge.rb +20 -0
  14. data/lib/fnordmetric/gauge_calculations.rb +28 -4
  15. data/lib/fnordmetric/gauge_modifiers.rb +39 -6
  16. data/lib/fnordmetric/logger.rb +19 -0
  17. data/lib/fnordmetric/numbers_widget.rb +5 -15
  18. data/lib/fnordmetric/pie_widget.rb +23 -0
  19. data/lib/fnordmetric/standalone.rb +1 -1
  20. data/lib/fnordmetric/timeline_widget.rb +16 -23
  21. data/lib/fnordmetric/toplist_widget.rb +25 -0
  22. data/lib/fnordmetric/widget.rb +3 -3
  23. data/pub/{fnordmetric/fnordmetric.css → fnordmetric.css} +46 -36
  24. data/pub/fnordmetric.js +1069 -0
  25. data/pub/loader.gif +0 -0
  26. data/pub/{highcharts → vendor}/highcharts.js +0 -0
  27. data/pub/{jquery-1.6.1.min.js → vendor/jquery-1.6.1.min.js} +0 -0
  28. data/readme.rdoc +228 -311
  29. data/spec/app_spec.rb +63 -3
  30. data/spec/gauge_modifiers_spec.rb +157 -2
  31. data/spec/gauge_spec.rb +143 -12
  32. data/spec/widget_spec.rb +18 -18
  33. metadata +33 -58
  34. data/.document +0 -5
  35. data/_spec/app_spec.rb +0 -178
  36. data/_spec/cache_spec.rb +0 -53
  37. data/_spec/combine_metric_spec.rb +0 -19
  38. data/_spec/core_spec.rb +0 -50
  39. data/_spec/count_metric_spec.rb +0 -32
  40. data/_spec/dashboard_spec.rb +0 -67
  41. data/_spec/event_spec.rb +0 -46
  42. data/_spec/metric_spec.rb +0 -118
  43. data/_spec/report_spec.rb +0 -87
  44. data/_spec/sum_metric_spec.rb +0 -33
  45. data/_spec/widget_spec.rb +0 -107
  46. data/doc/example_server.rb +0 -56
  47. data/doc/import_dump.rb +0 -26
  48. data/pub/fnordmetric/fnordmetric.js +0 -543
  49. data/pub/fnordmetric/widget_numbers.js +0 -71
  50. data/pub/fnordmetric/widget_timeline.css +0 -0
  51. data/pub/fnordmetric/widget_timeline.js +0 -110
  52. data/pub/highcharts/adapters/mootools-adapter.js +0 -12
  53. data/pub/highcharts/adapters/mootools-adapter.src.js +0 -243
  54. data/pub/highcharts/adapters/prototype-adapter.js +0 -14
  55. data/pub/highcharts/adapters/prototype-adapter.src.js +0 -284
  56. data/pub/highcharts/highcharts.src.js +0 -11103
  57. data/pub/highcharts/modules/exporting.js +0 -22
  58. data/pub/highcharts/modules/exporting.src.js +0 -703
  59. data/pub/highcharts/themes/dark-blue.js +0 -268
  60. data/pub/highcharts/themes/dark-green.js +0 -268
  61. data/pub/highcharts/themes/gray.js +0 -262
  62. data/pub/highcharts/themes/grid.js +0 -97
  63. data/pub/raphael-min.js +0 -8
  64. data/pub/raphael-utils.js +0 -221
  65. data/ulm_stats.rb +0 -198
@@ -0,0 +1 @@
1
+ 0.5.2
@@ -5,38 +5,30 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{fnordmetric}
8
- s.version = "0.5.1"
8
+ s.version = "0.5.2"
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 = %q{2011-12-10}
12
+ s.date = %q{2011-12-26}
13
13
  s.description = %q{FnordMetric is a Ruby Event-Tracking gem on steroids}
14
14
  s.email = %q{paul@paulasmuth.com}
15
15
  s.files = [
16
- ".document",
16
+ ".travis.yml",
17
17
  "Gemfile",
18
18
  "Gemfile.lock",
19
19
  "Rakefile",
20
20
  "VERSION",
21
- "_spec/app_spec.rb",
22
- "_spec/cache_spec.rb",
23
- "_spec/combine_metric_spec.rb",
24
- "_spec/core_spec.rb",
25
- "_spec/count_metric_spec.rb",
26
- "_spec/dashboard_spec.rb",
27
- "_spec/event_spec.rb",
28
- "_spec/metric_spec.rb",
29
- "_spec/report_spec.rb",
30
- "_spec/sum_metric_spec.rb",
31
- "_spec/widget_spec.rb",
32
- "doc/example_server.rb",
33
- "doc/import_dump.rb",
21
+ "doc/preview1.png",
22
+ "doc/preview2.png",
23
+ "doc/ulm_stats.rb",
24
+ "doc/version",
34
25
  "fnordmetric.gemspec",
35
26
  "haml/app.haml",
36
27
  "haml/widget.haml",
37
28
  "lib/fnordmetric.rb",
38
29
  "lib/fnordmetric/app.rb",
39
30
  "lib/fnordmetric/average_metric.rb",
31
+ "lib/fnordmetric/bars_widget.rb",
40
32
  "lib/fnordmetric/cache.rb",
41
33
  "lib/fnordmetric/combine_metric.rb",
42
34
  "lib/fnordmetric/context.rb",
@@ -53,34 +45,21 @@ Gem::Specification.new do |s|
53
45
  "lib/fnordmetric/metric_api.rb",
54
46
  "lib/fnordmetric/namespace.rb",
55
47
  "lib/fnordmetric/numbers_widget.rb",
48
+ "lib/fnordmetric/pie_widget.rb",
56
49
  "lib/fnordmetric/report.rb",
57
50
  "lib/fnordmetric/session.rb",
58
51
  "lib/fnordmetric/standalone.rb",
59
52
  "lib/fnordmetric/sum_metric.rb",
60
53
  "lib/fnordmetric/timeline_widget.rb",
54
+ "lib/fnordmetric/toplist_widget.rb",
61
55
  "lib/fnordmetric/widget.rb",
62
56
  "lib/fnordmetric/worker.rb",
63
- "pub/fnordmetric/fnordmetric.css",
64
- "pub/fnordmetric/fnordmetric.js",
65
- "pub/fnordmetric/widget_numbers.js",
66
- "pub/fnordmetric/widget_timeline.css",
67
- "pub/fnordmetric/widget_timeline.js",
68
- "pub/highcharts/adapters/mootools-adapter.js",
69
- "pub/highcharts/adapters/mootools-adapter.src.js",
70
- "pub/highcharts/adapters/prototype-adapter.js",
71
- "pub/highcharts/adapters/prototype-adapter.src.js",
72
- "pub/highcharts/highcharts.js",
73
- "pub/highcharts/highcharts.src.js",
74
- "pub/highcharts/modules/exporting.js",
75
- "pub/highcharts/modules/exporting.src.js",
76
- "pub/highcharts/themes/dark-blue.js",
77
- "pub/highcharts/themes/dark-green.js",
78
- "pub/highcharts/themes/gray.js",
79
- "pub/highcharts/themes/grid.js",
80
- "pub/jquery-1.6.1.min.js",
81
- "pub/raphael-min.js",
82
- "pub/raphael-utils.js",
57
+ "pub/fnordmetric.css",
58
+ "pub/fnordmetric.js",
59
+ "pub/loader.gif",
83
60
  "pub/sprite.png",
61
+ "pub/vendor/highcharts.js",
62
+ "pub/vendor/jquery-1.6.1.min.js",
84
63
  "readme.rdoc",
85
64
  "spec/app_spec.rb",
86
65
  "spec/context_spec.rb",
@@ -92,8 +71,7 @@ Gem::Specification.new do |s|
92
71
  "spec/session_spec.rb",
93
72
  "spec/spec_helper.rb",
94
73
  "spec/widget_spec.rb",
95
- "spec/worker_spec.rb",
96
- "ulm_stats.rb"
74
+ "spec/worker_spec.rb"
97
75
  ]
98
76
  s.homepage = %q{http://github.com/paulasmuth/fnordmetric}
99
77
  s.licenses = ["MIT"]
@@ -3,11 +3,13 @@
3
3
 
4
4
  %head
5
5
  %title Fnordmetric Dashboard
6
- %script(type="text/javascript" src="#{path_prefix}/jquery-1.6.1.min.js")
7
- %link(type="text/css" rel="stylesheet" href="#{path_prefix}/fnordmetric/fnordmetric.css")
8
- %script(type="text/javascript" src="#{path_prefix}/raphael-min.js")
9
- %script(type="text/javascript" src="#{path_prefix}/raphael-utils.js")
10
- %script(type="text/javascript" src="#{path_prefix}/fnordmetric/fnordmetric.js")
6
+
7
+ %script(type="text/javascript" src="#{path_prefix}/vendor/jquery-1.6.1.min.js")
8
+ %script(type="text/javascript" src="#{path_prefix}/vendor/highcharts.js")
9
+
10
+ %script(type="text/javascript" src="#{path_prefix}/fnordmetric.js")
11
+ %link(type="text/css" rel="stylesheet" href="#{path_prefix}/fnordmetric.css")
12
+
11
13
  :javascript
12
14
  FnordMetric.p = '#{path_prefix}';
13
15
 
@@ -37,6 +39,7 @@
37
39
 
38
40
  $('#tabs li.dashboard').click(function(){
39
41
  FnordMetric.renderDashboard($(this).attr('rel'));
42
+ window.location.hash = $(this).attr('rel');
40
43
  });
41
44
 
42
45
  $('#tabs li.sessions').click(function(){
@@ -56,6 +59,10 @@
56
59
  resizeViewport();
57
60
  $(window).resize(resizeViewport);
58
61
 
62
+ if(window.location.hash){
63
+ $('#tabs li.dashboard[rel="'+window.location.hash.slice(1)+'"]').trigger('click');
64
+ }
65
+
59
66
  });
60
67
 
61
68
 
@@ -128,6 +128,9 @@ require "fnordmetric/worker"
128
128
  require "fnordmetric/widget"
129
129
  require "fnordmetric/timeline_widget"
130
130
  require "fnordmetric/numbers_widget"
131
+ require "fnordmetric/bars_widget"
132
+ require "fnordmetric/toplist_widget"
133
+ require "fnordmetric/pie_widget"
131
134
  require "fnordmetric/namespace"
132
135
  require "fnordmetric/gauge_modifiers"
133
136
  require "fnordmetric/gauge_calculations"
@@ -57,16 +57,25 @@ class FnordMetric::App < Sinatra::Base
57
57
  ""
58
58
  end
59
59
 
60
- #get '/metric/:name' do
61
- # content_type 'application/json'
62
- # FnordMetric::MetricAPI.new(params).render
63
- #end
64
-
65
- #get '/widget/:name' do
66
- # @dashboard = FnordMetric.dashboards.first
67
- # @widget = @dashboard.widgets.first
68
- # haml :widget
69
- #end
60
+ get '/:namespace/gauge/:name' do
61
+
62
+ gauge = current_namespace.gauges.fetch(params[:name].intern)
63
+
64
+ data = if gauge.three_dimensional?
65
+ _t = (params[:at] || Time.now).to_i
66
+ { :count => gauge.field_values_total(_t), :values => gauge.field_values_at(_t) }
67
+ elsif params[:at] && params[:at] =~ /^[0-9]+$/
68
+ { (_t = gauge.tick_at(params[:at].to_i)) => gauge.value_at(_t) }
69
+ elsif params[:at] && params[:at] =~ /^([0-9]+)-([0-9]+)$/
70
+ _range = params[:at].split("-").map(&:to_i)
71
+ _values = gauge.values_in(_range.first.._range.last)
72
+ params[:sum] ? { :sum => _values.values.compact.map(&:to_i).sum } : _values
73
+ else
74
+ { (_t = gauge.tick_at(Time.now.to_i-gauge.tick)) => gauge.value_at(_t) }
75
+ end
76
+
77
+ data.to_json
78
+ end
70
79
 
71
80
  get '/:namespace/sessions' do
72
81
 
@@ -0,0 +1,26 @@
1
+ class FnordMetric::BarsWidget < FnordMetric::Widget
2
+
3
+ def data
4
+ super.merge(
5
+ :gauges => gauges.map(&:name),
6
+ :gauge_titles => gauge_titles,
7
+ :autoupdate => (@opts[:autoupdate] || 60),
8
+ :order_by => (@opts[:order_by] || 'value'),
9
+ :plot_style => (@opts[:plot_style] || 'vertical'),
10
+ :tick => tick
11
+ )
12
+ end
13
+
14
+ def gauge_titles
15
+ {}.tap do |_hash|
16
+ gauges.each do |gauge|
17
+ _hash.merge!(gauge.name => gauge.title)
18
+ end
19
+ end
20
+ end
21
+
22
+ def has_tick?
23
+ false
24
+ end
25
+
26
+ end
@@ -4,13 +4,13 @@ class FnordMetric::Context
4
4
 
5
5
  def initialize(opts, block)
6
6
  @block = block
7
- @opts = opts
7
+ @opts = opts
8
8
  end
9
9
 
10
10
  def call(event, redis)
11
11
  @redis = redis
12
- @event = event
13
- self.instance_eval(&@block)
12
+ @event = event
13
+ self.instance_eval(&@block)
14
14
  rescue Exception => e
15
15
  raise e if ENV['FNORDMETRIC_ENV'] == 'test'
16
16
  puts "error: #{e.message}"
@@ -18,6 +18,10 @@ class FnordMetric::Gauge
18
18
  def name
19
19
  @opts[:key]
20
20
  end
21
+
22
+ def title
23
+ @opts[:title] || name
24
+ end
21
25
 
22
26
  def key(_append=nil)
23
27
  [@opts[:key_prefix], "gauge", name, tick, _append].flatten.compact.join("-")
@@ -31,6 +35,10 @@ class FnordMetric::Gauge
31
35
  !@opts[:three_dimensional]
32
36
  end
33
37
 
38
+ def three_dimensional?
39
+ !!@opts[:three_dimensional]
40
+ end
41
+
34
42
  def progressive?
35
43
  !!@opts[:progressive]
36
44
  end
@@ -39,8 +47,20 @@ class FnordMetric::Gauge
39
47
  !!@opts[:unique]
40
48
  end
41
49
 
50
+ def average?
51
+ !!@opts[:average]
52
+ end
53
+
42
54
  def add_redis(_redis)
43
55
  @opts[:redis] = _redis
44
56
  end
45
57
 
58
+ def ticks_in(r)
59
+ (((r.last-r.first)/tick.to_f).ceil+1).times.map{ |n| tick_at(r.first + tick*(n-1)) }
60
+ end
61
+
62
+ def values_in(range)
63
+ values_at(ticks_in(range))
64
+ end
65
+
46
66
  end
@@ -1,8 +1,15 @@
1
1
  module FnordMetric::GaugeCalculations
2
2
 
3
3
  @@avg_per_session_proc = proc{ |_v, _t|
4
- #raise redis.get(tick_key(_t, :"sessions-count")).inspect
5
- (_v.to_f / (redis.get(tick_key(_t, :"sessions-count"))||0).to_i)
4
+ (_v.to_f / (redis.get(tick_key(_t, :"sessions-count"))||1).to_i)
5
+ }
6
+
7
+ @@count_per_session_proc = proc{ |_v, _t|
8
+ (redis.get(tick_key(_t, :"sessions-count"))||0).to_i
9
+ }
10
+
11
+ @@avg_per_count_proc = proc{ |_v, _t|
12
+ (_v.to_f / (redis.get(tick_key(_t, :"value-count"))||1).to_i)
6
13
  }
7
14
 
8
15
  def value_at(time, opts={}, &block)
@@ -27,8 +34,10 @@ module FnordMetric::GaugeCalculations
27
34
  end
28
35
 
29
36
  def calculate_value(_v, _t, opts, block)
30
- block = @@avg_per_session_proc if opts[:avg_per_session]
31
-
37
+ block = @@avg_per_count_proc if average?
38
+ #block = @@count_per_session_proc if unique?
39
+ block = @@avg_per_session_proc if unique? && average?
40
+
32
41
  if block
33
42
  instance_exec(_v, _t, &block)
34
43
  else
@@ -36,6 +45,21 @@ module FnordMetric::GaugeCalculations
36
45
  end
37
46
  end
38
47
 
48
+ def field_values_at(time, opts={}, &block)
49
+ opts[:max_fields] ||= 50
50
+ redis.zrevrange(
51
+ tick_key(time),
52
+ 0, opts[:max_fields]-1,
53
+ :withscores => true
54
+ ).in_groups_of(2).map do |key, val|
55
+ [key, calculate_value(val, time, opts, block)]
56
+ end
57
+ end
58
+
59
+ def field_values_total(time)
60
+ (redis.get(tick_key(time, :count))||0).to_i
61
+ end
62
+
39
63
  def redis
40
64
  @opts[:redis]
41
65
  end
@@ -5,6 +5,8 @@ module FnordMetric::GaugeModifiers
5
5
  assure_two_dimensional!(gauge)
6
6
  if gauge.unique?
7
7
  incr_uniq(gauge, value)
8
+ elsif gauge.average?
9
+ incr_avg(gauge, value)
8
10
  else
9
11
  incr_tick(gauge, value)
10
12
  end
@@ -18,26 +20,57 @@ module FnordMetric::GaugeModifiers
18
20
  end
19
21
  end
20
22
  else
21
- @redis.hincrby(gauge.key, gauge.tick_at(time), value)
23
+ @redis.hsetnx(gauge.key, gauge.tick_at(time), 0).callback do
24
+ @redis.hincrby(gauge.key, gauge.tick_at(time), value)
25
+ end
22
26
  end
23
27
  end
24
28
 
25
- def incr_uniq(gauge, value)
26
- return false unless session_key
29
+ def incr_uniq(gauge, value, field_name=nil)
30
+ return false if session_key.blank?
27
31
  @redis.sadd(gauge.tick_key(time, :sessions), session_key).callback do |_new|
28
32
  @redis.expire(gauge.tick_key(time, :sessions), gauge.tick)
29
- if _new
33
+ if (_new == 1) || (_new == true) #redis vs. em-redis
30
34
  @redis.incr(gauge.tick_key(time, :"sessions-count")).callback do |sc|
31
- incr_tick(gauge, value)
35
+ field_name ? incr_field_by(gauge, field_name, value) : incr_tick(gauge, value)
32
36
  end
33
37
  end
34
38
  end
35
39
  end
36
40
 
41
+ def incr_avg(gauge, value)
42
+ @redis.incr(gauge.tick_key(time, :"value-count")).callback do
43
+ incr_tick(gauge, value)
44
+ end
45
+ end
46
+
37
47
  def incr_field(gauge_name, field_name, value=1)
38
48
  gauge = fetch_gauge(gauge_name)
39
49
  assure_three_dimensional!(gauge)
40
- # here be dragons
50
+ if gauge.unique?
51
+ incr_uniq(gauge, value, field_name)
52
+ else
53
+ incr_field_by(gauge, field_name, value)
54
+ end
55
+ end
56
+
57
+ def incr_field_by(gauge, field_name, value)
58
+ @redis.zincrby(gauge.tick_key(time), value, field_name).callback do
59
+ @redis.incrby(gauge.tick_key(time, :count), 1)
60
+ end
61
+ end
62
+
63
+ def set_value(gauge_name, value)
64
+ gauge = fetch_gauge(gauge_name)
65
+ assure_two_dimensional!(gauge)
66
+ @redis.hset(gauge.key, gauge.tick_at(time), value)
67
+ end
68
+
69
+ def set_field(gauge_name, field_name, value)
70
+ gauge = fetch_gauge(gauge_name)
71
+ assure_three_dimensional!(gauge)
72
+ @redis.zadd(gauge.tick_key(time), value, field_name)
41
73
  end
42
74
 
75
+
43
76
  end
@@ -35,4 +35,23 @@ class FnordMetric::Logger
35
35
  fetcher.join
36
36
  end
37
37
 
38
+ def self.import(logfile_path)
39
+ redis = Redis.new
40
+ dump_file = File.open(logfile_path, 'r')
41
+
42
+ puts "reading #{logfile_path}..."
43
+ dump_lines = dump_file.read.split("\n")
44
+
45
+ puts "importing #{dump_lines.length} events..."
46
+ pre_uuid = rand(999999999999999999999)
47
+ log_every = (dump_lines.length / 150)
48
+ dump_lines.each_with_index do |line,n|
49
+ puts "#{n}/#{dump_lines.length} (#{((n/dump_lines.length.to_f)*100).to_i}%)" if n%log_every==0
50
+ my_uuid = "#{pre_uuid}-#{n}"
51
+ redis.set("fnordmetric-event-#{my_uuid}", line)
52
+ redis.lpush("fnordmetric-queue", my_uuid)
53
+ redis.expire("fnordmetric-event-#{my_uuid}", 3600*12)
54
+ end
55
+ end
56
+
38
57
  end
@@ -2,8 +2,9 @@ class FnordMetric::NumbersWidget < FnordMetric::Widget
2
2
 
3
3
  def data
4
4
  super.merge(
5
- :offsets => offsets,
6
- :gauges => data_gauges
5
+ :gauges => data_gauges,
6
+ :offsets => (@opts[:offsets] || [0, 1, "s30"]),
7
+ :autoupdate => (@opts[:autoupdate] || 0)
7
8
  )
8
9
  end
9
10
 
@@ -11,26 +12,15 @@ class FnordMetric::NumbersWidget < FnordMetric::Widget
11
12
  Hash.new.tap do |hash|
12
13
  gauges.each do |g|
13
14
  hash[g.name] = {
14
- :values => data_gauge(g),
15
- :title => g.name
15
+ :tick => g.tick,
16
+ :title => g.title
16
17
  }
17
18
  end
18
19
  end
19
20
  end
20
21
 
21
- def data_gauge(gauge)
22
- offsets.map do |offset|
23
- offset_time = Time.now.to_i - offset*gauge.tick
24
- [gauge.tick_at(offset_time), gauge.value_at(offset_time)]
25
- end
26
- end
27
-
28
22
  def has_tick?
29
23
  false
30
24
  end
31
25
 
32
- def offsets
33
- [0, 1, 30]
34
- end
35
-
36
26
  end