rrd-grapher 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/.gitignore +9 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +11 -0
  4. data/Guardfile +123 -0
  5. data/README.md +91 -0
  6. data/Rakefile +42 -0
  7. data/example_app/Gemfile +9 -0
  8. data/example_app/Guardfile +18 -0
  9. data/example_app/app.rb +38 -0
  10. data/example_app/assets/javascripts/available_rrds.coffee +13 -0
  11. data/example_app/assets/javascripts/collectd.coffee +48 -0
  12. data/example_app/config.ru +9 -0
  13. data/example_app/public/.gitignore +1 -0
  14. data/example_app/public/chosen/chosen-sprite.png +0 -0
  15. data/example_app/public/chosen/chosen.css +340 -0
  16. data/example_app/public/chosen/chosen.jquery.js +786 -0
  17. data/example_app/public/chosen/chosen.jquery.min.js +10 -0
  18. data/example_app/public/javascripts/available_rrds.js +16 -0
  19. data/example_app/public/javascripts/collectd.js +64 -0
  20. data/example_app/public/javascripts/jquery.timeago.js +148 -0
  21. data/example_app/public/stylesheets/Aristo/images/bg_fallback.png +0 -0
  22. data/example_app/public/stylesheets/Aristo/images/icon_sprite.png +0 -0
  23. data/example_app/public/stylesheets/Aristo/images/progress_bar.gif +0 -0
  24. data/example_app/public/stylesheets/Aristo/images/slider_handles.png +0 -0
  25. data/example_app/public/stylesheets/Aristo/images/ui-icons_222222_256x240.png +0 -0
  26. data/example_app/public/stylesheets/Aristo/images/ui-icons_454545_256x240.png +0 -0
  27. data/example_app/public/stylesheets/Aristo/theme.css +738 -0
  28. data/example_app/views/available_rrds.haml +26 -0
  29. data/example_app/views/collectd.haml +30 -0
  30. data/example_app/views/layout.haml +19 -0
  31. data/example_app/views/stylesheets/available_rrds.scss +7 -0
  32. data/example_notifier/Gemfile +2 -0
  33. data/example_notifier/notifier.rb +25 -0
  34. data/lib/rrd-grapher/assets/javascripts/app-dev.js +20 -0
  35. data/lib/rrd-grapher/assets/javascripts/app.js +20 -0
  36. data/lib/rrd-grapher/assets/javascripts/classes/format.coffee +35 -0
  37. data/lib/rrd-grapher/assets/javascripts/classes/graph.coffee +306 -0
  38. data/lib/rrd-grapher/assets/javascripts/classes/graph_definition.coffee +216 -0
  39. data/lib/rrd-grapher/assets/javascripts/classes/serie.coffee +13 -0
  40. data/lib/rrd-grapher/assets/javascripts/classes/size.coffee +5 -0
  41. data/lib/rrd-grapher/assets/javascripts/classes/static_line.coffee +44 -0
  42. data/lib/rrd-grapher/assets/javascripts/classes/time.coffee +17 -0
  43. data/lib/rrd-grapher/notifier/alarm_manager.rb +190 -0
  44. data/lib/rrd-grapher/notifier/alarm_trigger.rb +187 -0
  45. data/lib/rrd-grapher/notifier/alarms.rb +79 -0
  46. data/lib/rrd-grapher/notifier/collectdrb.rb +86 -0
  47. data/lib/rrd-grapher/notifier/data_struct.rb +46 -0
  48. data/lib/rrd-grapher/notifier/default_user_handler.rb +36 -0
  49. data/lib/rrd-grapher/notifier/parsers/bindata_parser.rb +144 -0
  50. data/lib/rrd-grapher/notifier/parsers/ruby_parser.rb +134 -0
  51. data/lib/rrd-grapher/notifier/structures.rb +80 -0
  52. data/lib/rrd-grapher/notifier.rb +87 -0
  53. data/lib/rrd-grapher/public/favicon.ico +0 -0
  54. data/lib/rrd-grapher/public/javascripts/app-dev.js +13709 -0
  55. data/lib/rrd-grapher/public/javascripts/app.js +4057 -0
  56. data/lib/rrd-grapher/public/javascripts/backbone/backbone.js +1155 -0
  57. data/lib/rrd-grapher/public/javascripts/backbone/backbone.min.js +32 -0
  58. data/lib/rrd-grapher/public/javascripts/backbone/underscore.js +841 -0
  59. data/lib/rrd-grapher/public/javascripts/backbone/underscore.min.js +27 -0
  60. data/lib/rrd-grapher/public/javascripts/classes/format.js +42 -0
  61. data/lib/rrd-grapher/public/javascripts/classes/graph.js +360 -0
  62. data/lib/rrd-grapher/public/javascripts/classes/graph_definition.js +298 -0
  63. data/lib/rrd-grapher/public/javascripts/classes/serie.js +32 -0
  64. data/lib/rrd-grapher/public/javascripts/classes/size.js +7 -0
  65. data/lib/rrd-grapher/public/javascripts/classes/static_line.js +48 -0
  66. data/lib/rrd-grapher/public/javascripts/classes/time.js +17 -0
  67. data/lib/rrd-grapher/public/javascripts/flot/.gitignore +4 -0
  68. data/lib/rrd-grapher/public/javascripts/flot/excanvas.min.js +1 -0
  69. data/lib/rrd-grapher/public/javascripts/flot/jquery.colorhelpers.min.js +1 -0
  70. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.crosshair.min.js +1 -0
  71. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.fillbetween.min.js +1 -0
  72. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.image.min.js +1 -0
  73. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.js +2604 -0
  74. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.navigate.min.js +1 -0
  75. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.pie.min.js +1 -0
  76. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.resize.min.js +1 -0
  77. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.selection.js +345 -0
  78. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.selection.min.js +1 -0
  79. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.stack.min.js +1 -0
  80. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.symbol.min.js +1 -0
  81. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.threshold.min.js +1 -0
  82. data/lib/rrd-grapher/public/javascripts/jquery/jquery-1.6.2.js +8981 -0
  83. data/lib/rrd-grapher/public/javascripts/jquery/jquery-1.6.2.min.js +18 -0
  84. data/lib/rrd-grapher/public/javascripts/jquery/jquery-ui-1.8.11.min.js +783 -0
  85. data/lib/rrd-grapher/public/javascripts/jquery/jquery.showtime.js +63 -0
  86. data/lib/rrd-grapher/public/javascripts/jquery/jquery.tpl.min.js +10 -0
  87. data/lib/rrd-grapher/resources.rb +14 -0
  88. data/lib/rrd-grapher/rrd.rb +238 -0
  89. data/lib/rrd-grapher/rrd_server.rb +78 -0
  90. data/lib/rrd-grapher/version.rb +4 -0
  91. data/lib/rrd-grapher/views/stylesheets/app.scss +111 -0
  92. data/lib/rrd-grapher.rb +12 -0
  93. data/rrd-grapher.gemspec +47 -0
  94. data/spec/common.rb +70 -0
  95. data/spec/data/myrouter.rrd +0 -0
  96. data/spec/data/subdata.rrd +0 -0
  97. data/spec/data/test.rrd +0 -0
  98. data/spec/factories.rb +23 -0
  99. data/spec/javascripts/helpers/jasmine-jquery-1.3.0.js +283 -0
  100. data/spec/javascripts/source/format_spec.coffee +18 -0
  101. data/spec/javascripts/source/graph_def_spec.coffee +27 -0
  102. data/spec/javascripts/source/graph_spec.coffee +63 -0
  103. data/spec/javascripts/source/serie_spec.coffee +28 -0
  104. data/spec/javascripts/source/static_line_spec.coffee +13 -0
  105. data/spec/javascripts/source/time_spec.coffee +26 -0
  106. data/spec/javascripts/support/jasmine.yml +78 -0
  107. data/spec/javascripts/support/jasmine_config.rb +23 -0
  108. data/spec/javascripts/support/jasmine_runner.rb +32 -0
  109. data/spec/unit/alarm_manager_spec.rb +252 -0
  110. data/spec/unit/alarm_trigger_spec.rb +26 -0
  111. data/spec/unit/data_struct_spec.rb +55 -0
  112. data/spec/unit/notifier_spec.rb +45 -0
  113. data/spec/unit/parsers/bindata_parser_spec.rb +184 -0
  114. data/spec/unit/parsers/ruby_parser_spec.rb +184 -0
  115. data/spec/unit/rrd_spec.rb +50 -0
  116. data/spec/unit/structures_spec.rb +28 -0
  117. data/tests/4series.rrd +0 -0
  118. data/tests/analyze_rrd.rb +62 -0
  119. data/tests/exact.rrd +0 -0
  120. data/tests/exact2.rrd +0 -0
  121. data/tests/filler.rb +46 -0
  122. metadata +414 -0
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ gems/
2
+ doc/
3
+ coverage/
4
+ .bundle/
5
+ public/javascripts/generated/*.js
6
+ spec/javascripts/*.js
7
+ .sass-cache/
8
+ .yardoc/
9
+ Gemfile.lock
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2-p290
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+
2
+ source :rubygems
3
+
4
+ # underscore.js makes sprockets raise an error wil latest 1.x version..
5
+ #gem 'sprockets', :git => 'git://github.com/matehat/sprockets.git'
6
+ gem 'sprockets', :git => 'git://github.com/salbito/sprockets.git', :branch => '1.0.x'
7
+ # gem 'bacon', :git => 'git://github.com/schmurfy/bacon.git'
8
+ gem 'schmurfy-bacon'
9
+ gem "bindata", "~> 1.4.2"
10
+
11
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,123 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ require 'sprockets'
5
+
6
+ guard 'yard' do
7
+ watch(%r{lib/.+\.rb})
8
+ end
9
+
10
+
11
+ # for the grapher
12
+ guard 'coffeescript',
13
+ :input => 'lib/rrd-grapher/assets/javascripts',
14
+ :output => 'lib/rrd-grapher/public/javascripts'
15
+
16
+ guard 'coffeescript',
17
+ :input => 'spec/javascripts/source',
18
+ :output => 'spec/javascripts'
19
+
20
+ guard 'sprockets', :destination => "lib/rrd-grapher/public/javascripts" do
21
+ watch (%r{lib/rrd-grapher/assets/javascripts/app.js})
22
+ watch (%r{lib/rrd-grapher/assets/javascripts/app-dev.js})
23
+ end
24
+
25
+
26
+ guard 'livereload', :apply_js_live => false do
27
+ watch(%r{^spec/javascripts/.+\.js$})
28
+ watch(%r{^lib/rrd-grapher/public/javascripts/.+\.js$})
29
+ watch(%r{^lib/rrd-grapher/views/stylesheets/.+\.scss$})
30
+ end
31
+
32
+
33
+
34
+
35
+
36
+ require 'bacon'
37
+ require 'guard/guard'
38
+
39
+ module ::Guard
40
+ class Bacon < Guard
41
+
42
+ def initialize(watchers=[], options={})
43
+ super
44
+ ::Bacon.extend(::Bacon::TestUnitOutput)
45
+ end
46
+
47
+ def start
48
+ puts "Guard::Bacon started."
49
+ true
50
+ end
51
+
52
+ # Called on Ctrl-C signal (when Guard quits)
53
+ def stop
54
+ true
55
+ end
56
+
57
+ # Called on Ctrl-Z signal
58
+ def reload
59
+ true
60
+ end
61
+
62
+ # Called on Ctrl-\ signal
63
+ # This method should be principally used for long action like running all specs/tests/...
64
+ def run_all
65
+ true
66
+ end
67
+
68
+ SPEC_FILE ||= /_spec\.rb$/.freeze
69
+ FILE_REG ||= %r{^lib/rrd-grapher/(?:[^/]+/)?(.*)\.rb$}.freeze
70
+
71
+ def run_spec(path)
72
+ if File.exists?(path)
73
+ pid = Kernel.fork do
74
+ puts " *** Running spec: #{path} ***"
75
+ counters = ::Bacon.run_file(path)
76
+ # system "bundle exec bacon -o TestUnit #{path}"
77
+ # {:installed_summary=>1, :specifications=>19, :depth=>0, :requirements=>30, :failed=>2}
78
+
79
+ all_specs = counters[:specifications]
80
+ failed = counters[:failed]
81
+
82
+ if counters[:failed] > 0
83
+ Notifier.notify("Specs: #{failed} Failures (#{all_specs} specs)",
84
+ :image => :failed,
85
+ :title => File.basename(path)
86
+ )
87
+ else
88
+ Notifier.notify("Specs: OK (#{all_specs} specs)",
89
+ :image => :success,
90
+ :title => File.basename(path)
91
+ )
92
+ end
93
+ end
94
+
95
+ Process.wait(pid)
96
+ end
97
+ end
98
+
99
+ def file_changed(path)
100
+ case
101
+ when path =~ SPEC_FILE then run_spec(path)
102
+ when path =~ FILE_REG then run_spec("spec/unit/#{$1}_spec.rb")
103
+ end
104
+
105
+ puts ""
106
+ end
107
+
108
+ # Called on file(s) modifications
109
+ def run_on_change(paths)
110
+ paths.each do |path|
111
+ file_changed(path)
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+
118
+
119
+ guard 'bacon' do
120
+ watch(%r{^spec/([^/]/)?.*_spec.rb$})
121
+ watch(%r{^lib/rrd-grapher/(?:[^/]+/)?(.*)\.rb$})
122
+ end
123
+
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+
2
+ ![screenshot](http://dl.dropbox.com/u/1313066/github/rrd-grapher.png "Screenshot")
3
+
4
+ # What is this ?
5
+
6
+ RRDGrapher is my attempt at designing an application capable of drawing meaningful
7
+ dynamic graphs from RRD files.
8
+
9
+ This project is built as a Rack middleware providing you the with the tools you need to
10
+ build you own views as you see fit, the middleware will provide:
11
+
12
+ - a REST inerface to your rrd files
13
+ - a javascript framework to create graphs easily (built on top of jQuery and Flot)
14
+ - some basic css to get you started (everything can then be overloaded in your application)
15
+
16
+ You can have a look at the example_app folder which is a fully working application.
17
+
18
+ # My goals
19
+
20
+ The main goal of this project is to allow easy creation of graphs from rrd files stored
21
+ by any tool capable of it (the source really does not matter). Here is a features list:
22
+
23
+ # Features
24
+
25
+ - you should be able to able to add a new graph in minutes
26
+ - the zoom (with mouse drag and drop) load new fresh data so your graph is as exact as possible
27
+ - you can decide if the zoom will affect every graph on the page or just one
28
+
29
+
30
+ # Notifier Demon
31
+
32
+ This one may go into another gem but lives there for now, I made a monitoring demon to receive
33
+ collectd packets and trigger alerts by reacting on the data received.
34
+
35
+ ## What can be monitored ?
36
+
37
+ Here s what the demon can monitor:
38
+
39
+ - min/max value : raise an alarm if the value go above or below a <X>
40
+ - missing data : raise an alarm if no data was received for <X> seconds
41
+ - clock drift : raise an alarm if the absolute difference between the timestamp
42
+ inside the packet and the local time is higher then <X> (this suppose that both
43
+ hosts have an UTC clock)
44
+
45
+ ## How to use it
46
+
47
+ The demon is desgined as a library and require an eventmachine reactor to run, here is a minimal
48
+ application using it (check the documentation or the source code for more informations):
49
+
50
+ ``` ruby
51
+ require 'rubygems'
52
+ require 'bundler/setup'
53
+ require 'rrd-grapher/notifier'
54
+
55
+ puts "Notifier started."
56
+
57
+ EM::run do
58
+ RRDNotifier::Server.start do |s|
59
+ s.register_alarm("*", "ping", "ping_droprate", :max => 5)
60
+ s.register_alarm("*", "uptime", "uptime", :monitor_presence => 2*60)
61
+
62
+ s.register_alarm("*", "load", "load", :max => 1, :index => 1)
63
+ s.register_alarm("*", "memory/*", "memory/active", :monitor_presence => 1)
64
+ end
65
+
66
+ end
67
+ ```
68
+
69
+
70
+
71
+ # Development
72
+
73
+ If you wan to contribute to this project, here how to do it (in the root folder):
74
+
75
+ $ bundle
76
+
77
+ Now you have all the require gems run guard, it will monitor the sources files
78
+ and rebuild the results as you change them (coffeescript, sass).
79
+ It will also package all the js files with sprockets in one file.
80
+
81
+ $ bundle exec guard (will take one console)
82
+
83
+ You can also force a full rebuild of everything with (coffeescript + sprockets):
84
+
85
+ $ rake build
86
+
87
+ Last thing you will certainly need is to start a webserver, any should do but
88
+ I currently use unicorn
89
+
90
+ $ unicorn
91
+
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require "bundler/gem_tasks"
2
+ require 'sprockets'
3
+
4
+ def pack_js(src_file)
5
+ secretary = ::Sprockets::Secretary.new(
6
+ :asset_root => "lib",
7
+ :source_files => ["lib/rrd-grapher/assets/javascripts/#{src_file}"],
8
+ :interpolate_constants => false
9
+ )
10
+
11
+ concatenation = secretary.concatenation
12
+ concatenation.save_to("lib/rrd-grapher/public/javascripts/#{src_file}")
13
+ secretary.install_assets
14
+ end
15
+
16
+ # compile and pack coffee files
17
+ task :build do
18
+ # core
19
+ sh "coffee -c -o lib/rrd-grapher/public/javascripts lib/rrd-grapher/assets/javascripts/"
20
+
21
+ # example_app
22
+ sh "coffee -c -o example_app/public/javascripts example_app/assets/javascripts/"
23
+
24
+ # sprockets
25
+ pack_js("app-dev.js")
26
+ pack_js("app.js")
27
+ end
28
+
29
+ task :test do
30
+ system("COVERAGE=1 bundle exec bacon spec/**/*_spec.rb")
31
+ end
32
+
33
+
34
+
35
+ begin
36
+ require 'jasmine'
37
+ load 'jasmine/tasks/jasmine.rake'
38
+ rescue LoadError
39
+ task :jasmine do
40
+ abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine"
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+
2
+ gem 'rrd-grapher', :path => File.expand_path('../..', __FILE__)
3
+ gem 'sinatra'
4
+ gem 'sinatra-content-for'
5
+ gem 'haml'
6
+
7
+ group(:dev) do
8
+ gem 'guard-coffeescript'
9
+ end
@@ -0,0 +1,18 @@
1
+
2
+ guard 'coffeescript',
3
+ :input => 'assets/javascripts',
4
+ :output => 'public/javascripts'
5
+
6
+ # guard 'coffeescript',
7
+ # :input => 'spec/javascripts/source',
8
+ # :output => 'spec/javascripts'
9
+
10
+
11
+
12
+ # guard 'livereload', :apply_js_live => false do
13
+ # watch(%r{^spec/javascripts/.+\.js$})
14
+ # watch(%r{^public/javascripts/.+\.js$})
15
+ # watch(%r{^views/stylesheets/.+\.scss$})
16
+ # watch(%r{^views/.+\.haml$})
17
+ # end
18
+
@@ -0,0 +1,38 @@
1
+ require 'rest-client'
2
+ require 'sinatra/base'
3
+ require 'sinatra/content_for'
4
+
5
+ class TestApp < Sinatra::Base
6
+ helpers Sinatra::ContentFor
7
+
8
+ set :haml, :format => :html5
9
+
10
+ # set :markdown, :layout_engine => :haml, :layout => :post
11
+ set :root, File.dirname(__FILE__)
12
+
13
+ get '/available_rrds' do
14
+ haml :available_rrds
15
+ end
16
+
17
+ get '/graph' do
18
+ haml :graph
19
+ end
20
+
21
+
22
+ get '/collectd' do
23
+ haml :collectd
24
+ end
25
+
26
+ # css
27
+
28
+ def self.dynamic_css(path)
29
+ get "/stylesheets/#{path}.css" do
30
+ content_type :css
31
+ scss "stylesheets/#{path}".to_sym
32
+ end
33
+ end
34
+
35
+ dynamic_css('available_rrds')
36
+ dynamic_css('graph')
37
+
38
+ end
@@ -0,0 +1,13 @@
1
+
2
+ list_rrd = (callback) ->
3
+ jQuery.get "/rrd", (o) ->
4
+ callback(o)
5
+
6
+ $ ->
7
+ list_rrd (data) ->
8
+ # $("#template").tmpl(data).appendTo("#target")
9
+ tmp = $("#template").tmpl(data)
10
+ tmp.appendTo("#data_list")
11
+ # $("#time").showTime( { div_hours: "h ", div_minutes: "m ", div_seconds: "s " } )
12
+ $(".time").timeago()
13
+
@@ -0,0 +1,48 @@
1
+
2
+ class window.TestGraph extends GraphDefinition
3
+ constructor: (container, host, @interface, ymin = null) ->
4
+ super(host, container, "Test Traffic (#{interface})", [ Format.size, Format.size ], ymin)
5
+
6
+ @graph.addSerie("#{@host}/interface/if_octets-#{@interface}", "rx", "(#{@interface}) Bytes Received")
7
+ @graph.addSerie("#{@host}/interface/if_octets-#{@interface}", "tx", "(#{@interface}) Bytes Sent", 2)
8
+
9
+
10
+
11
+ class CollectdPage extends GraphPage
12
+ constructor: (container, panel_container, host) ->
13
+ super(container, panel_container, host)
14
+
15
+ # @addGraph("NetworkGraph", "en0", 1 * Size.megabyte )
16
+ @addGraph("TestGraph", "en1", [20 * Size.kilobyte, 100 * Size.kilobyte ] )
17
+ @addGraph("MemoryGraph", "osx")
18
+ @addGraph("LoadGraph", 2.0)
19
+
20
+ $ ->
21
+ graphs = []
22
+
23
+ container = $("#graphs")
24
+ panel_container = $("#config_panel")
25
+
26
+ page = new CollectdPage(container, panel_container, "pomme.local")
27
+ # page.set_simple_interval(30)
28
+
29
+ $("#dateselect").datepicker().change ->
30
+ date_string = $(this).val()
31
+ time = Date.parse(date_string) / 1000
32
+
33
+ page.set_autorefresh(null)
34
+ page.set_interval(time, time + 24*60*60)
35
+
36
+ $("#rangeselect").chosen().change ->
37
+ page.set_autorefresh(null)
38
+ page.set_simple_interval( $(this).val() )
39
+
40
+ $("#linkedzoom").change (event) =>
41
+ if $(event.currentTarget).attr("checked")
42
+ page.refresh()
43
+
44
+ $("#autorefresh").change (event) =>
45
+ if $(event.currentTarget).attr("checked")
46
+ page.set_autorefresh(5000)
47
+ else
48
+ page.set_autorefresh(null)
@@ -0,0 +1,9 @@
1
+ require 'bundler/setup'
2
+ require 'rrd-grapher'
3
+
4
+ require File.expand_path('../app', __FILE__)
5
+
6
+ use RRDGrapher::RRDServer, :root_path => "/usr/local/var/lib/collectd/"
7
+ use RRDGrapher::ResourcesServer
8
+
9
+ run TestApp
@@ -0,0 +1 @@
1
+ javascripts/wijmo-open/