File Coverage

blib/lib/Log/Log4perl/Appender/Graylog.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


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.5'; # VERSION 1.5
5             my $VERSION = 1.5;
6             our @ISA = qw(Log::Log4perl::Appender);
7              
8 3     3   388746 use strict;
  3         9  
  3         73  
9 3     3   15 use warnings;
  3         7  
  3         65  
10              
11 3     3   384 use Sys::Hostname;
  3         744  
  3         137  
12 3     3   1094 use Data::UUID;
  3         1531  
  3         157  
13 3     3   1217 use POSIX qw(strftime);
  3         17143  
  3         23  
14 3     3   5883 use IO::Compress::Gzip qw( gzip $GzipError );
  3         71170  
  3         319  
15 3     3   1241 use IO::Socket;
  3         31121  
  3         12  
16 3     3   2351 use Data::DTO::GELF;
  0            
  0            
17             use Carp;
18             use Log::GELF::Util qw(
19             :all
20             );
21              
22              
23             ##################################################
24             # Log dispatcher writing to udp Graylog server
25             ##################################################
26             # 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
27             ##################################################
28             sub new {
29             ##################################################
30             my $proto = shift;
31             my $class = ref $proto || $proto;
32             my %params = @_;
33            
34             my $self = {
35             name => "unknown name",
36             PeerAddr => "",
37             PeerPort => "",
38             Proto => "udp",
39             Gzip => 1,
40             Chunked => 0,
41             %params,
42            
43             };
44             bless $self, $class;
45            
46             }
47              
48             sub _create_socket {
49             my ( $self, $socket_opts ) = @_;
50              
51             require IO::Socket::INET;
52             my $socket = IO::Socket::INET->new(
53             PeerAddr => $socket_opts->{host},
54             PeerPort => $socket_opts->{port},
55             Proto => $socket_opts->{protocol},
56             ) or die "Cannot create socket: $!";
57              
58             return $socket;
59             }
60             ##################################################
61             sub log {
62             ##################################################
63             my $self = shift;
64             my %params = @_;
65              
66             my $packet = Data::DTO::GELF->new(
67             'full_message' => $params{'message'},
68             'level' => $params{level},
69             'host' => $params{server} || $params{host} || hostname(),
70             '_uuid' => Data::UUID->new()->create_str(),
71             '_name' => $params{name},
72             '_category' => $params{log4p_category},
73             "_pid" => $$,
74              
75             );
76              
77              
78             my $msg = validate_message($packet->TO_HASH());
79             my $chunked = parse_size( $self->{Chunked} );
80             $msg = encode($msg);
81             $msg = compress($msg) if $self->{'Gzip'};
82             my $socket = $self->_create_socket(
83             { 'host' => $self->{'PeerAddr'},
84             'port' => $self->{'PeerPort'},
85             'protocol' => $self->{'Proto'}
86             }
87             );
88             $socket->send($_) foreach enchunk( $msg, $chunked );
89             $socket->close();
90              
91             }
92              
93             1;
94              
95             __END__
96              
97             =pod
98              
99             =encoding UTF-8
100              
101             =head1 NAME
102              
103             Log::Log4perl::Appender::Graylog - Log dispatcher writing to udp Graylog server
104              
105             =head1 VERSION
106              
107             version 1.5
108              
109             =head1 SYNOPSIS
110              
111             use Log::Log4perl::Appender::Graylog;
112            
113             my $appender = Log::Log4perl::Appender::Graylog->new(
114             PeerAddr => "glog.foo.com",
115             PeerPort => 12209,
116             Gzip => 1, # Glog2 usually requires gzip but can send plain text
117             );
118            
119             $appender->log(message => "Log me\n");
120            
121             or
122             log4perl.appender.SERVER = Log::Log4perl::Appender::Graylog
123             log4perl.appender.SERVER.layout = NoopLayout
124             log4perl.appender.SERVER.PeerAddr = <ip>
125             log4perl.appender.SERVER.PeerPort = 12201
126             log4perl.appender.SERVER.Gzip = 1
127              
128             =head1 DESCRIPTION
129              
130             This is a simple appender for writing to a graylog server.
131             It relies on L<IO::Socket::INET>. L<Log::GELF::Util>. This sends in the 1.1
132             format.
133              
134             =head1 NAME
135              
136             Log::Log4perl::Appender::Graylog; - Log to a Graylog server
137              
138             =head1 CONFIG
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