File Coverage

blib/lib/Net/Statsd/Tiny.pm
Criterion Covered Total %
statement 67 73 91.7
branch 14 22 63.6
condition 4 6 66.6
subroutine 15 16 93.7
pod 4 5 80.0
total 104 122 85.2


line stmt bran cond sub pod time code
1             package Net::Statsd::Tiny;
2              
3             # ABSTRACT: A tiny StatsD client that supports multimetric packets
4              
5 24     24   11790696 use v5.12;
  24         144  
6              
7 24     24   960 use warnings;
  24         144  
  24         2760  
8              
9 24     24   240 use parent qw/ Class::Accessor::Fast /;
  24         96  
  24         240  
10              
11 24     24   169656 use Carp ();
  24         48  
  24         1272  
12 24     24   192 use IO::Socket 1.18 ();
  24         696  
  24         816  
13 24     24   168 use Socket 2.026 ();
  24         408  
  24         10296  
14              
15             our $VERSION = 'v0.3.9';
16              
17              
18             __PACKAGE__->mk_ro_accessors(
19             qw/ host port proto prefix
20             autoflush max_buffer_size _socket /
21             );
22              
23             sub new {
24 23     23 1 350391661 my ( $class, @args ) = @_;
25              
26 23         823 my %args;
27 23 50 33     3160 if ( ( @args == 1 ) && ( ref( $args[0] ) eq 'HASH' ) ) {
28 0         0 %args = %{ $args[0] };
  0         0  
29             }
30             else {
31 23         3425 %args = @args;
32             }
33              
34 23         1752 my %DEFAULTS = (
35             host => '127.0.0.1',
36             port => 8125,
37             proto => 'udp',
38             prefix => '',
39             autoflush => 1,
40             max_buffer_size => 512,
41             );
42              
43 23         2996 foreach my $attr ( keys %DEFAULTS ) {
44 138 50       1451 next if exists $args{$attr};
45 0         0 $args{$attr} = $DEFAULTS{$attr};
46             }
47              
48             $args{_socket} = IO::Socket::INET->new(
49             PeerAddr => $args{host},
50             PeerPort => $args{port},
51             Proto => $args{proto},
52 23 50       1782 ) or die "Failed to initialize socket: $!";
53              
54 23         22648 my $self = $class->SUPER::new( \%args );
55              
56 23         2089 $self->{_buffer} = '';
57              
58 23         495 return $self;
59             }
60              
61              
62             BEGIN {
63 24     24   120 my $class = __PACKAGE__;
64              
65 24         144 my %PROTOCOL = (
66             set_add => 's',
67             counter => 'c',
68             gauge => 'g',
69             histogram => 'h',
70             meter => 'm',
71             timing => 'ms',
72             );
73              
74 24         120 foreach my $name ( keys %PROTOCOL ) {
75              
76 24     24   240 no strict 'refs'; ## no critic (ProhibitNoStrict)
  24         48  
  24         8256  
77              
78 144         336 my $suffix = '|' . $PROTOCOL{$name};
79              
80 144         648 *{"${class}::${name}"} = sub {
81 27     27   17010060 my ( $self, $metric, $value, $rate ) = @_;
82 27 100 100     754 if ( ( defined $rate ) && ( $rate < 1 ) ) {
83 4 100       467 $self->_record( $suffix . '|@' . $rate, $metric, $value )
84             if rand() < $rate;
85             }
86             else {
87 23         516 $self->_record( $suffix, $metric, $value );
88             }
89 144         792 };
90              
91             }
92              
93             # Alises for other Net::Statsd::Client or Etsy::StatsD
94              
95             {
96 24     24   240 no strict 'refs'; ## no critic (ProhibitNoStrict)
  24         120  
  24         3024  
  24         72  
97              
98 24         48 *{"${class}::update"} = \&counter;
  24         120  
99 24         72 *{"${class}::timing_ms"} = \&timing;
  24         15312  
100              
101             }
102              
103             }
104              
105             sub increment {
106 4     4 1 4001467 my ( $self, $metric, $rate ) = @_;
107 4         144 $self->counter( $metric, 1, $rate );
108             }
109              
110             sub decrement {
111 2     2 1 2000731 my ( $self, $metric, $rate ) = @_;
112 2         50 $self->counter( $metric, -1, $rate );
113             }
114              
115             sub _record {
116 24     24   318 my ( $self, $suffix, $metric, $value ) = @_;
117              
118 24 50       418 Carp::croak "malformed metric" if $metric =~ /[\N{U+00}-\N{U+1f}:|]/;
119 24 50       661 Carp::croak "malformed value" if $value =~ /[\N{U+00}-\N{U+1f}:|]/;
120              
121 24         5363 my $data = $self->prefix . $metric . ':' . $value . $suffix . "\n";
122              
123 24 100       1109 if ( $self->autoflush ) {
124 18         843 send( $self->_socket, $data, 0 );
125 18         1608 return;
126             }
127              
128 6         224 my $avail = $self->max_buffer_size - length( $self->{_buffer} );
129 6 100       37 $self->flush if length($data) > $avail;
130              
131 6         62 $self->{_buffer} .= $data;
132             }
133              
134              
135              
136             sub flush {
137 2     2 1 41 my ($self) = @_;
138              
139 2 50       10 if ( length($self->{_buffer}) ) {
140 2         127 send( $self->_socket, $self->{_buffer}, 0 );
141 2         232 $self->{_buffer} = '';
142             }
143             }
144              
145             sub DEMOLISH {
146 0     0 0   my ( $self, $is_global ) = @_;
147              
148 0 0         return if $is_global;
149              
150 0           $self->flush;
151             }
152              
153              
154             1;
155              
156             __END__