Reference
In This Article
Logging
Web servers typically log request details, so that you can perform tasks such as analytics, identification of invalid requests, and more.
Out-of-the-box, Swoole does not do this. As such, we provide these capabilities with this integration.
We log a number of items:
- When the web server starts, indicating the host and port on which it is running.
- When workers start, including the working directory and worker ID.
- When the web server stops.
- When the web server reloads workers.
- Each request (more on this below)
By default, logging is performed to STDOUT, using an internal logger. However,
you can use any PSR-3 compliant logger to
log application details. We emit logs detailing server operations using the
priority Psr\Log\LogLevel::NOTICE
(unless detailing an error, such as
inability to reload)), while Psr\Log\LogLevel::INFO
and Psr\Log\LogLevel::ERROR
are used to log requests (errors are used for response statuses greater than or
equal to 400).
Access Logs
Technically, the SwooleRequestHandlerRunner
doesn't use PSR-3 loggers
directly, but, rather, instances of Zend\Expressive\Swoole\Log\AccessLogInterface
.
This package-specific interface extends the PSR-3 interface to add two methods:
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Swoole\Http\Request;
use Zend\Expressive\Swoole\StaticResourceHandler\StaticResourceResponse;
interface AccessLogInterface extends LoggerInterface
{
public function logAccessForStaticResource(
Request $request,
StaticResourceResponse $response
) : void;
public function logAccessForPsr7Resource(
Request $request,
ResponseInterface $response
) : void;
}
To allow usage of a standard PSR-3 logger, we also provide a decorator,
Zend\Expressive\Swoole\Log\Psr3AccessLogDecorator
, which decorates the PSR-3
logger and provides a standard implementation for the two methods listed above.
If you have defined a PSR-3 LoggerInterface
service in your application, it
will be used automatically.
Formatting logs
The Apache web server has long provided flexible and robust logging capabilities, and its formats are used across a variety of web servers and logging platforms. As such, we have chosen to use its formats for our standard implementation. However, we allow you to plug in your own system as needed.
You can refer to the Apache mod_log_config documentation in order to understand the available placeholders available for format strings.
Formatting is provided to the Psr3AccessLogDecorator
via instances of the
interface Zend\Expressive\Swoole\Log\AccessLogFormatterInterface
:
interface AccessLogFormatterInterface
{
public function format(AccessLogDataMap $map) : string;
}
AccessLogDataMap
is a class used internally by the Psr3AccessLogDecorator
in
order to map Apache log placeholders to request/response values.
Our default AccessLogFormatterInterface
implementation, AccessLogFormatter
,
provides constants referencing the most common formats, but also allows you to
use arbitrary log formats that use the standard Apache placeholders. The formats
we include by default are:
AccessLogFormatter::FORMAT_COMMON
: Apache common log format:%h %l %u %t "%r" %>s %b
AccessLogFormatter::FORMAT_COMMON_VHOST
: Apache common log format + vhost:%v %h %l %u %t "%r" %>s %b
AccessLogFormatter::FORMAT_COMBINED
: Apache combined log format:%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"
AccessLogFormatter::FORMAT_REFERER
:%{Referer}i -> %U
AccessLogFormatter::FORMAT_AGENT
:%{User-Agent}i
AccessLogFormatter::FORMAT_VHOST
: Alternative Apache vhost format: '%v %l %u %t "%r" %>s %b';AccessLogFormatter::FORMAT_COMMON_DEBIAN
: Debian variant of common log format:%h %l %u %t “%r” %>s %O
;AccessLogFormatter::FORMAT_COMBINED_DEBIAN
: Debian variant of combined log format:%h %l %u %t “%r” %>s %O “%{Referer}i” “%{User-Agent}i”
;AccessLogFormatter::FORMAT_VHOST_COMBINED_DEBIAN
: Debian variant of combined log format + vhost:%v:%p %h %l %u %t “%r” %>s %O “%{Referer}i” “%{User-Agent}i"
;
Configuring a logger
You may subsitute your own logger implementation into the Swoole request handler runner.
Manual usage
If you are manually instantiating a Zend\Expressive\Swoole\SwooleRequestHandlerRunner
instance, you may provide it as the seventh argument to the constructor:
use Zend\Expressive\Swoole\SwooleRequestHandlerRunner;
$runner = new SwooleRequestHandlerRunner(
$application,
$serverRequestFactory,
$serverRequestErrorResponseGenerator,
$pidManager,
$serverFactory,
$staticResourceHandler,
$logger // <-- AccessLoggerInterface instance
);
Container usage
If you are using a PSR-11 container, the
SwooleRequestHandlerRunnerFactory
will retrieve a log instance using the
Zend\Expressive\Swoole\Log\AccessLogInterface
service.
You have two options for substituting your own logger from there.
First, if you already have a service which resolves to a Psr\Log\LoggerInterface
instance,
you can configure it by providing its name:
'zend-expressive-swoole' => [
'swoole-http-server' => [
'logger' => [
'logger-name' => 'my_logger', // define the logger service name here
],
],
],
If you don't want to manually provide the service name but you are okay with re-using your
existing PSR-3 logger, the provided Zend\Expressive\Swoole\Log\AccessLogFactory
will use
the Psr\Log\LoggerInterface
service to create a Psr3AccessLogDecorator
instance.
Since 2.4.0, the
Zend\Expressive\Swoole\Log\AccessLogFactory
will resolve the logger instance by using theZend\Expressive\Swoole\Log\SwooleLogger
service. If you were manually using this factory, you should register the service to theZend\Expressive\Swoole\Log\SwooleLoggerFactory
.
This factory also allows you to specify a custom AccessLogFormatterInterface
instance if you want. It will look up a service by the fully-qualified interface
name, and use it if present. Otherwise, it creates an AccessLogFormatter
instance for you.
In both cases the factory will also look at the following configuration values:
'zend-expressive-swoole' => [
'swoole-http-server' => [
'logger' => [
'format' => string, // one of the AccessLogFormatter::FORMAT_*
// constants, or a custom format string
'use-hostname-lookups' => bool, // Set to true to enable hostname lookups
],
],
],
Using Monolog as a PSR-3 logger
When using Monolog with a StreamHandler
,
you must supply a file or a stream resource descriptor. We recommend using one
of the following:
-
php://stdout
is a good choice, as this will generally write to the current console. -
php://stderr
is also a good choice, as this will generally write to the current console, and allows you to filter based on that output stream. -
When using Docker, generally one of either
/proc/1/fd/1
or/proc/1/fd/2
can be used, and are analogous toSTDOUT
andSTDERR
, respectively. We recommend usingphp://stdout
andphp://stderr
instead, as these will be mapped to the correct locations by the language.
ErrorLogHandler
If you plan to write to
STDERR
, you might consider instead using the MonologErrorLogHandler
, as this will use PHP'serror_log()
mechanism to write to the configured PHP error log. You can then either introspect that location, or configure theerror_log
php.ini
setting to point to either/dev/stderr
or, if on Docker,/proc/1/fd/2
.
Additionally, we recommend using the PsrLogMessageProcessor
with any Monolog
handler to ensure that any templated parameters are expanded by the logger.
As an example, the following is a factory that wires a StreamHandler
to a
Monolog\Logger
instance.
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Monolog\Processor\PsrLogMessageProcessor;
class LoggerFactory
{
public function __invoke(ContainerInterface $container) : LoggerInterface
{
$logger = new Logger('swoole-http-server');
$logger->pushHandler(new StreamHandler(
'php://stdout',
Logger::INFO,
$bubble = true,
$expandNewLines = true
));
$logger->pushProcessor(new PsrLogMessageProcessor());
return $logger;
}
}
If you then wire this to the Psr\Log\LoggerInterface
service, it will be used
by Swoole for the purposes of access logs as well.
Found a mistake or want to contribute to the documentation? Edit this page on GitHub!