Merge branch 'improve-log4perl-2565' into 'v2.0'
Enrich Log4Perl placeholders with request details See merge request lemonldap-ng/lemonldap-ng!234
This commit is contained in:
commit
525e6711d6
|
@ -210,7 +210,30 @@ Default values:
|
||||||
|
|
||||||
log4perlConfFile = /etc/log4perl.conf
|
log4perlConfFile = /etc/log4perl.conf
|
||||||
log4perlLogger = LLNG
|
log4perlLogger = LLNG
|
||||||
log4perlUserLogger = LLNG.user
|
log4perlUserLogger = LLNGuser
|
||||||
|
|
||||||
|
|
||||||
|
Sample ``log4perl.conf`` file
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
log4perl.logger.LLNG = DEBUG, Syslog
|
||||||
|
log4perl.logger.LLNGuser = INFO, Syslog
|
||||||
|
log4perl.appender.Syslog = Log::Dispatch::Syslog
|
||||||
|
log4perl.appender.Syslog.ident = LLNG
|
||||||
|
log4perl.appender.Syslog.layout = PatternLayout
|
||||||
|
log4perl.appender.Syslog.layout.ConversionPattern = [%p] %m
|
||||||
|
|
||||||
|
For additional information, please read the `Log4Perl documentation <https://metacpan.org/pod/Log::Log4perl>`__
|
||||||
|
|
||||||
|
.. versionadded:: 2.0.14
|
||||||
|
|
||||||
|
The following special formatters have been added to standard `PatternLayout placeholders <https://metacpan.org/pod/Log::Log4perl::Layout::PatternLayout>`__
|
||||||
|
|
||||||
|
* ``%Q{address}``: IP address of the request
|
||||||
|
* ``%Q{user}``: Username of the current user
|
||||||
|
* ``%Q{id}``: Session ID of the current user
|
||||||
|
* ``%E{ENV_VAR}``: content of the ``ENV_VAR`` variable
|
||||||
|
|
||||||
Sentry
|
Sentry
|
||||||
~~~~~~
|
~~~~~~
|
||||||
|
|
|
@ -80,12 +80,12 @@ logLevel = warn
|
||||||
;logger = Lemonldap::NG::Common::Logger::Log4perl
|
;logger = Lemonldap::NG::Common::Logger::Log4perl
|
||||||
;log4perlConfFile = /etc/log4perl.conf
|
;log4perlConfFile = /etc/log4perl.conf
|
||||||
;log4perlLogger = LLNG
|
;log4perlLogger = LLNG
|
||||||
;log4perlUserLogger = LLNG.user
|
;log4perlUserLogger = LLNGuser
|
||||||
;
|
;
|
||||||
; Here, Log4perl configuration is read from /etc/log4perl.conf. The "LLNG"
|
; Here, Log4perl configuration is read from /etc/log4perl.conf. The "LLNG"
|
||||||
; value points to the logger class. Example:
|
; value points to the logger class. Example:
|
||||||
; log4perl.logger.LLNG = WARN, File1
|
; log4perl.logger.LLNG = WARN, File1
|
||||||
; log4perl.logger.LLNG.user = INFO, File2
|
; log4perl.logger.LLNGuser = INFO, File2
|
||||||
; ...
|
; ...
|
||||||
|
|
||||||
; CONFIGURATION CHECK
|
; CONFIGURATION CHECK
|
||||||
|
|
|
@ -2,6 +2,7 @@ package Lemonldap::NG::Common::Logger::Log4perl;
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use Log::Log4perl;
|
use Log::Log4perl;
|
||||||
|
use Log::Log4perl::MDC;
|
||||||
|
|
||||||
our $VERSION = '2.0.0';
|
our $VERSION = '2.0.0';
|
||||||
|
|
||||||
|
@ -10,8 +11,41 @@ our $init = 0;
|
||||||
sub new {
|
sub new {
|
||||||
my ( $class, $conf, %args ) = @_;
|
my ( $class, $conf, %args ) = @_;
|
||||||
my $self = bless {}, $class;
|
my $self = bless {}, $class;
|
||||||
|
|
||||||
unless ($init) {
|
unless ($init) {
|
||||||
my $file = $conf->{log4perlConfFile} || '/etc/log4perl.conf';
|
my $file = $conf->{log4perlConfFile} || '/etc/log4perl.conf';
|
||||||
|
|
||||||
|
# Fix reporting of code location
|
||||||
|
Log::Log4perl->wrapper_register(
|
||||||
|
"Lemonldap::NG::Common::Logger::_Duplicate");
|
||||||
|
Log::Log4perl->wrapper_register(__PACKAGE__);
|
||||||
|
|
||||||
|
# map %E to the stored $req->env
|
||||||
|
Log::Log4perl::Layout::PatternLayout::add_global_cspec(
|
||||||
|
'E',
|
||||||
|
sub {
|
||||||
|
my $layout = shift;
|
||||||
|
my $subvar = $layout->{curlies};
|
||||||
|
my $req = Log::Log4perl::MDC->get("req");
|
||||||
|
return defined($req) ? $req->env->{$subvar} : undef;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
# map %Q to the stored $req
|
||||||
|
Log::Log4perl::Layout::PatternLayout::add_global_cspec(
|
||||||
|
'Q',
|
||||||
|
sub {
|
||||||
|
my $layout = shift;
|
||||||
|
my $subvar = $layout->{curlies};
|
||||||
|
my $req = Log::Log4perl::MDC->get("req");
|
||||||
|
if ( ref($req) and $req->can($subvar) ) {
|
||||||
|
return $req->$subvar;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
Log::Log4perl->init($file);
|
Log::Log4perl->init($file);
|
||||||
$init++;
|
$init++;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +57,16 @@ sub new {
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub setRequestObj {
|
||||||
|
my ($self, $req) = @_;
|
||||||
|
Log::Log4perl::MDC->put( "req", $req );
|
||||||
|
}
|
||||||
|
|
||||||
|
sub clearRequestObj {
|
||||||
|
my ($self, $req) = @_;
|
||||||
|
my $text = Log::Log4perl::MDC->remove();
|
||||||
|
}
|
||||||
|
|
||||||
sub AUTOLOAD {
|
sub AUTOLOAD {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
no strict;
|
no strict;
|
||||||
|
|
|
@ -344,10 +344,36 @@ sub run {
|
||||||
sub _run {
|
sub _run {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return sub {
|
return sub {
|
||||||
$self->handler( Lemonldap::NG::Common::PSGI::Request->new( $_[0] ) );
|
$self->_logAndHandle(
|
||||||
|
Lemonldap::NG::Common::PSGI::Request->new( $_[0] ) );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub _logAndHandle {
|
||||||
|
my ( $self, $req ) = @_;
|
||||||
|
|
||||||
|
# register the request object to the logging system
|
||||||
|
if ( ref( $self->logger ) and $self->logger->can('setRequestObj') ) {
|
||||||
|
$self->logger->setRequestObj($req);
|
||||||
|
}
|
||||||
|
if ( ref( $self->userLogger ) and $self->userLogger->can('setRequestObj') ) {
|
||||||
|
$self->userLogger->setRequestObj($req);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the handler
|
||||||
|
my $res = $self->handler($req);
|
||||||
|
|
||||||
|
# Clear the logging system before the next request
|
||||||
|
if ( ref( $self->logger ) and $self->logger->can('clearRequestObj') ) {
|
||||||
|
$self->logger->clearRequestObj($req);
|
||||||
|
}
|
||||||
|
if ( ref( $self->userLogger ) and $self->userLogger->can('clearRequestObj') ) {
|
||||||
|
$self->userLogger->clearRequestObj($req);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
__END__
|
__END__
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,24 @@ sub launch {
|
||||||
my $class = "Lemonldap::NG::Handler::ApacheMP2::$type";
|
my $class = "Lemonldap::NG::Handler::ApacheMP2::$type";
|
||||||
eval "require $class";
|
eval "require $class";
|
||||||
die $@ if ($@);
|
die $@ if ($@);
|
||||||
|
|
||||||
|
# register the request object to the logging system
|
||||||
|
if ( ref( $class->logger ) and $class->logger->can('setRequestObj') ) {
|
||||||
|
$class->logger->setRequestObj($req);
|
||||||
|
}
|
||||||
|
if ( ref( $class->userLogger ) and $class->userLogger->can('setRequestObj') ) {
|
||||||
|
$class->userLogger->setRequestObj($req);
|
||||||
|
}
|
||||||
|
|
||||||
my ($res) = $class->$sub($req);
|
my ($res) = $class->$sub($req);
|
||||||
|
|
||||||
|
# Clear the logging system before the next request
|
||||||
|
if ( ref( $class->logger ) and $class->logger->can('clearRequestObj') ) {
|
||||||
|
$class->logger->clearRequestObj($req);
|
||||||
|
}
|
||||||
|
if ( ref( $class->userLogger ) and $class->userLogger->can('clearRequestObj') ) {
|
||||||
|
$class->userLogger->clearRequestObj($req);
|
||||||
|
}
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ sub init {
|
||||||
|
|
||||||
## @methodi void _run()
|
## @methodi void _run()
|
||||||
# Check if protecton is activated then return a code ref that will launch
|
# Check if protecton is activated then return a code ref that will launch
|
||||||
# _authAndTrace() if protection in on or handler() else
|
# _logAuthTrace() if protection in on or handler() else
|
||||||
#@return code-ref
|
#@return code-ref
|
||||||
sub _run {
|
sub _run {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
@ -50,7 +50,7 @@ sub _run {
|
||||||
# Handle requests
|
# Handle requests
|
||||||
# Developers, be careful: Only this part is executed at each request
|
# Developers, be careful: Only this part is executed at each request
|
||||||
return sub {
|
return sub {
|
||||||
return $self->_authAndTrace(
|
return $self->_logAuthTrace(
|
||||||
Lemonldap::NG::Common::PSGI::Request->new( $_[0] ) );
|
Lemonldap::NG::Common::PSGI::Request->new( $_[0] ) );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ sub _run {
|
||||||
# Handle unprotected requests
|
# Handle unprotected requests
|
||||||
return sub {
|
return sub {
|
||||||
my $req = Lemonldap::NG::Common::PSGI::Request->new( $_[0] );
|
my $req = Lemonldap::NG::Common::PSGI::Request->new( $_[0] );
|
||||||
my $res = $self->handler($req);
|
my $res = $self->_logAndHandle($req);
|
||||||
push @{ $res->[1] }, $req->spliceHdrs;
|
push @{ $res->[1] }, $req->spliceHdrs;
|
||||||
return $res;
|
return $res;
|
||||||
};
|
};
|
||||||
|
@ -111,6 +111,31 @@ sub reload {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub _logAuthTrace {
|
||||||
|
my ( $self, $req, $noCall ) = @_;
|
||||||
|
|
||||||
|
# register the request object to the logging system
|
||||||
|
if ( ref( $self->logger ) and $self->logger->can('setRequestObj') ) {
|
||||||
|
$self->logger->setRequestObj($req);
|
||||||
|
}
|
||||||
|
if ( ref( $self->userLogger ) and $self->userLogger->can('setRequestObj') ) {
|
||||||
|
$self->userLogger->setRequestObj($req);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the handler
|
||||||
|
my $res = $self->_authAndTrace( $req, $noCall );
|
||||||
|
|
||||||
|
# Clear the logging system before the next request
|
||||||
|
if ( ref( $self->logger ) and $self->logger->can('clearRequestObj') ) {
|
||||||
|
$self->logger->clearRequestObj($req);
|
||||||
|
}
|
||||||
|
if ( ref( $self->userLogger ) and $self->userLogger->can('clearRequestObj') ) {
|
||||||
|
$self->userLogger->clearRequestObj($req);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
## @method private PSGI-Response _authAndTrace($req)
|
## @method private PSGI-Response _authAndTrace($req)
|
||||||
# Launch $self->api::run() and then handler() if
|
# Launch $self->api::run() and then handler() if
|
||||||
# response is 200.
|
# response is 200.
|
||||||
|
@ -138,7 +163,7 @@ sub _authAndTrace {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->logger->debug('User authenticated, calling handler()');
|
$self->logger->debug('User authenticated, calling handler()');
|
||||||
$res = $self->handler($req);
|
$res = $self->_logAndHandle($req);
|
||||||
push @{ $res->[1] }, $req->spliceHdrs;
|
push @{ $res->[1] }, $req->spliceHdrs;
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,15 +10,31 @@ extends 'Lemonldap::NG::Handler::PSGI::Router';
|
||||||
has 'authRoutes' => (
|
has 'authRoutes' => (
|
||||||
is => 'rw',
|
is => 'rw',
|
||||||
isa => 'HashRef',
|
isa => 'HashRef',
|
||||||
default =>
|
default => sub {
|
||||||
sub { { GET => {}, POST => {}, PUT => {}, PATCH => {}, DELETE => {}, OPTIONS => {} } }
|
{
|
||||||
|
GET => {},
|
||||||
|
POST => {},
|
||||||
|
PUT => {},
|
||||||
|
PATCH => {},
|
||||||
|
DELETE => {},
|
||||||
|
OPTIONS => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
has 'unAuthRoutes' => (
|
has 'unAuthRoutes' => (
|
||||||
is => 'rw',
|
is => 'rw',
|
||||||
isa => 'HashRef',
|
isa => 'HashRef',
|
||||||
default =>
|
default => sub {
|
||||||
sub { { GET => {}, POST => {}, PUT => {}, PATCH => {}, DELETE => {}, OPTIONS => {} } }
|
{
|
||||||
|
GET => {},
|
||||||
|
POST => {},
|
||||||
|
PUT => {},
|
||||||
|
PATCH => {},
|
||||||
|
DELETE => {},
|
||||||
|
OPTIONS => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
sub addRoute {
|
sub addRoute {
|
||||||
|
@ -69,7 +85,7 @@ sub _run {
|
||||||
|
|
||||||
return sub {
|
return sub {
|
||||||
my $req = Lemonldap::NG::Common::PSGI::Request->new( $_[0] );
|
my $req = Lemonldap::NG::Common::PSGI::Request->new( $_[0] );
|
||||||
my $res = $self->_authAndTrace( $req, 1 );
|
my $res = $self->_logAuthTrace( $req, 1 );
|
||||||
if ( $res->[0] < 300 ) {
|
if ( $res->[0] < 300 ) {
|
||||||
$self->routes( $self->authRoutes );
|
$self->routes( $self->authRoutes );
|
||||||
$req->userData( $self->api->data );
|
$req->userData( $self->api->data );
|
||||||
|
@ -87,10 +103,11 @@ sub _run {
|
||||||
else {
|
else {
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
$res = $self->handler($req);
|
$res = $self->_logAndHandle($req);
|
||||||
push @{ $res->[1] }, $req->spliceHdrs;
|
push @{ $res->[1] }, $req->spliceHdrs;
|
||||||
return $res;
|
return $res;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -25,7 +25,7 @@ sub _run {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
return sub {
|
return sub {
|
||||||
my $req = Lemonldap::NG::Common::PSGI::Request->new( $_[0] );
|
my $req = Lemonldap::NG::Common::PSGI::Request->new( $_[0] );
|
||||||
my $res = $self->_authAndTrace($req);
|
my $res = $self->_logAuthTrace($req);
|
||||||
push @{ $res->[1] }, $req->spliceHdrs,
|
push @{ $res->[1] }, $req->spliceHdrs,
|
||||||
Cookie => ( $req->{Cookie} // '' );
|
Cookie => ( $req->{Cookie} // '' );
|
||||||
return $res;
|
return $res;
|
||||||
|
|
|
@ -17,7 +17,7 @@ sub init {
|
||||||
}
|
}
|
||||||
|
|
||||||
## @method void _run()
|
## @method void _run()
|
||||||
# Return a subroutine that call _authAndTrace() and tranform redirection
|
# Return a subroutine that call _logAuthTrace() and tranform redirection
|
||||||
# response code from 302 to 401 (not authenticated) ones. This is required
|
# response code from 302 to 401 (not authenticated) ones. This is required
|
||||||
# because Nginx "auth_request" parameter does not accept it. The Nginx
|
# because Nginx "auth_request" parameter does not accept it. The Nginx
|
||||||
# configuration file should transform them back to 302 using:
|
# configuration file should transform them back to 302 using:
|
||||||
|
@ -31,7 +31,7 @@ sub _run {
|
||||||
return sub {
|
return sub {
|
||||||
my $req = $_[0];
|
my $req = $_[0];
|
||||||
$self->logger->debug('New request');
|
$self->logger->debug('New request');
|
||||||
my $res = $self->_authAndTrace(
|
my $res = $self->_logAuthTrace(
|
||||||
Lemonldap::NG::Common::PSGI::Request->new($req) );
|
Lemonldap::NG::Common::PSGI::Request->new($req) );
|
||||||
|
|
||||||
# Transform 302 responses in 401 since Nginx refuse it
|
# Transform 302 responses in 401 since Nginx refuse it
|
||||||
|
|
Loading…
Reference in New Issue
Block a user