-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
174 additions
and
122 deletions.
There are no files selected for viewing
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
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,3 +1,5 @@ | |||
require 'munin-ruby/version' | require 'munin-ruby/version' | ||
require 'munin-ruby/stat' | require 'munin-ruby/errors' | ||
require 'munin-ruby/parser' | |||
require 'munin-ruby/connection' | |||
require 'munin-ruby/node' | require 'munin-ruby/node' |
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
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,72 @@ | |||
require 'socket' | |||
|
|||
module Munin | |||
class Connection | |||
include Munin::Parser | |||
|
|||
attr_reader :host, :port | |||
|
|||
# Initialize a new connection to munin-node server | |||
# | |||
# host - Server host (default: 127.0.0.1) | |||
# port - Server port (default: 4949) | |||
# | |||
def initialize(host='127.0.0.1', port=4949) | |||
@host = host | |||
@port = port | |||
@socket = nil | |||
@connected = false | |||
end | |||
|
|||
# Returns true if socket is connected | |||
# | |||
def connected? | |||
@connected == true | |||
end | |||
|
|||
# Establish connection to the server | |||
# | |||
def connect | |||
begin | |||
@socket = TCPSocket.new(@host, @port) | |||
@socket.sync = true | |||
welcome = @socket.gets | |||
rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET => ex | |||
raise Munin::ConnectionError, ex.message | |||
rescue EOFError | |||
raise Munin::AccessDenied | |||
end | |||
end | |||
|
|||
# Close connection | |||
# | |||
def close | |||
@socket.close unless @socket.nil? | |||
end | |||
|
|||
# Send a string of data followed by a newline symbol | |||
# | |||
def send_data(str) | |||
connect unless connected? | |||
@socket.puts("#{str.strip}\n") | |||
end | |||
|
|||
# Reads a single line from socket | |||
# | |||
def read_line | |||
@socket.gets.strip | |||
end | |||
|
|||
# Reads a packet of data until '.' reached | |||
# | |||
def read_packet | |||
lines = [] | |||
while(str = @socket.readline) do | |||
break if str.strip == '.' | |||
lines << str.strip | |||
end | |||
parse_error(lines) | |||
lines | |||
end | |||
end | |||
end |
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
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,8 @@ | |||
module Munin | |||
class MuninError < StandardError ; end | |||
class ConnectionError < MuninError ; end | |||
class AccessDenied < MuninError ; end | |||
class InvalidResponse < MuninError ; end | |||
class UnknownService < MuninError ; end | |||
class BadExit < MuninError ; end | |||
end |
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
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,112 +1,55 @@ | |||
require 'socket' | |||
|
|||
module Munin | module Munin | ||
class SessionError < StandardError ; end | |||
class NoSuchService < StandardError ; end | |||
class AccessDenied < StandardError ; end | |||
|
|||
class Node | class Node | ||
attr_reader :host, :port | include Munin::Parser | ||
attr_reader :version, :services | |||
attr_reader :timestamp | |||
|
|
||
# Initialize a new Munin::Node object | attr_reader :connection | ||
|
|||
# Initialize a new Node instance | |||
# | # | ||
# host - Server hostname or IP address | # host - Server host | ||
# opts - Additional options. | # port - Server port | ||
# :port - Node server port (default to 4949) | |||
# :fetch - String or Array of service names ONLY to fetch | |||
# | # | ||
def initialize(host, opts={}) | def initialize(host='127.0.0.1', port=4949) | ||
@host = host | @connection = Munin::Connection.new(host, port) | ||
@port = opts[:port] || 4949 | |||
@stats = {} | |||
@services = [] | |||
@version = '' | |||
@only_services = opts[:fetch] || [] | |||
|
|||
if @only_services.kind_of?(Array) | |||
@only_services.uniq! | |||
elsif @only_services.kind_of?(String) | |||
@only_services = @only_services.scan(/[a-z\d\-\_]{1,}/i).uniq | |||
else | |||
@only_services = [] | |||
end | |||
|
|||
run | |||
end | end | ||
|
|
||
# Returns a set of parameters for the service | # Get a node version | ||
# | |||
# name - Service name | |||
# | |||
# @return [Munin::Stat] | |||
# | # | ||
def service(name) | def version | ||
if has_service?(name) | connection.send_data("version") | ||
@stats[name] | str = connection.read_line | ||
if str =~ /^munins node on/ | |||
str.split.last | |||
else | else | ||
raise Munin::NoSuchService, "Service with name #{name} does not exist." | raise InvalidResponse | ||
end | end | ||
end | end | ||
|
|
||
# Returns true if node has the service | # Get a list of all available metrics | ||
# | # | ||
# name - Service name | def list | ||
# | connection.send_data("list") | ||
def has_service?(name) | connection.read_line.split | ||
@stats.key?(name) | |||
end | end | ||
|
|
||
# Fetch multiple services at once | # Get a configuration information for service | ||
# | # | ||
# service_names - Array of service names to fetch | # service - Name of the service | ||
# | # | ||
def snapshot(service_names=[]) | def config(service) | ||
service_names.uniq.map { |n| service(n) } | connection.send_data("config #{service}") | ||
lines = connection.read_packet | |||
parse_config(lines) | |||
end | end | ||
|
|
||
private | # Get all service metrics values | ||
|
# | ||
# Fetch node information and stats | # service - Name of the service | ||
def run | # | ||
begin | |||
@timestamp = Time.now | |||
@socket = TCPSocket.new(@host, @port) | |||
@socket.sync = true ; @socket.gets | |||
fetch_version | |||
fetch_services | |||
@socket.close | |||
rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET => ex | |||
raise Munin::SessionError, ex.message | |||
rescue EOFError | |||
raise Munin::AccessDenied | |||
end | |||
end | |||
|
|||
# Fetch node server version | |||
def fetch_version | |||
@socket.puts("version") | |||
@version = @socket.readline.strip.split(' ').last | |||
end | |||
|
|||
# Fetch list of services and its stats | |||
def fetch_services | |||
@socket.puts("list") | |||
services = @socket.readline.split(' ').map { |s| s.strip }.sort | |||
services = services.select { |s| @only_services.include?(s) } unless @only_services.empty? | |||
services.each { |s| @services << s ; @stats[s] = fetch(s) } | |||
end | |||
|
|||
# Fetch service information | |||
def fetch(service) | def fetch(service) | ||
@socket.puts("fetch #{service}") | connection.send_data("fetch #{service}") | ||
content = [] | lines = connection.read_packet | ||
while(str = @socket.readline) do | parse_fetch(lines) | ||
break if str.strip == '.' | |||
content << str.strip.split(' ') | |||
end | |||
Stat.new(service, content) | |||
end | end | ||
end | end | ||
end | end |
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
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,57 @@ | |||
module Munin | |||
module Parser | |||
private | |||
|
|||
# Parse 'config' request | |||
# | |||
def parse_config(data) | |||
config = {:graph => {}, :metrics => {}} | |||
data.each do |l| | |||
if l =~ /^graph_/ | |||
key_name, value = l.scan(/^graph_([\w]+)\s(.*)/).flatten | |||
config[:graph][key_name] = value | |||
elsif l =~ /^[a-z]+\./ | |||
matches = l.scan(/^([a-z\d\-\_]+)\.([a-z\d\-\_]+)\s(.*)/).flatten | |||
config[:metrics][matches[0]] ||= {} | |||
config[:metrics][matches[0]][matches[1]] = matches[2] | |||
end | |||
end | |||
|
|||
# Now, lets process the args hash | |||
if config[:graph].key?('args') | |||
args = {} | |||
config[:graph]['args'].scan(/--([a-z\-\_]+)\s([\d]+)\s?/).each do |arg| | |||
args[arg.first] = arg.last | |||
end | |||
config[:graph]['args'] = args | |||
end | |||
|
|||
config | |||
end | |||
|
|||
# Parse 'fetch' request | |||
# | |||
def parse_fetch(data) | |||
process_data(data) | |||
end | |||
|
|||
def process_data(lines) | |||
data = {} | |||
lines.each do |line| | |||
line = line.split | |||
key = line.first.split('.value').first | |||
data[key] = line.last | |||
end | |||
data | |||
end | |||
|
|||
def parse_error(lines) | |||
if lines.size == 1 | |||
case lines.first | |||
when '# Unknown service' then raise UnknownService | |||
when '# Bad exit' then raise BadExit | |||
end | |||
end | |||
end | |||
end | |||
end |
This file was deleted.
Oops, something went wrong.
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
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,5 +1,5 @@ | |||
module Munin | module Munin | ||
unless defined?(::Munin::VERSION) | unless defined?(::Munin::VERSION) | ||
VERSION = '0.1.0' | VERSION = '0.2.0' | ||
end | end | ||
end | end |