Claude Skill

bitrix-logger

Covers PSR-3 logging in Bitrix — Bitrix\Main\Diag\Logger, FileLogger, SysLogger, NullLogger, LogFormatter, loggers section in .settings.php, named kernel loggers (main.Default, main.HttpClient, main.GeoIpManager, main.EventLog.*), integration with Monolog and third-party PSR-3 lo

LLM Mart · 0 points · 12 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download bxmaximum-bitrix-framework-skills-skills_bitrix-logger-66c40e0.zip · 3 KB
Part of bxmaximum/bitrix-framework-skills — 38 skills

Install

skills CLI npx skills add https://github.com/bxmaximum/bitrix-framework-skills/tree/main/skills/bitrix-logger
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install bxmaximum-bitrix-framework-skills@llmmart
Git git clone https://github.com/bxmaximum/bitrix-framework-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole bxmaximum/bitrix-framework-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Logging in Bitrix (PSR-3)

Bitrix follows the PSR-3 standard. In code, inject \Psr\Log\LoggerInterface, and in .settings.php, configure the specific implementation. Direct calls to AddMessage2Log are legacy; in new code, write via DI logger.

Built-in Implementations

All are in the \Bitrix\Main\Diag\ namespace:

Class Purpose
Logger Abstract base class; Logger::create('id', $params) creates a logger via factory
FileLogger Into a file, with auto-rotation when $maxLogSize is exceeded (default 1 MB)
SysLogger Into system syslog via openlog/syslog
EventLogger Into b_event_log table (Admin Panel → Event Log)
LogFormatter Default formatter: interpolates {placeholder}, renders exceptions and stacks
JsonLinesFormatter From 25.300.0; one JSON line per entry, convenient for ELK/Loki

Levels are constants of \Psr\Log\LogLevel::* (emergency, alert, critical, error, warning, notice, info, debug).

Service with Logger (DI — Recommended)

<?php declare(strict_types=1);

namespace Vendor\Module\Application\Service;

use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;

final class PostService
{
    public function __construct(
        private readonly LoggerInterface $logger = new NullLogger(),
    ) {}

    public function publish(int $postId): void
    {
        try
        {
            // ...
            $this->logger->info('Post {id} published', ['id' => $postId]);
        }
        catch (\Throwable $e)
        {
            $this->logger->error('Publish failed for post {id}: {exception}', [
                'id' => $postId,
                'exception' => $e,
            ]);
            throw $e;
        }
    }
}

Registration in /local/modules/vendor.module/.settings.php:

'services' => [
    'value' => [
        \Vendor\Module\Application\Service\PostService::class => [
            'constructor' => static fn (): \Vendor\Module\Application\Service\PostService =>
                new \Vendor\Module\Application\Service\PostService(
                    new \Bitrix\Main\Diag\FileLogger('/var/log/bitrix/post-service.log'),
                ),
        ],
    ],
    'readonly' => true,
],

PSR-3 Placeholders

Message is a template with {key}, values are taken from $context:

$logger->warning('User {userId} tried {action} on post {postId}', [
    'userId' => $uid, 'action' => 'delete', 'postId' => $pid,
]);

Special keys understood by LogFormatter:

  • {date} — current time (interpolated automatically).
  • {host} — HTTP_HOST (automatic).
  • {delimiter} — entry separator (automatic).
  • {exception} — \Throwable object → formats class, message, stack trace.
  • {trace} — manual stack trace: Diag\Helper::getBackTrace(6, DEBUG_BACKTRACE_IGNORE_ARGS, 3).

Enable arguments in stack trace:

$logger->setFormatter(new \Bitrix\Main\Diag\LogFormatter(showArguments: true, argMaxChars: 120));

Configuration via .settings.php — loggers section

Allows overriding loggers for named kernel points (main.HttpClient, main.Default, main.GeoIpManager) and your own identifiers.

return [
    'services' => [
        'value' => [
            'formatter.withArgs' => [
                'className' => \Bitrix\Main\Diag\LogFormatter::class,
                'constructorParams' => [true],
            ],
        ],
        'readonly' => true,
    ],
    'loggers' => [
        'value' => [
            'main.Default' => [
                'constructor' => static fn () => new \Bitrix\Main\Diag\FileLogger(
                    '/var/log/bitrix/app.log', 10 * 1024 * 1024,
                ),
                'level'     => \Psr\Log\LogLevel::INFO,
                'formatter' => 'formatter.withArgs',
            ],

            'main.HttpClient' => [
                'constructor' => static function (
                    \Bitrix\Main\Web\Http\DebugInterface $debug,
                    \Psr\Http\Message\RequestInterface $request,
                ) {
                    $debug->setDebugLevel(\Bitrix\Main\Web\HttpDebug::ALL);
                    return new \Bitrix\Main\Diag\FileLogger(
                        '/var/log/bitrix/http-' . spl_object_hash($request) . '.log',
                    );
                },
                'level' => \Psr\Log\LogLevel::DEBUG,
            ],

            'vendor.module.myLogger' => [
                'constructor' => static fn () => new \Bitrix\Main\Diag\FileLogger(
                    '/var/log/bitrix/vendor.module.log',
                ),
                'level' => \Psr\Log\LogLevel::DEBUG,
            ],
        ],
        'readonly' => true,
    ],
];

Important

  • constructor closures must be in .settings.php / .settings_extra.php — the file is not edited by Admin Panel, closures are not serialized.

  • level — threshold level; logger ignores messages below this.

  • formatter — key from services section.

  • Retrieving logger in code:

    $logger = \Bitrix\Main\Diag\Logger::create('vendor.module.myLogger');
    $logger = \Bitrix\Main\Diag\Logger::create('vendor.module.myLogger', [$this, $extraArg]);
    

Named Kernel Points

ID Used In Factory Parameters
main.Default AddMessage2Log, general default LOG_FILENAME, $showArgs
main.HttpClient Bitrix\Main\Web\HttpClient (including legacy and PSR-18) DebugInterface $debug, RequestInterface $request
main.GeoIpManager Bitrix\Main\Service\GeoIp\Manager —
main.EventLog.SysLogger CEventLog → syslog path —
main.EventLog.FileLogger CEventLog → file path $path, $maxSize

There are no named loggers main.Mail or main.Engine. Prefer constructor closures for FileLogger (see examples above) over className/settings arrays.

Configuring these loggers redirects all kernel calls — convenient for auditing external calls (see example in bitrix-http-client).

LoggerAware + Factory

For classes that should be supplied with a logger "by identifier":

final class Indexer implements \Psr\Log\LoggerAwareInterface
{
    use \Psr\Log\LoggerAwareTrait;

    public function run(): void
    {
        $this->ensureLogger()->info('Indexing started');
    }

    private function ensureLogger(): \Psr\Log\LoggerInterface
    {
        if ($this->logger === null)
        {
            $this->setLogger(\Bitrix\Main\Diag\Logger::create('vendor.module.indexer', [$this]));
        }
        return $this->logger;
    }
}

Monolog via Composer

composer require monolog/monolog

Integration into .settings.php:

'loggers' => [
    'value' => [
        'vendor.module.external' => [
            'constructor' => static function () {
                $log = new \Monolog\Logger('vendor.module');
                $log->pushHandler(new \Monolog\Handler\StreamHandler('/var/log/bitrix/monolog.log'));
                return $log;
            },
            'level' => \Psr\Log\LogLevel::DEBUG,
        ],
    ],
],

Checklist

  • PSR-3 standard followed (placeholders, context, exception key).
  • Loggers are configured via .settings.php rather than hardcoded in services.
  • Threshold level is set for each environment.
  • Loggers for external integrations (HttpClient) are redirected to separate files for audit.
  • For heavy load, JsonLinesFormatter is used for external collectors.
  • Logs are stored outside DOCUMENT_ROOT or protected by .htaccess.
  • Sensitive data (passwords, tokens) are stripped from context before logging.

Link exception_handling.log in .settings.php with named loggers for unified error tracking. See skill bitrix-settings.

Files (bitrix-framework-skills)
  • SKILL.md 8.2 KB
    ---
    name: bitrix-logger
    description: Covers PSR-3 logging in Bitrix — Bitrix\Main\Diag\Logger, FileLogger, SysLogger, NullLogger, LogFormatter, loggers section in .settings.php, named kernel loggers (main.Default, main.HttpClient, main.GeoIpManager, main.EventLog.*), integration with Monolog and third-party PSR-3 loggers. Applied when configuring module logs, debugging integrations, gathering errors from specific kernel components and log rotation. Key terms — Logger, FileLogger, SysLogger, LogFormatter, PSR-3, Monolog, loggers config, log level.
    ---
    
    # Logging in Bitrix (PSR-3)
    
    Bitrix follows the PSR-3 standard. In code, inject `\Psr\Log\LoggerInterface`, and in `.settings.php`, configure the specific implementation. Direct calls to `AddMessage2Log` are legacy; in new code, write via DI logger.
    
    ## Built-in Implementations
    
    All are in the `\Bitrix\Main\Diag\` namespace:
    
    | Class | Purpose |
    | --- | --- |
    | `Logger` | Abstract base class; `Logger::create('id', $params)` creates a logger via factory |
    | `FileLogger` | Into a file, with auto-rotation when `$maxLogSize` is exceeded (default 1 MB) |
    | `SysLogger` | Into system `syslog` via `openlog`/`syslog` |
    | `EventLogger` | Into `b_event_log` table (Admin Panel → Event Log) |
    | `LogFormatter` | Default formatter: interpolates `{placeholder}`, renders exceptions and stacks |
    | `JsonLinesFormatter` | From 25.300.0; one JSON line per entry, convenient for ELK/Loki |
    
    Levels are constants of `\Psr\Log\LogLevel::*` (`emergency`, `alert`, `critical`, `error`, `warning`, `notice`, `info`, `debug`).
    
    ## Service with Logger (DI — Recommended)
    
    ```php
    <?php declare(strict_types=1);
    
    namespace Vendor\Module\Application\Service;
    
    use Psr\Log\LoggerInterface;
    use Psr\Log\NullLogger;
    
    final class PostService
    {
        public function __construct(
            private readonly LoggerInterface $logger = new NullLogger(),
        ) {}
    
        public function publish(int $postId): void
        {
            try
            {
                // ...
                $this->logger->info('Post {id} published', ['id' => $postId]);
            }
            catch (\Throwable $e)
            {
                $this->logger->error('Publish failed for post {id}: {exception}', [
                    'id' => $postId,
                    'exception' => $e,
                ]);
                throw $e;
            }
        }
    }
    ```
    
    Registration in `/local/modules/vendor.module/.settings.php`:
    
    ```php
    'services' => [
        'value' => [
            \Vendor\Module\Application\Service\PostService::class => [
                'constructor' => static fn (): \Vendor\Module\Application\Service\PostService =>
                    new \Vendor\Module\Application\Service\PostService(
                        new \Bitrix\Main\Diag\FileLogger('/var/log/bitrix/post-service.log'),
                    ),
            ],
        ],
        'readonly' => true,
    ],
    ```
    
    ## PSR-3 Placeholders
    
    Message is a template with `{key}`, values are taken from `$context`:
    
    ```php
    $logger->warning('User {userId} tried {action} on post {postId}', [
        'userId' => $uid, 'action' => 'delete', 'postId' => $pid,
    ]);
    ```
    
    Special keys understood by `LogFormatter`:
    
    - `{date}` — current time (interpolated automatically).
    - `{host}` — HTTP_HOST (automatic).
    - `{delimiter}` — entry separator (automatic).
    - `{exception}` — `\Throwable` object → formats class, message, stack trace.
    - `{trace}` — manual stack trace: `Diag\Helper::getBackTrace(6, DEBUG_BACKTRACE_IGNORE_ARGS, 3)`.
    
    Enable arguments in stack trace:
    
    ```php
    $logger->setFormatter(new \Bitrix\Main\Diag\LogFormatter(showArguments: true, argMaxChars: 120));
    ```
    
    ## Configuration via `.settings.php` — `loggers` section
    
    Allows overriding loggers for named kernel points (`main.HttpClient`, `main.Default`, `main.GeoIpManager`) and your own identifiers.
    
    ```php
    return [
        'services' => [
            'value' => [
                'formatter.withArgs' => [
                    'className' => \Bitrix\Main\Diag\LogFormatter::class,
                    'constructorParams' => [true],
                ],
            ],
            'readonly' => true,
        ],
        'loggers' => [
            'value' => [
                'main.Default' => [
                    'constructor' => static fn () => new \Bitrix\Main\Diag\FileLogger(
                        '/var/log/bitrix/app.log', 10 * 1024 * 1024,
                    ),
                    'level'     => \Psr\Log\LogLevel::INFO,
                    'formatter' => 'formatter.withArgs',
                ],
    
                'main.HttpClient' => [
                    'constructor' => static function (
                        \Bitrix\Main\Web\Http\DebugInterface $debug,
                        \Psr\Http\Message\RequestInterface $request,
                    ) {
                        $debug->setDebugLevel(\Bitrix\Main\Web\HttpDebug::ALL);
                        return new \Bitrix\Main\Diag\FileLogger(
                            '/var/log/bitrix/http-' . spl_object_hash($request) . '.log',
                        );
                    },
                    'level' => \Psr\Log\LogLevel::DEBUG,
                ],
    
                'vendor.module.myLogger' => [
                    'constructor' => static fn () => new \Bitrix\Main\Diag\FileLogger(
                        '/var/log/bitrix/vendor.module.log',
                    ),
                    'level' => \Psr\Log\LogLevel::DEBUG,
                ],
            ],
            'readonly' => true,
        ],
    ];
    ```
    
    ### Important
    
    - `constructor` closures must be in `.settings.php` / `.settings_extra.php` — the file **is not edited** by Admin Panel, closures are not serialized.
    - `level` — threshold level; logger ignores messages below this.
    - `formatter` — key from `services` section.
    - Retrieving logger in code:
    
        ```php
        $logger = \Bitrix\Main\Diag\Logger::create('vendor.module.myLogger');
        $logger = \Bitrix\Main\Diag\Logger::create('vendor.module.myLogger', [$this, $extraArg]);
        ```
    
    ## Named Kernel Points
    
    | ID | Used In | Factory Parameters |
    | --- | --- | --- |
    | `main.Default` | `AddMessage2Log`, general default | `LOG_FILENAME`, `$showArgs` |
    | `main.HttpClient` | `Bitrix\Main\Web\HttpClient` (including legacy and PSR-18) | `DebugInterface $debug`, `RequestInterface $request` |
    | `main.GeoIpManager` | `Bitrix\Main\Service\GeoIp\Manager` | — |
    | `main.EventLog.SysLogger` | `CEventLog` → syslog path | — |
    | `main.EventLog.FileLogger` | `CEventLog` → file path | `$path`, `$maxSize` |
    
    There are **no** named loggers `main.Mail` or `main.Engine`. Prefer `constructor` closures for `FileLogger` (see examples above) over `className`/`settings` arrays.
    
    Configuring these loggers redirects all kernel calls — convenient for auditing external calls (see example in `bitrix-http-client`).
    
    ## LoggerAware + Factory
    
    For classes that should be supplied with a logger "by identifier":
    
    ```php
    final class Indexer implements \Psr\Log\LoggerAwareInterface
    {
        use \Psr\Log\LoggerAwareTrait;
    
        public function run(): void
        {
            $this->ensureLogger()->info('Indexing started');
        }
    
        private function ensureLogger(): \Psr\Log\LoggerInterface
        {
            if ($this->logger === null)
            {
                $this->setLogger(\Bitrix\Main\Diag\Logger::create('vendor.module.indexer', [$this]));
            }
            return $this->logger;
        }
    }
    ```
    
    ## Monolog via Composer
    
    ```bash
    composer require monolog/monolog
    ```
    
    Integration into `.settings.php`:
    
    ```php
    'loggers' => [
        'value' => [
            'vendor.module.external' => [
                'constructor' => static function () {
                    $log = new \Monolog\Logger('vendor.module');
                    $log->pushHandler(new \Monolog\Handler\StreamHandler('/var/log/bitrix/monolog.log'));
                    return $log;
                },
                'level' => \Psr\Log\LogLevel::DEBUG,
            ],
        ],
    ],
    ```
    
    ## Checklist
    
    - [ ] PSR-3 standard followed (placeholders, context, exception key).
    - [ ] Loggers are configured via `.settings.php` rather than hardcoded in services.
    - [ ] Threshold `level` is set for each environment.
    - [ ] Loggers for external integrations (`HttpClient`) are redirected to separate files for audit.
    - [ ] For heavy load, `JsonLinesFormatter` is used for external collectors.
    - [ ] Logs are stored outside `DOCUMENT_ROOT` or protected by `.htaccess`.
    - [ ] Sensitive data (passwords, tokens) are stripped from context before logging.
    
    Link `exception_handling.log` in `.settings.php` with named loggers for unified error tracking. See skill `bitrix-settings`.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related