haproxy-decklin 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/Gemfile +8 -0
- data/README.md +133 -0
- data/Rakefile +2 -0
- data/haproxy.gemspec +21 -0
- data/lib/haproxy.rb +21 -0
- data/lib/haproxy/csv_parser.rb +32 -0
- data/lib/haproxy/socket_reader.rb +94 -0
- data/lib/haproxy/stats_reader.rb +51 -0
- data/lib/haproxy/version.rb +3 -0
- data/spec/haproxy_spec.rb +6 -0
- data/spec/socket_reader_spec.rb +59 -0
- data/spec/spec_helper.rb +114 -0
- metadata +63 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# HAProxy RubyGem
|
|
2
|
+
|
|
3
|
+
This gem aims to provide an interface to query HAProxy for statistics,
|
|
4
|
+
and eventually management through the sockets API.
|
|
5
|
+
|
|
6
|
+
## What's HAProxy?
|
|
7
|
+
|
|
8
|
+
[HAProxy](http://haproxy.1wt.eu/) is the _Reliable, High Performance
|
|
9
|
+
TCP/HTTP Load Balancer_.
|
|
10
|
+
|
|
11
|
+
## Why this gem?
|
|
12
|
+
|
|
13
|
+
* I use HAProxy at my work.
|
|
14
|
+
* I wanted to know how to create gems.
|
|
15
|
+
* I wanted to contribute with OSS.
|
|
16
|
+
* Why not?
|
|
17
|
+
* All of the above.
|
|
18
|
+
|
|
19
|
+
## Example of use
|
|
20
|
+
|
|
21
|
+
#! /usr/bin/env ruby
|
|
22
|
+
require 'haproxy'
|
|
23
|
+
require 'pp'
|
|
24
|
+
|
|
25
|
+
haproxy = HAProxy.read_stats '/path/to/haproxy.stats.socket'
|
|
26
|
+
|
|
27
|
+
pp haproxy.info
|
|
28
|
+
|
|
29
|
+
# {:name=>"HAProxy",
|
|
30
|
+
# :version=>"1.3.22",
|
|
31
|
+
# :release_date=>"2009/10/14",
|
|
32
|
+
# :nbproc=>"1",
|
|
33
|
+
# :process_num=>"1",
|
|
34
|
+
# :pid=>"10222",
|
|
35
|
+
# :uptime=>"0d 0h33m12s",
|
|
36
|
+
# :uptime_sec=>"1992",
|
|
37
|
+
# :memmax_mb=>"0",
|
|
38
|
+
# :ulimit_n=>"4013",
|
|
39
|
+
# :maxsock=>"4013",
|
|
40
|
+
# :maxconn=>"2000",
|
|
41
|
+
# :maxpipes=>"0",
|
|
42
|
+
# :currconns=>"1",
|
|
43
|
+
# :pipesused=>"0",
|
|
44
|
+
# :pipesfree=>"0",
|
|
45
|
+
# :tasks=>"1",
|
|
46
|
+
# :run_queue=>"1",
|
|
47
|
+
# :node=>"roke",
|
|
48
|
+
# :"description:"=>nil}
|
|
49
|
+
|
|
50
|
+
pp haproxy.stats
|
|
51
|
+
|
|
52
|
+
# [{:pxname=>"app1",
|
|
53
|
+
# :svname=>"thin1",
|
|
54
|
+
# :qcur=>"0",
|
|
55
|
+
# :qmax=>"0",
|
|
56
|
+
# :scur=>"0",
|
|
57
|
+
# :smax=>"0",
|
|
58
|
+
# :slim=>"",
|
|
59
|
+
# :stot=>"0",
|
|
60
|
+
# :bin=>"0",
|
|
61
|
+
# :bout=>"0",
|
|
62
|
+
# :dreq=>"",
|
|
63
|
+
# :dresp=>"0",
|
|
64
|
+
# :ereq=>"",
|
|
65
|
+
# :econ=>"0",
|
|
66
|
+
# :eresp=>"0",
|
|
67
|
+
# :wretr=>"0",
|
|
68
|
+
# :wredis=>"0",
|
|
69
|
+
# :status=>"no check",
|
|
70
|
+
# :weight=>"1",
|
|
71
|
+
# :act=>"1",
|
|
72
|
+
# :bck=>"0",
|
|
73
|
+
# :chkfail=>"",
|
|
74
|
+
# :chkdown=>"",
|
|
75
|
+
# :lastchg=>"",
|
|
76
|
+
# :downtime=>"",
|
|
77
|
+
# :qlimit=>"",
|
|
78
|
+
# :pid=>"1",
|
|
79
|
+
# :iid=>"1",
|
|
80
|
+
# :sid=>"1",
|
|
81
|
+
# :throttle=>"",
|
|
82
|
+
# :lbtot=>"0",
|
|
83
|
+
# :tracked=>"",
|
|
84
|
+
# :type=>"2",
|
|
85
|
+
# :rate=>"0",
|
|
86
|
+
# :rate_lim=>"",
|
|
87
|
+
# :rate_max=>"0"},...]
|
|
88
|
+
|
|
89
|
+
#### HAProxy sample configuration
|
|
90
|
+
|
|
91
|
+
global
|
|
92
|
+
stats socket haproxy
|
|
93
|
+
|
|
94
|
+
defaults
|
|
95
|
+
mode http
|
|
96
|
+
option httplog
|
|
97
|
+
option httpclose
|
|
98
|
+
retries 3
|
|
99
|
+
option redispatch
|
|
100
|
+
maxconn 2000
|
|
101
|
+
contimeout 5000
|
|
102
|
+
clitimeout 50000
|
|
103
|
+
srvtimeout 50000
|
|
104
|
+
stats uri /haproxy
|
|
105
|
+
|
|
106
|
+
listen app1 0.0.0.0:10000
|
|
107
|
+
balance roundrobin
|
|
108
|
+
|
|
109
|
+
server thin1 127.0.0.1:10001
|
|
110
|
+
server thin1 127.0.0.1:10002
|
|
111
|
+
server thin1 127.0.0.1:10003
|
|
112
|
+
server thin1 127.0.0.1:10004
|
|
113
|
+
server thin1 127.0.0.1:10005
|
|
114
|
+
|
|
115
|
+
frontend app2
|
|
116
|
+
bind 0.0.0.0:10011
|
|
117
|
+
default_backend app2
|
|
118
|
+
|
|
119
|
+
backend app2
|
|
120
|
+
balance roundrobin
|
|
121
|
+
server thin1 127.0.0.1:10006
|
|
122
|
+
server thin1 127.0.0.1:10007
|
|
123
|
+
server thin1 127.0.0.1:10008
|
|
124
|
+
server thin1 127.0.0.1:10009
|
|
125
|
+
server thin1 127.0.0.1:10010
|
|
126
|
+
|
|
127
|
+
## Roadmap
|
|
128
|
+
|
|
129
|
+
* Improve documentation
|
|
130
|
+
* Improve CSV parsing
|
|
131
|
+
* Add tests
|
|
132
|
+
* Add examples
|
|
133
|
+
* Read stats from HTTP and CSV files
|
data/Rakefile
ADDED
data/haproxy.gemspec
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# -*- mode: ruby; encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "haproxy/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "haproxy-decklin"
|
|
7
|
+
s.version = HAProxy::VERSION
|
|
8
|
+
s.platform = Gem::Platform::RUBY
|
|
9
|
+
s.authors = ["Leandro López (inkel)"]
|
|
10
|
+
s.email = ["inkel.ar@gmail.com"]
|
|
11
|
+
s.homepage = "https://github.com/inkel/haproxy-ruby"
|
|
12
|
+
s.summary = 'HAProxy interface for reading statistics or managing servers (requires HAProxy 1.4+)'
|
|
13
|
+
s.description = 'This gem is intended for use as a HAProxy interface when you need to read statistics or if you like to manage proxies thru Ruby'
|
|
14
|
+
|
|
15
|
+
s.rubyforge_project = "haproxy"
|
|
16
|
+
|
|
17
|
+
s.files = `git ls-files`.split("\n")
|
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
20
|
+
s.require_paths = ["lib"]
|
|
21
|
+
end
|
data/lib/haproxy.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
libdir = File.dirname(__FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|
3
|
+
|
|
4
|
+
require 'uri'
|
|
5
|
+
Dir["#{libdir}/haproxy/*.rb"].each do |file|
|
|
6
|
+
require file
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module HAProxy
|
|
10
|
+
|
|
11
|
+
def self.read_stats(from)
|
|
12
|
+
uri = URI.parse(from)
|
|
13
|
+
|
|
14
|
+
if uri.is_a?(URI::Generic) and File.socket?(uri.path)
|
|
15
|
+
HAProxy::SocketReader.new(uri.path)
|
|
16
|
+
else
|
|
17
|
+
raise NotImplementedError, "Currently only sockets are implemented"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module HAProxy
|
|
2
|
+
class CSVParser
|
|
3
|
+
|
|
4
|
+
# Uses CSV header from HAProxy 1.5, which is backwards compatible
|
|
5
|
+
COLUMNS = "pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,dresp,ereq,econ,eresp,wretr,wredis,status,weight,act,bck,chkfail,chkdown,lastchg,downtime,qlimit,pid,iid,sid,throttle,lbtot,tracked,type,rate,rate_lim,rate_max,check_status,check_code,check_duration,hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail,req_rate,req_rate_max,req_tot,cli_abrt,srv_abrt".split(",").map(&:to_sym)
|
|
6
|
+
LIMIT = COLUMNS.length
|
|
7
|
+
|
|
8
|
+
def self.parse(line)
|
|
9
|
+
line.strip!
|
|
10
|
+
unless line.start_with? "#"
|
|
11
|
+
data = line.split(',')
|
|
12
|
+
pxname = data.shift
|
|
13
|
+
|
|
14
|
+
stats = { :pxname => pxname }
|
|
15
|
+
|
|
16
|
+
data.each_with_index do |value, i|
|
|
17
|
+
if i < LIMIT
|
|
18
|
+
stats[COLUMNS[i + 1]] = value
|
|
19
|
+
else
|
|
20
|
+
stats[:extra] = Array.new if stats[:extra].nil?
|
|
21
|
+
stats[:extra] << value
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
stats
|
|
26
|
+
else
|
|
27
|
+
raise ArgumentError, "Line is a comment"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
require 'socket'
|
|
2
|
+
require 'haproxy/stats_reader'
|
|
3
|
+
require 'haproxy/csv_parser'
|
|
4
|
+
|
|
5
|
+
module HAProxy
|
|
6
|
+
class SocketReader < HAProxy::StatsReader
|
|
7
|
+
|
|
8
|
+
def initialize(path)
|
|
9
|
+
raise ArgumentError, "Socket #{path} doesn't exists or is not a UNIX socket" unless File.exists?(path) and File.socket?(path)
|
|
10
|
+
@path = path
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def info
|
|
14
|
+
returning({}) do |info|
|
|
15
|
+
send_cmd "show info" do |line|
|
|
16
|
+
key, value = line.split(': ')
|
|
17
|
+
info[key.downcase.gsub('-', '_').to_sym] = value
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def errors
|
|
23
|
+
returning("") do |errors|
|
|
24
|
+
send_cmd "show errors" do |line|
|
|
25
|
+
errors << line
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def sessions
|
|
31
|
+
returning([]) do |sess|
|
|
32
|
+
send_cmd "show sess" do |line|
|
|
33
|
+
sess << line
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
TYPES = {
|
|
39
|
+
:frontend => 1,
|
|
40
|
+
:backend => 2,
|
|
41
|
+
:server => 4
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
def stats(types=[:all], options={})
|
|
45
|
+
params = {
|
|
46
|
+
:proxy => :all,
|
|
47
|
+
:server => :all
|
|
48
|
+
}.merge(options)
|
|
49
|
+
|
|
50
|
+
params[:proxy] = "-1" if params[:proxy].eql?(:all)
|
|
51
|
+
params[:server] = "-1" if params[:server].eql?(:all)
|
|
52
|
+
|
|
53
|
+
types = [types] unless types.is_a?(Array)
|
|
54
|
+
|
|
55
|
+
params[:type] = case
|
|
56
|
+
when types.eql?([:all])
|
|
57
|
+
"-1"
|
|
58
|
+
else
|
|
59
|
+
types.map{ |type| TYPES[type] }.inject(:+)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
cmd = "show stat #{params[:proxy]} #{params[:type]} #{params[:server]}"
|
|
63
|
+
|
|
64
|
+
returning([]) do |stats|
|
|
65
|
+
send_cmd(cmd) do |line|
|
|
66
|
+
stats << CSVParser.parse(line) unless line.start_with?('#')
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def frontends
|
|
72
|
+
stats :frontend, :proxy => :all, :server => :all
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def backends
|
|
76
|
+
stats :frontend, :proxy => :all, :server => :all
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def servers
|
|
80
|
+
stats :server, :proxy => :all, :server => :all
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
protected
|
|
84
|
+
|
|
85
|
+
def send_cmd(cmd, &block)
|
|
86
|
+
socket = UNIXSocket.new(@path)
|
|
87
|
+
socket.write(cmd + ';')
|
|
88
|
+
socket.each do |line|
|
|
89
|
+
yield(line.strip)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
libdir = File.dirname(__FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|
3
|
+
|
|
4
|
+
module HAProxy
|
|
5
|
+
|
|
6
|
+
class StatsReader
|
|
7
|
+
|
|
8
|
+
def info
|
|
9
|
+
raise NotImplementedError
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def errors
|
|
13
|
+
raise NotImplementedError
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def sessions
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def stats
|
|
21
|
+
raise NotImplementedError
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def frontends
|
|
25
|
+
raise NotImplementedError
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def backends
|
|
29
|
+
raise NotImplementedError
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def servers
|
|
33
|
+
raise NotImplementedError
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
protected
|
|
37
|
+
|
|
38
|
+
# Borrowed from Rails 3
|
|
39
|
+
def returning(value)
|
|
40
|
+
yield(value)
|
|
41
|
+
value
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def initialize
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require File.expand_path('../spec_helper.rb', __FILE__)
|
|
2
|
+
require File.expand_path('../../lib/haproxy', __FILE__)
|
|
3
|
+
|
|
4
|
+
describe HAProxy::SocketReader do
|
|
5
|
+
|
|
6
|
+
it "should accept an existing socket file" do
|
|
7
|
+
HAProxy::Test.with_socket do |path|
|
|
8
|
+
HAProxy::SocketReader.new(path).should_not be_nil
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should fail without an existing socket file" do
|
|
13
|
+
Tempfile.new('invalid-file') do |file|
|
|
14
|
+
file.path.should_not be_socket
|
|
15
|
+
HAProxy::SocketReader.new(file.path).should_raise ArgumentError
|
|
16
|
+
end.close!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should return a Hash with proxy information" do
|
|
20
|
+
HAProxy::Test.with_socket(:info) do |path|
|
|
21
|
+
reader = HAProxy::SocketReader.new(path)
|
|
22
|
+
reader.info.class.should == Hash
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should return a String when asking for errors" do
|
|
27
|
+
HAProxy::Test.with_socket(:without_errors) do |path|
|
|
28
|
+
reader = HAProxy::SocketReader.new(path)
|
|
29
|
+
reader.errors.class.should == String
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
HAProxy::Test.with_socket(:with_errors) do |path|
|
|
33
|
+
reader = HAProxy::SocketReader.new(path)
|
|
34
|
+
reader.errors.class.should == String
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should return a String when asking for sessions" do
|
|
39
|
+
HAProxy::Test.with_socket(:without_sessions) do |path|
|
|
40
|
+
reader = HAProxy::SocketReader.new(path)
|
|
41
|
+
reader.sessions.class.should == Array
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
HAProxy::Test.with_socket(:with_sessions) do |path|
|
|
45
|
+
reader = HAProxy::SocketReader.new(path)
|
|
46
|
+
reader.sessions.class.should == Array
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
[ :frontends, :backends, :servers ].each do |type|
|
|
51
|
+
it "should return an Array with #{type} information" do
|
|
52
|
+
HAProxy::Test.with_socket do |path|
|
|
53
|
+
reader = HAProxy::SocketReader.new(path)
|
|
54
|
+
reader.send(type).class.should == Array
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
|
|
3
|
+
module HAProxy
|
|
4
|
+
|
|
5
|
+
module Test
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
def temp_file_path
|
|
9
|
+
tmp = Tempfile.new('haproxy-ruby-mocksock')
|
|
10
|
+
path = tmp.path
|
|
11
|
+
tmp.close!
|
|
12
|
+
path
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def with_socket action = nil, &block
|
|
16
|
+
path = self.temp_file_path
|
|
17
|
+
|
|
18
|
+
UNIXServer.open(path) do |socket|
|
|
19
|
+
pid = Process.fork do
|
|
20
|
+
client = socket.accept
|
|
21
|
+
cmd, data = client.recvfrom(1024)
|
|
22
|
+
cmd.chomp!
|
|
23
|
+
client.send self.send(action || :unknown), 0
|
|
24
|
+
client.close
|
|
25
|
+
exit
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
block.call(path)
|
|
29
|
+
|
|
30
|
+
Process.kill "TERM", pid rescue nil
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def unknown
|
|
35
|
+
"Unknown command"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def info
|
|
39
|
+
"""Name: HAProxy
|
|
40
|
+
Version: 1.3.25
|
|
41
|
+
Release_date: 2010/06/16
|
|
42
|
+
Nbproc: 1
|
|
43
|
+
Process_num: 1
|
|
44
|
+
Pid: 20518
|
|
45
|
+
Uptime: 6d 7h07m46s
|
|
46
|
+
Uptime_sec: 544066
|
|
47
|
+
Memmax_MB: 0
|
|
48
|
+
Ulimit-n: 80110
|
|
49
|
+
Maxsock: 80110
|
|
50
|
+
Maxconn: 40000
|
|
51
|
+
Maxpipes: 0
|
|
52
|
+
CurrConns: 28
|
|
53
|
+
PipesUsed: 0
|
|
54
|
+
PipesFree: 0
|
|
55
|
+
Tasks: 125
|
|
56
|
+
Run_queue: 1
|
|
57
|
+
node: A1441
|
|
58
|
+
description
|
|
59
|
+
"""
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def with_errors
|
|
63
|
+
'''
|
|
64
|
+
[09/Mar/2011:16:05:48.038] frontend http-in (#1): invalid request
|
|
65
|
+
src 10.0.111.185, session #25765333, backend <NONE> (#-1), server <NONE> (#-1)
|
|
66
|
+
request length 352 bytes, error at position 23:
|
|
67
|
+
|
|
68
|
+
00000 POS LWqEQR/710 HTTP/1.1\x00\x00Content-Type: application/x-fcs\x00\x00
|
|
69
|
+
00058+ User- HTTP/1.1\r\n
|
|
70
|
+
00074 kwave Flash\r\n
|
|
71
|
+
00087 Host: 10.0.49.24\x00\x00Content-Length: 1\x00\x00P\r\n
|
|
72
|
+
00128 xy-Connection: Keep\r\n
|
|
73
|
+
00149 live\x00\x00Pragm\r\n
|
|
74
|
+
00162 no-cache\x00\x00X-NovINet: v1.2\x00\x00\x00\n
|
|
75
|
+
00192 \r\n
|
|
76
|
+
00194 \n
|
|
77
|
+
00195 k\xC3\xD9\xFB\x02\x9F\x02\r\x08\xBC\xDB\x1E\xD3Z[\xD4]\xDD%O\x0FX\x01
|
|
78
|
+
00218+ \xDD\x02\xB4\x98\xB4r\x87\xDB\x88\xD4\xBD\xA6\xBD\x80@\x15\x9D\x1A\xA7
|
|
79
|
+
00237+ \xE8,\x8B\x01\x1Ft\x97\x80\xDB\xBF\x87\xAD\x15\r\xDE\x9E\x0CL\x13 FB
|
|
80
|
+
00259+ \x822\xAA\xE0G\x10\t\xC3\xBC\e\xD0!\xC2dYh/\x01\x8A~\x85]z1\xC00\xBF
|
|
81
|
+
00286+ \xC5\x14\xFA\x7F\x03\xF2\xC1\x06\x10\r\n
|
|
82
|
+
00297 X\xA4Cqj0\xFC\x81\x14\xF2U\n
|
|
83
|
+
00309 (0\xBF\xC12<\xA0:\xB2\x84\xC5\xA1\xFAa01\xD0-\xF2\x85\xC8\xB0\r\n
|
|
84
|
+
00333 \x96$\x16\xB6\xB2\r,\x1D\x8B\x93\xAED\xBA\x9BE\r\n
|
|
85
|
+
00350 \r\n
|
|
86
|
+
'''
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def without_errors
|
|
90
|
+
""
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def with_sessions
|
|
94
|
+
'''0xa14a288: proto=tcpv4 src=10.0.16.1:56772 fe=http-in be=gelderlander_textlink srv=mongrel-10306 as=0 ts=08 age=49s calls=5 rq[f=00f0a0h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=4s,wx=,ax=] s0=[7,0h,fd=13,ex=] s1=[7,0h,fd=16,ex=] exp=4s
|
|
95
|
+
0x9745898: proto=tcpv4 src=10.0.73.31:2778 fe=http-in be=gelderlander_textlink srv=mongrel-10315 as=0 ts=08 age=42s calls=4 rq[f=009080h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=8s,wx=,ax=] s0=[7,0h,fd=19,ex=] s1=[7,8h,fd=20,ex=] exp=8s
|
|
96
|
+
0xa26cff0: proto=tcpv4 src=10.0.221.60:19546 fe=http-in be=limburger_textlink srv=mongrel-10708 as=0 ts=08 age=40s calls=4 rq[f=009080h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=10s,wx=,ax=] s0=[7,0h,fd=25,ex=] s1=[7,8h,fd=26,ex=] exp=10s
|
|
97
|
+
0x9f2dff0: proto=tcpv4 src=10.0.45.76:59090 fe=http-in be=tctubantia_textlink srv=mongrel-10507 as=0 ts=08 age=38s calls=5 rq[f=00f0a0h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=11s,wx=,ax=] s0=[7,0h,fd=23,ex=] s1=[7,0h,fd=24,ex=] exp=11s
|
|
98
|
+
0xa2cb998: proto=tcpv4 src=10.0.108.32:1734 fe=http-in be=tctubantia_textlink srv=mongrel-10505 as=0 ts=08 age=37s calls=3 rq[f=009080h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=12s,wx=,ax=] s0=[7,0h,fd=28,ex=] s1=[7,8h,fd=29,ex=] exp=12s
|
|
99
|
+
0xa04b7e8: proto=tcpv4 src=10.0.148.59:1158 fe=http-in be=destentor_textlink srv=mongrel-10403 as=0 ts=08 age=34s calls=4 rq[f=009080h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=16s,wx=,ax=] s0=[7,0h,fd=32,ex=] s1=[7,8h,fd=33,ex=] exp=16s
|
|
100
|
+
0x97d0b90: proto=tcpv4 src=10.0.133.111:50836 fe=http-in be=tctubantia_textlink srv=mongrel-10510 as=0 ts=08 age=21s calls=4 rq[f=009080h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=29s,wx=,ax=] s0=[7,0h,fd=1,ex=] s1=[7,8h,fd=8,ex=] exp=29s
|
|
101
|
+
0x96b1220: proto=tcpv4 src=10.0.217.27:14445 fe=http-in be=gelderlander_textlink srv=mongrel-10310 as=0 ts=08 age=19s calls=4 rq[f=009080h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=30s,wx=,ax=] s0=[7,0h,fd=21,ex=] s1=[7,8h,fd=22,ex=] exp=30s
|
|
102
|
+
0xa12e7a8: proto=tcpv4 src=10.0.34.84:49421 fe=http-in be=gelderlander_textlink srv=mongrel-10303 as=0 ts=08 age=16s calls=4 rq[f=009080h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=33s,wx=,ax=] s0=[7,0h,fd=15,ex=] s1=[7,8h,fd=17,ex=] exp=33s
|
|
103
|
+
0x9b5f570: proto=tcpv4 src=10.0.242.177:50124 fe=http-in be=limburger_textlink srv=mongrel-10701 as=0 ts=08 age=14s calls=4 rq[f=009080h,l=0,an=00h,rx=,wx=,ax=] rp[f=001000h,l=0,an=10h,rx=35s,wx=,ax=] s0=[7,0h,fd=38,ex=] s1=[7,8h,fd=40,ex=] exp=35s
|
|
104
|
+
0x9fda668: proto=unix_stream as=2 ts=09 age=0s calls=2 rq[f=00e042h,l=10,an=20h,rx=10s,wx=,ax=] rp[f=048060h,l=2499,an=00h,rx=,wx=10s,ax=] s0=[7,0h,fd=2,ex=] s1=[0,0h,fd=-1,ex=] exp=10s
|
|
105
|
+
'''
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def without_sessions
|
|
109
|
+
""
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: haproxy-decklin
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.3
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Leandro López (inkel)
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-02-07 00:00:00.000000000 Z
|
|
13
|
+
dependencies: []
|
|
14
|
+
description: This gem is intended for use as a HAProxy interface when you need to
|
|
15
|
+
read statistics or if you like to manage proxies thru Ruby
|
|
16
|
+
email:
|
|
17
|
+
- inkel.ar@gmail.com
|
|
18
|
+
executables: []
|
|
19
|
+
extensions: []
|
|
20
|
+
extra_rdoc_files: []
|
|
21
|
+
files:
|
|
22
|
+
- .gitignore
|
|
23
|
+
- Gemfile
|
|
24
|
+
- README.md
|
|
25
|
+
- Rakefile
|
|
26
|
+
- haproxy.gemspec
|
|
27
|
+
- lib/haproxy.rb
|
|
28
|
+
- lib/haproxy/csv_parser.rb
|
|
29
|
+
- lib/haproxy/socket_reader.rb
|
|
30
|
+
- lib/haproxy/stats_reader.rb
|
|
31
|
+
- lib/haproxy/version.rb
|
|
32
|
+
- spec/haproxy_spec.rb
|
|
33
|
+
- spec/socket_reader_spec.rb
|
|
34
|
+
- spec/spec_helper.rb
|
|
35
|
+
homepage: https://github.com/inkel/haproxy-ruby
|
|
36
|
+
licenses: []
|
|
37
|
+
post_install_message:
|
|
38
|
+
rdoc_options: []
|
|
39
|
+
require_paths:
|
|
40
|
+
- lib
|
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
42
|
+
none: false
|
|
43
|
+
requirements:
|
|
44
|
+
- - ! '>='
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
48
|
+
none: false
|
|
49
|
+
requirements:
|
|
50
|
+
- - ! '>='
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '0'
|
|
53
|
+
requirements: []
|
|
54
|
+
rubyforge_project: haproxy
|
|
55
|
+
rubygems_version: 1.8.11
|
|
56
|
+
signing_key:
|
|
57
|
+
specification_version: 3
|
|
58
|
+
summary: HAProxy interface for reading statistics or managing servers (requires HAProxy
|
|
59
|
+
1.4+)
|
|
60
|
+
test_files:
|
|
61
|
+
- spec/haproxy_spec.rb
|
|
62
|
+
- spec/socket_reader_spec.rb
|
|
63
|
+
- spec/spec_helper.rb
|