fnordmetric 0.7.5 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. data/doc/V1.0-ROADMAP +97 -0
  2. data/doc/full_example.rb +95 -511
  3. data/doc/legacy_example.rb +640 -0
  4. data/doc/minimal_example.rb +26 -0
  5. data/doc/preview3.png +0 -0
  6. data/fnordmetric.gemspec +3 -2
  7. data/lib/fnordmetric/acceptors/acceptor.rb +29 -0
  8. data/lib/fnordmetric/{inbound_stream.rb → acceptors/tcp_acceptor.rb} +8 -5
  9. data/lib/fnordmetric/{inbound_datagram.rb → acceptors/udp_acceptor.rb} +9 -8
  10. data/lib/fnordmetric/api.rb +2 -2
  11. data/lib/fnordmetric/context.rb +37 -18
  12. data/lib/fnordmetric/defaults.rb +9 -0
  13. data/lib/fnordmetric/ext.rb +72 -0
  14. data/lib/fnordmetric/gauge.rb +37 -10
  15. data/lib/fnordmetric/gauge_calculations.rb +38 -16
  16. data/lib/fnordmetric/gauge_modifiers.rb +67 -0
  17. data/lib/fnordmetric/gauge_rendering.rb +40 -0
  18. data/lib/fnordmetric/gauge_validations.rb +15 -0
  19. data/lib/fnordmetric/gauges/distribution_gauge.rb +85 -0
  20. data/lib/fnordmetric/gauges/timeseries_gauge.rb +143 -0
  21. data/lib/fnordmetric/gauges/toplist_gauge.rb +44 -0
  22. data/lib/fnordmetric/histogram.rb +57 -0
  23. data/lib/fnordmetric/logger.rb +42 -36
  24. data/lib/fnordmetric/namespace.rb +47 -23
  25. data/lib/fnordmetric/session.rb +6 -6
  26. data/lib/fnordmetric/standalone.rb +15 -35
  27. data/lib/fnordmetric/timeseries.rb +79 -0
  28. data/lib/fnordmetric/toplist.rb +61 -0
  29. data/lib/fnordmetric/version.rb +1 -1
  30. data/lib/fnordmetric/web/app.rb +122 -0
  31. data/lib/fnordmetric/web/app_helpers.rb +42 -0
  32. data/lib/fnordmetric/{dashboard.rb → web/dashboard.rb} +4 -0
  33. data/lib/fnordmetric/{event.rb → web/event.rb} +7 -2
  34. data/lib/fnordmetric/web/reactor.rb +87 -0
  35. data/lib/fnordmetric/web/web.rb +53 -0
  36. data/lib/fnordmetric/web/websocket.rb +38 -0
  37. data/lib/fnordmetric/widgets/bars_widget.rb +44 -0
  38. data/lib/fnordmetric/{html_widget.rb → widgets/html_widget.rb} +0 -0
  39. data/lib/fnordmetric/widgets/numbers_widget.rb +56 -0
  40. data/lib/fnordmetric/{pie_widget.rb → widgets/pie_widget.rb} +0 -0
  41. data/lib/fnordmetric/widgets/timeseries_widget.rb +55 -0
  42. data/lib/fnordmetric/widgets/toplist_widget.rb +64 -0
  43. data/lib/fnordmetric/worker.rb +26 -25
  44. data/lib/fnordmetric.rb +85 -115
  45. data/readme.md +362 -0
  46. data/spec/gauge_like_shared.rb +54 -0
  47. data/spec/gauge_spec.rb +2 -36
  48. data/spec/namespace_spec.rb +25 -11
  49. data/spec/spec_helper.rb +4 -0
  50. data/spec/{inbound_stream_spec.rb → tcp_acceptor_spec.rb} +3 -3
  51. data/spec/timeseries_gauge_spec.rb +54 -0
  52. data/spec/{inbound_datagram_spec.rb → udp_acceptor_spec.rb} +3 -3
  53. data/web/fnordmetric.css +786 -0
  54. data/web/haml/app.haml +38 -0
  55. data/web/haml/distribution_gauge.haml +118 -0
  56. data/web/haml/timeseries_gauge.haml +80 -0
  57. data/web/haml/toplist_gauge.haml +194 -0
  58. data/web/img/head.png +0 -0
  59. data/web/img/list.png +0 -0
  60. data/web/img/list_active.png +0 -0
  61. data/web/img/list_hover.png +0 -0
  62. data/web/img/loader_white.gif +0 -0
  63. data/web/img/navbar.png +0 -0
  64. data/web/img/navbar_btn.png +0 -0
  65. data/web/img/picto_gauge.png +0 -0
  66. data/web/js/fnordmetric.bars_widget.js +178 -0
  67. data/web/js/fnordmetric.dashboard_view.js +99 -0
  68. data/web/js/fnordmetric.gauge_view.js +260 -0
  69. data/web/js/fnordmetric.html_widget.js +21 -0
  70. data/web/js/fnordmetric.js +255 -0
  71. data/web/js/fnordmetric.numbers_widget.js +121 -0
  72. data/web/js/fnordmetric.overview_view.js +35 -0
  73. data/web/js/fnordmetric.pie_widget.js +118 -0
  74. data/web/js/fnordmetric.realtime_timeline_widget.js +175 -0
  75. data/web/js/fnordmetric.session_view.js +343 -0
  76. data/web/js/fnordmetric.timeline_widget.js +333 -0
  77. data/web/js/fnordmetric.timeseries_widget.js +388 -0
  78. data/web/js/fnordmetric.toplist_widget.js +112 -0
  79. data/web/js/fnordmetric.ui.js +91 -0
  80. data/web/js/fnordmetric.util.js +244 -0
  81. data/{pub → web}/loader.gif +0 -0
  82. data/web/vendor/d3.v2.js +9382 -0
  83. data/web/vendor/font-awesome/css/font-awesome.css +239 -0
  84. data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
  85. data/web/vendor/font-awesome/font/fontawesome-webfont.svg +175 -0
  86. data/web/vendor/font-awesome/font/fontawesome-webfont.svgz +0 -0
  87. data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
  88. data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
  89. data/web/vendor/jquery-1.6.2.min.js +18 -0
  90. data/web/vendor/jquery-ui.min.js +413 -0
  91. data/web/vendor/jquery.maskedinput.js +252 -0
  92. data/web/vendor/rickshaw.css +286 -0
  93. data/web/vendor/rickshaw.fnordmetric.js +2676 -0
  94. metadata +129 -79
  95. data/Gemfile +0 -6
  96. data/README.md +0 -404
  97. data/Rakefile +0 -6
  98. data/doc/version +0 -1
  99. data/haml/app.haml +0 -79
  100. data/haml/widget.haml +0 -9
  101. data/lib/fnordmetric/app.rb +0 -163
  102. data/lib/fnordmetric/average_metric.rb +0 -7
  103. data/lib/fnordmetric/bars_widget.rb +0 -26
  104. data/lib/fnordmetric/combine_metric.rb +0 -7
  105. data/lib/fnordmetric/count_metric.rb +0 -13
  106. data/lib/fnordmetric/funnel_widget.rb +0 -2
  107. data/lib/fnordmetric/metric.rb +0 -80
  108. data/lib/fnordmetric/metric_api.rb +0 -37
  109. data/lib/fnordmetric/numbers_widget.rb +0 -26
  110. data/lib/fnordmetric/report.rb +0 -29
  111. data/lib/fnordmetric/sum_metric.rb +0 -13
  112. data/lib/fnordmetric/timeline_widget.rb +0 -30
  113. data/lib/fnordmetric/toplist_widget.rb +0 -25
  114. data/pub/fnordmetric.css +0 -145
  115. data/pub/fnordmetric.js +0 -1179
  116. data/pub/vendor/highcharts.js +0 -170
  117. data/pub/vendor/jquery-1.6.1.min.js +0 -18
@@ -1,44 +1,39 @@
1
1
  class FnordMetric::Worker
2
2
 
3
- def initialize(namespaces, opts)
4
- @namespaces = {}
5
- @opts = opts
6
- configure(namespaces)
7
- end
3
+ def initialize
4
+ @namespaces = FnordMetric.namespaces
5
+ @opts = FnordMetric.options
8
6
 
9
- def ready!
10
- @redis = EM::Hiredis.connect(@opts[:redis_url])
11
- tick
7
+ FnordMetric.register(self)
12
8
  end
13
9
 
14
- def configure(namespaces)
15
- namespaces.each do |key, block|
16
- @namespaces[key] = FnordMetric::Namespace.new(key, @opts.clone)
17
- @namespaces[key].instance_eval(&block)
18
- end
10
+ def initialized
11
+ FnordMetric.log("worker started")
12
+ EM.next_tick(&method(:tick))
19
13
  end
20
14
 
21
15
  def tick
22
- @redis.blpop(queue_key, 1).callback do |list, event_id|
16
+ redis.blpop(queue_key, 1).callback do |list, event_id|
23
17
  EM.next_tick(&method(:tick))
24
18
  if event_id
25
- @redis.get(event_key(event_id)).callback do |event_data|
26
- process_event(event_id, event_data) if event_data
19
+ redis.get(event_key(event_id)).callback do |event_data|
20
+ process_event(event_id, event_data) if event_data
27
21
  FnordMetric.log("event_lost: event_data not found for event-id '#{event_id}' - maybe expired?") unless event_data
28
- @redis.hincrby(stats_key, :events_processed, 1)
22
+ redis.hincrby(stats_key, :events_processed, 1)
29
23
  end
30
24
  end
31
25
  end
32
26
  end
33
27
 
34
28
  def process_event(event_id, event_data)
35
- EM.defer do
36
- parse_json(event_data).tap do |event|
29
+ EM.next_tick do
30
+ event = parse_json(event_data)
31
+ if event
37
32
  event[:_time] ||= Time.now.to_i
38
33
  event[:_eid] = event_id
39
34
  announce_event(event)
40
- publish_event(event)
41
- expire_event(event_id)
35
+ publish_event(event)
36
+ expire_event(event_id)
42
37
  end
43
38
  end
44
39
  end
@@ -59,16 +54,16 @@ class FnordMetric::Worker
59
54
  [@opts[:redis_prefix], 'stats'].join("-")
60
55
  end
61
56
 
62
- def announce_event(event)
63
- namespace(event[:_namespace]).ready!(@redis).announce(event)
57
+ def announce_event(event)
58
+ namespace(event[:_namespace]).ready!(redis).announce(event)
64
59
  end
65
60
 
66
61
  def expire_event(event_id)
67
- @redis.expire(event_key(event_id), @opts[:event_data_ttl])
62
+ redis.expire(event_key(event_id), @opts[:event_data_ttl])
68
63
  end
69
64
 
70
65
  def publish_event(event)
71
- @redis.publish(pubsub_key, event[:_eid])
66
+ redis.publish(pubsub_key, event.to_json)
72
67
  end
73
68
 
74
69
  def namespace(key)
@@ -79,6 +74,12 @@ class FnordMetric::Worker
79
74
  event = Yajl::Parser.new(:symbolize_keys => true).parse(data)
80
75
  event[:_namespace] = event[:_namespace].to_sym if event[:_namespace]
81
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
82
83
  end
83
84
 
84
85
  end
data/lib/fnordmetric.rb CHANGED
@@ -5,22 +5,52 @@ require "active_support/core_ext"
5
5
  require 'yajl'
6
6
  require 'sinatra/base'
7
7
  require 'haml'
8
+ require 'json'
9
+ require "thin"
8
10
  require 'rack/server'
11
+ require 'rack/websocket'
9
12
 
10
13
  require "fnordmetric/ext"
11
14
  require "fnordmetric/version"
12
15
 
13
16
  module FnordMetric
14
17
 
18
+ @@options = nil
19
+ @@pool = []
20
+
15
21
  @@namespaces = {}
16
- @@server_configuration = nil
17
22
 
18
23
  def self.namespace(key=nil, &block)
19
24
  @@namespaces[key] = block
20
25
  end
21
26
 
22
- def self.server_configuration=(configuration)
23
- @@server_configuration = configuration
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
+ host, port = options[:redis_url].gsub("redis://", "").split(":")
51
+ redis_opts = { :host => host }
52
+ redis_opts.merge!(:port => port) if port
53
+ Redis.new(redis_opts)
24
54
  end
25
55
 
26
56
  def self.default_options(opts = {})
@@ -39,37 +69,14 @@ module FnordMetric
39
69
  }.merge(opts)
40
70
  end
41
71
 
42
- def self.options(opts = {})
43
- default_options(@@server_configuration || {}).merge(opts)
44
- end
45
-
46
- def self.start_em(opts = {})
47
- EM.run do
48
-
49
- trap("TERM", &method(:shutdown))
50
- trap("INT", &method(:shutdown))
51
-
52
- opts = options(opts)
53
- app = embedded(opts)
54
-
55
- if opts[:web_interface]
56
- server = opts[:web_interface_server].downcase
57
- unless ["thin", "hatetepe"].include? server
58
- raise "Need an EventMachine webserver, but #{server} isn't"
59
- end
60
-
61
- host, port = *opts[:web_interface]
62
- Rack::Server.start :app => app, :server => server,
63
- :Host => host, :Port => port
64
- log "listening on http://#{host}:#{port}"
65
- end
66
- end
67
- end
68
-
69
72
  def self.log(msg)
70
73
  puts "[#{Time.now.strftime("%y-%m-%d %H:%M:%S")}] #{msg}"
71
74
  end
72
75
 
76
+ def self.error(msg)
77
+ log "[ERROR] #{msg}"; nil
78
+ end
79
+
73
80
  def self.error!(msg)
74
81
  raise msg if ENV['FNORDMETRIC_ENV'] == 'test'
75
82
  puts(msg); exit!
@@ -83,106 +90,69 @@ module FnordMetric
83
90
  sleep(1); run
84
91
  end
85
92
 
86
- def self.shutdown
93
+ def self.shutdown(fnord=nil)
87
94
  log "shutting down, byebye"
88
95
  EM.stop
89
96
  end
90
97
 
91
- def self.connect_redis(redis_url)
92
- EM::Hiredis.connect(redis_url)
93
- end
98
+ def self.start_em
99
+ EM.run do
94
100
 
95
- def self.print_stats(opts, redis) # FIXME: refactor this mess
96
- keys = [:events_received, :events_processed]
97
- redis.llen("#{opts[:redis_prefix]}-queue") do |queue_length|
98
- redis.hmget("#{opts[:redis_prefix]}-stats", *keys) do |data|
99
- data_human = keys.size.times.map{|n|"#{keys[n]}: #{data[n]}"}
100
- log "#{data_human.join(", ")}, queue_length: #{queue_length}"
101
+ trap("TERM", &method(:shutdown))
102
+ trap("INT", &method(:shutdown))
103
+
104
+ EM.next_tick do
105
+ (@@pool || []).map(&:initialized)
101
106
  end
107
+
102
108
  end
103
109
  end
104
110
 
105
- def self.standalone
106
- require "fnordmetric/logger"
107
- require "fnordmetric/standalone"
111
+ def self.server_configuration=(configuration)
112
+ puts "DEPRECATION WARNING - FIXPAUL"
113
+ self.options=(configuration)
108
114
  end
109
115
 
110
- # returns a Rack app which can be mounted under any path.
111
- # `:start_worker` starts a worker
112
- # `:inbound_stream` starts the TCP interface
113
- # `:print_stats` periodicaly prints worker stats
114
- def self.embedded(opts={})
115
- opts = options(opts)
116
- app = nil
117
-
118
- if opts[:rack_app] or opts[:web_interface]
119
- app = FnordMetric::App.new(@@namespaces.clone, opts)
120
- end
121
-
122
- EM.next_tick do
123
- if opts[:start_worker]
124
- worker = Worker.new(@@namespaces.clone, opts)
125
- worker.ready!
126
- end
127
-
128
- if opts[:inbound_stream]
129
- inbound_class = opts[:inbound_protocol] == :udp ? InboundDatagram : InboundStream
130
- begin
131
- inbound_stream = inbound_class.start(opts)
132
- log "listening on #{opts[:inbound_protocol]}##{opts[:inbound_stream].join(":")}"
133
- rescue
134
- log "cant start #{inbound_class.name}. port in use?"
135
- end
136
- end
137
-
138
- if opts[:print_stats]
139
- redis = connect_redis(opts[:redis_url])
140
- EM::PeriodicTimer.new(opts[:print_stats]) do
141
- print_stats(opts, redis)
142
- end
143
- end
144
- end
145
-
146
- app
116
+ def self.standalone
117
+ puts "DEPRECATION WARNING - FIXPAUL"
118
+ require "fnordmetric/standalone"
119
+ start_em
147
120
  end
148
121
 
149
122
  end
150
123
 
151
- require "fnordmetric/api"
152
- require "fnordmetric/udp_client"
153
- require "fnordmetric/inbound_stream"
154
- require "fnordmetric/inbound_datagram"
155
- require "fnordmetric/worker"
156
- require "fnordmetric/widget"
157
- require "fnordmetric/timeline_widget"
158
- require "fnordmetric/numbers_widget"
159
- require "fnordmetric/bars_widget"
160
- require "fnordmetric/toplist_widget"
161
- require "fnordmetric/pie_widget"
162
- require "fnordmetric/html_widget"
163
- require "fnordmetric/namespace"
164
- require "fnordmetric/gauge_modifiers"
165
124
  require "fnordmetric/gauge_calculations"
166
- require "fnordmetric/context"
125
+ require "fnordmetric/gauge_modifiers"
126
+ require "fnordmetric/gauge_validations"
127
+ require "fnordmetric/gauge_rendering"
167
128
  require "fnordmetric/gauge"
129
+ require "fnordmetric/gauges/timeseries_gauge"
130
+ require "fnordmetric/gauges/toplist_gauge"
131
+ require "fnordmetric/gauges/distribution_gauge"
132
+ require "fnordmetric/context"
133
+ require "fnordmetric/histogram"
134
+ require "fnordmetric/timeseries"
135
+ require "fnordmetric/toplist"
136
+ require "fnordmetric/namespace"
168
137
  require "fnordmetric/session"
169
- require "fnordmetric/app"
170
- require "fnordmetric/dashboard"
171
- require "fnordmetric/event"
172
-
173
-
174
- #require "fnordmetric/metric_api"
175
-
176
-
177
- #require "fnordmetric/cache"
178
- #require "fnordmetric/report"
179
- #require "fnordmetric/metric"
180
- #require "fnordmetric/average_metric"
181
- #require "fnordmetric/count_metric"
182
- #require "fnordmetric/combine_metric"
183
- #require "fnordmetric/sum_metric"
184
- #require "fnordmetric/widget"
185
-
186
- #
187
- #require "fnordmetric/funnel_widget"
188
-
138
+ require "fnordmetric/api"
139
+ require "fnordmetric/worker"
140
+ require "fnordmetric/logger"
141
+ require "fnordmetric/defaults"
142
+ require "fnordmetric/web/web"
143
+ require "fnordmetric/web/app_helpers"
144
+ require "fnordmetric/web/app"
145
+ require "fnordmetric/web/websocket"
146
+ require "fnordmetric/web/reactor"
147
+ require "fnordmetric/web/event"
148
+ require "fnordmetric/web/dashboard"
149
+ require "fnordmetric/acceptors/acceptor"
150
+ require "fnordmetric/acceptors/tcp_acceptor"
151
+ require "fnordmetric/acceptors/udp_acceptor"
152
+ require "fnordmetric/widget"
153
+ require "fnordmetric/widgets/timeseries_widget"
154
+ require "fnordmetric/widgets/numbers_widget"
155
+ require "fnordmetric/widgets/bars_widget"
156
+ require "fnordmetric/widgets/toplist_widget"
157
+ require "fnordmetric/widgets/pie_widget"
158
+ require "fnordmetric/widgets/html_widget"