arhx/telegram-log-channel
Laravel log channel that sends Monolog messages to a Telegram chat via bot token and chat ID. Configure via .env or logging.php, add to your logging stack, and it safely falls back to a NullHandler when unset. Includes optional queued job failure alerts.
Install the package:
composer require arhx/telegram-log-channel
The service provider auto-registers.
Configure .env:
TELEGRAM_LOG_BOT_TOKEN=your_bot_token_here
TELEGRAM_LOG_CHAT_ID=your_chat_id_here
TELEGRAM_LOG_LEVEL=error # Optional: defaults to 'debug'
Enable the channel:
.env:
LOG_STACK=daily,telegram
config/logging.php:
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'telegram'],
],
Test immediately:
php artisan telegram-log:test
Verify a test message appears in your Telegram chat.
Standard Usage:
Log::error('User not found', ['user_id' => 123]);
If TELEGRAM_LOG_LEVEL is error or lower, the message sends to Telegram.
Conditional Logging:
Use Monolog’s if logic to filter messages:
if (app()->environment('production')) {
Log::channel('telegram')->info('Production event');
}
Queue::failing by default.TELEGRAM_LOG_QUEUE_FAILURES=false
QueueFailureListener in app/Providers/EventServiceProvider:
public function boot()
{
Queue::failing(function ($connection, $job, $exception) {
Log::channel('telegram')->error(
"Job [{$job->resolveName()}] failed on {$connection} queue",
['exception' => $exception->getMessage()]
);
});
}
config/logging.php:
'telegram' => [
'driver' => 'telegram',
'processors' => [
function ($record) {
$record['formatted'] = "[$record['level_name']] {$record['message']}";
return $record;
},
],
],
TELEGRAM_LOG_LEVEL=debug
TELEGRAM_LOG_LEVEL=error
TELEGRAM_THROW=true # Fail loudly if Telegram API fails
// In a custom QueueFailureListener
$telegramClient = new TelegramClient($token, $chatId);
try {
$telegramClient->send($message);
} catch (RateLimitException $e) {
// Retry logic or log to another channel
}
'stack' => [
'driver' => 'stack',
'channels' => ['telegram', 'daily'], // Telegram first for alerts
],
app/Providers/AppServiceProvider:
use Monolog\Logger;
public function boot()
{
Logger::addLevel('custom', Logger::WARNING);
}
php artisan vendor:publish --tag=telegram-log-channel-config
Then update config/telegram-log-channel.php:
return [
'queue_failures' => env('TELEGRAM_LOG_QUEUE_FAILURES', true),
];
Recursive Logging:
// Avoid this in processors:
Log::channel('telegram')->info('Processed'); // ❌ Recursion risk
Telegram API Limits:
telegram-notify job).Queue::later(now()->addSeconds(10), fn() => $telegramClient->send($message));
Config Cache Issues:
php artisan config:cache, publish the config first:
php artisan vendor:publish --tag=telegram-log-channel-config
TELEGRAM_LOG_QUEUE_FAILURES may not load correctly.Log Level Mismatches:
error level. If TELEGRAM_LOG_LEVEL is higher (e.g., critical), failures won’t trigger.TELEGRAM_LOG_LEVEL=error or lower.Bot Permissions:
php artisan telegram-log:test
Sensitive Data Exposure:
except in log arrays):
Log::error('Failed', ['user_id' => 123, 'except' => ['password']]);
Test Locally:
TELEGRAM_LOG_LEVEL=debug to verify all logs are sent.curl "https://api.telegram.org/bot<TOKEN>/getUpdates"
Enable Debug Mode:
TELEGRAM_THROW=true in .env to see API errors:
TELEGRAM_THROW=true
Inspect Monolog:
single file channel to debug:
'telegram' => [
'driver' => 'telegram',
'handler' => 'single', // Fallback to file if Telegram fails
],
Check Queue Listeners:
Queue::failing listener is registered:
php artisan queue:listen
Queue::fake();
Bus::dispatch(new FailingJob());
Queue::assertPushed(FailingJob::class);
Custom Message Formatting:
TelegramHandler in app/Handlers/TelegramHandler.php:
namespace App\Handlers;
use Arhx\TelegramLogChannel\TelegramHandler as BaseHandler;
class TelegramHandler extends BaseHandler
{
protected function formatMessage($record)
{
return "[{$record['level_name']}] {$record['message']}\n```json
{$record['context']}
```";
}
}
config/logging.php:
'telegram' => [
'driver' => 'custom-telegram',
'handler' => App\Handlers\TelegramHandler::class,
],
Add Retry Logic:
TelegramClient to retry failed API calls:
use Arhx\TelegramLogChannel\TelegramClient as BaseClient;
class TelegramClient extends BaseClient
{
public function send($message, $maxRetries = 3)
{
$retries = 0;
while ($retries < $maxRetries) {
try {
return parent::send($message);
} catch (RateLimitException $e) {
sleep(2 ** $retries); // Exponential backoff
$retries++;
}
}
throw new \RuntimeException('Failed to send message after retries');
}
}
Dynamic Chat IDs:
'telegram' => [
'driver' => 'telegram',
'chat_id_resolver' => function ($record) {
return $record['level'] === Logger::ERROR
? env('TELEGRAM_ERROR_CHAT_ID')
: env('TELEGRAM_DEBUG_CHAT_ID');
},
],
How can I help you explore Laravel packages today?