From b5caab89cca3129c2dd426ae0cf9ea0983e9be13 Mon Sep 17 00:00:00 2001 From: hylom Date: Tue, 21 Mar 2017 21:32:24 +0900 Subject: [PATCH] Plugins: add AccessLog plugin --- src/configs/newslash.conf.example | 5 ++ src/newslash_web/lib/Newslash/Plugin/AccessLog.pm | 57 ++++++++++++++++++ .../lib/Newslash/Plugin/AccessLog/Debug.pm | 22 +++++++ .../lib/Newslash/Plugin/AccessLog/LocalFile.pm | 68 ++++++++++++++++++++++ src/newslash_web/lib/Newslash/Web.pm | 4 ++ 5 files changed, 156 insertions(+) create mode 100644 src/newslash_web/lib/Newslash/Plugin/AccessLog.pm create mode 100644 src/newslash_web/lib/Newslash/Plugin/AccessLog/Debug.pm create mode 100644 src/newslash_web/lib/Newslash/Plugin/AccessLog/LocalFile.pm diff --git a/src/configs/newslash.conf.example b/src/configs/newslash.conf.example index 5169ca59..5a42d069 100644 --- a/src/configs/newslash.conf.example +++ b/src/configs/newslash.conf.example @@ -29,6 +29,11 @@ System: salt: '' readonly: 0 +Log: + debug: 0 + access_log: /var/log/newslash/access.log + local_file: 1 + Story: title_max_byte: 100 diff --git a/src/newslash_web/lib/Newslash/Plugin/AccessLog.pm b/src/newslash_web/lib/Newslash/Plugin/AccessLog.pm new file mode 100644 index 00000000..1a3bb75c --- /dev/null +++ b/src/newslash_web/lib/Newslash/Plugin/AccessLog.pm @@ -0,0 +1,57 @@ +package Newslash::Plugin::AccessLog; +use Mojo::Base 'Mojolicious::Plugin'; + +use POSIX qw(strftime locale_h); + +sub add_hook { + my ($self, $app) = @_; + + $app->hook(after_build_tx => sub { + my ($tx, $app) = @_; + $tx->on(finish => sub { + my $tx = shift; + my $log = $self->format_log($tx); + $self->write_log($log); + }); + }); +} + +sub write_log { + my ($self, $log) = @_; +} + +sub format_log { + my ($self, $tx) = @_; + + # LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined + # remote_host logname remote_user [DD/MON/YYYY:HH:MM:SS +tzone] "REQUEST" final_status size_of_response "referer" "user-agent" + + my $remote_host = $tx->original_remote_address || "-"; + my $logname = "-"; + my $remote_user = "-"; + + my $locale_org = setlocale(LC_TIME, "C"); + my $timestamp = strftime('[%d/%b/%Y:%H:%M:%S %z]', localtime); + setlocale(LC_TIME, $locale_org); + + # build request line + my $url = $tx->req->url; + my $path = $url->path_query; + my $method = $tx->req->method; + my $version = $tx->req->version; + my $request = "\"$method $path HTTP/$version\""; + + my $status = $tx->res->code || "-"; + my $size = $tx->res->body_size || "-"; + + my $referer = $tx->req->headers->referrer; + my $ua = $tx->req->headers->user_agent; + + $referer = $referer ? "\"$referer\"" : "-"; + $ua = $ua ? "\"$ua\"" : "-"; + + return "$remote_host $logname $remote_user $timestamp $request $status $size $referer $ua"; +} + + +1; diff --git a/src/newslash_web/lib/Newslash/Plugin/AccessLog/Debug.pm b/src/newslash_web/lib/Newslash/Plugin/AccessLog/Debug.pm new file mode 100644 index 00000000..cd8d9e2a --- /dev/null +++ b/src/newslash_web/lib/Newslash/Plugin/AccessLog/Debug.pm @@ -0,0 +1,22 @@ +package Newslash::Plugin::AccessLog::Debug; +use Mojo::Base 'Newslash::Plugin::AccessLog'; + +use IO::File; +use File::Basename; + +sub register { + my ($self, $app, $conf) = @_; + $conf ||= {}; + return if !$conf->{debug}; + + $self->{app} = $app; + $self->add_hook($app); +} + +sub write_log { + my ($self, $log) = @_; + $self->{app}->log->debug($log); +} + + +1; diff --git a/src/newslash_web/lib/Newslash/Plugin/AccessLog/LocalFile.pm b/src/newslash_web/lib/Newslash/Plugin/AccessLog/LocalFile.pm new file mode 100644 index 00000000..ac2f69c6 --- /dev/null +++ b/src/newslash_web/lib/Newslash/Plugin/AccessLog/LocalFile.pm @@ -0,0 +1,68 @@ +package Newslash::Plugin::AccessLog::LocalFile; +use Mojo::Base 'Newslash::Plugin::AccessLog'; + +use IO::File; +use File::Basename; +use Mojo::Util qw(dumper); + +sub DESTROY { + my $self = shift; + if ($self->{fh}) { + $self->{fh}->close; + } +} + +sub register { + my ($self, $app, $conf) = @_; + $conf ||= {}; + return if !$conf->{local_file}; + + $self->{app} = $app; + + my $log_dest = $conf->{access_log}; + $self->{fh} = $self->_open_or_create_file($log_dest); + if (!$self->{fh}) { + $app->log->error("cannot open access log file: $log_dest"); + die "cannot open access log file: $log_dest"; + } + if ($conf->{autoflush}) { + $self->{fh}->autoflush; + } + + $self->add_hook($app); +} + +sub write_log { + my ($self, $log) = @_; + print {$self->{fh}} "$log\n"; +} + +sub _open_or_create_file { + my ($self, $pathname) = @_; + + if (-w $pathname) { + return IO::File->new($pathname, "a"); + } + + if (-e $pathname) { + $self->{app}->log->error("AccessLog::LocalFile: $pathname exists, but not writable"); + return; + } + + my $parent = dirname($pathname); + if (! -d $parent) { + $self->{app}->log->error("AccessLog::LocalFile: cannot create $pathname: $parent not exists"); + return; + } + + my $fh = IO::File->new($pathname, "a"); + if (!$fh) { + $self->{app}->log->error("AccessLog::LocalFile: cannot create $pathname"); + return; + } + + return $fh; +} + + +1; diff --git a/src/newslash_web/lib/Newslash/Web.pm b/src/newslash_web/lib/Newslash/Web.pm index 159c0af4..4c2fed9e 100644 --- a/src/newslash_web/lib/Newslash/Web.pm +++ b/src/newslash_web/lib/Newslash/Web.pm @@ -29,6 +29,10 @@ sub startup { # when "test" mode, output debug logs. $app->log->level('debug') if $app->mode eq 'test'; + # enable logging + $app->plugin('Newslash::Plugin::AccessLog::Debug', $app->config->{Log}); + $app->plugin('Newslash::Plugin::AccessLog::LocalFile', $app->config->{Log}); + # secret key for hasing $app->secrets([$app->config->{System}->{secret_key},]); -- 2.11.0