Skip to content

Logging

Since essence v0.9.0, all TBE packages log through a single PSR-3 helper, tbeLog(), with a shared level policy and automatic webhook context. This page defines the convention every package (and host app) follows.

Level Policy

LevelMeaningExamples
infoBusiness event — something that is supposed to happen, happenedinvoice paid, wallet credited, service provisioned, campaign completed
warningExpected user friction or misconfiguration — no stack trace neededvalidation failure, stale callback button, gateway rejected a request, unregistered state answer
errorGenuine bug — always with ['exception' => $e]unhandled exception, failed Telegram API init, failed webhook setup
debugHigh-volume diagnostics, off in productionper-message campaign send failures, backup-restore file progress

With production at LOG_LEVEL=info, the error count becomes a real alarm signal: errors are bugs, warnings are friction, info is the business ledger.

tbeLog()

php
tbeLog('billing')->info('Invoice paid', [
    'invoice_id' => $invoice->getKey(),
    'price' => $invoice->price,
]);

tbeLog('essence')->error('Failed to create bot: ' . $e->getMessage(), ['exception' => $e]);

The helper returns a TbeLogger (PSR-3 LoggerInterface). Every entry automatically gains:

  • package — the tag you pass to tbeLog() (omit for none; each package uses its own name: essence, billing, user-wallet, gateway-card, gateway-zibal, affiliates, announcements, settings, user-management, host apps use their app name, e.g. vshop)
  • bot_id, update_id, update_type, chat_id, user_id, state — pulled from the current wHook() context when a webhook is active; silently omitted otherwise

Logging never throws: any failure inside the logger is swallowed so it can never break bot flow.

Rules

  1. One entry per event. Never split one failure across multiple log calls.
  2. Identifiers, not payloads. Log invoice_id, chat_id, amounts — never full update JSON or message text. The full update already goes to the bug-report Telegram chat as a document.
  3. Traces only for bugs. Expected exceptions log at warning with no trace; the catch-all path logs error with ['exception' => $e] (Laravel's formatter appends the stack trace).
  4. Sensitive values are redacted. e.g. settings logs [redacted] for SENSITIVE-type setting values.

Configuration

php
// config/tbe-essence.php
'logging' => [
    // Log channel for all TBE packages; null uses the app's default channel.
    'channel' => env('TBE_LOG_CHANNEL'),
    // Also push debug/bug reports to the bug_report Telegram chat.
    'telegram_notify' => env('TBE_LOG_TELEGRAM_NOTIFY', true),
],
  • channel: null (default) — everything goes to the app's default channel; existing bots need no changes.
  • telegram_notify — controls whether debugMessage(), mixedDebugMessage() and exceptionReport() also send to the bug_report.telegram_chat_id chat.

Host App Setup (Reference: vshop)

vshop separates bot traffic from app/framework logs with two rotated daily channels:

php
// config/logging.php
'telegram' => [
    'driver' => 'daily',
    'path' => storage_path('logs/telegram.log'),
    'level' => env('LOG_LEVEL', 'debug'),
    'days' => env('LOG_DAILY_DAYS', 14),
    'replace_placeholders' => true,
],
dotenv
LOG_CHANNEL=stack
LOG_STACK=daily          # app log, rotated, 14 days
LOG_LEVEL=info           # debug only while actively diagnosing
TBE_LOG_CHANNEL=telegram # bot traffic → telegram-YYYY-MM-DD.log

Both files show up in Log Viewer automatically; filter bot entries by the package context key.

Bug Reports via Telegram

exceptionReport($e) (used by the catch-all in ExceptionHandler) does two things:

  1. Logs one error entry with the exception.
  2. If bug_report.telegram_chat_id is set and telegram_notify is on, sends a summary message plus .trace and .update documents to that chat.

debugMessage() / mixedDebugMessage() log a single warning and (optionally) mirror it to the same chat.