{"slug":"bitrix-logger","title":"bitrix-logger","summary":"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","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-08-28T17:01:57.424071Z","repo":{"url":"https://github.com/bxmaximum/bitrix-framework-skills","stars":32,"forks":5,"license":null,"updatedAt":"2026-08-25T17:45:16Z"},"bodyHtml":"<hr>\n<h2>name: bitrix-logger\ndescription: 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.</h2>\n<h1>Logging in Bitrix (PSR-3)</h1>\n<p>Bitrix follows the PSR-3 standard. In code, inject <code>\\Psr\\Log\\LoggerInterface</code>, and in <code>.settings.php</code>, configure the specific implementation. Direct calls to <code>AddMessage2Log</code> are legacy; in new code, write via DI logger.</p>\n<h2>Built-in Implementations</h2>\n<p>All are in the <code>\\Bitrix\\Main\\Diag\\</code> namespace:</p>\n<table>\n<thead>\n<tr>\n<th>Class</th>\n<th>Purpose</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>Logger</code></td>\n<td>Abstract base class; <code>Logger::create('id', $params)</code> creates a logger via factory</td>\n</tr>\n<tr>\n<td><code>FileLogger</code></td>\n<td>Into a file, with auto-rotation when <code>$maxLogSize</code> is exceeded (default 1 MB)</td>\n</tr>\n<tr>\n<td><code>SysLogger</code></td>\n<td>Into system <code>syslog</code> via <code>openlog</code>/<code>syslog</code></td>\n</tr>\n<tr>\n<td><code>EventLogger</code></td>\n<td>Into <code>b_event_log</code> table (Admin Panel → Event Log)</td>\n</tr>\n<tr>\n<td><code>LogFormatter</code></td>\n<td>Default formatter: interpolates <code>{placeholder}</code>, renders exceptions and stacks</td>\n</tr>\n<tr>\n<td><code>JsonLinesFormatter</code></td>\n<td>From 25.300.0; one JSON line per entry, convenient for ELK/Loki</td>\n</tr>\n</tbody>\n</table>\n<p>Levels are constants of <code>\\Psr\\Log\\LogLevel::*</code> (<code>emergency</code>, <code>alert</code>, <code>critical</code>, <code>error</code>, <code>warning</code>, <code>notice</code>, <code>info</code>, <code>debug</code>).</p>\n<h2>Service with Logger (DI — Recommended)</h2>\n<pre><code>&lt;?php declare(strict_types=1);\n\nnamespace Vendor\\Module\\Application\\Service;\n\nuse Psr\\Log\\LoggerInterface;\nuse Psr\\Log\\NullLogger;\n\nfinal class PostService\n{\n    public function __construct(\n        private readonly LoggerInterface $logger = new NullLogger(),\n    ) {}\n\n    public function publish(int $postId): void\n    {\n        try\n        {\n            // ...\n            $this-&gt;logger-&gt;info('Post {id} published', ['id' =&gt; $postId]);\n        }\n        catch (\\Throwable $e)\n        {\n            $this-&gt;logger-&gt;error('Publish failed for post {id}: {exception}', [\n                'id' =&gt; $postId,\n                'exception' =&gt; $e,\n            ]);\n            throw $e;\n        }\n    }\n}\n</code></pre>\n<p>Registration in <code>/local/modules/vendor.module/.settings.php</code>:</p>\n<pre><code>'services' =&gt; [\n    'value' =&gt; [\n        \\Vendor\\Module\\Application\\Service\\PostService::class =&gt; [\n            'constructor' =&gt; static fn (): \\Vendor\\Module\\Application\\Service\\PostService =&gt;\n                new \\Vendor\\Module\\Application\\Service\\PostService(\n                    new \\Bitrix\\Main\\Diag\\FileLogger('/var/log/bitrix/post-service.log'),\n                ),\n        ],\n    ],\n    'readonly' =&gt; true,\n],\n</code></pre>\n<h2>PSR-3 Placeholders</h2>\n<p>Message is a template with <code>{key}</code>, values are taken from <code>$context</code>:</p>\n<pre><code>$logger-&gt;warning('User {userId} tried {action} on post {postId}', [\n    'userId' =&gt; $uid, 'action' =&gt; 'delete', 'postId' =&gt; $pid,\n]);\n</code></pre>\n<p>Special keys understood by <code>LogFormatter</code>:</p>\n<ul>\n<li><code>{date}</code> — current time (interpolated automatically).</li>\n<li><code>{host}</code> — HTTP_HOST (automatic).</li>\n<li><code>{delimiter}</code> — entry separator (automatic).</li>\n<li><code>{exception}</code> — <code>\\Throwable</code> object → formats class, message, stack trace.</li>\n<li><code>{trace}</code> — manual stack trace: <code>Diag\\Helper::getBackTrace(6, DEBUG_BACKTRACE_IGNORE_ARGS, 3)</code>.</li>\n</ul>\n<p>Enable arguments in stack trace:</p>\n<pre><code>$logger-&gt;setFormatter(new \\Bitrix\\Main\\Diag\\LogFormatter(showArguments: true, argMaxChars: 120));\n</code></pre>\n<h2>Configuration via <code>.settings.php</code> — <code>loggers</code> section</h2>\n<p>Allows overriding loggers for named kernel points (<code>main.HttpClient</code>, <code>main.Default</code>, <code>main.GeoIpManager</code>) and your own identifiers.</p>\n<pre><code>return [\n    'services' =&gt; [\n        'value' =&gt; [\n            'formatter.withArgs' =&gt; [\n                'className' =&gt; \\Bitrix\\Main\\Diag\\LogFormatter::class,\n                'constructorParams' =&gt; [true],\n            ],\n        ],\n        'readonly' =&gt; true,\n    ],\n    'loggers' =&gt; [\n        'value' =&gt; [\n            'main.Default' =&gt; [\n                'constructor' =&gt; static fn () =&gt; new \\Bitrix\\Main\\Diag\\FileLogger(\n                    '/var/log/bitrix/app.log', 10 * 1024 * 1024,\n                ),\n                'level'     =&gt; \\Psr\\Log\\LogLevel::INFO,\n                'formatter' =&gt; 'formatter.withArgs',\n            ],\n\n            'main.HttpClient' =&gt; [\n                'constructor' =&gt; static function (\n                    \\Bitrix\\Main\\Web\\Http\\DebugInterface $debug,\n                    \\Psr\\Http\\Message\\RequestInterface $request,\n                ) {\n                    $debug-&gt;setDebugLevel(\\Bitrix\\Main\\Web\\HttpDebug::ALL);\n                    return new \\Bitrix\\Main\\Diag\\FileLogger(\n                        '/var/log/bitrix/http-' . spl_object_hash($request) . '.log',\n                    );\n                },\n                'level' =&gt; \\Psr\\Log\\LogLevel::DEBUG,\n            ],\n\n            'vendor.module.myLogger' =&gt; [\n                'constructor' =&gt; static fn () =&gt; new \\Bitrix\\Main\\Diag\\FileLogger(\n                    '/var/log/bitrix/vendor.module.log',\n                ),\n                'level' =&gt; \\Psr\\Log\\LogLevel::DEBUG,\n            ],\n        ],\n        'readonly' =&gt; true,\n    ],\n];\n</code></pre>\n<h3>Important</h3>\n<ul>\n<li><p><code>constructor</code> closures must be in <code>.settings.php</code> / <code>.settings_extra.php</code> — the file <strong>is not edited</strong> by Admin Panel, closures are not serialized.</p>\n</li>\n<li><p><code>level</code> — threshold level; logger ignores messages below this.</p>\n</li>\n<li><p><code>formatter</code> — key from <code>services</code> section.</p>\n</li>\n<li><p>Retrieving logger in code:</p>\n<pre><code>$logger = \\Bitrix\\Main\\Diag\\Logger::create('vendor.module.myLogger');\n$logger = \\Bitrix\\Main\\Diag\\Logger::create('vendor.module.myLogger', [$this, $extraArg]);\n</code></pre>\n</li>\n</ul>\n<h2>Named Kernel Points</h2>\n<table>\n<thead>\n<tr>\n<th>ID</th>\n<th>Used In</th>\n<th>Factory Parameters</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>main.Default</code></td>\n<td><code>AddMessage2Log</code>, general default</td>\n<td><code>LOG_FILENAME</code>, <code>$showArgs</code></td>\n</tr>\n<tr>\n<td><code>main.HttpClient</code></td>\n<td><code>Bitrix\\Main\\Web\\HttpClient</code> (including legacy and PSR-18)</td>\n<td><code>DebugInterface $debug</code>, <code>RequestInterface $request</code></td>\n</tr>\n<tr>\n<td><code>main.GeoIpManager</code></td>\n<td><code>Bitrix\\Main\\Service\\GeoIp\\Manager</code></td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>main.EventLog.SysLogger</code></td>\n<td><code>CEventLog</code> → syslog path</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>main.EventLog.FileLogger</code></td>\n<td><code>CEventLog</code> → file path</td>\n<td><code>$path</code>, <code>$maxSize</code></td>\n</tr>\n</tbody>\n</table>\n<p>There are <strong>no</strong> named loggers <code>main.Mail</code> or <code>main.Engine</code>. Prefer <code>constructor</code> closures for <code>FileLogger</code> (see examples above) over <code>className</code>/<code>settings</code> arrays.</p>\n<p>Configuring these loggers redirects all kernel calls — convenient for auditing external calls (see example in <code>bitrix-http-client</code>).</p>\n<h2>LoggerAware + Factory</h2>\n<p>For classes that should be supplied with a logger \"by identifier\":</p>\n<pre><code>final class Indexer implements \\Psr\\Log\\LoggerAwareInterface\n{\n    use \\Psr\\Log\\LoggerAwareTrait;\n\n    public function run(): void\n    {\n        $this-&gt;ensureLogger()-&gt;info('Indexing started');\n    }\n\n    private function ensureLogger(): \\Psr\\Log\\LoggerInterface\n    {\n        if ($this-&gt;logger === null)\n        {\n            $this-&gt;setLogger(\\Bitrix\\Main\\Diag\\Logger::create('vendor.module.indexer', [$this]));\n        }\n        return $this-&gt;logger;\n    }\n}\n</code></pre>\n<h2>Monolog via Composer</h2>\n<pre><code>composer require monolog/monolog\n</code></pre>\n<p>Integration into <code>.settings.php</code>:</p>\n<pre><code>'loggers' =&gt; [\n    'value' =&gt; [\n        'vendor.module.external' =&gt; [\n            'constructor' =&gt; static function () {\n                $log = new \\Monolog\\Logger('vendor.module');\n                $log-&gt;pushHandler(new \\Monolog\\Handler\\StreamHandler('/var/log/bitrix/monolog.log'));\n                return $log;\n            },\n            'level' =&gt; \\Psr\\Log\\LogLevel::DEBUG,\n        ],\n    ],\n],\n</code></pre>\n<h2>Checklist</h2>\n<ul>\n<li><input disabled=\"disabled\" type=\"checkbox\"> PSR-3 standard followed (placeholders, context, exception key).</li>\n<li><input disabled=\"disabled\" type=\"checkbox\"> Loggers are configured via <code>.settings.php</code> rather than hardcoded in services.</li>\n<li><input disabled=\"disabled\" type=\"checkbox\"> Threshold <code>level</code> is set for each environment.</li>\n<li><input disabled=\"disabled\" type=\"checkbox\"> Loggers for external integrations (<code>HttpClient</code>) are redirected to separate files for audit.</li>\n<li><input disabled=\"disabled\" type=\"checkbox\"> For heavy load, <code>JsonLinesFormatter</code> is used for external collectors.</li>\n<li><input disabled=\"disabled\" type=\"checkbox\"> Logs are stored outside <code>DOCUMENT_ROOT</code> or protected by <code>.htaccess</code>.</li>\n<li><input disabled=\"disabled\" type=\"checkbox\"> Sensitive data (passwords, tokens) are stripped from context before logging.</li>\n</ul>\n<p>Link <code>exception_handling.log</code> in <code>.settings.php</code> with named loggers for unified error tracking. See skill <code>bitrix-settings</code>.</p>\n","files":[{"path":"SKILL.md","sizeBytes":8379,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-08-28T17:03:51.792378Z","sha256":"7455B866B482B28D1A1FF90321AFAF2CC0DBEF5771D50F0EA54D93910E5C08E3","sizeBytes":3197},"review":null,"source":{"repositoryUrl":"https://github.com/bxmaximum/bitrix-framework-skills","path":"skills/bitrix-logger","license":null,"commit":"66c40e0ac8bdb3a3b68c3e53745b006659341594","subtreeSha":"B1D01435231D556D432CEE142D82F8DBB2BD045A6B2C91B6609E93BC6C7C8301","lastSyncedAt":"2026-09-18T13:48:07.304681Z"},"reviewedAt":"2026-08-28T17:07:21.638505Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/bxmaximum/bitrix-framework-skills/tree/main/skills/bitrix-logger"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install bxmaximum-bitrix-framework-skills@llmmart"},{"target":"git","command":"git clone https://github.com/bxmaximum/bitrix-framework-skills.git"}]}