first initial
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
package steffen::MojoPlug::Syslog;
|
||||
use Mojo::Base 'Mojolicious::Plugin';
|
||||
use Sys::Syslog qw(:standard :macros);
|
||||
|
||||
our $VERSION = '__VERSION__';
|
||||
|
||||
my %PRIORITY = (
|
||||
debug => LOG_DEBUG,
|
||||
error => LOG_ERR,
|
||||
fatal => LOG_CRIT,
|
||||
info => LOG_INFO,
|
||||
warn => LOG_WARNING,
|
||||
);
|
||||
|
||||
sub register {
|
||||
my ($self, $app, $config) = @_;
|
||||
my $log_warn = $config->{log_warn} || '1';
|
||||
my $log_level = $config->{level} || 'info';
|
||||
my $log_color = $config->{color} && $config->{color} eq 1 ? 1 : 0;
|
||||
my $only_syslog = $config->{only_syslog} && $config->{only_syslog} eq 1 ? 1 : 0;
|
||||
|
||||
if ( $Mojolicious::VERSION < 9.20 ) {
|
||||
if ( $config->{access_log} && $config->{access_log} ne '' ) {
|
||||
$config->{access_log} = undef;
|
||||
$app->log->warn('Mojo access_log geht erst ab Version 9.20, wird deaktiviert');
|
||||
}
|
||||
|
||||
if ( $log_level =~ /trace/ ) {
|
||||
$log_level = 'debug';
|
||||
$app->log->warn('Mojo Trace geht erst ab Version 9.20, setze auf debug');
|
||||
}
|
||||
}
|
||||
|
||||
if ( $Mojolicious::VERSION > 9.00 ) {
|
||||
$app->log->color( $log_color )
|
||||
} elsif ( $log_color == 1 ) {
|
||||
$app->log->warn('Mojo Log Color geht erst ab Version 9.01');
|
||||
}
|
||||
|
||||
if ( $log_level =~ /trace|debug|info|warn|error|fatal/ ) {
|
||||
$app->log->level( lc $log_level);
|
||||
} else {
|
||||
return $app->log->error(sprintf('REGISTERED failed: %s V%s, loglevel: %s is unknown', __PACKAGE__, $VERSION, $log_level));
|
||||
}
|
||||
|
||||
$self->_add_syslog($app, %$config)
|
||||
if $config->{enable} // $ENV{MOJO_SYSLOG_ENABLE}
|
||||
// $app->mode ne 'development';
|
||||
|
||||
$self->_add_access_log($app, %$config)
|
||||
if $config->{access_log} // $ENV{MOJO_SYSLOG_ACCESS_LOG};
|
||||
|
||||
if ($log_warn eq '1') {
|
||||
$SIG{__WARN__} = sub {
|
||||
|
||||
my $msg = join ' ', @_;
|
||||
chomp $msg;
|
||||
|
||||
$app->log->warn($msg)
|
||||
if $app->mode eq 'development' && $only_syslog == 0; # wenn syslog aus ist dann auch im Developermode kein errorlog
|
||||
syslog $PRIORITY{warn}, '%s [MOJO] %s', 'WARN', $msg;
|
||||
};
|
||||
}
|
||||
$app->log->info(sprintf('REGISTERED: %s V%s', __PACKAGE__, $VERSION)) if $config->{verbose};
|
||||
}
|
||||
|
||||
sub _add_access_log {
|
||||
my ($self, $app, %config) = @_;
|
||||
|
||||
my $log_format = $config{access_log} || $ENV{MOJO_SYSLOG_ACCESS_LOG} || 'v1';
|
||||
$log_format = '%H "%P" (%I) %C %M (%Ts)' if $log_format =~ /^v?1$/;
|
||||
$log_format = '%R %H %U %C "%F" "%A" (%Ts)' if $log_format =~ /^v?2$/;
|
||||
|
||||
$app->hook(
|
||||
before_routes => sub {
|
||||
shift->helpers->timing->begin(__PACKAGE__);
|
||||
}
|
||||
);
|
||||
|
||||
my %extractors = (
|
||||
A => sub { $_[1]->headers->user_agent || '' },
|
||||
C => sub { $_[2]->code },
|
||||
F => sub { $_[1]->headers->referrer || '' },
|
||||
H => sub { $_[1]->method },
|
||||
I => sub { $_[1]->request_id },
|
||||
M => sub { $_[2]->message || $_[2]->default_message($_[2]->code) },
|
||||
P => sub { $_[1]->url->path->to_abs_string },
|
||||
R => sub { $_[0]->tx->remote_address },
|
||||
T => sub { $_[0]->helpers->timing->elapsed(__PACKAGE__) // 0 },
|
||||
U => sub { $_[1]->url->to_abs->to_string },
|
||||
);
|
||||
|
||||
my $app_log = $log_format =~ m!\%I\b! && $app->log;
|
||||
|
||||
my $re = join '|', sort keys %extractors;
|
||||
$re = qr{\%($re)};
|
||||
|
||||
$app->hook(
|
||||
after_dispatch => sub {
|
||||
my $c = shift;
|
||||
my $log = $app_log || $c->log;
|
||||
my ($req, $res) = ($c->req, $c->res);
|
||||
my $level = $res->is_server_error ? 'warn' : 'trace';
|
||||
my $message = $log_format;
|
||||
$message =~ s!$re!$extractors{$1}->($c, $req, $res)!ge;
|
||||
$log->$level($message);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub _add_syslog {
|
||||
my ($self, $app, %config) = @_;
|
||||
|
||||
$config{facility} ||= $ENV{MOJO_SYSLOG_FACILITY} || LOG_USER;
|
||||
$config{ident} ||= $ENV{MOJO_SYSLOG_IDENT} || $app->moniker;
|
||||
$config{logopt} ||= $ENV{MOJO_SYSLOG_LOGOPT} || 'ndelay';
|
||||
|
||||
openlog @config{qw(ident logopt facility)};
|
||||
$app->log->unsubscribe('message') if $config{only_syslog};
|
||||
$app->log->unsubscribe(message => \&_syslog);
|
||||
$app->log->on(message => \&_syslog);
|
||||
}
|
||||
|
||||
sub _syslog {
|
||||
my ($log, $level, @msg) = @_;
|
||||
my $loglevel = $level eq 'trace' ? 'debug': $level;
|
||||
|
||||
syslog $PRIORITY{$loglevel}, '%s [MOJO] %s', uc $level, join ' ', @msg if $PRIORITY{$loglevel};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
steffen::MojoPlugin::Syslog - A plugin for enabling a Mojolicious app to log to syslog
|
||||
original Mojolicious::Plugin::Syslog modified for mlands
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Mojolicious::Lite;
|
||||
plugin syslog => {facility => 'local0'};
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
L<steffen::MojoPlug::Syslog> is a L<Mojolicious> plugin for making
|
||||
L<Mojo::Log> use L<Sys::Syslog> in addition (or instead) of file logging.
|
||||
|
||||
This can be useful when starting Hypnotoad through Systemd, but want simple
|
||||
logging of error messages to syslog.
|
||||
|
||||
This plugin can also be used for only access logging, as an alternative to
|
||||
L<Mojolicious::Plugin::AccessLog>. This is done by forcing L</enable> to
|
||||
"0" and enabling L</access_log>.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=head2 register
|
||||
|
||||
$app->plugin(steffen::MojoPlugin::Syslog => \%config);
|
||||
$self->register($app, \%config);
|
||||
|
||||
Used to register the plugin in your L<Mojolicious> application. Available
|
||||
config parameters are:
|
||||
|
||||
=over 2
|
||||
|
||||
=item * access_log
|
||||
|
||||
Used to enable logging of access to resources with a route enpoint. This means
|
||||
that static files will not be logged, even if this option is enabled. It is
|
||||
also possible to set the default value using the C<MOJO_SYSLOG_ACCESS_LOG>
|
||||
environment variable.
|
||||
|
||||
This can be "v1", "v2" or a custom format. The default is currently "v1", but
|
||||
that might change in the future.
|
||||
|
||||
.---------------------------------------.
|
||||
| Version | Format |
|
||||
|---------|-----------------------------|
|
||||
| v1 | %H "%P" (%I) %C %M (%Ts) |
|
||||
| v2 | %R %H %U %C "%F" "%A" (%Ts) |
|
||||
'---------------------------------------'
|
||||
|
||||
Supported log variables:
|
||||
|
||||
.----------------------------------------------------.
|
||||
| Variable | Value |
|
||||
|----------|-----------------------------------------|
|
||||
| %A | User-Agent request header |
|
||||
| %C | Response status code, ex "200" |
|
||||
| %F | Referer request header |
|
||||
| %H | HTTP request method, ex "GET", "POST" |
|
||||
| %I | Mojolicious request ID |
|
||||
| %M | Response message, ex OK |
|
||||
| %P | Request URL path |
|
||||
| %R | Remote address |
|
||||
| %T | Time in seconds for this request |
|
||||
| %U | Absolute request URL, without user info |
|
||||
'----------------------------------------------------'
|
||||
|
||||
=item * enable
|
||||
|
||||
Need to be true to activate this plugin. Will use the "MOJO_SYSLOG_ENABLE"
|
||||
environment variable or default to true if L<Mojolicious/mode> is something
|
||||
else than "development"
|
||||
|
||||
=item * facility
|
||||
|
||||
The syslog facility to use. Default to "MOJO_SYSLOG_FACILITY" environment
|
||||
variable or default to "user".
|
||||
|
||||
The default is EXPERIMENTAL.
|
||||
|
||||
=item * ident
|
||||
|
||||
The syslog ident to use. Default to "MOJO_SYSLOG_IDENT" environment variable or
|
||||
L<Mojolicious/moniker>.
|
||||
|
||||
=item * only_syslog
|
||||
|
||||
Set this to true to disabled the default L<Mojo::Log> logging to file/stderr.
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Jan Henning Thorsen
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (C) 2019, Jan Henning Thorsen.
|
||||
|
||||
This program is free software, you can redistribute it and/or modify it under
|
||||
the terms of the Artistic License version 2.0.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user