PHPackages                             knotlog/knotlog - 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. [HTTP &amp; Networking](/categories/http)
4. /
5. knotlog/knotlog

ActiveLibrary[HTTP &amp; Networking](/categories/http)

knotlog/knotlog
===============

Wide logging implementation for PHP - one comprehensive, context-rich event per request

0.5.0(2mo ago)112.5k↓37.6%MITPHPPHP ^8.4CI passing

Since Dec 31Pushed 2mo agoCompare

[ Source](https://github.com/shadowhand/knotlog)[ Packagist](https://packagist.org/packages/knotlog/knotlog)[ RSS](/packages/knotlog-knotlog/feed)WikiDiscussions main Synced yesterday

READMEChangelogDependencies (29)Versions (11)Used By (0)

Knotlog
=======

[](#knotlog)

[![Become a Supporter](https://camo.githubusercontent.com/28a4011c597c1f2866c7419fcefd80ec11a8591e34f94612242c09e86e8a30dc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f70617472656f6e2d73706f6e736f722532306d652d6536343631612e737667)](https://www.patreon.com/shadowhand)[![Latest Stable Version](https://camo.githubusercontent.com/64173fe5d9e102babb58ce84a6424850e8a5c8b2dfa0375325dcad4036091786/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6b6e6f746c6f672f6b6e6f746c6f672e737667)](https://packagist.org/packages/knotlog/knotlog)[![License](https://camo.githubusercontent.com/caaeb233b17549d5241a4b2850f815dd2fe9fa7421dd33ac28a85bfb75b89fd3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6b6e6f746c6f672f6b6e6f746c6f672e737667)](https://github.com/shadowhand/knotlog/blob/master/LICENSE)[![Build Status](https://camo.githubusercontent.com/4c129a3559c710bbe0118cb466ea7c6418b578a3e72f1909629437aa159bc4d5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f736861646f7768616e642f6b6e6f746c6f672f74657374732e796d6c3f6272616e63683d6d61696e)](https://github.com/shadowhand/knotlog)

**Wide logging for PHP**

Knotlog is inspired by the ideas of [loggingsucks.com](https://loggingsucks.com) and implements wide logging as a first-class pattern in PHP. Avoid the pitfalls of traditional logging by using a single structured log event that captures all relevant context of a request as a canonical log line, dramatically improving observability and debugging capabilities.

Transform debugging from archaeological grep sessions into analytical queries with structured, queryable data.

The Problem with Traditional Logging
------------------------------------

[](#the-problem-with-traditional-logging)

Traditional logging is broken:

- **String search is ineffective**: Logs are treated as unstructured text, making it difficult to correlate events
- **Optimized for writing, not querying**: Developers emit what is convenient, not what is useful
- **Missing business context**: Standard logs lack the rich dimensionality needed for real investigations

The Wide Logging Solution
-------------------------

[](#the-wide-logging-solution)

Instead of asking "what is my code doing?", ask "what happened to this request?"

A proper wide event contains:

- Infrastructure context (service name, version, region, deployment)
- Request metadata (method, path, duration, status)
- User information (ID, subscription level, account age)
- Business data (cart contents, payment method, features enabled)
- Error details (type, code, message, stack trace)

Installation
------------

[](#installation)

```
composer require knotlog/knotlog
```

Requirements
------------

[](#requirements)

- PHP 8.4 or newer

Basic Usage
-----------

[](#basic-usage)

```
use Knotlog\Log;
use Knotlog\Writer\FileWriter;

$log = new Log();

// Build up context throughout your request
$log->set('user_id', $userId);
$log->set('request_method', $_SERVER['REQUEST_METHOD']);
$log->set('request_path', $_SERVER['REQUEST_URI']);
$log->set('subscription_tier', $user->subscriptionTier);
$log->set('cart_value', $cart->total());
$log->set('response_status', 200);
$log->set('duration_ms', $duration);

// At the end of the request, emit the wide event
new FileWriter()->write($log);
```

The `Log` class implements `JsonSerializable`, so it can be directly encoded to JSON for structured logging systems.

Collecting Multiple Entries
---------------------------

[](#collecting-multiple-entries)

Knotlog also has an `append()` method that allows adding multiple values under a single key, without overwriting:

```
$log->append('features', 'new_checkout');
$log->append('features', 'recommendations');
```

This is useful in situations where related items are populated by different parts of the codebase.

### Service Logging

[](#service-logging)

Additionally, Knotlog provides a `LogList` class that can be passed to dependencies and used to attach multiple entries under a single key. This is useful for cases where a service should be able to log multiple related items, without directly having access to the main `Log` instance, such as:

- Collecting external API calls
- Tracking database statements executed
- Recording multiple commands or queries in a CQRS system

```
use Knotlog\LogList;

$statements = new LogList();

// Attach the list to the main log.
$log->set('db', $statements);

// Pass the list to a database connection.
$db = new Connection(log: $statements, /* ... */);
```

Then, inside the service class (`Connection` in this example), use the `LogList` to add entries:

```
$this->log->push(
    // This class would be application-specific and is not provided by Knotlog
    new LogQuery(
        sql: 'SELECT * FROM users WHERE id = ?',
        params: [5513],
    )
);

// Push an entry for every query executed, or specific queries of interest.
$this->log->push(
    new LogQuery(
        sql: 'SELECT * FROM orders WHERE user_id = ?',
        params: [5513],
    ),
);
```

⚠️ *LogList entries MUST be objects. Complex objects SHOULD implement JsonSerializable.*

The `LogList` maintains insertion order and will encode as a JSON array:

```
{
  "db": [
    {"sql": "SELECT * FROM users WHERE id = ?", "params": [5513]},
    {"sql": "SELECT * FROM orders WHERE user_id = ?", "params": [5513]}
  ]
}
```

Exception Logging
-----------------

[](#exception-logging)

It is **not** recommended to add exception objects to Knotlog. Exception tracing is better handled by other systems, such as [Monolog](https://seldaek.github.io/monolog/) or another [PSR-3](https://www.php-fig.org/psr/psr-3/) logger.

For convenience, `Log` provides a `hasError()` method that will return true if either the `exception` or `error`keys are set in the log. This is particularly useful for determining if the log should be output when sampling is enabled.

HTTP Middleware
---------------

[](#http-middleware)

Knotlog provides a [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware to log request and response context.

```
use Knotlog\Http\LogRequestResponse;

// Logs request and response metadata
$stack->add(new LogRequestResponse($log));
```

Knotlog provides a middleware to log uncaught exception context and generate error responses.

```
use Knotlog\Http\LogRequestError;
use Knotlog\Http\ServerErrorResponseFactory;

// The error factory creates a response from a throwable
// The default factory creates a minimal 500 response
$errorFactory = new ServerErrorResponseFactory($responseFactory, $streamFactory);

// Logs uncaught exception type and message, and outputs an error response
$stack->add(new LogRequestError($errorFactory, $log));
```

Knotlog provides a middleware to flag every response with a 400+ status code as an error in the log. The error is set to the HTTP reason phrase (e.g., "Not Found", "Internal Server Error"). This is particularly useful when log sampling is in effect, ensuring that error responses are always logged.

```
use Knotlog\Http\LogResponseError;

// Sets error to the reason phrase for 400+ status codes
$stack->add(new LogResponseError($log));
```

When using these middleware, the order should be (from first to last):

- `LogResponseError` - execute the request, flag error responses
- `LogRequestResponse` - log the request, execute the request, log the response
- `LogRequestError` - catch uncaught exceptions, log them, generate error response

⚠️ *The order may depend on the application middleware stack. Some frameworks prefer a last-in-first-out order.*

Console Events
--------------

[](#console-events)

Knotlog provides a [Symfony Console](https://symfony.com/doc/current/components/console.html) event listener that logs command execution and error context.

```
use Knotlog\Console\LogCommandError;
use Knotlog\Console\LogCommandEvent;
use Symfony\Component\Console\ConsoleEvents;

// Logs command metadata on execution
$eventDispatcher->addListener(ConsoleEvents::COMMAND, new LogCommandEvent($log));

// Logs uncaught exception type and message
$eventDispatcher->addListener(ConsoleEvents::ERROR, new LogCommandError($log));
```

If you prefer not to use the event system, you can manually log console context:

```
use Knotlog\Console\LogCommand;

// Log command metadata during execution
$log->set('console', LogCommand::fromCommand($command, $input));
```

Log Writers
-----------

[](#log-writers)

Knotlog provides a `LogWriter` interface to enable flexible output destinations for wide log events. The interface defines a contract with a single method `write(Log $log): void`.

### FileWriter

[](#filewriter)

The `FileWriter` writes log events to a file.

```
use Knotlog\Writer\FileWriter;

// Write to stderr (default)
$writer = new FileWriter();

// Write to a specific file
$writer = new FileWriter('/var/log/app.log');

// Write the log event
$writer->write($log);
```

### LoggerWriter

[](#loggerwriter)

The `LoggerWriter` outputs log events to any [PSR-3](https://www.php-fig.org/psr/psr-3/) compatible logger using message interpolation.

```
use Knotlog\Writer\LoggerWriter;

// Use with any PSR-3 logger
$writer = new LoggerWriter($psrLogger);

// Customize the message and error keys
$writer = new LoggerWriter($psrLogger, messageKey: 'msg', errorKey: 'err');

// Write the log event
$writer->write($log);
```

The writer automatically routes log events to the appropriate log level:

- `error()` - when the log contains an error or exception (uses `{error}` placeholder)
- `info()` - for all other log events (uses `{message}` placeholder)

The entire log context is passed to the logger, allowing it to format and process the data according to its own implementation. The message key can be customized to match your logging schema.

### SampledWriter

[](#sampledwriter)

The `SampledWriter` is a decorator that samples log events based on a configurable rate, while always logging errors.

```
use Knotlog\Writer\SampledWriter;
use Knotlog\Writer\FileWriter;

// Sample 1 in 5 requests (20%)
$writer = new SampledWriter(new FileWriter(), 5);

// Sample 1 in 100 requests (1%)
$writer = new SampledWriter(new FileWriter(), 100);

// Write the log event (might be sampled out unless it's an error)
$writer->write($log);
```

The sampled writer ensures that:

- All log events with errors or exceptions are always written (sampling is bypassed)
- Non-error events are sampled at the specified rate
- The sampling decision is made once at construction time and applies to all writes

This is particularly useful for high-traffic applications where logging every successful request would be prohibitively expensive, while still capturing all errors for debugging.

### ToggledWriter

[](#toggledwriter)

The `ToggledWriter` is a decorator that allows log writing to be enabled or disabled at runtime.

```
use Knotlog\Writer\ToggledWriter;
use Knotlog\Writer\FileWriter;

// Enabled by default
$writer = new ToggledWriter(new FileWriter());

// Or start disabled
$writer = new ToggledWriter(new FileWriter(), writeLogs: false);

// Disable writing at any point
$writer->disable();

// Re-enable writing
$writer->enable();

// Only writes if enabled
$writer->write($log);
```

This is useful for conditionally disabling log output based on runtime configuration, such as feature flags or environment-specific settings.

Log Formatters
--------------

[](#log-formatters)

Knotlog provides a `LogFormatter` interface to enable flexible formatting of log lines. The interface defines a contract with a single method `format(Log $log): string`.

### JsonFormatter

[](#jsonformatter)

The `JsonFormatter` formats log events as JSON strings. Additional flags may be passed through to `json_encode`:

```
$formatter = new JsonFormatter(JSON_PRETTY_PRINT);
```

License
-------

[](#license)

MIT License, see `LICENSE` file for details.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance84

Actively maintained with recent releases

Popularity22

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

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 ~24 days

Total

5

Last Release

84d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/38203?v=4)[Woody Gilk](/maintainers/shadowhand)[@shadowhand](https://github.com/shadowhand)

---

Top Contributors

[![shadowhand](https://avatars.githubusercontent.com/u/38203?v=4)](https://github.com/shadowhand "shadowhand (27 commits)")

---

Tags

psr-7psr-3logginglogspsr-15loggercontextualstructuredwideknot

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[aws/aws-sdk-php

AWS SDK for PHP - Use Amazon Web Services in your PHP project

6.3k543.5M2.6k](/packages/aws-aws-sdk-php)[psr/http-server-handler

Common interface for HTTP server-side request handler

180114.7M1.2k](/packages/psr-http-server-handler)[psr/http-server-middleware

Common interface for HTTP server-side middleware

185103.9M1.9k](/packages/psr-http-server-middleware)[league/route

Fast routing and dispatch component including PSR-15 middleware, built on top of FastRoute.

6683.3M145](/packages/league-route)[analog/analog

Fast, flexible, easy PSR-3-compatible PHP logging package with dozens of handlers.

3511.6M24](/packages/analog-analog)[mezzio/mezzio

PSR-15 Middleware Microframework

3923.8M125](/packages/mezzio-mezzio)

PHPackages © 2026

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