PHPackages                             terrazza/logger - 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. terrazza/logger

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

terrazza/logger
===============

logger

1.0.0(4y ago)0812MITPHPPHP &gt;=7.4

Since May 23Pushed 4y agoCompare

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

READMEChangelog (1)Dependencies (3)Versions (2)Used By (2)

Terrazza/Logger
===============

[](#terrazzalogger)

This component is an implementation of PSR/Log standard with some extensions.

*Structure*
-----------

[](#structure)

1. the [Logger](#object-logger) component
    has to be initialized with 0-n [ChannelHandler](#object-channel-handler)
    and provides the common known methods:
    - warning
    - error
    - notice
    - ...
2. the [ChannelHandler](#object-channel-handler) component
    is responsible to determine
    1. the target/writer (required)
    2. the recordFormatter (required)
    3. a channelFilter (optional)
    4. all related [LogHandler](#object-log-handler) for this channel
3. the [LogHandler](#object-log-handler) component
    determines
    - the logLevel
    - the format (optional, default: from ChannelHandler-&gt;recordFormatter)

*The Terrazza/Logger component differ to the common PSR/Log implementation in handling the "Format". The Writer Component handles multiple "rows" and combines it. Within this difference its possible to forward a transformed format and keep his keys per row.
For example: write the message/format into a json object or db.*

*Object/Classes*
----------------

[](#objectclasses)

1. [Logger](#object-logger)
    1. [method: registerChannelHandler](#object-logger-registerChannelHandler)
    2. [method: registerExceptionHandler](#object-logger-registerExceptionHandler)
    3. [method: registerErrorHandler](#object-logger-registerErrorHandler)
    4. [method: registerFatalHandler](#object-logger-registerFatalHandler)
    5. [method: setExceptionFileName](#object-logger-setExceptionFileName)
    6. [constructor: context (array)](#object-logger-constructor-context)
2. Handler
    1. [ChannelHandler](#object-channel-handler)
    2. [LogHandler](#object-log-handler)
3. [LogRecord](#object-record)
    1. [LogRecordTrace](#object-record-trace)
4. [LogRecordFormatter](#object-log-record-formatter)
5. [LogHandlerFilter](#object-log-handler-filter)
6. [Converter](#object-converter)
7. [Install](#install)
8. [Requirements](#require)
9. [Examples](#examples)

### Logger

[](#logger)

The Logger object/methods is/are close to the common PSR implementations but!
The Logger is initialized with channelHandler(s) and not Handler

> each channelHandler executes only one logHandler

#### method: registerChannelHandler

[](#method-registerchannelhandler)

adds a channelHandler to the logger (not immutable).

#### method: registerExceptionHandler

[](#method-registerexceptionhandler)

register a callback for php exception handler.

> well-developed projects should handle/cover all exceptions by themselves, but ;-)

#### method: registerErrorHandler

[](#method-registererrorhandler)

register a callback for php error handler.

> sometime this kind of errors can't be catched without this workaround

#### method: registerFatalHandler

[](#method-registerfatalhandler)

register a callback for php shutdown.

> sometime this kind of errors can't be catched without this workaround

#### method: setExceptionFileName

[](#method-setexceptionfilename)

The method:addMessage itself is covered with try/catch.
The catch handler writes the Exception.Message to a file which can be set with the method setExceptionFileName.

> notice:
> default: php://stderr

#### constructor: context (array)

[](#constructor-context-array)

The logger can be initialized, next to the name, with an initialized context.
This context can be addressed separately.

*example of usage*
a class is injected with the component and inside the constructor

```
$logger = new Logger("name", ["user" => "Value"]);
$logger->notice("hello", ["my" => "value"]);
$format = ["{Context.my} {iContext.user}"];

```

### Handler

[](#handler)

#### ChannelHandler

[](#channelhandler)

A ChannelHandler collects [LogHandler](#object-log-handler) to the same channel and provides

- the same writer
- the same formatter
    for each [LogHandler](#object-log-handler).

A ChannelHandler can be registered through the [Logger](#object-logger) with

- the [method: registerChannelHandler](#object-logger-registerChannelHandler)
- the \_\_constructor (3rd argument as variadic)

##### method: getWriter

[](#method-getwriter)

##### method: getFormatter

[](#method-getformatter)

##### method: getFilter

[](#method-getfilter)

##### method: getLogHandler (LogHandlerInterface\[\])

[](#method-getloghandler-loghandlerinterface)

##### method: pushLogHandler

[](#method-pushloghandler)

Method to add a new [LogHandler](#object-log-handler).
The logHandler-array will be key-sorted, to prevent multiple write transaction for different LogLevels.

##### method: getEffectedHandler

[](#method-geteffectedhandler)

return the matched [LogHandler](#object-log-handler) for a given LogRecord.

##### method: writeRecord

[](#method-writerecord)

for a passed [LogHandler](#object-log-handler) the record will be

- formatted
- and written to the Writer

#### LogHandler

[](#loghandler)

The SingleHandler provides the common way to create a handler for a Logger. The only difference to the common implementation:

- instead of logLevel
- the SingleHandler has to be injected within a [Channel](#object-channel)

### LogRecord

[](#logrecord)

Against the common PSR implementation our component deals with an object and not an array.
LogRecord properties:

- logDate (\\Datetime)
- loggerName (string)
- logLevel (int)
- logMessage (string)
- memUsed (int)
- memAllocated (int)
- [LogRecordTrace](#object-record-trace)
- context (array)
- initContext (array)

additional, the object provides

- logLevelName (string)

#### method/static createRecord

[](#methodstatic-createrecord)

this method is used inside *Logger* to create a new LogRecord object.

#### method: getToken()

[](#method-gettoken)

this method is used in the *LogRecordFormatterInterface* to get the LogRecord "encoded". Every element can be accessed through his "format" e.g. {Level}{LevelName}{Context.name}

```
return [
  'Date'         => $this->getLogDate(),
  'Level'        => $this->getLogLevel(),
  'LevelName'    => $this->getLogLevelName(),
  'LoggerName'   => $this->getLoggerName(),
  'MemUsed'      => $this->getMemUsed(),
  'MemAllocated' => $this->getMemAllocated(),
  'Message'      => $this->getLogMessage(),
  'Context'      => $this->getContext(),
  'iContext'     => $this->getInitContext(),
  'Trace'        => [
    "Namespace"    => $this->getTrace()->getNamespace(),
    "Line"         => $this->getTrace()->getLine(),
    "Classname"    => $this->getTrace()->getClassname(),
    "Function"     => $this->getTrace()->getFunction(),
    "Method"       => $this->getTrace()->getClassname()."::".$this->getTrace()->getFunction(),
    "sMethod"      => basename($this->getTrace()->getClassname())."::".$this->getTrace()->getFunction(),
  ]
]

```

### LogRecordTrace

[](#logrecordtrace)

The LogRecordTrace object is generated in the [Logger](#object-logger) during a [LogRecord](#object-record) is created.
Base on *debug\_backtrace(DEBUG\_BACKTRACE\_IGNORE\_ARGS)* every Record get additional properties:

- Namespace
- Classname
- Function
- Line

### LogRecordFormatter

[](#logrecordformatter)

The LogRecordFormatter converts/maps a record to an array
. Initialized properties:

- NonScalarConverterInterface
- format (array)
- valueConverter (array, optional)

#### NonScalarConverter (NonScalarConverterInterface)

[](#nonscalarconverter-nonscalarconverterinterface)

The NonScalarConverter convert a nonScalar value (e.g. from Context) into a string.
Actually the provided class *NonScalarJsonEncode* use json\_encode and prefix it with the attribute name.

The NonScalarConverter is used, when a formatter-line includes a nonScalar and a scalar content.

*example of usage*:

```
use Terrazza\Component\Logger\Converter\NonScalar\NonScalarJsonConverter;

$record = ["message" => "myMessage", "key" => ["value1", "value2"]];
echo (new NonScalarJsonEncode())->getValue($context["key"]); // key:{"value1", "value2"}

// in context of the formatter it will be
$format = ["{Message}:{Context.key}"];                 // ... myMessage:key:{"value1", "value2"}
$format = ["Context" => "{Message}:{Context.key}"];    // ... myMessage:key:{"value1", "value2"}

```

a ValueConverter (LogRecordValueConverterInterface) can be used to convert special value based on his key.

#### method: pushConverter

[](#method-pushconverter)

to map/convert a special value, based on his key, push a special converter.
This converter has to fulfill LogRecordValueConverterInterface.

#### method: formatRecord

[](#method-formatrecord)

Maps the Record against the $format and returns a mapped array.
Unknown patterns (e.g. {undefined}) are removed from the response.
Empty "Lines" are also removed.

##### example

[](#example)

The example uses an additional ValueConverter for the Record value "Date".

```
use DateTime;
use Terrazza\Component\Logger\LogRecordValueConverterInterface;
use Terrazza\Component\Logger\LOgRecord;
use Terrazza\Component\Logger\Formatter\LogRecordFormatter;
use Terrazza\Component\Logger\Converter\NonScalar\NonScalarJsonEncode;

class RecordTokenValueDate implements LogRecordValueConverterInterface {
    private string $dateFormat;
    public function __construct(string $dateFormat="Y-m-d H:i:s.u") {
        $this->dateFormat                           = $dateFormat;
    }
    public function getValue($value) {
        return $value->format($this->dateFormat);
    }
}

$formatter = new LogRecordFormatter(
   new NonScalarJsonEncode,
   ["Date", "Message"]
);
$formatter->pushConverter("Date", new RecordTokenValueDate);

$record  = LogRecord::create("LoggerName", 100, "myMessage");
var_dump($formatter->formatRecord($record));
/*
[
   "Date" => 2022-12-31 23:59:01,
   "Message" => "myMessage"
]
*/

```

### LogHandlerFilter

[](#loghandlerfilter)

[LogHandler](object-log-handler) can have a LogHandlerFilter.
Properties:

- include (array, optional)
- exclude (array, optional)
- start (array, optional)

#### method: isHandling (string $callerNamespace) : bool

[](#method-ishandling-string-callernamespace--bool)

**include**
preg\_match callerNamespace against include patterns
**exclude**
preg\_match callerNamespace against exclude patterns
**start**
preg\_match callerNamespace against start patterns
if preg\_match is true all further isHandling will be true. *(exclude filter overrules start)*

### Converter

[](#converter)

A [LogRecord](#object-record) will be first converted/mapped with the [RecordFormatter](#object-formatter)
Afterwards, it depends on the target/writer the array has to be formatted again.

We actually include/provide two Converter:

- convert to a string, json type
- convert to a string, e.g. for console logging In any case the Converter is injected into the [Writer](#object-writer-stream).

#### FormattedRecordFlat

[](#formattedrecordflat)

Converts the mapped LogRecord into a string within a delimiter for each row.
For nonScalar values we use json\_encode to convert the value.

##### method: setNonScalarPrefix(string $delimiter)

[](#method-setnonscalarprefixstring-delimiter)

by using this method nonScalar values will be prefixed with the dataKey and the delimiter.
arguments:

- delimiter (string, required)
- encodingFlags (int, optional)

*example of usage*:

```
use Terrazza\Component\Logger\Converter\FormattedRecord\FormattedRecordFlat;

$formatter = new FormattedRecordFlat("|",0);
echo $formatter->convert(["message" => "myMessage", "context" => ["k" => "v"]);
//myMessage|{"k":"v"}

$formatter->setNonScalarPrefix(":");
echo $formatter->convert(["message" => "myMessage", "context" => ["k" => "v"]);
//myMessage|context:{"k":"v"}

```

#### FormattedRecordJson

[](#formattedrecordjson)

Converts the mapped LogRecord into a string by using json\_encode.
arguments:

- encodingFlags (int, optional)

*example of usage*:

```
use Terrazza\Component\Logger\Converter\FormattedRecord\FormattedRecordJson;

$formatter = new FormattedRecordJson(0);
echo $formatter->convert(["message" => "myMessage", "context" => ["k" => "v"]);
//{"message" : "myMessage", "context": {"k":"v"}}

```

### Writer

[](#writer)

#### StreamFile

[](#streamfile)

Save converted record to a file.
arguments:

- converter (IFormattedRecordConverter, required)
- filename (string required)
- flags (int, optional, default: 0)

> the converter should convert the formatted LogRecord into a string.

```
use Terrazza\Component\Logger\Writer\StreamFile;
use Terrazza\Component\Logger\Converter\FormattedRecord\FormattedRecordFlat;

$logFile    = "log.txt";
@unlink($logFile);
$converter  = new FormattedRecordFlat("|",0);
$writer     = new StreamFile($converter, $logFile);
$writer->write(["message" => "myMessage", "context" => ["k" => "v"]);

$logContent = file_get_contents($logFile);
echo $logContent;
//{"message" : "myMessage", "context": {"k":"v"}}

```

How to install
--------------

[](#how-to-install)

### Install via composer

[](#install-via-composer)

```
composer require terrazza/logger

```

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

[](#requirements)

- php &gt;= 7.4

### composer packages

[](#composer-packages)

- psr/log

Examples
--------

[](#examples)

### 1. create a ChannelHandler

[](#1-create-a-channelhandler)

```
use Terrazza\Component\Logger\Converter\FormattedRecord\FormattedRecordFlat;
use Terrazza\Component\Logger\Writer\StreamFile;
use Terrazza\Component\Logger\Formatter\RecordFormatter;
use Terrazza\Component\Logger\Converter\NonScalar\NonScalarJsonEncode;
use Terrazza\Component\Logger\Handler\ChannelHandler;

$writeConverter   = new FormattedRecordFlat("|",0);
$writer           = new StreamFile($writeConverter, "test.log");
$formatter        = new RecordFormatter(new NonScalarJsonEncode(), [
   "Message" => "{Level}-{Message}-{Context.pid}"
]);
$channelHandler   = new ChannelHandler($writer, $formatter);

```

#### 2. create a LogHandler

[](#2-create-a-loghandler)

> notice
> next code lines depends on previous example... (create a ChannelHandler)

```
use Terrazza\Component\Logger\Handler\LogHandler;
use Terrazza\Component\Logger\Logger;

$handler          = new LogHandler(Logger::WARNING);
// push handler into previouse create channelHandler
$channelHandler->pushLogHandler($handler);

```

### 3. create within a handler

[](#3-create-within-a-handler)

> notice:
> next code lines depends on previous example... (create a LogHandler)

```
use Terrazza\Component\Logger\Logger;

// additinal we initialize the Context with pid = getmypid
// the formatter uses {Context.pid} and will print it

$logger           = new Logger("loggerName", ["pid" => "myPID"], $channelHandler);
$logger->error($message = "message");

```

### create and registerChannelHandler

[](#create-and-registerchannelhandler)

```
use Terrazza\Component\Logger\Logger;

$logger           = new Logger("loggerName", ["pid" => getmypid()]);
$logger           = $logger->registerChannelHandler($channelHandler);
$logger->error($message = "message");

```

### Usage of Logger

[](#usage-of-logger)

#### produce a NOTICE

[](#produce-a-notice)

```
$logger->notice("myMessage");
// by using our examples above this message will not be printed
// ...cause the logLevel for the Handler is WARNING

```

#### produce an ERROR

[](#produce-an-error)

```
$logger->error("myMessage");
// output to file will be: 400-myMessage-myPID

```

###  Health Score

23

—

LowBetter than 26% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity9

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

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

Unknown

Total

1

Last Release

1491d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/175504887?v=4)[webfux](/maintainers/webfux)[@webfux](https://github.com/webfux)

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[sentry/sentry

PHP SDK for Sentry (http://sentry.io)

1.9k240.0M314](/packages/sentry-sentry)[matomo/matomo

Matomo is the leading Free/Libre open analytics platform

21.6k38.2k](/packages/matomo-matomo)[illuminate/log

The Illuminate Log package.

6225.0M601](/packages/illuminate-log)[tempest/framework

The PHP framework that gets out of your way.

2.2k31.1k12](/packages/tempest-framework)[api-platform/metadata

API Resource-oriented metadata attributes and factories

244.5M182](/packages/api-platform-metadata)[pagemachine/typo3-formlog

Form log for TYPO3

23233.9k7](/packages/pagemachine-typo3-formlog)

PHPackages © 2026

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