Published on 2010-09-20 by John Collins. Socials: YouTube - X - Spotify - Amazon Music - Apple Podcast |
In a previous tutorial, I showed you how to install Facebook Scribe on a Linux server. In this tutorial we will continue to look at Scribe, but this time from the client perspective. Note that this tutorial assumes that you already have your Scribe and Thrift environment set up as outlined in the previous tutorial.
You can log messages to Scribe from many different languages. In this tutorial I will show you how to use Thrift to generate a PHP client, and then use that client from your own PHP project to log messages.
Begin by copying all of the PHP library source files shipped with Thrift to the location where we want to use them from (in my case I'm using /opt/scribe/testapp):
[jcollins@redhat testapp]$ cp -R /opt/scribe/thrift-0.4.0/lib/php/src phpscribe
You should now have a phpscribe folder that looks something like this:
[jcollins@redhat testapp]$ ls -l phpscribe/ total 76 -rw-r--r-- 1 jcollins jcollins 1914 2010-09-20 14:58 autoload.php drwxr-xr-x 3 jcollins jcollins 4096 2010-09-20 14:58 ext drwxr-xr-x 2 jcollins jcollins 4096 2010-09-20 14:58 protocol drwxr-xr-x 2 jcollins jcollins 4096 2010-09-20 14:58 server -rw-r--r-- 1 jcollins jcollins 22870 2010-09-20 14:58 Thrift.php drwxr-xr-x 2 jcollins jcollins 4096 2010-09-20 14:58 transport [jcollins@redhat testapp]$
Next we will use Thrift to build the client libraries we will need for Scribe and fb303:
[jcollins@redhat testapp]$ /usr/local/bin/thrift -o ./phpscribe -I /usr/local/share \ --gen php /opt/scribe/scribe/if/scribe.thrift [jcollins@redhat testapp]$ /usr/local/bin/thrift -o ./phpscribe -I /usr/local/share \ --gen php /usr/local/share/fb303/if/fb303.thrift
As Thrift will place the files in a folder named gen-php but our Scribe client will expect them to be in packages, a quick folder rename will sort that out:
[jcollins@redhat testapp]$ mv phpscribe/gen-php/ phpscribe/packages
You should now have a folder structure that looks like this:
[jcollins@redhat testapp]$ tree phpscribe/ phpscribe/ |-- Thrift.php |-- autoload.php |-- ext | `-- thrift_protocol | |-- config.m4 | |-- php_thrift_protocol.cpp | `-- php_thrift_protocol.h |-- packages | |-- fb303 | | |-- FacebookService.php | | `-- fb303_types.php | `-- scribe | |-- scribe.php | `-- scribe_types.php |-- protocol | |-- TBinaryProtocol.php | `-- TProtocol.php |-- server | |-- TServer.php | `-- TSimpleServer.php `-- transport |-- TBufferedTransport.php |-- TFramedTransport.php |-- THttpClient.php |-- TMemoryBuffer.php |-- TNullTransport.php |-- TPhpStream.php |-- TServerSocket.php |-- TServerTransport.php |-- TSocket.php |-- TSocketPool.php |-- TTransport.php `-- TTransportFactory.php
Next up we will want to actually log something to Scribe. Here is the sample source code (sampleclient.php), please pay close attention to the comments:
<?php // Set this to where you have the Scribe and Thrift libary files. It MUST be set! $GLOBALS['THRIFT_ROOT'] = './phpscribe'; // Include all of the lib files we need. require_once $GLOBALS['THRIFT_ROOT'].'/packages/scribe/scribe.php'; require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php'; require_once $GLOBALS['THRIFT_ROOT'].'/transport/TFramedTransport.php'; require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php'; // A message in Scribe is made up of two parts: the category (a key) and the actual // message. $message = array(); $message['category'] = 'PHP'; $message['message'] = 'Hello to Scribe from PHP!'; // Create a new LogEntry instance to hold our message, then add it to a new $messages // array (we can submit multiple messages at the same time if we want to). $entry = new LogEntry($message); $messages = array($entry); // These settings should really be in a config file somewhere. $socket = new TSocket('localhost', 1463, true); $transport = new TFramedTransport($socket); $protocol = new TBinaryProtocol($transport, false, false); // This is the actual Scribe client instance. $scribeClient = new scribeClient($protocol, $protocol); try { // Open the socket... $transport->open(); // ...log the messages... $scribeClient->Log($messages); // ...and close the socket. $transport->close(); }catch (TException $e) { // In reality, you would want something more robust here like logging to a text // file if Scribe is down. echo $e->getMessage()."\n\n"; } ?>
There are some important caveats here:
Now run your PHP script and assuming there were no errors, you message should be logged to Scribe.
[jcollins@redhat testapp]$ php scribeclient.php
Assuming that your Scribe server is up-and-running, you should change directory to where it stores its log files:
[jcollins@redhat ~]$ cd /tmp/scribetest/
Now list the contents of the directory, and you should now see a PHP folder which maps to the category of our message:
[jcollins@redhat scribetest]$ ls -l total 32 drwxr-xr-x 2 root root 4096 2010-09-20 15:35 PHP ...
Now drill into that folder...
[jcollins@redhat scribetest]$ cd PHP/ [jcollins@redhat PHP]$ ls -l total 12 -rw-r--r-- 1 root root 104 2010-09-20 16:41 PHP_00000 lrwxrwxrwx 1 root root 29 2010-09-20 15:35 PHP_current -> /tmp/scribetest/PHP/PHP_00000
If you tail the current symbolic link ("sym link"), you will see your message:
[jcollins@redhat PHP]$ tail PHP_current Hello to Scribe from PHP!
If you are currently using flat files or database tables to store your logging information in your PHP project, and you are finding that it is causing you problems with performance bottle necks or even stability when your application is under heavy load, you might consider introducing Scribe into your architecture. The code above can be easily modified to slot into an existing Logger.write(...) method, for example, without interfering with existing application code.
Updated 2021 : note that the above post was originally published in 2010, but is left here for archival purposes. Sadly just a few years after I published this, work stopped on Scribe. It is a shame, as it was a very nice solution for log file aggregation, which is still a vital DevOps requirement today.