PHPackages                             timdev/timdev-log - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. timdev/timdev-log

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

timdev/timdev-log
=================

(Very) opinionated structured logging for PHP. Probably not for you.

0.1.2(4y ago)051MITPHPPHP ^8.0

Since Sep 26Pushed 4y ago1 watchersCompare

[ Source](https://github.com/timdev/timdev-log)[ Packagist](https://packagist.org/packages/timdev/timdev-log)[ RSS](/packages/timdev-timdev-log/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (9)Versions (4)Used By (0)

timdev/log
==========

[](#timdevlog)

> (Very) Opinionated, structured, logging for PHP. Probably not for you.

- Build on top of [monolog](https://github.com/Seldaek/monolog) and [timdev/stack-logger](https://git.timdev.com/tim/php-stack-logger).
- Logs are structured as [ndjson](http://ndjson.org/)

Goals
-----

[](#goals)

This package represents my (admittedly evolving) approach to logging for PHP applications. It composes [timdev/stack-logger](https://github.com/timdev/php-stack-logger/) with [monolog](https://github.com/Seldaek/monolog) to produce a distinct flavor of [ndjson](http://ndjson.org/) logs.

The main goal is to reduce the number of things I need to decide or remember when setting up logging in PHP application. Therefore, configuration knobs are intentionally minimized.

The Logger
----------

[](#the-logger)

The logger extends timdev/stack-logger's MonologStackLogger, providing a static factory with only three scalar arguments (only one of which is required). It also provides a couple of convenience methods to help log application events and exceptions. And that's it.

Included Middleware
-------------------

[](#included-middleware)

StackLogger opens up some nice possibilities. Particularly in middleware-based web applications, it can be nice to add some persistent context to the logger instance early in the request, so it's included in all subsequent logging calls.

This library includes several StackLogger-aware PSR-15-compatible middleware that I've used in web app projects.

### TimDev\\Log\\Middleware\\LogRequestAttributes

[](#timdevlogmiddlewarelogrequestattributes)

Extracts request attributes from the PSR7 ServerRequest and adds them as context to the logger.

Example:

```
use Psr\Http\Message\ServerRequestInterface as SRI;
use TimDev\Log\Middleware\LogRequestAttributes;

$middleware = new LogRequestAttributes(
    // A StackLogger instance
    $logger,
    // map of context-key => request-attribute name | callable
    [
        // Extract 'user_id' attribute from request, and set the 'uid'
        // context value on the logger.
        'uid' => 'user_id',

        // The above is a shortcut for:
        'uid2' => fn(SRI $req) => $req->getAttribute('user_id'),

        // If you want other data from the request, you can use the same pattern
        // to get it. For example:
        'ref' => fn(SRI $req) => $req->getHeader('Referer')[0] ?? null
    ];
);
```

The middleware will not set context keys for `null` values.

For more example usage, see the [tests](tests/Middleware/LogRequestAttributesTest.php)

### TimDev\\Log\\Middleware\\DevelopmentRedirect

[](#timdevlogmiddlewaredevelopmentredirect)

This middleware strips the `Location` header from redirect-responses and replaces the body with basic HTML document that includes a meta-refresh tag.

This is handy if you're using something like Monolog's BrowserConsoleHandler that relies on emitting javascript for the browser to execute in order to push log messages to the browser's console.

Example:

```
use Psr\Http\Message\ServerRequestInterface as SRI;
use TimDev\Log\Middleware\DevelopmentRedirect;

// Seconds to delay before refreshing. Default is zero.
$delaySeconds = 2;
$middleware = new DevelopmentRedirect($delaySeconds);
```

This middleware should usually be added *early* in your pipeline, since it only touches the response, and you want the response-mutation to happen last or nearly-last. In my projects, I typically do something like this:

```
// ErrorHandler is the outermost middleware.
$app->pipe(ErrorHandler::class);
// If we're adding it, the DR middlware is the second outer-most.
if (getenv('APP_ENV') === 'development'){
    $app->pipe(new DevelopmentRedirect(1));
}
// ... all the rest of my middlewares.
```

Framework Integration
---------------------

[](#framework-integration)

### Mezzio

[](#mezzio)

To date, I've been using this setup with [Mezzio](https://github.com/mezzio/mezzio)-based applications.

This package provides a [ConfigProvider](src/ConfigProvider.php) and a [LoggerFactory](src/DI/LoggerFactory.php).

To set this logger up in your mezzio project, just add the ConfigProvider in your config, and you'll have a logger in your container:

```
$logger = $container->get(\TimDev\Log\Logger::class);

// It's a PSR3 logger!
$logger->info('I can do PSR3 things ...');

// It's a StackLogger!
$childLogger = $logger->withContext(['some' => 'context']);
$childLogger->debug('foo');

// You can throw exceptions at it!
$ex = new \LogicException('Ya dun goofed!');
$logger->exception($ex);

// etc
```

You can configure the logger in any of your `config/autoload/*.php` files as appropriate. A full configuration might look like:

**config/autoload/timdev\_log.local.php**

```
return [
    'timdev' => [
        'log' => [
            'name'    => 'my-app',              // default: 'app'
            'logfile' => 'data/logs/app.log'    // default: 'php://stdout'
            'enable_browser_console' => true,   // default: false
            'dev_redir_delay_seconds' => 2      // default: 0
        ]
    ]
];
```

###  Health Score

23

—

LowBetter than 26% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity8

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

3

Last Release

1741d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/4eb475c7f4d3d1df5053f83417bf4e756a35b59d1686cd7d379055da2828017f?d=identicon)[timdev](/maintainers/timdev)

---

Top Contributors

[![timdev](https://avatars.githubusercontent.com/u/513999?v=4)](https://github.com/timdev "timdev (18 commits)")

### Embed Badge

![Health badge](/badges/timdev-timdev-log/health.svg)

```
[![Health](https://phpackages.com/badges/timdev-timdev-log/health.svg)](https://phpackages.com/packages/timdev-timdev-log)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

34.8k543.8M20.1k](/packages/laravel-framework)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k15](/packages/tempest-framework)[cakephp/cakephp

The CakePHP framework

8.9k19.5M1.8k](/packages/cakephp-cakephp)[phpro/grumphp

A composer plugin that enables source code quality checks.

4.3k16.7M1.0k](/packages/phpro-grumphp)[spatie/flare-client-php

Send PHP errors to Flare

177161.5M23](/packages/spatie-flare-client-php)[getgrav/grav

Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS

15.6k86.4k1](/packages/getgrav-grav)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
