riemann-client-0.2.3/0000755000175000017500000000000012410625222013643 5ustar debiandebianriemann-client-0.2.3/README.markdown0000644000175000017500000000343212410625222016346 0ustar debiandebianInstalling ========== gem install riemann-client Use === ``` ruby require 'riemann/client' # Create a client. Host, port and timeout are optional. c = Riemann::Client.new host: 'localhost', port: 5555, timeout: 5 # Send a simple event c << {service: 'testing', metric: 2.5} # Or a more complex one c << { host: 'web3', service: 'api latency', state: 'warn', metric: 63.5, description: "63.5 milliseconds per request", time: Time.now.to_i - 10 } # :host defaults to gethostname(). :time defaults to current unix time. You # can explicitly override host... c << {host: nil, service: 'the cloud', state: 'nebulous'} # Get all the states from the server c['true'] # Or specific states matching a query c['host =~ "%.dc1" and (state = "critical" or state = "warning")'] ``` Transports ========== Riemann::Client sends small events over UDP by default, and uses TCP for queries and large events. UDP sends are essentially "shouting into the void". They will not block your application and are roughly an order of magnitude faster than TCP, but you will not know if the server is down or encountered an error. You can specify what transport to use by selecting a subclient: ``` ruby c.udp << { :state "ok" } # => nil c.tcp << { :state "ok" } # => # c.tcp["true"] # => [#, ...] c.udp["true"] # => raise Riemann::Client::Unsupported ``` Client state management ======================= Riemann::Client provides some classes to make managing state updates easier. Riemann::MetricThread starts a thread to poll a metric periodically, which can be used to flush an accumulated value to ustate at regular intervals. Riemann::AutoState bundles a state and a client together. Any changes to the AutoState automatically send the new state to the client. riemann-client-0.2.3/metadata.yml0000644000175000017500000000451312410625222016151 0ustar debiandebian--- !ruby/object:Gem::Specification name: riemann-client version: !ruby/object:Gem::Version version: 0.2.3 platform: ruby authors: - Kyle Kingsbury autorequire: bindir: bin cert_chain: [] date: 2014-04-30 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: beefcake requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 0.3.5 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 0.3.5 - !ruby/object:Gem::Dependency name: trollop requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 1.16.2 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 1.16.2 - !ruby/object:Gem::Dependency name: mtrc requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 0.0.4 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 0.0.4 description: email: aphyr@aphyr.com executables: [] extensions: [] extra_rdoc_files: [] files: - lib/riemann.rb - lib/riemann/attribute.rb - lib/riemann/auto_state.rb - lib/riemann/client.rb - lib/riemann/client/tcp.rb - lib/riemann/client/tcp_socket.rb - lib/riemann/client/udp.rb - lib/riemann/event.rb - lib/riemann/message.rb - lib/riemann/metric_thread.rb - lib/riemann/query.rb - lib/riemann/state.rb - lib/riemann/version.rb - LICENSE - README.markdown homepage: https://github.com/aphyr/riemann-ruby-client licenses: [] metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 1.8.7 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: riemann-client rubygems_version: 2.0.14 signing_key: specification_version: 4 summary: Client for the distributed event system Riemann. test_files: [] riemann-client-0.2.3/lib/0000755000175000017500000000000012410625222014411 5ustar debiandebianriemann-client-0.2.3/lib/riemann.rb0000644000175000017500000000051712410625222016372 0ustar debiandebianmodule Riemann $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__)) require 'rubygems' require 'beefcake' require 'timeout' require 'riemann/version' require 'riemann/state' require 'riemann/attribute' require 'riemann/event' require 'riemann/query' require 'riemann/message' require 'riemann/client' end riemann-client-0.2.3/lib/riemann/0000755000175000017500000000000012410625222016042 5ustar debiandebianriemann-client-0.2.3/lib/riemann/event.rb0000644000175000017500000001321612410625222017513 0ustar debiandebianmodule Riemann class Event require 'set' include Beefcake::Message optional :time, :int64, 1 optional :state, :string, 2 optional :service, :string, 3 optional :host, :string, 4 optional :description, :string, 5 repeated :tags, :string, 7 optional :ttl, :float, 8 repeated :attributes, Attribute, 9 optional :metric_sint64, :sint64, 13 optional :metric_d, :double, 14 optional :metric_f, :float, 15 # Fields which don't really exist in protobufs, but which are reserved # and can't be used as attributes. VIRTUAL_FIELDS = Set.new([:metric]) # Fields which are specially encoded in the Event protobuf--that is, they # can't be used as attributes. RESERVED_FIELDS = fields.map do |i, field| field.name.to_sym end.reduce(VIRTUAL_FIELDS) do |set, field| set << field end # Average a set of states together. Chooses the mean metric, the mode # state, mode service, and the mean time. If init is provided, its values # override (where present) the computed ones. def self.average(states, init = Event.new) init = case init when Event init.dup else Event.new init end # Metric init.metric_f ||= states.inject(0.0) { |a, state| a + (state.metric || 0) } / states.size if init.metric_f.nan? init.metric_f = 0.0 end # Event init.state ||= mode states.map(&:state) init.service ||= mode states.map(&:service) # Time init.time = begin times = states.map(&:time).compact (times.inject(:+) / times.size).to_i rescue end init.time ||= Time.now.to_i init end # Sum a set of states together. Adds metrics, takes the mode state, mode # service and the mean time. If init is provided, its values override # (where present) the computed ones. def self.sum(states, init = Event.new) init = case init when Event init.dup else Event.new init end # Metric init.metric_f ||= states.inject(0.0) { |a, state| a + (state.metric || 0) } if init.metric_f.nan? init.metric_f = 0.0 end # Event init.state ||= mode states.map(&:state) init.service ||= mode states.map(&:service) # Time init.time = begin times = states.map(&:time).compact (times.inject(:+) / times.size).to_i rescue end init.time ||= Time.now.to_i init end # Finds the maximum of a set of states. Metric is the maximum. Event is the # highest, as defined by Dash.config.state_order. Time is the mean. def self.max(states, init = Event.new) init = case init when Event init.dup else Event.new init end # Metric init.metric_f ||= states.inject(0.0) { |a, state| a + (state.metric || 0) } if init.metric.nan? init.metric = 0.0 end # Event init.state ||= states.inject(nil) do |max, state| state.state if Dash.config[:state_order][state.state] > Dash.config[:state_order][max] end # Time init.time = begin times = states.map(&:time).compact (times.inject(:+) / times.size).to_i rescue end init.time ||= Time.now.to_i init end def self.mode(array) array.inject(Hash.new(0)) do |counts, e| counts[e] += 1 counts end.sort_by { |e, count| count }.last.first rescue nil end # Partition a list of states by a field # Returns a hash of field_value => state def self.partition(states, field) states.inject({}) do |p, state| k = state.send field if p.include? k p[k] << state else p[k] = [state] end p end end # Sorts states by a field. nil values first. def self.sort(states, field) states.sort do |a, b| a = a.send field b = b.send field if a.nil? -1 elsif b.nil? 1 else a <=> b end end end def initialize(hash = nil) if hash if hash[:metric] super hash self.metric = hash[:metric] else super hash end # Add extra attributes to the event as Attribute instances with values # converted to String self.attributes = hash.map do |key, value| unless RESERVED_FIELDS.include? key.to_sym Attribute.new(:key => key.to_s, :value => (hash[key] || hash[key.to_sym]).to_s) end end.compact else super() end @time ||= Time.now.to_i end def metric metric_d || metric_sint64 || metric_f end def metric=(m) if Integer === m and (-(2**63)...2**63) === m # Long self.metric_sint64 = m self.metric_f = m.to_f else self.metric_d = m.to_f self.metric_f = m.to_f end end # Look up attributes def [](k) if RESERVED_FIELDS.include? k.to_sym super else r = attributes.find {|a| a.key.to_s == k.to_s }.value end end # Set attributes def []=(k, v) if RESERVED_FIELDS.include? k.to_sym super else a = self.attributes.find {|a| a.key == k.to_s } if(a) a.value = v.to_s else self.attributes << Attribute.new(:key => k.to_s, :value => v.to_s) end end end end end riemann-client-0.2.3/lib/riemann/state.rb0000644000175000017500000000103312410625222017504 0ustar debiandebianmodule Riemann class State include Beefcake::Message optional :time, :int64, 1 optional :state, :string, 2 optional :service, :string, 3 optional :host, :string, 4 optional :description, :string, 5 optional :once, :bool, 6 repeated :tags, :string, 7 optional :ttl, :float, 8 optional :metric_f, :float, 15 def initialize(*a) super *a @time ||= Time.now.to_i end def metric @metric || metric_f end def metric=(m) @metric = m end end end riemann-client-0.2.3/lib/riemann/client/0000755000175000017500000000000012410625222017320 5ustar debiandebianriemann-client-0.2.3/lib/riemann/client/tcp_socket.rb0000644000175000017500000002527212410625222022013 0ustar debiandebianrequire 'socket' require 'fcntl' module Riemann class Client # Socket: A specialized socket that has been configure class TcpSocket class Error < Riemann::Client::Error; end class Timeout < Error; end # Internal: # The timeout for reading in seconds. Defaults to 2 attr_accessor :read_timeout # Internal: # The timeout for connecting in seconds. Defaults to 2 attr_reader :connect_timeout # Internal: # The timeout for writing in seconds. Defaults to 2 attr_reader :write_timeout # Internal: # The host this socket is connected to attr_reader :host # Internal: # The port this socket is connected to attr_reader :port # Internal # # Used for setting TCP_KEEPIDLE: overrides tcp_keepalive_time for a single # socket. # # http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html # # tcp_keepalive_time: # # The interval between the last data packet sent (simple ACKs are not # considered data) and the first keepalive probe; after the connection is # marked to need keepalive, this counter is not used any further. attr_reader :keepalive_idle # Internal # # Used for setting TCP_KEEPINTVL: overrides tcp_keepalive_intvl for a single # socket. # # http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html # # tcp_keepalive_intvl: # # The interval between subsequential keepalive probes, regardless of what # the connection has exchanged in the meantime. attr_reader :keepalive_interval # Internal # # Used for setting TCP_KEEPCNT: overrides tcp_keepalive_probes for a single # socket. # # http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html # # tcp_keepalive_probes: # # The number of unacknowledged probes to send before considering the # connection dead and notifying the application layer. attr_reader :keepalive_count # Internal: Create and connect to the given location. # # options, same as Constructor # # Returns an instance of KJess::Socket def self.connect(options = {}) s = new(options) s.connect return s end # Internal: Creates a new KJess::Socket def initialize( options = {} ) @host = options[:host] @port = options[:port] @connect_timeout = options[:connect_timeout] || options[:timeout] || 2 @read_timeout = options[:read_timeout] || options[:timeout] || 2 @write_timeout = options[:write_timeout] || options[:timeout] || 2 @keepalive_active = options.fetch(:keepalive_active, true) @keepalive_idle = options[:keepalive_idle] || 60 @keepalive_interval = options[:keepalive_interval] || 30 @keepalive_count = options[:keepalive_count] || 5 @socket = nil end # Internal: Return whether or not the keepalive_active flag is set. def keepalive_active? @keepalive_active end # Internal: Low level socket allocation and option configuration # # Using the options from the initializer, a new ::Socket is created that # is: # # TCP, IPv4 only, autoclosing on exit, nagle's algorithm is disabled and has # TCP Keepalive options set if keepalive is supported. # # Returns a new ::Socket instance def blank_socket sock = ::Socket.new(::Socket::AF_INET, ::Socket::SOCK_STREAM, 0) # close file descriptors if we exec sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) # Disable Nagle's algorithm sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1) if using_keepalive? then sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE , true) sock.setsockopt(::Socket::SOL_TCP, ::Socket::TCP_KEEPIDLE , keepalive_idle) sock.setsockopt(::Socket::SOL_TCP, ::Socket::TCP_KEEPINTVL, keepalive_interval) sock.setsockopt(::Socket::SOL_TCP, ::Socket::TCP_KEEPCNT , keepalive_count) end return sock end # Internal: Return the connected raw Socket. # # If the socket is closed or non-existent it will create and connect again. # # Returns a ::Socket def socket return @socket unless closed? @socket ||= connect() end # Internal: Closes the internal ::Socket # # Returns nothing def close @socket.close unless closed? @socket = nil end # Internal: Return true the socket is closed. def closed? return true if @socket.nil? return true if @socket.closed? return false end # Internal: # # Connect to the remote host in a non-blocking fashion. # # Raise Error if there is a failure connecting. # # Return the ::Socket on success def connect # Calculate our timeout deadline deadline = Time.now.to_f + connect_timeout # Lookup destination address, we only want IPv4 , TCP addrs = ::Socket.getaddrinfo(host, port, ::Socket::AF_INET, ::Socket::SOCK_STREAM ) errors = [] conn_error = lambda { raise errors.first } sock = nil addrs.find( conn_error ) do |addr| sock = connect_or_error( addr, deadline, errors ) end return sock end # Internal: Connect to the destination or raise an error. # # Connect to the address or capture the error of the connection # # addr - An address returned from Socket.getaddrinfo() # deadline - the after which we should raise a timeout error # errors - a collection of errors to append an error too should we have one. # # Make an attempt to connect to the given address. If it is successful, # return the socket. # # Should the connection fail, append the exception to the errors array and # return false. # def connect_or_error( addr, deadline, errors ) timeout = deadline - Time.now.to_f raise Timeout, "Could not connect to #{host}:#{port}" if timeout <= 0 return connect_nonblock( addr, timeout ) rescue Error => e errors << e return false end # Internal: Connect to the give address within the timeout. # # Make an attempt to connect to a single address within the given timeout. # # Return the ::Socket when it is connected, or raise an Error if no # connection was possible. def connect_nonblock( addr, timeout ) sockaddr = ::Socket.pack_sockaddr_in(addr[1], addr[3]) sock = blank_socket() sock.connect_nonblock( sockaddr ) return sock rescue Errno::EINPROGRESS if IO.select(nil, [sock], nil, timeout).nil? sock.close rescue nil raise Timeout, "Could not connect to #{host}:#{port} within #{timeout} seconds" end return connect_nonblock_finalize( sock, sockaddr ) rescue => ex sock.close rescue nil raise Error, "Could not connect to #{host}:#{port}: #{ex.class}: #{ex.message}", ex.backtrace end # Internal: Make sure that a non-blocking connect has truely connected. # # Ensure that the given socket is actually connected to the given adddress. # # Returning the socket if it is and raising an Error if it isn't. def connect_nonblock_finalize( sock, sockaddr ) sock.connect_nonblock( sockaddr ) return sock rescue Errno::EISCONN return sock rescue => ex sock.close rescue nil raise Error, "Could not connect to #{host}:#{port}: #{ex.class}: #{ex.message}", ex.backtrace end # Internal: say if we are using TCP Keep Alive or not # # We will return true if the initialization options :keepalive_active is # set to true, and if all the constants that are necessary to use TCP keep # alive are defined. # # It may be the case that on some operating systems that the constants are # not defined, so in that case we do not want to attempt to use tcp keep # alive if we are unable to do so in any case. # # Returns true or false def using_keepalive? using = false if keepalive_active? then using = [ :SOL_SOCKET, :SO_KEEPALIVE, :SOL_TCP, :TCP_KEEPIDLE, :TCP_KEEPINTVL, :TCP_KEEPCNT].all? do |c| ::Socket.const_defined? c end end return using end # Reads length bytes from the socket # # length - the number of bytes to read from the socket # outbuf - an optional buffer to store the bytes in # # Returns the bytes read if no outbuf is specified def read(length, outbuf = nil) if outbuf outbuf.replace('') buf = outbuf else buf = '' end while buf.length < length unless rb = readpartial(length - buf.length) break end buf << rb end return buf end # Internal: Read up to a maxlen of data from the socket and store it in outbuf # # maxlen - the maximum number of bytes to read from the socket # outbuf - the buffer in which to store the bytes. # # Returns the bytes read def readpartial(maxlen, outbuf = nil) return socket.read_nonblock(maxlen, outbuf) rescue Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::ECONNRESET if wait_readable(read_timeout) retry else raise Timeout, "Could not read from #{host}:#{port} in #{read_timeout} seconds" end end # Internal: Write the given data to the socket # # buf - the data to write to the socket. # # Raises an error if it is unable to write the data to the socket within the # write_timeout. # # returns nothing def write(buf) until buf.nil? or (buf.length == 0) do written = socket.write_nonblock(buf) buf = buf[written, buf.length] end rescue Errno::EWOULDBLOCK, Errno::EINTR, Errno::EAGAIN, Errno::ECONNRESET if wait_writable(write_timeout) retry else raise Timeout, "Could not write to #{host}:#{port} in #{write_timeout} seconds" end end def wait_writable(timeout = nil) IO.select(nil, [@socket], nil, timeout || write_timeout) end def wait_readable(timeout = nil) IO.select([@socket], nil, nil, timeout || read_timeout) end end end endriemann-client-0.2.3/lib/riemann/client/udp.rb0000644000175000017500000000325212410625222020437 0ustar debiandebianmodule Riemann class Client class UDP < Client MAX_SIZE = 16384 attr_accessor :host, :port, :socket, :max_size def initialize(opts = {}) @host = opts[:host] || HOST @port = opts[:port] || PORT @max_size = opts[:max_size] || MAX_SIZE @locket = Mutex.new end def connect @socket = UDPSocket.new end def close @locket.synchronize do @socket.close end end def connected? !!@socket && @socket.closed? end # Read a message from a stream def read_message(s) raise Unsupported end def send_recv(*a) raise Unsupported end def send_maybe_recv(message) with_connection do |s| x = message.encode '' unless x.length < @max_size raise TooBig end s.send(x, 0, @host, @port) nil end end # Yields a connection in the block. def with_connection tries = 0 @locket.synchronize do begin tries += 1 yield(@socket || connect) rescue IOError => e raise if tries > 3 connect and retry rescue Errno::EPIPE => e raise if tries > 3 connect and retry rescue Errno::ECONNREFUSED => e raise if tries > 3 connect and retry rescue Errno::ECONNRESET => e raise if tries > 3 connect and retry rescue InvalidResponse => e raise if tries > 3 connect and retry end end end end end end riemann-client-0.2.3/lib/riemann/client/tcp.rb0000644000175000017500000000470012410625222020434 0ustar debiandebianrequire 'monitor' require 'riemann/client/tcp_socket' module Riemann class Client class TCP < Client attr_accessor :host, :port, :socket # Public: Set a socket factory -- an object responding # to #call(options) that returns a Socket object def self.socket_factory=(factory) @socket_factory = factory end # Public: Return a socket factory def self.socket_factory @socket_factory || proc { |options| TcpSocket.connect(options) } end def initialize(options = {}) @options = options @locket = Monitor.new end def socket @locket.synchronize do if @pid && @pid != Process.pid close end if @socket and not @socket.closed? return @socket end @socket = self.class.socket_factory.call(@options) @pid = Process.pid return @socket end end def close @locket.synchronize do if @socket && !@socket.closed? @socket.close end @socket = nil end end def connected? !@socket && @socket.closed? end # Read a message from a stream def read_message(s) if buffer = s.read(4) and buffer.size == 4 length = buffer.unpack('N').first begin str = s.read length message = Riemann::Message.decode str rescue => e puts "Message was #{str.inspect}" raise end unless message.ok puts "Failed" raise ServerError, message.error end message else raise InvalidResponse, "unexpected EOF" end end def send_recv(message) with_connection do |s| s.write(message.encode_with_length) read_message(s) end end alias send_maybe_recv send_recv # Yields a connection in the block. def with_connection tries = 0 @locket.synchronize do begin tries += 1 yield(socket) rescue IOError, Errno::EPIPE, Errno::ECONNREFUSED, InvalidResponse, Timeout::Error, Riemann::Client::TcpSocket::Error close raise if tries > 3 retry rescue Exception close raise end end end end end end riemann-client-0.2.3/lib/riemann/auto_state.rb0000644000175000017500000000462412410625222020545 0ustar debiandebianmodule Riemann class AutoState # Binds together a state hash and a Client. Any change made here # sends the state to the client. Useful when updates to a state are made # decoherently, e.g. across many methods. Combine with MetricThread (or # just Thread.new { loop { autostate.flush; sleep n } }) to ensure regular # updates. # # example: # # class Job # def initialize # @state = AutoState.new # @state.service = 'job' # @state.state = 'starting up' # # run # end # # def run # loop do # begin # a # b # rescue Exception => e # @state.once( # state: 'error', # description: e.to_s # ) # end # end # end # # def a # @state.state = 'heavy lifting a' # ... # end # # def b # @state.state = 'heavy lifting b' # ... # end def initialize(client = Client.new, state = {}) @client = client @state = state end def description=(description) @state[:description] = description flush end def description @state[:description] end # Send state to client def flush @state[:time] = Time.now.to_i @client << @state end def host=(host) @state[:host] = host flush end def host @state[:host] end def metric=(metric) @state[:metric] = metric flush end alias metric_f= metric= def metric @state[:metric] end alias metric_f metric # Performs multiple updates, followed by flush. # Example: merge state: critical, metric_f: 10235.3 def merge(opts) @state.merge! opts flush end alias << merge # Issues an immediate update of the state with tag "once" # set, but does not update the local state. Useful for transient errors. # Opts are merged with the state. def once(opts) o = @state.merge opts o[:time] = Time.now.to_i o[:tags] = ((o[:tags] | ["once"]) rescue ["once"]) @client << o end def state=(state) @state[:state] = state flush end def state @state[:state] end def service=(service) @state[:service] = service flush end def service @state[:service] end end end riemann-client-0.2.3/lib/riemann/metric_thread.rb0000644000175000017500000000220212410625222021175 0ustar debiandebianclass Riemann::MetricThread # A metric thread is simple: it wraps some metric object which responds to <<, # and every interval seconds, calls #flush which replaces the object and calls # a user specified function. INTERVAL = 10 attr_accessor :interval attr_accessor :metric # client = Riemann::Client.new # m = MetricThread.new Mtrc::Rate do |rate| # client << rate # end # # loop do # sleep rand # m << rand # end def initialize(klass, *klass_args, &f) @klass = klass @klass_args = klass_args @f = f @interval = INTERVAL @metric = new_metric start end def <<(*a) @metric.<<(*a) end def new_metric @klass.new *@klass_args end def flush old, @metric = @metric, new_metric @f[old] end def start raise RuntimeError, "already running" if @runner @running = true @runner = Thread.new do while @running sleep @interval begin flush rescue Exception => e end end @runner = nil end end def stop stop! @runner.join end def stop! @running = false end end riemann-client-0.2.3/lib/riemann/message.rb0000644000175000017500000000055012410625222020013 0ustar debiandebianmodule Riemann class Message include Beefcake::Message optional :ok, :bool, 2 optional :error, :string, 3 repeated :states, State, 4 optional :query, Query, 5 repeated :events, Event, 6 def encode_with_length buffer = '' encoded = encode buffer "#{[encoded.length].pack('N')}#{encoded}" end end end riemann-client-0.2.3/lib/riemann/version.rb0000644000175000017500000000004712410625222020055 0ustar debiandebianmodule Riemann VERSION = '0.2.3' end riemann-client-0.2.3/lib/riemann/attribute.rb0000644000175000017500000000021012410625222020363 0ustar debiandebianmodule Riemann class Attribute include Beefcake::Message required :key, :string, 1 optional :value, :string, 2 end end riemann-client-0.2.3/lib/riemann/query.rb0000644000175000017500000000015212410625222017532 0ustar debiandebianmodule Riemann class Query include Beefcake::Message optional :string, :string, 1 end end riemann-client-0.2.3/lib/riemann/client.rb0000644000175000017500000000354612410625222017655 0ustar debiandebianrequire 'riemann' class Riemann::Client class Error < RuntimeError; end class InvalidResponse < Error; end class ServerError < Error; end class Unsupported < Error; end class TooBig < Unsupported; end require 'thread' require 'socket' require 'time' HOST = '127.0.0.1' PORT = 5555 TIMEOUT = 5 require 'riemann/client/tcp' require 'riemann/client/udp' attr_reader :tcp, :udp def initialize(opts = {}) @options = opts.dup @options[:host] ||= HOST @options[:port] ||= PORT @options[:timeout] ||= TIMEOUT @udp = UDP.new(@options) @tcp = TCP.new(@options) end def host @options[:host] end def port @options[:port] end def timeout @options[:timeout] end # Send a state def <<(event_opts) # Create state case event_opts when Riemann::State event = event_opts when Riemann::Event event = event_opts else unless event_opts.include? :host event_opts[:host] = Socket.gethostname end event = Riemann::Event.new(event_opts) end message = Riemann::Message.new :events => [event] # Transmit send_maybe_recv message end # Returns an array of states matching query. def [](query) response = query(query) (response.events || []) | (response.states || []) end # Close both UDP and TCP sockets. def close @udp.close @tcp.close end # Connect both UDP and TCP sockets. def connect udp.connect tcp.connect end def connected? tcp.connected? and udp.connected? end # Ask for states def query(string = "true") send_recv Riemann::Message.new(:query => Riemann::Query.new(:string => string)) end def send_recv(*a) @tcp.send_recv *a end def send_maybe_recv(*a) begin @udp.send_maybe_recv *a rescue TooBig @tcp.send_maybe_recv *a end end end riemann-client-0.2.3/LICENSE0000644000175000017500000000206312410625222014651 0ustar debiandebianThe MIT License Copyright (c) 2011 Kyle Kingsbury Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.