File Coverage

blib/lib/Ganglia/Gmetric/PP.pm
Criterion Covered Total %
statement 40 40 100.0
branch 13 20 65.0
condition 3 7 42.8
subroutine 9 9 100.0
pod 4 4 100.0
total 69 80 86.2


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Ganglia::Gmetric::PP - Pure Perl emitter/parser of Ganglia gmetric monitoring
4             packets
5              
6             =head1 SYNOPSIS
7              
8             my $gmetric = Ganglia::Gmetric::PP->new(host => 'localhost', port => 8649);
9             $gmetric->send($type, $name, $value, $units, $slope, $tmax, $dmax);
10              
11             =head1 DESCRIPTION
12              
13             This module constructs Ganglia packets in the manner of the gmetric program and
14             sends them via UDP to a gmond. Additionally it can receive and/or parse gmetric
15             packets which is useful for constructing proxies. Though written in pure Perl
16             with no non-core dependencies, it tries to be fast.
17              
18             =cut
19              
20             package Ganglia::Gmetric::PP;
21              
22             our $VERSION = '1.04';
23              
24 3     3   112872 use strict;
  3         7  
  3         121  
25 3     3   16 use warnings;
  3         6  
  3         98  
26              
27 3     3   14 use base 'Exporter', 'IO::Socket::INET';
  3         15  
  3         3388  
28              
29             our @EXPORT_OK = qw(
30             GANGLIA_VALUE_STRING
31             GANGLIA_VALUE_UNSIGNED_CHAR
32             GANGLIA_VALUE_CHAR
33             GANGLIA_VALUE_UNSIGNED_SHORT
34             GANGLIA_VALUE_SHORT
35             GANGLIA_VALUE_UNSIGNED_INT
36             GANGLIA_VALUE_INT
37             GANGLIA_VALUE_FLOAT
38             GANGLIA_VALUE_DOUBLE
39             GANGLIA_SLOPE_ZERO
40             GANGLIA_SLOPE_POSITIVE
41             GANGLIA_SLOPE_NEGATIVE
42             GANGLIA_SLOPE_BOTH
43             GANGLIA_SLOPE_UNSPECIFIED
44             METRIC_INDEX_TYPE
45             METRIC_INDEX_NAME
46             METRIC_INDEX_VALUE
47             METRIC_INDEX_UNITS
48             METRIC_INDEX_SLOPE
49             METRIC_INDEX_TMAX
50             METRIC_INDEX_DMAX
51             );
52             our %EXPORT_TAGS = (
53             'all' => \@EXPORT_OK,
54             );
55              
56             =head1 FUNCTIONS
57              
58             =over 4
59              
60             =item * $gmetric = Ganglia::Gmetric::PP->new(host => $host, port => $port)
61              
62             Constructs a new object which sends gmetric packets to the specified C
63             and UDP C. If omitted, they default to localhost and 8649, respectively.
64              
65             =item * $gmond = Ganglia::Gmetric::PP->new(listen_host => $host, listen_port => $port)
66              
67             Constructs a new object which receives gmetric packets (e.g. in a gmond replacement).
68             If the $gmetric will be used for receiving packets, C and
69             C may be specified as well.
70              
71             =cut
72              
73             sub new {
74 7     7 1 2028204 my $proto = shift;
75 7   33     111 my $class = ref($proto) || $proto;
76              
77 7         117 my %p = @_;
78              
79 7         15 my %opts;
80              
81 7 100       43 $opts{LocalHost} = $p{listen_host} if $p{listen_host};
82 7 50       29 $opts{LocalPort} = $p{listen_port} if $p{listen_port};
83              
84 7 100       94 unless (%opts) {
85 3   50     60 $opts{PeerHost} = $p{host} || 'localhost';
86 3   50     25 $opts{PeerPort} = $p{port} || 8649;
87             }
88              
89 7         160 my $self = IO::Socket::INET->new(
90             Proto => 'udp',
91             %opts,
92             );
93              
94 7 50       6129 die "failed to create socket: $!" unless $self;
95              
96 7         54 return bless $self, $class;
97             }
98              
99             =item * $gmetric->send($type, $name, $value, $units, $slope, $tmax, $dmax)
100              
101             Sends a Ganglia message. The parameters are:
102              
103             =over 4
104              
105             =item * $type
106              
107             The type of data being sent. Must be one of these importable constants:
108              
109             =over 4
110              
111             =item * GANGLIA_VALUE_STRING
112              
113             =item * GANGLIA_VALUE_UNSIGNED_CHAR
114              
115             =item * GANGLIA_VALUE_CHAR
116              
117             =item * GANGLIA_VALUE_UNSIGNED_SHORT
118              
119             =item * GANGLIA_VALUE_SHORT
120              
121             =item * GANGLIA_VALUE_UNSIGNED_INT
122              
123             =item * GANGLIA_VALUE_INT
124              
125             =item * GANGLIA_VALUE_FLOAT
126              
127             =item * GANGLIA_VALUE_DOUBLE
128              
129             =back
130              
131             =item * $name
132              
133             The name of the metric.
134              
135             =item * $value
136              
137             The current value of the metric.
138              
139             =item * $units
140              
141             A string describing the units of measure for the metric.
142              
143             =item * $slope
144              
145             A description of how the metric tends to change over time. Must be one of these importable constants:
146              
147             =over 4
148              
149             =item * GANGLIA_SLOPE_ZERO
150              
151             Data is fixed, mostly unchanging.
152              
153             =item * GANGLIA_SLOPE_POSITIVE
154              
155             Value is always increasing (counter).
156              
157             =item * GANGLIA_SLOPE_NEGATIVE
158              
159             Value is always decreasing.
160              
161             =item * GANGLIA_SLOPE_BOTH
162              
163             Value can be anything.
164              
165             =back
166              
167             =item * $tmax
168              
169             The maximum time in seconds between gmetric calls.
170              
171             =item * $dmax
172              
173             The lifetime in seconds of this metric.
174              
175             =back
176              
177             =cut
178              
179             # exported constants. see http://code.google.com/p/embeddedgmetric/wiki/GmetricProtocol
180             use constant {
181 3         924 GANGLIA_VALUE_STRING => 'string',
182             GANGLIA_VALUE_UNSIGNED_CHAR => 'uint8',
183             GANGLIA_VALUE_CHAR => 'int8',
184             GANGLIA_VALUE_UNSIGNED_SHORT => 'uint16',
185             GANGLIA_VALUE_SHORT => 'int16',
186             GANGLIA_VALUE_UNSIGNED_INT => 'uint32',
187             GANGLIA_VALUE_INT => 'int32',
188             GANGLIA_VALUE_FLOAT => 'float',
189             GANGLIA_VALUE_DOUBLE => 'double',
190              
191             GANGLIA_SLOPE_ZERO => 0, # data is fixed, mostly unchanging
192             GANGLIA_SLOPE_POSITIVE => 1, # is always increasing (counter)
193             GANGLIA_SLOPE_NEGATIVE => 2, # is always decreasing
194             GANGLIA_SLOPE_BOTH => 3, # can be anything
195             GANGLIA_SLOPE_UNSPECIFIED => 4,
196              
197             METRIC_INDEX_TYPE => 0,
198             METRIC_INDEX_NAME => 1,
199             METRIC_INDEX_VALUE => 2,
200             METRIC_INDEX_UNITS => 3,
201             METRIC_INDEX_SLOPE => 4,
202             METRIC_INDEX_TMAX => 5,
203             METRIC_INDEX_DMAX => 6,
204 3     3   102987 };
  3         8  
205              
206             # internal constants
207             use constant {
208 3         1077 MAGIC_ID => 0,
209             GMETRIC_FORMAT => 'N(N/a*x![4])4N3',
210              
211             DEFAULT_UNITS => '',
212             DEFAULT_SLOPE => 3,
213             DEFAULT_TMAX => 60,
214             DEFAULT_DMAX => 0,
215 3     3   17 };
  3         6  
216              
217             sub send {
218 169     169 1 20744 my $self = shift;
219 169         647 my @msg = (MAGIC_ID, @_);
220 169 100       435 $msg[4] = DEFAULT_UNITS unless defined $msg[4];
221 169 50       403 $msg[5] = DEFAULT_SLOPE unless defined $msg[5];
222 169 50       575 $msg[6] = DEFAULT_TMAX unless defined $msg[6];
223 169 50       462 $msg[7] = DEFAULT_DMAX unless defined $msg[7];
224 169         2128 $self->SUPER::send(pack GMETRIC_FORMAT, @msg);
225             }
226              
227             =item * @metric = $gmetric->receive()
228              
229             Waits for a single gmetric packet on the UDP listen port and returns the parsed
230             metric (see C).
231              
232             =cut
233              
234             sub receive {
235 34     34 1 9304316 my $self = shift;
236 34 50       305 return() unless $self->recv(my $buf, 1 << 14);
237 34         1058 return $self->parse($buf);
238             }
239              
240             =item * @metric = Ganglia::Gmetric::PP->parse($packet_data)
241              
242             Parses a gmetric packet, which is typically received by a UDP server.
243              
244             The elements returned match the arguments to C:
245              
246             ($type, $name, $value, $units, $slope, $tmax, $dmax) = @metric;
247              
248             This function may die if the given data does not resemble a gmetric packet.
249              
250             =cut
251              
252             sub parse {
253 43     43 1 6077 my @res = unpack GMETRIC_FORMAT, $_[1];
254 43 50       145 die "bad magic" unless shift(@res) == MAGIC_ID;
255 43         226 return @res;
256             }
257              
258             1;
259              
260             =back
261              
262             =head1 AUTHOR
263              
264             Adam Thomason, Eathomason@cpan.org
265              
266             =head1 COPYRIGHT AND LICENSE
267              
268             Copyright (C) 2007-2009 by Six Apart, Ecpan@sixapart.comE
269              
270             This library is free software; you can redistribute it and/or modify
271             it under the same terms as Perl itself, either Perl version 5.8.6 or,
272             at your option, any later version of Perl 5 you may have available.
273              
274             =cut