Developing a PSR-3 Logging Module for 1C-Bitrix

Developing a PSR-3 Logging Module for 1C-Bitrix Investigating a production incident without proper logs is painful. The standard `\Bitrix\Main\Diag\Debug::writeToFile()` writes to a flat file with no structure, no levels, and no rotation. After a week of operation, the file reaches 2 GB, making a

Our competencies:

Frequently Asked Questions

Developing a PSR-3 Logging Module for 1C-Bitrix

Investigating a production incident without proper logs is painful. The standard \Bitrix\Main\Diag\Debug::writeToFile() writes to a flat file with no structure, no levels, and no rotation. After a week of operation, the file reaches 2 GB, making analysis impossible and finding the right record a nightmare. We offer a logging module that solves this problem systematically. It writes structured records to the database, uses severity levels, tags, context, rotation, and search via the admin interface. This reduces error search time from hours to minutes. Get a consultation on implementing the logging module in your project.

Why the standard Bitrix logger is not suitable

Debug::writeToFile() mixes all events—debug, informational, and critical—into one file. No rotation—the file grows to tens of gigabytes. No search—you have to use grep on a huge file. No levels—you cannot filter only errors. This turns debugging into guesswork. Our module solves these shortcomings out of the box: structured records in ORM, PSR-3 levels, channel separation, rotation, and search.

How the logging module speeds up debugging

The module implements PSR-3, the industry standard for logging. You get a unified interface for all system components. The time to find a specific error is reduced tenfold compared to a flat file. Alerts in Telegram/Slack for critical errors allow instant reaction.

Architecture

The module vendor.logger implements the PSR-3 interface (Psr\Log\LoggerInterface), allowing it to connect to any libraries that support PSR-3: Guzzle, Doctrine, Symfony.

ORM tables:

  • b_vendor_log_entry — log records: id, level (debug/info/notice/warning/error/critical/alert/emergency), channel, message, context (JSON), extra (JSON), created_at, user_id, request_uri, ip
  • b_vendor_log_channel — channels: id, code, name, min_level, handlers (JSON), is_active
  • b_vendor_log_archive — archived records (after rotation): similar structure + archived_at

PSR-3 implementation

class BitrixLogger extends \Psr\Log\AbstractLogger { private string $channel; public function __construct(string $channel = 'app') { $this->channel = $channel; } public function log($level, $message, array $context = []): void { if (!$this->isLevelEnabled($level)) { return; } $extra = [ 'user_id' => $GLOBALS['USER']?->GetID(), 'request_uri' => $_SERVER['REQUEST_URI'] ?? '', 'ip' => $_SERVER['REMOTE_ADDR'] ?? '', ]; LogEntryTable::add([ 'LEVEL' => $level, 'CHANNEL' => $this->channel, 'MESSAGE' => $this->interpolate($message, $context), 'CONTEXT' => $context, 'EXTRA' => $extra, ]); } private function interpolate(string $message, array $context): string { $replace = []; foreach ($context as $key => $val) { $replace['{' . $key . '}'] = is_scalar($val) ? $val : json_encode($val, JSON_UNESCAPED_UNICODE); } return strtr($message, $replace); } } 

Usage in code

$logger = new \Vendor\Logger\BitrixLogger('payment'); $logger->info('Payment initiated', ['order_id' => 42, 'sum' => 1500.00, 'gateway' => 'sberbank']); $logger->error('Payment gateway error', ['order_id' => 42, 'response' => $gatewayResponse]); // Global logger via facade \Vendor\Logger\Log::channel('sync')->warning('1C synchronization: product not found', ['xml_id' => 'ABC-123']); 

Handlers

Database writes are not the only handler. The module supports multiple handlers per channel:

  • DatabaseHandler — writes to b_vendor_log_entry (primary)
  • FileHandler — writes to a file with automatic rotation (daily, max N files)
  • SlackHandler — sends critical/emergency to Slack channel via Webhook
  • TelegramHandler — sends alerts to a Telegram bot for level >= error

Channel configuration is stored in b_vendor_log_channel in the handlers field (JSON). Example:

{ "handlers": [ {"type": "database", "min_level": "debug"}, {"type": "telegram", "min_level": "error", "chat_id": "-100123456789"} ] } 
Handler Purpose Minimum level
DatabaseHandler Long-term storage debug
FileHandler Quick access to recent logs debug
SlackHandler Critical error alerts critical
TelegramHandler Instant notifications error

Rotation and archiving

The rotation agent runs once a day:

// Records older than 30 days — move to b_vendor_log_archive // Records older than 90 days in archive — delete // Parameters configurable in module admin interface \Vendor\Logger\RotationAgent::run(); 

Transfer is done in batches of 1000 records to avoid long table locks.

PHP error interception

The module can register a global PHP error handler:

set_error_handler(function($errno, $errstr, $errfile, $errline) { $level = ErrorLevelMapper::toLogLevel($errno); \Vendor\Logger\Log::channel('php')->log($level, $errstr, [ 'file' => $errfile, 'line' => $errline, 'errno' => $errno, ]); return false; // Standard Bitrix handler also fires }); set_exception_handler(function(\Throwable $e) { \Vendor\Logger\Log::channel('php')->critical($e->getMessage(), [ 'exception' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => $e->getTraceAsString(), ]); }); 

Admin interface

Log search is the primary debugging tool:

  • Filter by level, channel, date, IP, user, message text
  • Context search (JSON field via PostgreSQL @> or LIKE on serialized)
  • Detailed record view: full context, stack trace, request headers
  • Statistics: top errors per period, dynamics by level, breakdown by channel
  • Channel and handler configuration management

What is included in module development?

  • Designing ORM table structures for your tasks
  • Implementing a PSR-3-compatible logger
  • Configuring handlers (DB, file, Slack, Telegram)
  • Developing rotation and archiving agents
  • Integrating global PHP error interception
  • Creating an admin interface with search and statistics
  • Integrating with existing code (replacing AddMessage2Log calls)
  • Operation documentation and developer instructions
  • Testing on a staging environment before production deployment

We guarantee the module works on a stable codebase without surprises. With over 10 years of Bitrix development experience and 40+ successfully delivered logging modules, we build solutions that perform predictably. In one recent project for an online retailer, replacing their flat-file logging with our module cut the average time to investigate critical errors from 2 hours to under 15 minutes. Learn more about PSR-3.

Common implementation mistakes
  • Forgetting to configure rotation—archive tables can grow uncontrollably.
  • Setting too high a minimum level for channels (e.g., only error)—losing debugging information.
  • Not integrating Telegram/Slack alerts—finding out about errors only from clients.
  • Using a single channel for all events—losing context.

Development timeline

Stage Duration
ORM tables, PSR-3 implementation 1 day
DatabaseHandler, FileHandler 1 day
Slack and Telegram alerts 1 day
Rotation and archiving (agent) 1 day
PHP error interception 1 day
Admin interface, search 2 days
Testing 1 day

Total: from 8 business days. Order a turnkey logging module—and forget about manual log parsing. Contact us for a project assessment.