|
|
@ -10,10 +10,50 @@ use Getopt::Long; |
|
|
|
use YAML::Tiny; |
|
|
|
use YAML::Tiny; |
|
|
|
use MIME::Base64; |
|
|
|
use MIME::Base64; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### Global vars #### |
|
|
|
|
|
|
|
|
|
|
|
my $conf = {}; |
|
|
|
my $conf = {}; |
|
|
|
my $cmd = { |
|
|
|
my $cmd = { |
|
|
|
config => '/etc/systemd/journal-gelf.yml' |
|
|
|
config => '/etc/systemd/journal-gelf.yml' |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
my $cursor = undef; |
|
|
|
|
|
|
|
my $last_save = 0; |
|
|
|
|
|
|
|
my $cursor_re = qr{^s=[a-z\d]+;i=[a-z\d]+;b=[a-z\d]+;m=[a-z\d]+;t=[a-z\d]+;x=[a-z\d]+$}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### End global vars |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### Routines ##### |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub help { |
|
|
|
|
|
|
|
print <<"_EOF" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Usage: $0 --url=<URL> [--compress|--no-compress] [--user=production --password=secr3t] [--state=/path/to/file] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* --url is the http or https URL where you will push your gelf formated logs. This is mandatory |
|
|
|
|
|
|
|
* --compress or --no-compress : will turn on or off gzip compression of logs. Default is on, but can be usefull to disable for debugging |
|
|
|
|
|
|
|
* --username and --password may be used if URL is protected with a basic auth mecanism. Either both or none must be provided |
|
|
|
|
|
|
|
* --state can be used to specify where to record the last correctly sent message, so we can start from here when |
|
|
|
|
|
|
|
systemd-journal-gelf is restarted or if there's a network problem. Default value is /var/lib/systemd-journal-gelf/state |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_EOF |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub save_cursor { |
|
|
|
|
|
|
|
if ($cursor and $cursor =~ m/$cursor_re/){ |
|
|
|
|
|
|
|
open CURSOR, ">", $conf->{state}; |
|
|
|
|
|
|
|
print CURSOR $cursor; |
|
|
|
|
|
|
|
close CURSOR |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sub handle_stop { |
|
|
|
|
|
|
|
print "Saving current cursor to " . $conf->{state} . "\n"; |
|
|
|
|
|
|
|
save_cursor(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### End Routines #### |
|
|
|
|
|
|
|
|
|
|
|
GetOptions ( |
|
|
|
GetOptions ( |
|
|
|
'c|config=s' => \$cmd->{config}, |
|
|
|
'c|config=s' => \$cmd->{config}, |
|
|
@ -62,6 +102,10 @@ if ( |
|
|
|
|
|
|
|
|
|
|
|
print "Starting the Systemd Journal GELF uploader daemon\n"; |
|
|
|
print "Starting the Systemd Journal GELF uploader daemon\n"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Catch SIGTERM and save the cursor ! |
|
|
|
|
|
|
|
$SIG{TERM} = 'handle_stop'; |
|
|
|
|
|
|
|
$SIG{INT} = 'handle_stop'; |
|
|
|
|
|
|
|
|
|
|
|
my $ua = LWP::UserAgent->new( |
|
|
|
my $ua = LWP::UserAgent->new( |
|
|
|
env_proxy => 1, |
|
|
|
env_proxy => 1, |
|
|
|
keep_alive => 1 |
|
|
|
keep_alive => 1 |
|
|
@ -86,7 +130,7 @@ open CURSOR, "+<", $conf->{state}; |
|
|
|
if ( -e $conf->{state} ){ |
|
|
|
if ( -e $conf->{state} ){ |
|
|
|
my $cursor = <CURSOR>; |
|
|
|
my $cursor = <CURSOR>; |
|
|
|
close CURSOR; |
|
|
|
close CURSOR; |
|
|
|
if ( $cursor and $cursor =~ m/^s=[a-z\d]+;i=[a-z\d]+;b=[a-z\d]+;m=[a-z\d]+;t=[a-z\d]+;x=[a-z\d]+$/ ){ |
|
|
|
if ( $cursor and $cursor =~ m/$cursor_re/ ){ |
|
|
|
print "Valid cursor found in " . $conf->{state} . ", will start back from here\n"; |
|
|
|
print "Valid cursor found in " . $conf->{state} . ", will start back from here\n"; |
|
|
|
$cursor_arg = " --after-cursor='" . $cursor . "'"; |
|
|
|
$cursor_arg = " --after-cursor='" . $cursor . "'"; |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -149,12 +193,7 @@ while ( my $entry = <JOURNAL> ){ |
|
|
|
} |
|
|
|
} |
|
|
|
$resp = $ua->post( |
|
|
|
$resp = $ua->post( |
|
|
|
$conf->{url}, |
|
|
|
$conf->{url}, |
|
|
|
Content => Compress::Zlib::memGzip( |
|
|
|
Content => ($conf->{compress}) ? Compress::Zlib::memGzip(encode('utf-8', to_json($gelf))) : encode('utf-8', to_json($gelf)) |
|
|
|
encode( |
|
|
|
|
|
|
|
'utf-8', |
|
|
|
|
|
|
|
to_json($gelf) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
); |
|
|
|
); |
|
|
|
$retry = ($retry > 0) ? $retry * 2 : 1; |
|
|
|
$retry = ($retry > 0) ? $retry * 2 : 1; |
|
|
|
} while (not $resp->is_success and $retry < 600); |
|
|
|
} while (not $resp->is_success and $retry < 600); |
|
|
@ -162,9 +201,13 @@ while ( my $entry = <JOURNAL> ){ |
|
|
|
# The message has been accepted, we can save the current cursor and |
|
|
|
# The message has been accepted, we can save the current cursor and |
|
|
|
# continue |
|
|
|
# continue |
|
|
|
if ($resp->is_success){ |
|
|
|
if ($resp->is_success){ |
|
|
|
open CURSOR, ">", $conf->{state}; |
|
|
|
$cursor = $msg->{__CURSOR}; |
|
|
|
print CURSOR $msg->{__CURSOR}; |
|
|
|
# Save the current cursor to disk if |
|
|
|
close CURSOR |
|
|
|
# it hasn't been done for the past 30 sec |
|
|
|
|
|
|
|
if (time - $last_save > 30) { |
|
|
|
|
|
|
|
$last_save = time; |
|
|
|
|
|
|
|
save_cursor(); |
|
|
|
|
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
# We can't upload our current message for |
|
|
|
# We can't upload our current message for |
|
|
|
# too much time, no much left we can do, lets die and hope |
|
|
|
# too much time, no much left we can do, lets die and hope |
|
|
@ -172,17 +215,3 @@ while ( my $entry = <JOURNAL> ){ |
|
|
|
die "Error sending data to GELF server\n"; |
|
|
|
die "Error sending data to GELF server\n"; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sub help { |
|
|
|
|
|
|
|
print <<"_EOF" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Usage: $0 --url=<URL> [--compress|--no-compress] [--user=production --password=secr3t] [--state=/path/to/file] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* --url is the http or https URL where you will push your gelf formated logs. This is mandatory |
|
|
|
|
|
|
|
* --compress or --no-compress : will turn on or off gzip compression of logs. Default is on, but can be usefull to disable for debugging |
|
|
|
|
|
|
|
* --username and --password may be used if URL is protected with a basic auth mecanism. Either both or none must be provided |
|
|
|
|
|
|
|
* --state can be used to specify where to record the last correctly sent message, so we can start from here when |
|
|
|
|
|
|
|
systemd-journal-gelf is restarted or if there's a network problem. Default value is /var/lib/systemd-journal-gelf/state |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_EOF |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|