- Repository
- Munin (master)
- Last change
- 2018-08-17
- Graph Categories
- Family
- contrib
- Capabilities
- Language
- Perl
- Authors
haproxy_ng
Sadly there is no documentation for this plugin.
#!/usr/bin/perl -w
#
# haproxy_ng - Munin plugin HAProxy
# Copyright (C) 2012 Redpill Linpro AS
#
# Author: Trygve Vea <tv@redpill-linpro.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Graph stats from the haproxy daemon
#
# Parameters supported:
#
# config
#
# Configurable variables
#
# url - Override default status-url
# username - Basic authentication username
# password - Basic authentication password
#
# Example:
#
# [haproxy_ng]
# env.url http://backend.example.com/haproxy-status;csv;norefresh
# env.username monitor
# env.password somepasswordorother
#
# Magic markers:
#%# family=contrib
use Munin::Plugin::HTTP;
need_multigraph();
my $URL = exists $ENV{'url'} ? $ENV{'url'} : "http://localhost/haproxy-status;csv;norefresh";
my $ua = Munin::Plugin::HTTP->new;
my @types = qw(frontend backend server);
my $url = $URL;
my $response = $ua->get($url);
my $content = $response->content;
my $set;
my @columns;
my %datas = ();
my @graph_parameters = ('total','order','scale','vlabel','args', 'category');
my @field_parameters = ('graph', 'min', 'max', 'draw', 'cdef', 'warning', 'colour', 'info', 'type', 'negative');
my %aspects = (
'Bandwidth' => {
'title' => 'Bandwidth usage',
'category' => 'loadbalancer',
'vlabel' => 'per second',
'values' => {
'bin' => {
'type' => 'DERIVE',
'min' => 0,
'graph' => 'no'
},
'bout' => {
'type' => 'DERIVE',
'draw' => 'AREASTACK',
'min' => 0,
'label' => 'bytes',
'info' => 'Bytes transferred',
'negative' => 'bin'
}
}
},
'Sessions' => {
'title' => 'Sessions',
'category' => 'loadbalancer',
'vlabel' => 'current',
'values' => {
'scur' => {
'type' => 'GAUGE',
'draw' => 'AREASTACK',
'min' => 0,
'label' => 'sessions',
'info' => 'Current sessions',
}
}
},
'SessionRate' => {
'title' => 'SessionRate',
'category' => 'loadbalancer',
'vlabel' => 'current',
'values' => {
'stot' => {
'type' => 'DERIVE',
'draw' => 'AREASTACK',
'min' => 0,
'label' => 'sessions',
'info' => 'sessions',
}
}
},
'Uptime' => {
'title' => 'Uptime',
'category' => 'loadbalancer',
'vlabel' => 'seconds',
'values' => {
'lastchg' => {
'type' => 'GAUGE',
'draw' => 'LINE2',
'min' => 0,
'label' => 'seconds',
'info' => 'Seconds',
}
}
},
'Active' => {
'title' => 'Active Servers',
'category' => 'loadbalancer',
'vlabel' => 'servers',
'values' => {
'act' => {
'type' => 'GAUGE',
'draw' => 'LINE2',
'min' => 0,
'label' => 'servers',
'info' => 'Number of active servers'
}
}
},
'ErrorReq' => {
'title' => 'Request errors',
'category' => 'loadbalancer',
'vlabel' => 'per second',
'values' => {
'ereq' => {
'type' => 'DERIVE',
'draw' => 'LINE2',
'min' => 0,
'label' => 'requests',
'info' => 'Number of request errors'
}
}
},
'ErrorResp' => {
'title' => 'Response errors',
'category' => 'loadbalancer',
'vlabel' => 'per second',
'values' => {
'eresp' => {
'type' => 'DERIVE',
'draw' => 'LINE2',
'min' => 0,
'label' => 'requests',
'info' => 'Number of response errors'
}
}
}
);
my %graphs = (
'BandwidthFront' => {
'lines' => 'frontend',
'title' => 'Bandwidth usage by Frontend',
'aspect' => 'Bandwidth'
},
'BandwidthBack' => {
'lines' => 'backend',
'title' => 'Bandwidth usage by Backend',
'aspect' => 'Bandwidth',
},
'BandwidthBack.BACKEND' => {
'lines' => 'server',
'title' => 'Bandwidth usage by backend: BACKEND',
'aspect' => 'Bandwidth',
},
'SessionsFront' => {
'lines' => 'frontend',
'title' => 'Current Sessions by Frontend',
'aspect' => 'Sessions'
},
'SessionsBack' => {
'lines' => 'backend',
'title' => 'Current Sessions by Backend',
'aspect' => 'Sessions'
},
'SessionsBack.BACKEND' => {
'lines' => 'server',
'title' => 'Current Sessions by backend: BACKEND',
'aspect' => 'Sessions'
},
'SessionRateFront' => {
'lines' => 'frontend',
'title' => 'Session rate by Frontend',
'aspect' => 'SessionRate'
},
'SessionRateBack' => {
'lines' => 'backend',
'title' => 'Session rate by Backend',
'aspect' => 'SessionRate'
},
'SessionRateBack.BACKEND' => {
'lines' => 'server',
'title' => 'Session rate by backend: BACKEND',
'aspect' => 'SessionRate'
},
'Uptime' => {
'lines' => 'backend',
'title' => 'Uptime by Backend',
'aspect' => 'Uptime'
},
'Uptime.BACKEND' => {
'lines' => 'server',
'title' => 'Uptime by servers in BACKEND',
'aspect' => 'Uptime'
},
'Active' => {
'lines' => 'backend',
'title' => 'Active servers by Backend',
'aspect' => 'Active'
},
'ErrorsFront' => {
'lines' => 'frontend',
'title' => 'Request errors by Frontend',
'aspect' => 'ErrorReq'
},
'ErrorsBack' => {
'lines' => 'backend',
'title' => 'Response errors by Backend',
'aspect' => 'ErrorResp'
},
'ErrorsBack.BACKEND' => {
'lines' => 'server',
'title' => 'Response errors by backend: BACKEND',
'aspect' => 'ErrorResp'
}
);
my @lines = split(/\n/,$content);
foreach ( @lines )
{
my $i = 0;
my @line = split(/,/,$_);
if ( !$set )
{
$set++;
@columns = @line;
$columns[0] =~ s/^# //;
next;
}
foreach(@line)
{
$datas{$types[$line[32]]}{$line[0]}{$line[1]}{$columns[$i]} = $_;
$i++;
}
}
sub fetch_graph
{
my $name = shift;
my $printname = $name;
$printname =~ s/-/_/g;
my $graphkey = shift;
my @names = split(/\./,$name);
my $backend = $names[1];
my $data;
my $aspect = $graphs{$graphkey}{'aspect'};
print "multigraph HAP$printname\n";
if(!defined $ARGV[0]){ $data = 'values'; }
elsif ( $ARGV[0] eq 'config' ) { $data = 'config' }
if ( $data eq 'config' ) {
my $title = $graphs{$graphkey}{'title'};
$title =~ s/BACKEND/$backend/g;
print "graph_title $title\n";
foreach (@graph_parameters) {
if (!defined($aspects{$aspect}{$_})) {
next;
}
print "graph_$_ $aspects{$aspect}{$_}\n";
}
}
foreach $val (sort keys %{$aspects{$aspect}{'values'}}) {
if ( $graphs{$graphkey}{'lines'} eq 'frontend' )
{
foreach my $tmpfe ( sort keys %{$datas{'frontend'}} )
{
$fe = clean_fieldname ($tmpfe);
if ( $data eq 'config' ) {
print $fe."_$val.label $fe\n";
foreach (@field_parameters) {
if (!defined($aspects{$aspect}{'values'}{$val}{$_})) {
next;
}
if ( $_ eq 'negative' )
{
print $fe."_$val.$_ $fe"."_$aspects{$aspect}{'values'}{$val}{$_}\n";
}
else
{
print $fe."_$val.$_ $aspects{$aspect}{'values'}{$val}{$_}\n";
}
}
}
else {
if ( $val eq 'lastchg' and $datas{'frontend'}{$tmpfe}{'FRONTEND'}{'status'} eq 'DOWN' ) {
print $fe."_".$val.".value 0\n";
}
else {
print $fe."_".$val.".value ".$datas{'frontend'}{$tmpfe}{'FRONTEND'}{$val}."\n";
}
}
}
}
elsif ( $graphs{$graphkey}{'lines'} eq 'backend' )
{
foreach my $tmpbe ( sort keys %{$datas{'backend'}} )
{
$be = clean_fieldname ($tmpbe);
if ( $data eq 'config' ) {
print $be."_$val.label $be\n";
foreach (@field_parameters) {
if (!defined($aspects{$aspect}{'values'}{$val}{$_})) {
next;
}
if ( $_ eq 'negative' )
{
print $be."_$val.$_ $be"."_$aspects{$aspect}{'values'}{$val}{$_}\n";
}
else
{
print $be."_$val.$_ $aspects{$aspect}{'values'}{$val}{$_}\n";
}
}
}
else {
if ( $val eq 'lastchg' and $datas{'backend'}{$tmpbe}{'BACKEND'}{'status'} eq 'DOWN' ) {
print $be."_".$val.".value 0\n";
}
else {
print $be."_".$val.".value ".$datas{'backend'}{$tmpbe}{'BACKEND'}{$val}."\n";
}
}
}
}
elsif ( $graphs{$graphkey}{'lines'} eq 'server' )
{
my $cleanbackend = clean_fieldname($backend);
foreach my $tmpserver ( sort keys %{$datas{'server'}{$backend}} )
{
$server = clean_fieldname ($tmpserver);
if ( $data eq 'config' ) {
print $server."_$val.label $server\n";
foreach (@field_parameters) {
if (!defined($aspects{$aspect}{'values'}{$val}{$_})) {
next;
}
if ( $_ eq 'negative' )
{
print $server."_$val.$_ $server"."_$aspects{$aspect}{'values'}{$val}{$_}\n";
}
else
{
print $server."_$val.$_ $aspects{$aspect}{'values'}{$val}{$_}\n";
}
}
}
else {
if ( $val eq 'lastchg' and $datas{'server'}{$backend}{$tmpserver}{'status'} eq 'DOWN' ) {
print $server."_".$val.".value 0\n";
}
else {
print $server."_".$val.".value ".$datas{'server'}{$backend}{$tmpserver}{$val}."\n";
}
}
}
}
}
print "\n";
}
sub proc_graph
{
my $g = shift;
my $pre = shift;
my $level = shift;
foreach( sort keys %{$g} )
{
my $name = $_;
my @name_tokens = split(/\./, $name);
my $aspect = $name_tokens[0];
my $graphkey = $name;
if ( $name =~ /BACKEND/ )
{
foreach my $be (sort keys %{$datas{'backend'}})
{
my $name = $name;
$name =~ s/BACKEND/$be/;
fetch_graph($name, $graphkey, $be);
}
}
else
{
fetch_graph($name, $graphkey);
}
}
}
proc_graph(\%graphs, "", 0);