Created
February 22, 2009 06:19
-
-
Save tmm1/68361 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class ReactorLatency < Graph | |
| name 'reactor_latency' | |
| vlabel 'microseconds' | |
| scale 'no' | |
| category 'application' | |
| next_tick 'next_tick latency' | |
| timer 'timer latency' | |
| def self.fetch | |
| start = Time.now | |
| EM.add_timer(0){ | |
| diff = Time.now-start | |
| value :timer, "%f" % (diff*1_000_000) | |
| start = Time.now | |
| EM.next_tick{ | |
| diff = Time.now-start | |
| value :next_tick, "%f" % (diff*1_000_000) | |
| super | |
| } | |
| } | |
| end | |
| end | |
| EM.run{ | |
| # Run a munin node on port 4949. You must configure a munin master to poll this node for data. | |
| Graph::Server.start 'node.example.com', :port => 4949 | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class String | |
| def space_case | |
| gsub(/([a-z]|[A-Z]+)([A-Z])/){ "#{$1} #{$2}" } | |
| end | |
| def snake_case | |
| gsub(/\B[A-Z][^A-Z]/, '_\&').downcase.gsub(' ', '_') | |
| end | |
| end | |
| class Graph | |
| List = [] unless defined? List | |
| def self.inherited klass | |
| List << klass | |
| klass.instance_variable_set('@title', klass.to_s.space_case) | |
| klass.instance_variable_set('@data', {}) | |
| end | |
| def self.name n = nil | |
| if n | |
| @name = n | |
| else | |
| @name ||= to_s | |
| end | |
| end | |
| Attributes = %w[ title vlabel category info args order scale period ].map{|a| a.intern } unless defined? Attributes | |
| Attributes.each do |prop| | |
| class_eval %[ | |
| def self.#{prop} str = nil | |
| if str | |
| @#{prop} = str | |
| else | |
| @#{prop} | |
| end | |
| end | |
| ] | |
| end | |
| def self.config | |
| config = Attributes.inject('') do |attrs, prop| | |
| if val = __send__(prop) | |
| attrs << "graph_#{prop} #{val}\n" | |
| end | |
| attrs | |
| end | |
| @data_keys ||= [] | |
| @data ||= {} | |
| @data_keys.uniq.each do |key| | |
| @data[key].each do |type, setting| | |
| next if type == :value | |
| config << "#{key}.#{type} #{setting}\n" | |
| end | |
| end | |
| config | |
| end | |
| def self.default opts = nil | |
| if opts | |
| @default = opts | |
| else | |
| @default || {} | |
| end | |
| end | |
| def self.data name, desc, opts = {} | |
| (@data_keys ||= []) << name | |
| (@data[name] ||= {}).merge! default.merge(opts).merge(:label => desc) | |
| end | |
| class << self; alias :method_missing :data end | |
| def self.value name, val = nil | |
| if val | |
| @data[name][:value] = val | |
| else | |
| @data[name][:value] | |
| end | |
| end | |
| def self.fetch | |
| output = @data.inject('') do |attrs, (key, val)| | |
| attrs << "#{key}.value #{val[:value]}\n" if val[:value] | |
| attrs | |
| end | |
| yield output | |
| end | |
| end | |
| module Graph::Server | |
| def initialize node, opts | |
| @node, @settings = node, opts | |
| end | |
| def post_init | |
| set_comm_inactivity_timeout 250 | |
| send_data "# munin node at #{@node}\n" | |
| end | |
| def receive_data data | |
| (@buf ||= BufferedTokenizer.new).extract(data).each do |line| | |
| case line.strip | |
| when /^list/ | |
| send_data Graph::List.map{|g| g.name }.join(" ") + "\n" | |
| when /^config\s*(.*)/ | |
| if graph = Graph::List.find{|g| g.name == $1 } | |
| send_data graph.config | |
| else | |
| send_data "# Unknown service\n" | |
| end | |
| send_data ".\n" | |
| when /^fetch\s*(.*)/ | |
| if graph = Graph::List.find{|g| g.name == $1 } | |
| graph.fetch{ |data| | |
| send_data data | |
| send_data ".\n" | |
| } | |
| else | |
| send_data "# Unknown service\n" | |
| send_data ".\n" | |
| end | |
| when /^nodes/ | |
| send_data "#{@node}\n" | |
| send_data ".\n" | |
| when /^version/ | |
| send_data "munins node on #{@node} version: 1.2.5\n" | |
| when /^quit/ | |
| close_connection | |
| else | |
| send_data "# Unknown command. Try list, nodes, config, fetch, version or quit\n" | |
| end | |
| end | |
| end | |
| class Error < Exception; end | |
| def self.start node, opts = {} | |
| if socket = opts[:socket] | |
| FileUtils.rm socket if File.exist? socket | |
| at_exit{ FileUtils.rm socket if File.exist? socket } | |
| server = EM.start_server socket, self, node, opts | |
| FileUtils.chmod 0777, socket | |
| server | |
| elsif opts[:port] | |
| EM.start_server opts[:host] || 'localhost', opts[:port], self, node, opts | |
| else | |
| raise Error, 'no socket or port provided' | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
