ntfy is a simple HTTP-based pub-sub notification service that allows you to send push notifications to your phone or desktop from any script or application. It’s particularly useful for monitoring tasks, alerting about events, or sending logs from applications like Monolog.
Here’s how you can integrate Monolog with ntfy:
Setup Monolog
1 2 3 |
composer require monolog/monolog |
ntfy Handler Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
<?php require 'vendor/autoload.php'; use Monolog\Logger; use Monolog\Handler\StreamHandler; use Monolog\Handler\HandlerInterface; use Monolog\Formatter\FormatterInterface; use Monolog\LogRecord; // Custom ntfy handler class NtfyHandler implements HandlerInterface { private $ntfyTopic; private $ntfyServer; private $priority; private $title; public function __construct( string $ntfyTopic, string $ntfyServer = 'https://ntfy.sh', string $priority = 'default', string $title = 'Monolog Alert' ) { $this->ntfyTopic = $ntfyTopic; $this->ntfyServer = $ntfyServer; $this->priority = $priority; $this->title = $title; } public function handle(LogRecord $record): bool { $url = $this->ntfyServer . '/' . $this->ntfyTopic; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $record->message); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Title: ' . $this->title . ': ' . $record->level->getName(), 'Priority: ' . $this->mapLogLevelToPriority($record->level), 'Tags: monolog,' . strtolower($record->level->getName()) ]); $result = curl_exec($ch); curl_close($ch); return $result !== false; } private function mapLogLevelToPriority($level): string { // Map Monolog levels to ntfy priorities switch ($level) { case Logger::EMERGENCY: case Logger::ALERT: case Logger::CRITICAL: return '5'; // urgent case Logger::ERROR: return '4'; // high case Logger::WARNING: return '3'; // default case Logger::NOTICE: return '2'; // low default: return '1'; // min } } public function isHandling(LogRecord $record): bool { return true; } public function setFormatter(FormatterInterface $formatter): HandlerInterface { return $this; } public function getFormatter(): FormatterInterface { throw new \LogicException('This handler does not use formatters'); } } |
Testdrive
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// Create logger with ntfy handler $logger = new Logger('app'); $logger->pushHandler(new NtfyHandler( 'your-unique-topic', // Use a unique, hard-to-guess topic name 'https://ntfy.sh', // ntfy server - you can use the public one or self-host 'default', // Default priority 'MyApp' // Title prefix )); // Add standard handlers too if you want $logger->pushHandler(new StreamHandler('app.log', Logger::DEBUG)); // Send a test message $logger->error('Something went wrong!'); |