mirror of
				https://git.haproxy.org/git/haproxy.git/
				synced 2025-10-31 00:21:00 +01:00 
			
		
		
		
	In the SNMP fields descriptions, "Haproxy" was mentioned, let's make it consistent with the rest.
		
			
				
	
	
		
			250 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
| #
 | |
| # Net-SNMP perl plugin for HAProxy
 | |
| # Version 0.30
 | |
| #
 | |
| # Copyright 2007-2010 Krzysztof Piotr Oledzki <ole@ans.pl>
 | |
| #
 | |
| # 1. get a variable from "show stat":
 | |
| #  1.3.6.1.4.1.29385.106.1.$type.$field.$iid.$sid
 | |
| #   type: 0->frontend, 1->backend, 2->server, 3->socket
 | |
| #
 | |
| # 2. get a variable from "show info":
 | |
| #  1.3.6.1.4.1.29385.106.2.$req.$varnr
 | |
| #
 | |
| # TODO:
 | |
| # - implement read timeout
 | |
| #
 | |
| 
 | |
| use NetSNMP::agent (':all');
 | |
| use NetSNMP::ASN qw(:all);
 | |
| use IO::Socket::UNIX;
 | |
| 
 | |
| use strict;
 | |
| 
 | |
| my $agent = new NetSNMP::agent('Name' => 'HAProxy');
 | |
| my $sa = "/var/run/haproxy.stat";
 | |
| 
 | |
| use constant OID_HAPROXY => '1.3.6.1.4.1.29385.106';
 | |
| use constant OID_HAPROXY_STATS => OID_HAPROXY . '.1';
 | |
| use constant OID_HAPROXY_INFO => OID_HAPROXY . '.2';
 | |
| 
 | |
| my $oid_stat = new NetSNMP::OID(OID_HAPROXY_STATS);
 | |
| my $oid_info = new NetSNMP::OID(OID_HAPROXY_INFO);
 | |
| 
 | |
| use constant STATS_PXNAME => 0;
 | |
| use constant STATS_SVNAME => 1;
 | |
| use constant STATS_IID => 27;
 | |
| use constant STATS_SID => 28;
 | |
| use constant STATS_TYPE => 32;
 | |
| 
 | |
| use constant FIELD_INDEX => 10001;
 | |
| use constant FIELD_NAME => 10002;
 | |
| 
 | |
| my %info_vars = (
 | |
| 	0	=> 'Name',
 | |
| 	1	=> 'Version',
 | |
| 	2	=> 'Release_date',
 | |
| 	3	=> 'Nbproc',
 | |
| 	4	=> 'Process_num',
 | |
| 	5	=> 'Pid',
 | |
| 	6	=> 'Uptime',
 | |
| 	7	=> 'Uptime_sec',
 | |
| 	8	=> 'Memmax_MB',
 | |
| 	9	=> 'Ulimit-n',
 | |
| 	10	=> 'Maxsock',
 | |
| 	11	=> 'Maxconn',
 | |
| 	12	=> 'Maxpipes',
 | |
| 	13	=> 'CurrConns',
 | |
| 	14	=> 'PipesUsed',
 | |
| 	15	=> 'PipesFree',
 | |
| 	16	=> 'Tasks',
 | |
| 	17	=> 'Run_queue',
 | |
| 	18	=> 'node',
 | |
| 	19	=> 'description',
 | |
| );
 | |
| 
 | |
| sub find_next_stat_id {
 | |
| 	my($type, $field, $proxyid, $sid) = @_;
 | |
| 
 | |
| 	my $obj = 1 << $type;
 | |
| 
 | |
| 	my $np = -1;
 | |
| 	my $nl = -1;
 | |
| 
 | |
| 	my $sock = new IO::Socket::UNIX (Peer => $sa, Type => SOCK_STREAM, Timeout => 1);
 | |
| 	next if !$sock;
 | |
| 
 | |
| 	print $sock "show stat -1 $obj -1\n";
 | |
| 
 | |
| 	while(<$sock>) {
 | |
| 		chomp;
 | |
| 		my @d = split(',');
 | |
| 
 | |
| 		last if !$d[$field] && $field != FIELD_INDEX && $field != FIELD_NAME && /^#/;
 | |
| 		next if /^#/;
 | |
| 
 | |
| 		next if $d[STATS_TYPE] != $type;
 | |
| 
 | |
| 		next if ($d[STATS_IID] < $proxyid) || ($d[STATS_IID] == $proxyid && $d[STATS_SID] <= $sid);
 | |
| 
 | |
| 		if ($np == -1 || $d[STATS_IID] < $np || ($d[STATS_IID] == $np && $d[STATS_SID] < $nl)) {
 | |
| 			$np = $d[STATS_IID];
 | |
| 			$nl = $d[STATS_SID];
 | |
| 			next;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	close($sock);
 | |
| 
 | |
| 	return 0 if ($np == -1);
 | |
| 
 | |
| 	return "$type.$field.$np.$nl"
 | |
| }
 | |
| 
 | |
| sub haproxy_stat {
 | |
| 	my($handler, $registration_info, $request_info, $requests) = @_;
 | |
| 
 | |
| 	for(my $request = $requests; $request; $request = $request->next()) {
 | |
| 		my $oid = $request->getOID();
 | |
| 
 | |
| 		$oid =~ s/$oid_stat//;
 | |
| 		$oid =~ s/^\.//;
 | |
| 
 | |
| 		my $mode = $request_info->getMode();
 | |
| 
 | |
| 		my($type, $field, $proxyid, $sid, $or) = split('\.', $oid, 5);
 | |
| 
 | |
| 		next if $type > 3 || defined($or);
 | |
| 
 | |
| 		if ($mode == MODE_GETNEXT) {
 | |
| 
 | |
| 			$type = 0 if !$type;
 | |
| 			$field = 0 if !$field;
 | |
| 			$proxyid = 0 if !$proxyid;
 | |
| 			$sid = 0 if !$sid;
 | |
| 
 | |
| 			my $nextid = find_next_stat_id($type, $field, $proxyid, $sid);
 | |
| 			$nextid = find_next_stat_id($type, $field+1, 0, 0) if !$nextid;
 | |
| 			$nextid = find_next_stat_id($type+1, 0, 0, 0) if !$nextid;
 | |
| 
 | |
| 			if ($nextid) {
 | |
| 				($type, $field, $proxyid, $sid) = split('\.', $nextid);
 | |
| 				$request->setOID(sprintf("%s.%s", OID_HAPROXY_STATS, $nextid));
 | |
| 				$mode = MODE_GET;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if ($mode == MODE_GET) {
 | |
| 				next if !defined($proxyid) || !defined($type) || !defined($sid) || !defined($field);
 | |
| 
 | |
| 				my $obj = 1 << $type;
 | |
| 
 | |
| 				my $sock = new IO::Socket::UNIX (Peer => $sa, Type => SOCK_STREAM, Timeout => 1);
 | |
| 				next if !$sock;
 | |
| 
 | |
| 				print $sock "show stat $proxyid $obj $sid\n";
 | |
| 
 | |
| 				while(<$sock>) {
 | |
| 					chomp;
 | |
| 					my @data = split(',');
 | |
| 
 | |
| 					last if !defined($data[$field]) && $field != FIELD_INDEX && $field != FIELD_NAME;
 | |
| 
 | |
| 					if ($proxyid) {
 | |
| 						next if $data[STATS_IID] ne $proxyid;
 | |
| 						next if $data[STATS_SID] ne $sid;
 | |
| 						next if $data[STATS_TYPE] ne $type;
 | |
| 					}
 | |
| 
 | |
| 					if ($field == FIELD_INDEX) {
 | |
| 						$request->setValue(ASN_OCTET_STR,
 | |
| 							sprintf("%s.%s", $data[STATS_IID],
 | |
| 								$data[STATS_SID]));
 | |
| 					} elsif ($field == FIELD_NAME) {
 | |
| 						$request->setValue(ASN_OCTET_STR,
 | |
| 							sprintf("%s/%s", $data[STATS_PXNAME],
 | |
| 								$data[STATS_SVNAME]));
 | |
| 					} else {
 | |
| 						$request->setValue(ASN_OCTET_STR, $data[$field]);
 | |
| 					}
 | |
| 
 | |
| 					close($sock);
 | |
| 					last;
 | |
| 				}
 | |
| 
 | |
| 				close($sock);
 | |
| 				next;
 | |
| 		}
 | |
| 
 | |
|   	}
 | |
| }
 | |
| 
 | |
| sub haproxy_info {
 | |
| 	my($handler, $registration_info, $request_info, $requests) = @_;
 | |
| 
 | |
| 	for(my $request = $requests; $request; $request = $request->next()) {
 | |
| 		my $oid = $request->getOID();
 | |
| 
 | |
| 		$oid =~ s/$oid_info//;
 | |
| 		$oid =~ s/^\.//;
 | |
| 
 | |
| 		my $mode = $request_info->getMode();
 | |
| 
 | |
| 		my($req, $nr, $or) = split('\.', $oid, 3);
 | |
| 
 | |
| 		next if $req >= 2 || defined($or);
 | |
| 
 | |
| 		if ($mode == MODE_GETNEXT) {
 | |
| 			$req = 0 if !defined($req);
 | |
| 			$nr  = -1 if !defined($nr);
 | |
| 
 | |
| 			if (!defined($info_vars{$nr+1})) {
 | |
| 				$req++;
 | |
| 				$nr = -1;
 | |
| 			}
 | |
| 
 | |
| 			next if $req >= 2;
 | |
| 
 | |
| 			$request->setOID(sprintf("%s.%s.%s", OID_HAPROXY_INFO, $req, ++$nr));
 | |
| 			$mode = MODE_GET;
 | |
| 			
 | |
| 		}
 | |
| 
 | |
| 		if ($mode == MODE_GET) {
 | |
| 
 | |
| 			next if !defined($req) || !defined($nr);
 | |
| 
 | |
| 			if ($req == 0) {
 | |
| 				next if !defined($info_vars{$nr});
 | |
| 				$request->setValue(ASN_OCTET_STR, $info_vars{$nr});
 | |
| 				next;
 | |
| 			}
 | |
| 
 | |
| 			if ($req == 1) {
 | |
| 				next if !defined($info_vars{$nr});
 | |
| 
 | |
| 				my $sock = new IO::Socket::UNIX (Peer => $sa, Type => SOCK_STREAM, Timeout => 1);
 | |
| 				next if !$sock;
 | |
| 
 | |
| 				print $sock "show info\n";
 | |
| 
 | |
| 				while(<$sock>) {
 | |
| 					chomp;
 | |
| 					my ($key, $val) = /(.*):\s*(.*)/;
 | |
| 
 | |
| 					next if $info_vars{$nr} ne $key;
 | |
| 
 | |
| 					$request->setValue(ASN_OCTET_STR, $val);
 | |
| 					last;
 | |
| 				}
 | |
| 
 | |
| 				close($sock);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| $agent->register('HAProxy stat', OID_HAPROXY_STATS, \&haproxy_stat);
 | |
| $agent->register('HAProxy info', OID_HAPROXY_INFO, \&haproxy_info);
 | |
| 
 |