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.6'; # VERSION 1.6
5             my $VERSION = 1.6;
6             our @ISA = qw(Log::Log4perl::Appender);
7              
8 3     3   475252 use strict;
  3         9  
  3         72  
9 3     3   14 use warnings;
  3         6  
  3         70  
10              
11 3     3   377 use Sys::Hostname;
  3         784  
  3         132  
12 3     3   1283 use Data::UUID;
  3         1561  
  3         156  
13 3     3   1168 use POSIX qw(strftime);
  3         14421  
  3         16  
14 3     3   4799 use IO::Compress::Gzip qw( gzip $GzipError );
  3         76728  
  3         327  
15 3     3   1367 use IO::Socket;
  3         34873  
  3         12  
16 3     3   2259 use Data::DTO::GELF;
  0            
  0            
17             use Carp;
18             use Log::GELF::Util qw(
19             :all
20             );
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             my $proto = shift;
30             my $class = ref $proto || $proto;
31             my %params = @_;
32              
33             my $self = {
34             name => "unknown name",
35             PeerAddr => "",
36             PeerPort => "",
37             Proto => "udp",
38             Gzip => 1,
39             Chunked => 0,
40             %params,
41              
42             };
43             bless $self, $class;
44              
45             }
46              
47             sub _create_socket {
48             my ( $self, $socket_opts ) = @_;
49              
50             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             ) or die "Cannot create socket: $!";
56              
57             return $socket;
58             }
59             ##################################################
60             sub log {
61             ##################################################
62             my $self = shift;
63             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             "_pid" => $$,
73              
74             );
75              
76             my $msg = validate_message( $packet->TO_HASH() );
77             my $chunked = parse_size( $self->{Chunked} );
78             $msg = encode($msg);
79             $msg = compress($msg) if $self->{'Gzip'};
80             my $socket = $self->_create_socket(
81             { 'host' => $self->{'PeerAddr'},
82             'port' => $self->{'PeerPort'},
83             'protocol' => $self->{'Proto'}
84             }
85             );
86             $socket->send($_) foreach enchunk( $msg, $chunked );
87             $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.6
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