Skip to content

Instantly share code, notes, and snippets.

@tmm1
Created October 18, 2008 20:01
Show Gist options
  • Save tmm1/17730 to your computer and use it in GitHub Desktop.
Save tmm1/17730 to your computer and use it in GitHub Desktop.
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