haproxy-decklin 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|