Middleware to generate access logs for each request using the Apache's access log format

Overview

middlewares/access-log

Latest Version on Packagist Software License Testing Total Downloads

Middleware to generate access logs for each request using the Apache's access log format. This middleware requires a Psr log implementation, for example monolog.

Requirements

Installation

This package is installable and autoloadable via Composer as middlewares/access-log.

composer require middlewares/access-log

Example

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

//Create the logger
$logger = new Logger('access');
$logger->pushHandler(new StreamHandler(fopen('/access-log.txt', 'r+')));

$dispatcher = new Dispatcher([
    new Middlewares\AccessLog($logger)
]);

$response = $dispatcher->dispatch(new ServerRequest());

Usage

This middleware uses PSR-3 logger standard to store the logs, so you need to pass a Psr\Log\LoggerInterface instance to the constructor.

format

This option allows to define the format used to save the log messages. You can create your own format (More info about the available options) ou use one of the following constants provided with predefined formats:

  • AccessLog::FORMAT_COMMON (Used by default)
  • AccessLog::FORMAT_COMMON_VHOST
  • AccessLog::FORMAT_COMBINED
  • AccessLog::FORMAT_REFERER
  • AccessLog::FORMAT_AGENT
  • AccessLog::FORMAT_VHOST
  • AccessLog::FORMAT_COMMON_DEBIAN
  • AccessLog::FORMAT_COMBINED_DEBIAN
  • AccessLog::FORMAT_VHOST_COMBINED_DEBIAN
use Middlewares\AccessLog;

$format = AccessLog::FORMAT_COMMON_VHOST;

$accessLog = (new AccessLog($logger))->format($format);

ipAttribute

By default uses the REMOTE_ADDR server parameter to get the client ip. This option allows to use a request attribute. Useful to combine with any ip detection middleware, for example client-ip:

attribute('ip'), //use that attribute (new Middlewares\AccessLog($logger))->ipAttribute('ip') ]);">
Dispatcher::run([
    //detect the client ip and save it in "ip" attribute
    (new Middlewares\ClientIP())->attribute('ip'),

    //use that attribute
    (new Middlewares\AccessLog($logger))->ipAttribute('ip')
]);

hostnameLookups

Enable the hostnameLookups flag used to get the remote hostname (%h). By default is false.

context

By default there is no context passed into the logger. When setting this context callable it will be called each time an request is logged with both the request and response. Letting you set context to the log entry:

$dispatcher = new Dispatcher([
    //detect the client ip and save it in ip attribute
    (new Middlewares\ClientIP())->attribute('ip'),
    
    // Add UUID for the request so we can trace logs later in case somethings goes wrong
    new Middlewares\Uuid(),

    // Use the data from the other two middleware and use it as context for logging
    (new Middlewares\AccessLog($logger))
        ->context(function (ServerRequestInterface $request, ResponseInterface $response) {
            return [
                'request-id' => $request->getHeaderLine('X-Uuid'),
                'client-ip' => $request->getAttribute('ip'),
            ];
        })
]);

Custom format string

The format string tries to mimic the directives described in Apache Httpd server documentation.

A custom format can be defined by placing "%" directives in the format string, which are replaced in the log file by the values as follows:

Format String Description
%% The percent sign.
%a Client IP address of the server request (see the ipAttribute option).
%{c}a Client IP address of the server request (see the ipAttribute option, differs from the original Apache directive behavior).
%A Local IP-address.
%B Size of response in bytes, excluding HTTP headers.
%b Size of response in bytes, excluding HTTP headers. In CLF format, i.e. a - rather than a 0 when no bytes are sent.
%{VARNAME}C The contents of cookie VARNAME in the server request sent to the server.
%D The time taken to serve the request, in microseconds.
%{VARNAME}e The contents of the environment variable VARNAME.
%f Filename.
%h Remote hostname. Will log the IP address if hostnameLookups is set to false, which is the default
%H The request protocol.
%{VARNAME}i The contents of VARNAME: header line(s) in the request sent to the server.
%m The request method.
%{VARNAME}n The contents of attribute VARNAME in the server request (differs from the original Apache directive behavior).
%{VARNAME}o The contents of VARNAME: header line(s) in the reply.
%p The canonical port of the server serving the request.
%{format}p The canonical port of the server serving the request or the string - for remote. Valid formats are canonical, local, or remote (differs from the original Apache directive behavior).
%q The query string (prepended with a ? if a query string exists, otherwise an empty string).
%r First line of request.
%s Status.
%t Time the request was received, in the format [18/Sep/2011:19:18:28 -0400]. The last number indicates the timezone offset from GMT
%{format}t The time, in the form given by format, which should be in an extended strftime(3) format (potentially localized). If the format starts with begin: (default) the time is taken at the beginning of the request processing. If it starts with end: it is the time when the log entry gets written, close to the end of the request processing. In addition to the formats supported by strftime(3), the following format tokens are supported: sec, msec, usec (differs from the original Apache directive behavior).
%T The time taken to serve the request, in seconds.
%{UNIT}T The time taken to serve the request, in a time unit given by UNIT. Valid units are ms for milliseconds, us for microseconds, and s for seconds. Using s gives the same result as %T without any format; using us gives the same result as %D.
%u Remote user if the request was authenticated. May be bogus if return status (%s) is 401 (unauthorized).
%U The URL path requested, not including any query string.
%v The host of the server request (differs from the original Apache directive behavior).
%V The server name that appears in the server param of the request, or the request host if not available (differs from the original Apache directive behavior).
%I Bytes received, including request and headers. Cannot be zero.
%O Bytes sent, including headers.
%S Bytes transferred (received and sent), including request and headers, cannot be zero. This is the combination of %I and %O.

The following Apache Httpd server directives are not implemented in this middleware:

Format String Description
%k Will print the string -.
%l Will print the string -.
%L Will print the string -.
%P Will print the string -.
%{format}P Will print the string -.
%R Will print the string -.
%X Will print the string -.
%{VARNAME}^ti Will print the string -.
%{VARNAME}^to Will print the string -.

Please see CHANGELOG for more information about recent changes and CONTRIBUTING for contributing details.

The MIT License (MIT). Please see LICENSE for more information.

Comments
  • Use different severity for client errors

    Use different severity for client errors

    Important: this should probably be considered as a BC-breaking change, since log severity will change.

    The ERROR severity in logs is used for things that developers MUST track and fix when possible. However, the 4xx status codes are related to client mistakes - and the API developers are usually unable to solve.

    By using WARNING for 4xx we allow users of this middleware to have the opportunity to fine-tune their production logging and potentially ignore client errors.

    opened by lcobucci 7
  • Function strftime() is deprecated

    Function strftime() is deprecated

    Full error message:

    PHP message: PHP Deprecated:  Function strftime() is deprecated in /var/www/vendor/middlewares/access-log/src/AccessLogFormats.php on line 270
    
    opened by paveljanda 3
  • Fix message size return when body size is unknown

    Fix message size return when body size is unknown

    When the body size of a message is unknown, the current code throws the following error:

    Uncaught TypeError: Return value of Middlewares\AccessLogFormats::getMessageSize() must be of the type int or null, string returned

    This patch fixes it.

    opened by ajgarlag 3
  • Add support to log request attributes

    Add support to log request attributes

    In Apache, the main use for notes is to pass information from one module to another within the same request. These notes can be logged using the %{}n pattern, currently not implemented in this middleware.

    In a similar way, the PSR-7 Server Request provide the attributes array to inject parameters that can be passed to another middleware. As I need to log some of these attributes, I think we can reuse this pattern to log attributes.

    What do you think?

    opened by ajgarlag 3
  • [RFC] Read IP from request attribute

    [RFC] Read IP from request attribute

    Detecting client IP is a tricky business, so the need for a middleware like https://github.com/middlewares/client-ip/

    What do you think about adding an option to read IP parameter from a request attribute?

    opened by ajgarlag 3
  • installation by composer

    installation by composer

    Hello,

    I'm trying to get the middleware by composer for my application, but when I run the composer require middlewares/access-log command I get the following message in my terminal:

    Your requirements could not be resolved to an installable set of packages.
    
      Problem 1
        - Installation request for middlewares/access-log ^1.0 -> satisfiable by middlewares/access-log[v1.0.0].
        - middlewares/access-log v1.0.0 requires psr/log-implementation ^1.0 -> no matching package found.
    
    Potential causes:
     - A typo in the package name
     - The package is not available in a stable-enough version according to your minimum-stability setting
       see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.
     - It's a private package and you forgot to add a custom repository to find it
    
    Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
    
    Installation failed, deleting ./composer.json.
    

    Is this a problem in the package?

    opened by thalysonalexr 2
  • Issue with switch from strftime() to date()

    Issue with switch from strftime() to date()

    https://github.com/middlewares/access-log/blob/205cfd7d47c3523c60624815244851fa0a97ed1f/src/AccessLog.php#L182

    It seems like the default value for getRequestTime() isn't compatible with the changes. Default format should use date() format rather than strftime()

    example: Before -> [17/May/2022:10:51:10 -0600] After change -> [%17/%b/%2022:%10:%May:%th %136]

    opened by bbouchard-seedbox 1
  • AccessLog: added 3rd argument to context function: $message

    AccessLog: added 3rd argument to context function: $message

    For some structured logs, there may be a need to use the original message - which is not currently possible. Using this simple change, we can use the original message and not create it again manually.

    An example: when using ECS logging, we may need to put the original message 127.0.0.1 - - [01/Apr/2022:10:28:41 +0100] \"GET / HTTP/1.1\" 200 - into another field. Using elastic ECS logging, the target result shall be similar to:

    {
        "@timestamp": "2022-04-01T10:28:41.800328+00:00",
        "ecs.version": "1.2.0",
        "log.level": "INFO",
        "message": "127.0.0.1 - - [01/Apr/2022:10:28:41 +0100] \"GET / HTTP/1.1\" 200 -",
        "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:98.0) Gecko/20100101 Firefox/98.0",
        "event" {
            "original": "127.0.0.1 - - [01/Apr/2022:10:28:41 +0100] \"GET / HTTP/1.1\" 200 -"
        }
        ...
    }
    

    Currently, the event.original field is not possible to create. With this PR it is quite simple:

    $middleware = new AccessLog();
    $middleware->context(function(ServerRequestInterface $request, ResponseInterface $response, string $message): array {
    	return [
    		'user_agent' => $request->getHeaderLine('User-Agent'),
    		'event' => [
    			'type' => 'access',
    			'original' => $message,
    		],
    	];
    });
    
    opened by paveljanda 1
  • Write dash on empty body

    Write dash on empty body

    In http://httpd.apache.org/docs/current/mod/mod_log_config.html#formats it states that:

    %b | Size of response in bytes, excluding HTTP headers. In CLF format, i.e. a '-' rather than a 0 when no bytes are sent.

    opened by ajgarlag 1
  • Do not omit the identd position.

    Do not omit the identd position.

    This info is missed, so a dash must be written in its position.

    It represents the %l param of the Common Log format described in Apache documentation http://httpd.apache.org/docs/current/mod/mod_log_config.html

    opened by ajgarlag 1
  • Refactorized the code

    Refactorized the code

    This change uses strtr instead sprintf to generate the messages, providing more flexibility to customize the output format. It also fixes some bugs like append the uri's query to the path or replace %h value (ip) by %v (virtual host) instead prepend it.

    opened by oscarotero 0
Owner
Middlewares
PSR-15 HTTP Middlewares
Middlewares
Routes and Middleware for Using OAuth2 Server within a Slim Framework API

Chadicus\Slim\OAuth2 A collection of OAuth2 Server routes, middleware and utilities for use within a Slim 3 Framework API Requirements Chadicus\Slim\O

Chad Gray 126 Oct 8, 2022
A PHP implementation of ActivityPub protocol based upon the ActivityStreams 2.0 data format.

ActivityPhp ActivityPhp is an implementation of ActivityPub layers in PHP. It provides two layers: A client to server protocol, or "Social API" This p

Landrok 175 Dec 24, 2022
Log user authentication details and send new device notifications.

Laravel Authentication Log is a package which tracks your user's authentication information such as login/logout time, IP, Browser, Location, etc. as well as sends out notifications via mail, slack, or sms for new devices and failed logins.

John S Nwanosike 2 Mar 13, 2022
A Guzzle middleware to keep track of redirects

A Guzzle middleware to keep track of redirects This package contains middleware for Guzzle that allows you to track redirects that happened during a r

Spatie 17 Oct 9, 2022
PSR-7 and PSR-15 JWT Authentication Middleware

PSR-7 and PSR-15 JWT Authentication Middleware This middleware implements JSON Web Token Authentication. It was originally developed for Slim but can

Mika Tuupola 782 Dec 18, 2022
PSR-7 and PSR-15 HTTP Basic Authentication Middleware

PSR-7 and PSR-15 Basic Auth Middleware This middleware implements HTTP Basic Authentication. It was originally developed for Slim but can be used with

Mika Tuupola 430 Dec 30, 2022
Limit access to your Laravel applications by using invite codes

Doorman Doorman provides a way to limit access to your Laravel applications by using invite codes. Invite Codes: Can be tied to a specific email addre

Ashley Clarke 964 Dec 31, 2022
PHP class to generate and verify Google Authenticator 2-factor authentication

Google Authenticator PHP class Copyright (c) 2012-2016, http://www.phpgangsta.de Author: Michael Kliewe, @PHPGangsta and contributors Licensed under t

Michael Kliewe 2.1k Jan 2, 2023
An authorization library that supports access control models like ACL, RBAC, ABAC in PHP .

PHP-Casbin Documentation | Tutorials | Extensions Breaking News: Laravel-authz is now available, an authorization library for the Laravel framework. P

PHP-Casbin 1.1k Dec 14, 2022
Dynamic ACL is a package that handles Access Control Level on your Laravel Application.

Dynamic ACL Dynamic ACL is a package that handles Access Control Level on your Laravel Application. It's fast to running and simple to use. Install an

yasin 8 Jul 31, 2022
The Salla OAuth Client library is designed to provide client applications with secure delegated access to Salla Merchant stores.

Salla Provider for OAuth 2.0 Client This package provides Salla OAuth 2.0 support for the PHP League's OAuth 2.0 Client. To use this package, it will

Salla 14 Nov 27, 2022
Register ,Login , Logout , having access control

Helo what's up dude read by the name of creator lov3yp :D This script is inspired by Lov3yp#2018 And Burak karahan Installation steps: !- Import the s

Lov3yp 2 Nov 1, 2021
The easiest and most intuitive way to add access management to your Filament Resource Models through `spatie/laravel-permission`

Filament Shield The easiest and most intuitive way to add access management to your Filament Resource Models (more coming soon ?? ) One Plugin to rule

Bezhan Salleh 329 Jan 2, 2023
An authorization library that supports access control models like ACL, RBAC, ABAC in Laravel.

Laravel Authorization Laravel-authz is an authorization library for the laravel framework. It's based on Casbin, an authorization library that support

PHP-Casbin 243 Jan 4, 2023
Tech-Admin is Laravel + Bootstrap Admin Panel With User Management And Access Control based on Roles and Permissions.

Tech-Admin | Laravel 8 + Bootstrap 4 Tech-Admin is Admin Panel With Preset of Roles, Permissions, ACL, User Management, Profile Management. Features M

TechTool India 39 Dec 23, 2022
An authorization library that supports access control models like ACL, RBAC, ABAC for webman plugin

An authorization library that supports access control models like ACL, RBAC, ABAC for webman plugin

PHP-Casbin 18 Dec 30, 2022
Authentication, authorization and access control for PHP

Jasny Auth Authentication, authorization and access control for PHP. Features Multiple authorization strategies, like groups (for acl) and levels. Aut

Arnold Daniels 105 Dec 12, 2022
GUI manager for RBAC (Role Base Access Control) Yii2. Easy to manage authorization of user

RBAC Manager for Yii 2 GUI manager for RBAC (Role Base Access Control) Yii2. Easy to manage authorization of user ?? . Documentation Important: If you

MDMunir Software 1.2k Jan 7, 2023
Set up Laravel Auth guards using Eloquent in seconds

Nightguard Set up Auth guards using Eloquent in seconds. Introduction Laravel guards provide a super convenient way of authorizing different areas of

Luke Downing 10 Mar 18, 2021