johnf-fnordmetric 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. data/Gemfile +6 -0
  2. data/Rakefile +9 -0
  3. data/fnordmetric.gemspec +41 -0
  4. data/lib/fnordmetric/acceptors/acceptor.rb +42 -0
  5. data/lib/fnordmetric/acceptors/amqp_acceptor.rb +56 -0
  6. data/lib/fnordmetric/acceptors/fyrehose_acceptor.rb +43 -0
  7. data/lib/fnordmetric/acceptors/stomp_acceptor.rb +71 -0
  8. data/lib/fnordmetric/acceptors/tcp_acceptor.rb +58 -0
  9. data/lib/fnordmetric/acceptors/udp_acceptor.rb +37 -0
  10. data/lib/fnordmetric/api.rb +46 -0
  11. data/lib/fnordmetric/cache.rb +20 -0
  12. data/lib/fnordmetric/context.rb +96 -0
  13. data/lib/fnordmetric/defaults.rb +22 -0
  14. data/lib/fnordmetric/enterprise/compatibility_handler.rb +42 -0
  15. data/lib/fnordmetric/ext.rb +75 -0
  16. data/lib/fnordmetric/gauge.rb +98 -0
  17. data/lib/fnordmetric/gauge_calculations.rb +106 -0
  18. data/lib/fnordmetric/gauge_modifiers.rb +144 -0
  19. data/lib/fnordmetric/gauge_rendering.rb +40 -0
  20. data/lib/fnordmetric/gauge_validations.rb +15 -0
  21. data/lib/fnordmetric/gauges/distribution_gauge.rb +87 -0
  22. data/lib/fnordmetric/gauges/server_health_gauge.rb +13 -0
  23. data/lib/fnordmetric/gauges/timeseries_gauge.rb +138 -0
  24. data/lib/fnordmetric/gauges/toplist_gauge.rb +44 -0
  25. data/lib/fnordmetric/histogram.rb +64 -0
  26. data/lib/fnordmetric/logger.rb +63 -0
  27. data/lib/fnordmetric/namespace.rb +208 -0
  28. data/lib/fnordmetric/session.rb +139 -0
  29. data/lib/fnordmetric/standalone.rb +20 -0
  30. data/lib/fnordmetric/timeseries.rb +79 -0
  31. data/lib/fnordmetric/toplist.rb +61 -0
  32. data/lib/fnordmetric/udp_client.rb +22 -0
  33. data/lib/fnordmetric/util.rb +25 -0
  34. data/lib/fnordmetric/version.rb +3 -0
  35. data/lib/fnordmetric/web/app.rb +63 -0
  36. data/lib/fnordmetric/web/app_helpers.rb +42 -0
  37. data/lib/fnordmetric/web/dashboard.rb +40 -0
  38. data/lib/fnordmetric/web/event.rb +99 -0
  39. data/lib/fnordmetric/web/reactor.rb +127 -0
  40. data/lib/fnordmetric/web/web.rb +59 -0
  41. data/lib/fnordmetric/web/websocket.rb +41 -0
  42. data/lib/fnordmetric/widget.rb +82 -0
  43. data/lib/fnordmetric/widgets/bars_widget.rb +44 -0
  44. data/lib/fnordmetric/widgets/html_widget.rb +28 -0
  45. data/lib/fnordmetric/widgets/numbers_widget.rb +80 -0
  46. data/lib/fnordmetric/widgets/pie_widget.rb +23 -0
  47. data/lib/fnordmetric/widgets/timeseries_widget.rb +65 -0
  48. data/lib/fnordmetric/widgets/toplist_widget.rb +68 -0
  49. data/lib/fnordmetric/worker.rb +89 -0
  50. data/lib/fnordmetric/zero_config_gauge.rb +138 -0
  51. data/lib/fnordmetric.rb +149 -0
  52. data/run_specs.sh +11 -0
  53. data/spec/api_spec.rb +49 -0
  54. data/spec/context_spec.rb +42 -0
  55. data/spec/dashboard_spec.rb +38 -0
  56. data/spec/event_spec.rb +170 -0
  57. data/spec/ext_spec.rb +14 -0
  58. data/spec/fnordmetric_spec.rb +56 -0
  59. data/spec/gauge_like_shared.rb +56 -0
  60. data/spec/gauge_modifiers_spec.rb +583 -0
  61. data/spec/gauge_spec.rb +230 -0
  62. data/spec/namespace_spec.rb +114 -0
  63. data/spec/session_spec.rb +231 -0
  64. data/spec/spec_helper.rb +49 -0
  65. data/spec/tcp_acceptor_spec.rb +35 -0
  66. data/spec/timeseries_gauge_spec.rb +56 -0
  67. data/spec/udp_acceptor_spec.rb +35 -0
  68. data/spec/util_spec.rb +46 -0
  69. data/spec/widget_spec.rb +113 -0
  70. data/spec/worker_spec.rb +40 -0
  71. data/web/.gitignore +4 -0
  72. data/web/build.sh +34 -0
  73. data/web/css/fnordmetric.core.css +868 -0
  74. data/web/fnordmetric-core.css +1409 -0
  75. data/web/fnordmetric-core.js +3420 -0
  76. data/web/fnordmetric-ui.css +282 -0
  77. data/web/fnordmetric-ui.js +12032 -0
  78. data/web/haml/app.haml +20 -0
  79. data/web/haml/distribution_gauge.haml +118 -0
  80. data/web/haml/timeseries_gauge.haml +80 -0
  81. data/web/haml/toplist_gauge.haml +194 -0
  82. data/web/img/head.png +0 -0
  83. data/web/img/list.png +0 -0
  84. data/web/img/list_active.png +0 -0
  85. data/web/img/list_hover.png +0 -0
  86. data/web/img/loader.gif +0 -0
  87. data/web/img/loader_white.gif +0 -0
  88. data/web/img/navbar.png +0 -0
  89. data/web/img/navbar_btn.png +0 -0
  90. data/web/img/picto_gauge.png +0 -0
  91. data/web/js/fnordmetric.bars_widget.js +178 -0
  92. data/web/js/fnordmetric.dashboard_view.js +99 -0
  93. data/web/js/fnordmetric.gauge_explorer.js +173 -0
  94. data/web/js/fnordmetric.gauge_view.js +260 -0
  95. data/web/js/fnordmetric.html_widget.js +21 -0
  96. data/web/js/fnordmetric.js +315 -0
  97. data/web/js/fnordmetric.numbers_widget.js +122 -0
  98. data/web/js/fnordmetric.overview_view.js +35 -0
  99. data/web/js/fnordmetric.pie_widget.js +118 -0
  100. data/web/js/fnordmetric.realtime_timeline_widget.js +175 -0
  101. data/web/js/fnordmetric.session_view.js +342 -0
  102. data/web/js/fnordmetric.timeline_widget.js +333 -0
  103. data/web/js/fnordmetric.timeseries_widget.js +405 -0
  104. data/web/js/fnordmetric.toplist_widget.js +119 -0
  105. data/web/js/fnordmetric.ui.js +91 -0
  106. data/web/js/fnordmetric.util.js +248 -0
  107. data/web/vendor/font-awesome/css/font-awesome-ie7.min.css +22 -0
  108. data/web/vendor/font-awesome/css/font-awesome.css +540 -0
  109. data/web/vendor/font-awesome/css/font-awesome.min.css +33 -0
  110. data/web/vendor/font-awesome/font/FontAwesome.otf +0 -0
  111. data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
  112. data/web/vendor/font-awesome/font/fontawesome-webfont.svg +284 -0
  113. data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
  114. data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
  115. data/web/vendor/jquery-1.6.2.min.js +18 -0
  116. data/web/vendor/jquery-ui.min.js +6 -0
  117. data/web/vendor/jquery.combobox.js +129 -0
  118. data/web/vendor/jquery.maskedinput.js +252 -0
  119. metadata +444 -0
@@ -0,0 +1,23 @@
1
+ class FnordMetric::PieWidget < 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
+ )
9
+ end
10
+
11
+ def gauge_titles
12
+ {}.tap do |_hash|
13
+ gauges.each do |gauge|
14
+ _hash.merge!(gauge.name => gauge.title)
15
+ end
16
+ end
17
+ end
18
+
19
+ def has_tick?
20
+ false
21
+ end
22
+
23
+ end
@@ -0,0 +1,65 @@
1
+ class FnordMetric::TimeseriesWidget < FnordMetric::Widget
2
+
3
+ def self.execute(namespace, event)
4
+ resp = if event["cmd"] == "values_at"
5
+ {
6
+ :cmd => :values_at,
7
+ :gauges => event["gauges"].map{ |gkey|
8
+ _gauge = namespace.gauges[gkey.to_sym]
9
+ unless _gauge
10
+ return { :error => "gauge not found: #{gkey}" }
11
+ end
12
+
13
+ t_since = FnordMetric::Util.parse_time(event["since"].to_s)
14
+ t_until = FnordMetric::Util.parse_time(event["until"].to_s)
15
+
16
+ vals = _gauge.values_in(t_since..t_until)
17
+ { :key => gkey, :vals => vals, :title => _gauge.title }
18
+ }
19
+ }
20
+ end
21
+
22
+ return false unless resp
23
+
24
+ resp.merge(
25
+ :type => "widget_response",
26
+ :widget_key => event["widget_key"]
27
+ )
28
+ end
29
+
30
+ def data
31
+ super.merge(
32
+ :series => series,
33
+ :gauges => gauges.map(&:name),
34
+ :start_timestamp => ticks.first,
35
+ :end_timestamp => ticks.last,
36
+ :xticks => (@opts[:xticks] || 30),
37
+ :autoupdate => (@opts[:autoupdate] || 60),
38
+ :include_current => !!@opts[:include_current],
39
+ :default_style => (@opts[:plot_style] || 'line'),
40
+ :async_chart => true,
41
+ :tick => tick
42
+ )
43
+ end
44
+
45
+ def series
46
+ colors = FnordMetric::COLORS.dup
47
+
48
+ gauges.map do |gauge|
49
+ {
50
+ :name => gauge.name,
51
+ :title => gauge.title,
52
+ :data => [{:x => ticks.first, :y => 0}],
53
+ :color => colors.unshift(colors.pop).first
54
+ }
55
+ end
56
+ end
57
+
58
+ def has_tick?
59
+ true
60
+ end
61
+
62
+ end
63
+
64
+ class FnordMetric::TimelineWidget < FnordMetric::TimeseriesWidget
65
+ end
@@ -0,0 +1,68 @@
1
+ class FnordMetric::ToplistWidget < FnordMetric::Widget
2
+
3
+ def self.execute(namespace, event)
4
+ t = Time.now.to_i
5
+
6
+ return false unless event["gauge"]
7
+
8
+ resp = if event["cmd"] == "values_for"
9
+ vals = execute_values_for(namespace.gauges[event["gauge"].to_sym], t)
10
+
11
+ {
12
+ :cmd => :values_for,
13
+ :gauge => event["gauge"],
14
+ :values => vals,
15
+ :count => vals.inject(0){ |m, (k,c)| m + c }
16
+ }
17
+ end
18
+
19
+ return false unless resp
20
+
21
+ resp.merge(
22
+ :type => "widget_response",
23
+ :widget_key => event["widget_key"]
24
+ )
25
+ end
26
+
27
+ def self.execute_values_for(gauge, time)
28
+ gauge.field_values_at(time).sort do |a,b|
29
+ a.first.to_i <=> b.first.to_i
30
+ end.map do |a|
31
+ [a.first, a.second.to_i]
32
+ end
33
+ end
34
+
35
+ def data
36
+ super.merge(
37
+ :gauges => data_gauges,
38
+ :autoupdate => (@opts[:autoupdate] || 0),
39
+ :render_target => @opts[:render_target],
40
+ :ticks => @opts[:ticks],
41
+ :click_callback => @opts[:click_callback],
42
+ :async_chart => true,
43
+ :tick => tick,
44
+ :limit => @opts[:limit],
45
+ :no_min_height => @opts[:no_min_height]
46
+ ).tap do |dat|
47
+ dat.merge!(
48
+ :gauges => @opts[:_gauges]
49
+ ) if dat[:ticks]
50
+ end
51
+ end
52
+
53
+ def data_gauges
54
+ Hash.new.tap do |hash|
55
+ gauges.each do |g|
56
+ hash[g.name] = {
57
+ :tick => g.tick,
58
+ :title => g.title
59
+ }
60
+ end
61
+ end
62
+ end
63
+
64
+ def has_tick?
65
+ false
66
+ end
67
+
68
+ end
@@ -0,0 +1,89 @@
1
+ class FnordMetric::Worker
2
+
3
+ def initialize(opts = {})
4
+ @namespaces = FnordMetric.namespaces
5
+ @opts = FnordMetric.options(opts)
6
+
7
+ FnordMetric.register(self)
8
+ end
9
+
10
+ def initialized
11
+ FnordMetric.log("worker started")
12
+ EM.next_tick(&method(:tick))
13
+ end
14
+
15
+ def tick
16
+ redis.blpop(queue_key, 1).callback do |list, event_id|
17
+ EM.next_tick(&method(:tick))
18
+ if event_id
19
+ redis.get(event_key(event_id)).callback do |event_data|
20
+ process_event(event_id, event_data) if event_data
21
+ FnordMetric.log("event_lost: event_data not found for event-id '#{event_id}' - maybe expired?") unless event_data
22
+ redis.hincrby(stats_key, :events_processed, 1)
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def process_event(event_id, event_data)
29
+ EM.next_tick do
30
+ event = parse_json(event_data)
31
+ if event
32
+ event[:_time] ||= Time.now.to_i
33
+ event[:_eid] = event_id
34
+ announce_event(event)
35
+ publish_event(event)
36
+ expire_event(event_id)
37
+ end
38
+ end
39
+ end
40
+
41
+ def pubsub_key
42
+ [@opts[:redis_prefix], 'announce'].join("-")
43
+ end
44
+
45
+ def queue_key
46
+ [@opts[:redis_prefix], 'queue'].join("-")
47
+ end
48
+
49
+ def event_key(event_id)
50
+ [@opts[:redis_prefix], 'event', event_id].join("-")
51
+ end
52
+
53
+ def stats_key
54
+ [@opts[:redis_prefix], 'stats'].join("-")
55
+ end
56
+
57
+ def announce_event(event)
58
+ namespace(event[:_namespace]).ready!(redis, sync_redis).announce(event)
59
+ end
60
+
61
+ def expire_event(event_id)
62
+ redis.expire(event_key(event_id), @opts[:event_data_ttl])
63
+ end
64
+
65
+ def publish_event(event)
66
+ redis.publish(pubsub_key, event.to_json)
67
+ end
68
+
69
+ def namespace(key)
70
+ (@namespaces[key] || @namespaces.first.last).clone
71
+ end
72
+
73
+ def parse_json(data)
74
+ event = Yajl::Parser.new(:symbolize_keys => true).parse(data)
75
+ event[:_namespace] = event[:_namespace].to_sym if event[:_namespace]
76
+ event
77
+ rescue Yajl::ParseError => e
78
+ FnordMetric.error "invalid json: #{e.to_s}"; false
79
+ end
80
+
81
+ def redis
82
+ @redis ||= EM::Hiredis.connect(FnordMetric.options[:redis_url]) # FIXPAUL
83
+ end
84
+
85
+ def sync_redis
86
+ @sync_redis ||= FnordMetric.mk_redis
87
+ end
88
+
89
+ end
@@ -0,0 +1,138 @@
1
+ class FnordMetric::ZeroConfigGauge
2
+
3
+ TYPES = [:_incr, :_decr, :_avg, :_min, :_max, :_set]
4
+
5
+ Handler = proc do
6
+ if data[:gauge]
7
+ gauge_key = data[:gauge].to_sym
8
+ else
9
+ FnordMetric.error("missing key for zero config event: gauge")
10
+ next
11
+ end
12
+
13
+ unless data[:value]
14
+ FnordMetric.error("missing key for zero config event: value")
15
+ next
16
+ end
17
+
18
+ gauge = if namespace.gauges.has_key?(gauge_key)
19
+ namespace.gauges[gauge_key]
20
+ else
21
+ namespace.opt_gauge(gauge_key,
22
+ :flush_interval => data[:flush_interval],
23
+ :average => (type == :_avg),
24
+ :zero_config => true)
25
+ end
26
+
27
+ case type
28
+
29
+ when :_set
30
+ set_value gauge, data[:value].to_i
31
+
32
+ when :_incr
33
+ incr_tick gauge, data[:value].to_i
34
+
35
+ when :_decr
36
+ FnordMetric.error("_decr is not yet implemented")
37
+
38
+ when :_avg
39
+ incr_avg gauge, data[:value].to_i
40
+
41
+ when :_min, :_max
42
+ FnordMetric.error("_min/_max is not yet implemented")
43
+
44
+ end
45
+ end
46
+
47
+ class EmtpyGauge
48
+
49
+ def self.tick
50
+ FnordMetric.options[:default_flush_interval]
51
+ end
52
+
53
+ def self.retention
54
+ tick * 10
55
+ end
56
+
57
+ def self.tick_at(time, _tick=tick)
58
+ (time/_tick.to_f).floor*_tick
59
+ end
60
+
61
+ def group
62
+ "Gauges"
63
+ end
64
+
65
+ def unit
66
+ nil
67
+ end
68
+
69
+ def key_nouns
70
+ ["Key", "Keys"]
71
+ end
72
+
73
+ def key(_append=nil)
74
+ "----empty-gauge----"
75
+ end
76
+
77
+ def tick_key(_time, _append=nil)
78
+ "----empty-gauge----"
79
+ end
80
+
81
+ def tick_keys(_range, _append=nil)
82
+ ["----empty-gauge----"]
83
+ end
84
+
85
+ def retention_key(_time, _append=nil)
86
+ "----empty-gauge----"
87
+ end
88
+
89
+ def two_dimensional?
90
+ true
91
+ end
92
+
93
+ def three_dimensional?
94
+ false
95
+ end
96
+
97
+ def progressive?
98
+ false
99
+ end
100
+
101
+ def unique?
102
+ false
103
+ end
104
+
105
+ def average?
106
+ false
107
+ end
108
+
109
+ def has_series?
110
+ false
111
+ end
112
+
113
+ end
114
+
115
+ def initialize(key, namespace)
116
+ @key = key
117
+ @namespace = namespace
118
+ end
119
+
120
+ def name
121
+ @key
122
+ end
123
+
124
+ def title
125
+ @key
126
+ end
127
+
128
+ def method_missing(*msg)
129
+ gauge = @namespace.gauges[@key]
130
+
131
+ if gauge
132
+ gauge.send(*msg)
133
+ else
134
+ EmtpyGauge.send(*msg)
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,149 @@
1
+ require "eventmachine"
2
+ require 'em-hiredis'
3
+ require 'redis'
4
+ require "active_support/core_ext"
5
+ require 'yajl'
6
+ require 'sinatra/base'
7
+ require 'haml'
8
+ require 'json'
9
+ require "thin"
10
+ require 'rack/server'
11
+ require 'rack/websocket'
12
+
13
+ require "fnordmetric/ext"
14
+ require "fnordmetric/version"
15
+
16
+ module FnordMetric
17
+
18
+ @@options = nil
19
+ @@pool = []
20
+
21
+ @@namespaces = {}
22
+
23
+ def self.namespace(key=nil, &block)
24
+ @@namespaces[key] = block
25
+ end
26
+
27
+ def self.namespaces
28
+ {}.tap do |_namespaces|
29
+ @@namespaces.each do |key, block|
30
+ _namespaces[key] = FnordMetric::Namespace.new(key, options.clone)
31
+ _namespaces[key].instance_eval(&block)
32
+ _namespaces[key].instance_eval(&FnordMetric::DEFAULT_PROC)
33
+ end
34
+ end
35
+ end
36
+
37
+ def self.options(opts = {})
38
+ default_options(@@options || {}).merge(opts)
39
+ end
40
+
41
+ def self.options=(opts)
42
+ @@options = opts
43
+ end
44
+
45
+ def self.register(obj)
46
+ @@pool.push(obj)
47
+ end
48
+
49
+ def self.mk_redis
50
+ Redis.new(:url => options[:redis_url])
51
+ end
52
+
53
+ def self.default_options(opts = {})
54
+ FnordMetric::DEFAULT_OPTIONS.merge(opts)
55
+ end
56
+
57
+ def self.log(msg)
58
+ puts "[#{Time.now.strftime("%y-%m-%d %H:%M:%S")}] #{msg}"
59
+ end
60
+
61
+ def self.error(msg)
62
+ log "[ERROR] #{msg}"; nil
63
+ end
64
+
65
+ def self.error!(msg)
66
+ raise msg if ENV['FNORDMETRIC_ENV'] == 'test'
67
+ puts(msg); exit!
68
+ end
69
+
70
+ def self.run
71
+ start_em
72
+ rescue Exception => e
73
+ raise e
74
+ log "!!! eventmachine died, restarting... #{e.message}"
75
+ sleep(1); run
76
+ end
77
+
78
+ def self.shutdown(fnord=nil)
79
+ log "shutting down, byebye"
80
+ EM.stop
81
+ end
82
+
83
+ def self.start_em
84
+ EM.run do
85
+
86
+ trap("TERM", &method(:shutdown))
87
+ trap("INT", &method(:shutdown))
88
+
89
+ EM.next_tick do
90
+ (@@pool || []).map(&:initialized)
91
+ end
92
+
93
+ end
94
+ end
95
+
96
+ def self.server_configuration=(configuration)
97
+ puts "DEPRECATION WARNING - FIXPAUL"
98
+ self.options=(configuration)
99
+ end
100
+
101
+ def self.standalone
102
+ puts "DEPRECATION WARNING - FIXPAUL"
103
+ require "fnordmetric/standalone"
104
+ start_em
105
+ end
106
+
107
+ end
108
+
109
+ require "fnordmetric/gauge_calculations"
110
+ require "fnordmetric/gauge_modifiers"
111
+ require "fnordmetric/gauge_validations"
112
+ require "fnordmetric/gauge_rendering"
113
+ require "fnordmetric/gauge"
114
+ require "fnordmetric/zero_config_gauge"
115
+ require "fnordmetric/gauges/timeseries_gauge"
116
+ require "fnordmetric/gauges/toplist_gauge"
117
+ require "fnordmetric/gauges/distribution_gauge"
118
+ require "fnordmetric/context"
119
+ require "fnordmetric/histogram"
120
+ require "fnordmetric/timeseries"
121
+ require "fnordmetric/toplist"
122
+ require "fnordmetric/namespace"
123
+ require "fnordmetric/session"
124
+ require "fnordmetric/api"
125
+ require "fnordmetric/worker"
126
+ require "fnordmetric/logger"
127
+ require "fnordmetric/defaults"
128
+ require "fnordmetric/util"
129
+ require "fnordmetric/web/web"
130
+ require "fnordmetric/web/app_helpers"
131
+ require "fnordmetric/web/app"
132
+ require "fnordmetric/web/websocket"
133
+ require "fnordmetric/web/reactor"
134
+ require "fnordmetric/web/event"
135
+ require "fnordmetric/web/dashboard"
136
+ require "fnordmetric/acceptors/acceptor"
137
+ require "fnordmetric/acceptors/tcp_acceptor"
138
+ require "fnordmetric/acceptors/udp_acceptor"
139
+ require "fnordmetric/acceptors/fyrehose_acceptor"
140
+ require "fnordmetric/acceptors/amqp_acceptor"
141
+ require "fnordmetric/acceptors/stomp_acceptor"
142
+ require "fnordmetric/widget"
143
+ require "fnordmetric/widgets/timeseries_widget"
144
+ require "fnordmetric/widgets/numbers_widget"
145
+ require "fnordmetric/widgets/bars_widget"
146
+ require "fnordmetric/widgets/toplist_widget"
147
+ require "fnordmetric/widgets/pie_widget"
148
+ require "fnordmetric/widgets/html_widget"
149
+ require "fnordmetric/enterprise/compatibility_handler"
data/run_specs.sh ADDED
@@ -0,0 +1,11 @@
1
+ #!/bin/bash
2
+
3
+ (cd $(dirname $0)/../fnordmetric-ui && \
4
+ ./build.sh)
5
+
6
+ (cd $(dirname $0)/web && \
7
+ ./build.sh)
8
+
9
+ (cd $(dirname $0) && \
10
+ bundle install && \
11
+ bundle exec rspec)
data/spec/api_spec.rb ADDED
@@ -0,0 +1,49 @@
1
+ require ::File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe FnordMetric::Event do
4
+
5
+ include FnordMetric
6
+
7
+ before(:all) do
8
+ @now = Time.utc(1992,01,13,5,23,23).to_i
9
+ @redis = Redis.new
10
+ @redis_wrap = RedisWrap.new(@redis)
11
+
12
+ @namespace = "fnordmetric-test-ns1234-api"
13
+ @timeline = "#{@namespace}-timeline"
14
+
15
+ @opts = {
16
+ :namespace_prefix => "#{@namespace}",
17
+ :redis_prefix => "fnordmetric-test",
18
+ :redis => @redis
19
+ }
20
+ @api = FnordMetric::API.new @opts
21
+ end
22
+
23
+ describe "creating events using API" do
24
+
25
+ before(:each) do
26
+ @redis.keys("fnordmetric-test-*").each { |k| @redis.del(k) }
27
+ end
28
+
29
+ it "should create an event from a (json-)string" do
30
+ json_string = {
31
+ :_type => "Fn0rd123",
32
+ :_time => @now
33
+ }.to_json
34
+ event_id = @api.event(json_string)
35
+ event = FnordMetric::Event.find(event_id, @opts)
36
+ event.type.should == "Fn0rd123"
37
+ end
38
+
39
+ it "should create an event from a hash" do
40
+ event_id = @api.event(
41
+ :_type => "Fn0rd234",
42
+ :_time => @now
43
+ )
44
+ event = FnordMetric::Event.find(event_id, @opts)
45
+ event.type.should == "Fn0rd234"
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,42 @@
1
+ require ::File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe FnordMetric::Context do
4
+
5
+ before(:all) do
6
+ @redis = Redis.new
7
+ @redis_wrap = RedisWrap.new(@redis)
8
+ end
9
+
10
+ before(:each) do
11
+ @redis.keys("fnordmetrictest*").each { |k| @redis.del(k) }
12
+ end
13
+
14
+ it "should fetch a gauge by key"
15
+ it "should fetch a gauge by gauge"
16
+ it "should raise an error if unable to fetch a gauge"
17
+
18
+ it "should expose the current session_key" do
19
+ ns = FnordMetric::Namespace.new(
20
+ :myns_253,
21
+ :redis_prefix => "fnordmetrictest"
22
+ )
23
+ ns.opt_event(:fnordbar, {}) do
24
+ session_key.should == "145d3f6dee1a770e3a3c550b3993dc81"
25
+ end
26
+ ns.ready!(@redis_wrap, @redis).announce(
27
+ :_eid => "35r2423",
28
+ :_time => Time.now.to_i,
29
+ :_type => "fnordbar",
30
+ :_session => "sess213"
31
+ )
32
+ end
33
+
34
+ it "should instance-eval the handler on call" do
35
+ Thread.current["fnord_123"] = false
36
+ my_block = proc{ Thread.current["fnord_123"] = "35r25" }
37
+ context = FnordMetric::Context.new({}, my_block)
38
+ context.call({}, nil, nil)
39
+ Thread.current["fnord_123"].should == "35r25"
40
+ end
41
+
42
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ require ::File.expand_path('../spec_helper.rb', __FILE__)
3
+
4
+ describe FnordMetric::Dashboard do
5
+
6
+ before(:each) do
7
+ end
8
+
9
+ it "should remember it's title" do
10
+ dashboard = FnordMetric::Dashboard.new(:title => 'My Foobar Dashboard')
11
+ dashboard.title.should == 'My Foobar Dashboard'
12
+ end
13
+
14
+ it "should build a token" do
15
+ dashboard = FnordMetric::Dashboard.new(:title => 'My!F00bar-.Dash_board'){ |dash| }
16
+ dashboard.token.should == 'MyF00barDash_board'
17
+ end
18
+
19
+ it "should build the correct token if the dashboard name contains whitespaces" do
20
+ dashboard = FnordMetric::Dashboard.new(:title => 'My!F00bar Dash_board'){ |dash| }
21
+ dashboard.token.should == 'MyF00barDash_board'
22
+ end
23
+
24
+ it "should build the correct token if the dashboard name contains non-english characters" do
25
+ dashboard = FnordMetric::Dashboard.new(:title => 'Новая статистика!'){ |dash| }
26
+ dashboard.token.should_not be_empty
27
+ end
28
+
29
+ it "should add a widget" do
30
+ pending("fix this")
31
+ #dashboard = FnordMetric::Dashboard.new(:title => 'My!F00bar-.Dash_board'){ |dash| }
32
+ #FnordMetric.metric(:my_metric, :sum => :my_field)
33
+ #idget = FnordMetric.widget(:my_widget, :metrics => :my_metric, :title => "My Widget", :type => :timeline)
34
+ #dashboard.add_widget(widget)
35
+ #dashboard.widgets.first.should == widget
36
+ end
37
+
38
+ end