Development of a 1C-Bitrix logging module

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1177
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

1C-Bitrix Logging Module Development

Debugging a production incident without proper logs is a painful experience. The standard \Bitrix\Main\Diag\Debug::writeToFile() writes to a flat file with no structure, no severity levels, and no rotation. After a week of operation you end up with a 2 GB file that is impossible to analyse or search. The logging module solves this systematically: structured records in the database, severity levels, tags, context, rotation, and search via the administrative interface.

Architecture

The vendor.logger module implements the PSR-3 interface (Psr\Log\LoggerInterface), making it compatible with any library that supports PSR-3 (Guzzle, Doctrine, Symfony components).

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): same 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 sync: product not found', ['xml_id' => 'ABC-123']);

Handlers

Writing to the database is 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, maximum N files)
  • SlackHandler — sends critical/emergency messages to a Slack channel via Webhook
  • TelegramHandler — sends alerts to a Telegram bot when 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"}
  ]
}

Rotation and Archiving

The rotation agent runs once per day:

// Records older than 30 days — moved to b_vendor_log_archive
// Records older than 90 days in the archive — deleted
// Parameters are configurable in the module's administrative interface
\Vendor\Logger\RotationAgent::run();

Transfer is performed in batches of 1,000 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; // Bitrix standard handler still 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(),
    ]);
});

Administrative Interface

Log search is the primary debugging tool:

  • Filtering by level, channel, date, IP, user, and message text
  • Search within context (JSON field via PostgreSQL @> or LIKE on serialized data)
  • Detailed record view: full context, call stack, request headers
  • Statistics: top errors for a period, dynamics by level, breakdown by channel
  • Channel and handler configuration management

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
Administrative interface, search 2 days
Testing 1 day

Total: 8 working days. Integration with external monitoring systems (Sentry, Graylog) — additional 1–2 days.