Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Telegram Logger Laravel Package

jeffersongoncalves/laravel-telegram-logger

A Laravel package that adds a Telegram logging channel, sending application logs directly to Telegram chats via a bot. Configure the bot token, chat ID, and log level to receive real-time notifications and monitor errors, warnings, and other events from your Laravel app.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a monolog handler + queued delivery pipeline, not a general-purpose Telegram SDK. The first thing to understand is that it plugs into Laravel's logging stack as a channel — everything else (dedup, grouping, rate limiting, formatting) happens inside that channel.

  1. Install and publish config:
    composer require jeffersongoncalves/laravel-telegram-logger
    php artisan vendor:publish --tag=telegram-logger-config
    
  2. Set the two required values — bot token and default chat id — in .env. Missing either produces a graceful no-op, not an exception, so a misconfigured install looks identical to a quiet one. Verify immediately.
  3. Wire it into config/logging.php as a channel and point a stack at it. Don't make it the default channel on day one; add it alongside your existing single/daily channel so you keep local disk logs while you evaluate volume.
  4. Run php artisan telegram-logger:test to confirm the plumbing, then php artisan telegram-logger:test --exception to see what a real throwable renders as (sections, clamping, the stacktrace.txt reply document).

First real use case: a production stack that keeps daily for greppable history and adds telegram at error level only. That gives you paging for free without drowning the chat in info noise.

Before going live, check the version constraints: PHP 8.2+ and Laravel 12.61+ / 13. On an older Laravel this package simply won't install — there's no backport path.

Implementation Patterns

Channel-per-destination, not per-level. Because routing (per-level chat ids, forum topics, silent levels) is config-driven inside the handler, resist the urge to define five separate logging channels. One telegram channel with a routing map is easier to reason about and keeps dedup/rate-limit state in one place.

Stack it, don't replace it. The intended production pipeline from its Discord sibling is stack: [daily, telegram]. The package's HTML formatting is tuned for humans on a phone; your disk logs remain the forensic source of truth.

Choose your grouping key deliberately. The three meaningful strategies:

  • level+message — good default for high-traffic apps; collapses the same 500 across many users into one alert.
  • exception — best for jobs and console commands where the class + message is stable and you want one alert per root cause.
  • message — noisiest; only useful if you interpolate identifiers out of messages first.
  • callback — the escape hatch when none of the above fits (e.g. group by tenant id).

Lean on the occurred N× roll-up. Combined with the default 20/min global rate limit, this is what makes the package survivable during an incident. Tune the per-error limit rather than the global one — you want one error to be capped hard while unrelated errors still get through.

Exploit the reply-document behaviour. The 4096-char clamp means the message body is a summary; the full stacktrace arrives as stacktrace.txt replying to it. Train yourself to open the reply rather than the message when debugging — the message will truncate mid-frame on deep traces.

Route by level, and use silent levels. warning and notice to a quiet ops topic with disable_notification: true, error+ to the on-call topic with sound. Forum topics need the chat to actually be a forum — a topic id against a normal group will fail delivery (and, per the async design, fail fast as a 4xx).

Mentions for ownership. @username mentions on error+ only. Mentioning on every warning gets the feature muted within a week.

Redaction is a safety net, not a licence. Keys and value patterns are redacted and bot tokens are always masked — but the Exception section includes exception messages, which routinely embed user input, SQL fragments, and URLs with query strings. Add your app-specific patterns (tokens, emails, card numbers) to the redaction config before enabling error level.

Queue it, and size the worker accordingly. Delivery is a queued job, so the Telegram API round-trip never blocks a request. But that job is now in your queue alongside real work: on a busy worker, alert delivery can lag behind a backlog. If alerting latency matters, give the logger its own queue/connection so a stuck default queue doesn't silence your pager.

Test the failure path in staging. Point the config at an invalid chat id and confirm the 4xx path reports Telegram's description to your fallback channel. That message ("chat not found", "bot was blocked by the user") is the single most useful diagnostic this package produces, and it's the thing that will save you at 3am.

Gotchas and Tips

The graceful no-op is the sharpest edge. Missing token or chat id means zero errors and zero messages. Nothing in your application logs will hint that alerting is dead. Treat a periodic telegram-logger:test (scheduled, with the result alerted elsewhere) as mandatory, and prefer failing loudly in staging by asserting on the test command's exit code.

The HTML rendering is escaped, but the truncation is not frame-aware. A clamped message can cut mid-<pre> block. Telegram is tolerant of this in practice, but if you see malformed messages, that's why — not a formatting bug in your code.

Config keys live in two places. The handler config lives in the package config; the channel entry lives in config/logging.php. A typo in via or a missing handler reference produces a silently broken channel. After editing, clear config cache — config:cache in production will happily serve your stale pre-fix values.

parameters.retry_after is a Telegram field, not yours. It's read from the 429 response body. If you self-host a proxy in front of the Bot API that rewrites the response, 429 handling breaks. Same for anything that mangles the 5xx classification — the retry-with-backoff vs fail-fast split hinges on the status code, and a proxy that returns 200 with an error body will make failures vanish.

Async means logs can be lost on a crash. If the worker dies between the log write and job execution, that alert is gone. Pair with a disk channel (which you're doing anyway) and don't rely on Telegram as your audit trail.

Dedup state is process-local. Deduplication and grouping windows live in the handler's memory for the lifetime of the worker/request. On a multi-worker or Octane setup, each worker dedups independently — you'll get up to N copies of an error, not one global copy. The rate limit is the backstop here, not the dedup. If you need cluster-wide dedup, this package isn't the tool.

Context and Extra sections can be huge. Laravel's default context (user, request id, etc.) is usually fine, but the Extra section carries whatever array you pass to Log::error($msg, $context). Passing a full Eloquent model or a large payload will blow through the 4096 clamp and push useful info off the message. Log identifiers, not objects.

Livewire / Job / Command sections are conditional. They only appear when the log record originates inside those contexts. If your Job section is always empty, the exception is escaping from a place that doesn't carry job context — usually a queued listener rather than the job itself. Don't chase it as a config bug.

Version floors are hard. Laravel 12.61+ is a specific minor, not "12.x". Pin that in CI and in your composer.json if you rely on this in production; a routine composer update on a slightly older app will resolve to a different version or fail outright.

Extension points are thin by design. There's no custom formatter or transport registration — if you need a different message shape, you're editing published views/config or forking. Conversely, that means upgrades are low-risk, which is worth something for a component wired into your error path.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk