Secure logging with Monolog & Papertrail

Send PHP application log data to Papertrail using Monolog over TCP
Thu, November 2nd, 2017
blueoakinteractive

We've been using Papertrail for remote logging on a few applications lately. Their service is simple to set up, affordable and has awesome features like filter based alerting. Feeding our application logs into their system allows us to be notified whenever API calls fail or other errors are thrown as well as providing an audit trail for discovery in the future.

We host a lot of our applications on Platform.sh. Recently, the logs being generated from applications on Platform.sh stopped reporting to Papertrail. After investigating, we determined that Platform.sh recently stopped outbound UDP traffic for security reasons. This meant we had to find another way to send the log data to Papertrail. We had been using something similar to what's in the Papertrail documentation https://help.papertrailapp.com/kb/configuration/configuring-centralized….

UPD is faster, so it's great for logging applications and we weren't sending any sensitive data over the wire, so UDP was acceptable for us initially. TCP is a more reliable protocol and having it wrapped in TLS is more secure. Since Platform.sh made the change, we didn't really have a choice. Fortunately, Papertrail allows logs to be sent over TCP to the same endpoint.

I was unable to find a specific example on how to do this, and the methods I tried initially didn't work. I eventually figured out that you have to use the SocketHandler provided by Monolog and specify "tls://" as the schema for the socket. The SocketHandler is a wrapper for fsockopen, but hardcodes the port as -1. Fortunately, passing the port in the connection string works.

Below is an example of how you can send application log data to Papertrail over TCP/TLS using Monolog. Make sure to replace TCP_HOST and TCP_PORT constant definitions with your endpoint.

<?php

require 'vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\SocketHandler;

define('TCP_HOST', '[HOSTNAME]');
define('TCP_PORT', '[PORT-NUMBER]');

// Setup the logger.
$logger = new Logger('my_logger');

// Add the TCP socket handler wrapped in TLS.
$handler = new SocketHandler('tls://' . TCP_HOST . ':' . TCP_PORT);
$handler->setPersistent(true);

// Tell the logger to use the new socket handler.
$logger->pushHandler($handler);

// Send an error to papertrail!
$logger->addError('TCP error send to Papertrail over TCP/TPS');