Created
October 18, 2008 20:01
-
-
Save tmm1/17730 to your computer and use it in GitHub Desktop.
This file contains 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 ].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 = default | |
(@data_keys ||= []) << name | |
(@data[name] ||= {}).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 opts[:socket] | |
server = EM.start_server opts[:socket], self, node, opts | |
FileUtils.chmod 0777, opts[: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 | |
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{ | |
Graph::Server.start 'test.com', :port => 4949 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment