Plack::Middleware::AccessLog::Timed cannot record %D and %T fields properly
This is because both Plack::Middleware::AccessLog::Timed and Apache::LogFormat::Compiler has a bug
Both of those bugs will make breaking changes
Background
According to documentation of Plack::Middleware::AccessLog::Timed, we can record the time taken to serve the request to logfile with fomat including %D and/or %T.
This log is formatted by Apache::LogFormat::Compiler. In its document, %T and %D are described as below:
%T custom field for handling times in subclasses
%D custom field for handling sub-second times in subclasses
When I run that test, the test fails (result), and from its result, current behavior looks like follows:
if a request took 2 seconds,
%T should be 2, but currently 2000000
%D should be 2000000 (2_000_000), but currently 2
Investigation
This is caused by a bug in Plack::Middleware::AccessLog::Timed and another in Apache::LogFormat::Compiler.
Plack::Middleware::AccessLog::Timed
From documentation of Apache::LogFormat::Compiler, Apache::LogFormat::Compiler::log_line expects its argument $reqtime to be in microseconds.
But Plack::Middleware::AccessLog::Timed passes $now - $time in seconds as $reqtime argument.
The bug in Apache::LogFormat::Compiler is simple.
When $reqtime is passed to log_line, %T shoule be formatted to int($reqtime/1_000_000), but with current implementation it's formatted to int($reqtime*1_000_000).
tl;dr
Plack::Middleware::AccessLog::Timed
cannot record%D
and%T
fields properlyPlack::Middleware::AccessLog::Timed
andApache::LogFormat::Compiler
has a bugBackground
According to documentation of
Plack::Middleware::AccessLog::Timed
, we can record the time taken to serve the request to logfile withfomat
including%D
and/or%T
. This log is formatted byApache::LogFormat::Compiler
. In its document,%T
and%D
are described as below:And according to Apache's LogFormat templates (its superset) those format string are described as below:
%T
%D
That means:
%T
should be2
%D
should be2000000
(2_000_000
).Current behavior
I wrote a test code to check current behavior of
Plack::Middleware::AccessLog::Timed
: https://github.com/astj/Plack/commit/d03ab21bd9b56959d93bb68e708d63ebe5c36630When I run that test, the test fails (result), and from its result, current behavior looks like follows:
%T
should be2
, but currently2000000
%D
should be2000000
(2_000_000
), but currently2
Investigation
This is caused by a bug in
Plack::Middleware::AccessLog::Timed
and another inApache::LogFormat::Compiler
.Plack::Middleware::AccessLog::Timed
From documentation of
Apache::LogFormat::Compiler
,Apache::LogFormat::Compiler::log_line
expects its argument$reqtime
to be in microseconds. ButPlack::Middleware::AccessLog::Timed
passes$now - $time
in seconds as$reqtime
argument.P::M::AccessLog::Timed
passes differences of twoTime::HiRes::gettimeofday
Time::HiRes::gettimeofday
returns floating seconds when called in scalar contextWith this commit this bug will be fixed, but due to
Apache::LogFormat::Compiler
's bug, that test still fails. : https://github.com/astj/Plack/commit/dac66093f454cc0da52ee3333b265f0383f196d7Apache::LogFormat::Compiler
The bug in
Apache::LogFormat::Compiler
is simple. When$reqtime
is passed tolog_line
,%T
shoule be formatted toint($reqtime/1_000_000)
, but with current implementation it's formatted toint($reqtime*1_000_000)
.I wrote a test code to check this behavior: https://github.com/astj/Apache-LogFormat-Compiler/commit/ea41df7282c0020ad957ed0d72c5190b20a88eec Unless this bug fixed,
%T
fields inPlack::Middleware::AccessLog::Timed
's output remains still broken.Suggestion
My suggestion is follows:
Apache::LogFormat::Compiler
Plack::Middleware::AccessLog::Timed
and add dependency of new version ofApache::LogFormat::Compiler