File Coverage

blib/lib/Log/Log4perl/Appender/Graylog.pm
Criterion Covered Total %
statement 49 49 100.0
branch 3 4 75.0
condition 2 6 33.3
subroutine 13 13 100.0
pod 1 2 50.0
total 68 74 91.8


line stmt bran cond sub pod time code
1             package Log::Log4perl::Appender::Graylog;
2              
3             # ABSTRACT: Log dispatcher writing to udp Graylog server
4             our $VERSION = '1.7'; # VERSION 1.7
5             my $VERSION = 1.7;
6             our @ISA = qw(Log::Log4perl::Appender);
7              
8 3     3   384160 use strict;
  3         7  
  3         77  
9 3     3   14 use warnings;
  3         7  
  3         65  
10              
11 3     3   414 use Sys::Hostname;
  3         790  
  3         155  
12 3     3   1133 use Data::UUID;
  3         1573  
  3         163  
13 3     3   1190 use POSIX qw(strftime);
  3         15011  
  3         18  
14 3     3   5072 use IO::Compress::Gzip qw( gzip $GzipError );
  3         79553  
  3         475  
15 3     3   1372 use IO::Socket;
  3         32531  
  3         14  
16 3     3   2210 use Data::DTO::GELF;
  3         13  
  3         140  
17 3     3   27 use Carp;
  3         7  
  3         237  
18 3         1690 use Log::GELF::Util qw(
19             :all
20 3     3   1963 );
  3         87542  
21              
22             ##################################################
23             # Log dispatcher writing to udp Graylog server
24             ##################################################
25             # cmd line example echo -n '{ "version": "1.1", "host": "example.org", "short_message": "A short message", "level": 5, "_some_info": "foo" }' | nc -w0 -u graylog.xo.gy 12201
26             ##################################################
27             sub new {
28             ##################################################
29 2     2 1 6051 my $proto = shift;
30 2   33     38 my $class = ref $proto || $proto;
31 2         15 my %params = @_;
32              
33 2         20 my $self = {
34             name => "unknown name",
35             PeerAddr => "",
36             PeerPort => "",
37             Proto => "udp",
38             Gzip => 1,
39             Chunked => 0,
40             %params,
41              
42             };
43 2         13 bless $self, $class;
44              
45             }
46              
47             sub _create_socket {
48 2     2   6 my ( $self, $socket_opts ) = @_;
49              
50 2         22 require IO::Socket::INET;
51             my $socket = IO::Socket::INET->new(
52             PeerAddr => $socket_opts->{host},
53             PeerPort => $socket_opts->{port},
54             Proto => $socket_opts->{protocol},
55 2 50       26 ) or die "Cannot create socket: $!";
56              
57 2         4077 return $socket;
58             }
59             ##################################################
60             sub log {
61             ##################################################
62 2     2 0 47940 my $self = shift;
63 2         11 my %params = @_;
64              
65             my $packet = Data::DTO::GELF->new(
66             'full_message' => $params{'message'},
67             'level' => $params{level},
68             'host' => $params{server} || $params{host} || hostname(),
69             '_uuid' => Data::UUID->new()->create_str(),
70             '_name' => $params{name},
71             '_category' => $params{log4p_category},
72 2   33     32 "_pid" => $$,
73              
74             );
75              
76 2         427 my $msg = validate_message( $packet->TO_HASH() );
77 2         889 my $chunked = parse_size( $self->{Chunked} );
78 2         78 $msg = encode($msg);
79 2 100       742 $msg = compress($msg) if $self->{'Gzip'};
80             my $socket = $self->_create_socket(
81             { 'host' => $self->{'PeerAddr'},
82             'port' => $self->{'PeerPort'},
83 2         2690 'protocol' => $self->{'Proto'}
84             }
85             );
86 2         15 $socket->send($_) foreach enchunk( $msg, $chunked );
87 2         4993 $socket->close();
88              
89             }
90              
91             1;
92              
93             __END__
94              
95             =pod
96              
97             =encoding UTF-8
98              
99             =head1 NAME
100              
101             Log::Log4perl::Appender::Graylog - Log dispatcher writing to udp Graylog server
102              
103             =head1 VERSION
104              
105             version 1.7
106              
107             =head1 SYNOPSIS
108              
109             use Log::Log4perl::Appender::Graylog;
110            
111             my $appender = Log::Log4perl::Appender::Graylog->new(
112             PeerAddr => "glog.foo.com",
113             PeerPort => 12209,
114             Gzip => 1, # Glog2 usually requires gzip but can send plain text
115             );
116            
117             $appender->log(message => "Log me\n");
118            
119             or
120             log4perl.appender.SERVER = Log::Log4perl::Appender::Graylog
121             log4perl.appender.SERVER.layout = NoopLayout
122             log4perl.appender.SERVER.PeerAddr = <ip>
123             log4perl.appender.SERVER.PeerPort = 12201
124             log4perl.appender.SERVER.Gzip = 1
125              
126             =head1 DESCRIPTION
127              
128             This is a simple appender for writing to a graylog server.
129              
130             It relies on L<IO::Socket::INET>. L<Log::GELF::Util>. This sends in the 1.1
131             format.
132              
133             =head1 NAME
134              
135             Log::Log4perl::Appender::Graylog; - Log to a Graylog server
136              
137             =head1 CONFIG
138              
139             log4perl.appender.SERVER = Log::Log4perl::Appender::Graylog
140             log4perl.appender.SERVER.layout = NoopLayout
141             log4perl.appender.SERVER.PeerAddr = <ip>
142             log4perl.appender.SERVER.PeerPort = 12201
143             log4perl.appender.SERVER.Gzip = 1
144             log4perl.appender.SERVER.Chunked = <0|lan|wan>
145            
146             layout This needs to be NoopLayout as we do not want any special formatting.
147             Gzip Accepts an integer specifying if to compress the message.
148             Chunked Accepts an integer specifying the chunk size or the special string values lan or wan corresponding to 8154 or 1420 respectively.
149              
150             =head1 EXAMPLE
151              
152             Write a server quickly using the IO::Socket:
153             (based on orelly-perl-cookbook-ch17)
154              
155             use strict;
156             use IO::Socket;
157             my($sock, $oldmsg, $newmsg, $hisaddr, $hishost, $MAXLEN, $PORTNO);
158             $MAXLEN = 8192;
159             $PORTNO = 12201;
160             $sock = IO::Socket::INET->new(LocalPort => $PORTNO, Proto => 'udp')
161             or die "socket: $@";
162             print "Awaiting UDP messages on port $PORTNO\n";
163             $oldmsg = "This is the starting message.";
164             while ($sock->recv($newmsg, $MAXLEN)) {
165             my($port, $ipaddr) = sockaddr_in($sock->peername);
166             $hishost = gethostbyaddr($ipaddr, AF_INET);
167             print "Client $hishost said ``$newmsg''\n";
168             $sock->send($oldmsg);
169             $oldmsg = "[$hishost] $newmsg";
170             }
171             die "recv: $!";
172              
173             Start it and then run the following script as a client:
174              
175             use Log::Log4perl qw(:easy);
176             my $conf = q{
177             log4perl.category = WARN, Graylog
178             log4perl.appender.Graylog = Log::Log4perl::Appender::Graylog
179             log4perl.appender.Graylog.PeerAddr = localhost
180             log4perl.appender.Graylog.PeerPort = 12201
181             log4perl.appender.Graylog.layout = SimpleLayout
182            
183             };
184            
185             Log::Log4perl->init( \$conf );
186            
187             sleep(2);
188            
189             for ( 1 .. 10 ) {
190             ERROR("Quack!");
191             sleep(5);
192             }
193              
194             =head1 COPYRIGHT AND LICENSE
195              
196             Copyright 2017 by Brandon "Dimentox Travanti" Husbands E<lt>xotmid@gmail.comE<gt>
197              
198             This library is free software; you can redistribute it and/or modify
199             it under the same terms as Perl itself.
200              
201             =head1 AUTHOR
202              
203             Brandon "Dimentox Travanti" Husbands <xotmid@gmail.com>
204              
205             =head1 COPYRIGHT AND LICENSE
206              
207             This software is copyright (c) 2017 by Brandon "Dimentox Travanti" Husbands.
208              
209             This is free software; you can redistribute it and/or modify it under
210             the same terms as the Perl 5 programming language system itself.
211              
212             =cut