TL;DR – Laravel’s Papertrail integration wasn’t working when deployed to platform.sh, who appear to block UDP connections. The solution is to create a TCP-based custom logger in Laravel.
UPDATE: My friend Carl Alexander (Hi Carl) found this solution, and then found a simpler way to achieve it. See his post How to send Laravel Vapor Logs to Papertrail.
I was working on Laravel project this week that outputs its logs to Papertrail, a log management SaaS that includes a remote syslog service that allows you to push your logs directly from your application to their log collector. I’ll be honest, I’m only played in their dashboard for a bit, but it looks pretty cool. Laravel 5.7 added Papertrail as a built-in option in it’s logging service.
I deployed the site to the hosting environment for this project, which is on platform.sh – another pretty cool service I’m learning about. I like anything that can spin up a new environment based on your Git branch!
And….. the logs stopped working.
After more hours than I care to admit, I found the problem. The logger that Laravel uses to send events to Papertrail works using the User Datagram Protocol (UDP). which is faster for this type of work than the Transmission Control Protocol (TCP).
Thank you to this blog post, “Secure logging with Monolog & Papertrail“, I discovered that platform.sh blocks UDP connections.
The User Datagram Protocol (UDP) is an alternative to the, also IP based, Transmission Control Protocol (TCP). Unlike TCP, it doesn’t have the same rules around establishing a connection with a remote host before sending data. Instead, it just sends the data, and assumes it will reach its destination.
If something goes wrong….like the remote host having the UDP protocol blocked… the sending host will never know.
Luckily, Papertrail also supports receiving log events over TCP! Now we just need to make a new channel for Laravel.
Making a TCP Logger for PaperTrail in Laravel
First, you need to create a custom Monolog logger than works over TCP. I made mine to App\Logging\PapertrailTcpLogger.php
:
<?php namespace App\Logging; use Monolog\Logger; use Monolog\Handler\SocketHandler; class PapertrailTcpLogger { /** * Create a custom Monolog instance to write to * PaperTrail using TCP instead of UDP. * * @param array $config * @return \Monolog\Logger */ public function __invoke(array $config) { // Setup the logger. $logger = new Logger('trusedlogin_papertrail_logger'); // Add the TCP socket handler wrapped in TLS. $handler = new SocketHandler('tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT')); $handler->setPersistent(true); // Tell the logger to use the new socket handler. $logger->pushHandler($handler); return $logger; } }
Then, you modify the config\logging.php
configuration file, adding your new logger as a channel in Laravel:
'papertrail_tcp' => [ 'driver' => 'custom', 'level' => 'debug', 'via' => \App\Logging\PapertrailTcpLogger::class ],
Finally, make sure that your Papertrail “Log Destination” is set up to allow TCP connections:
Voila! You should have your Laravel logs showing up in Papertrail!