Permalink
Browse files

Adding Sylog as a logging engine

  • Loading branch information...
lorenzo committed May 14, 2013
1 parent b85d03d commit 018e5d0659fbac893dd49b1a5314f1293f300e30
Showing with 253 additions and 0 deletions.
  1. +158 −0 lib/Cake/Log/Engine/SyslogLog.php
  2. +95 −0 lib/Cake/Test/Case/Log/Engine/SyslogLogTest.php
@@ -0,0 +1,158 @@
+<?php
+/**
+ * Syslog logger engine for CakePHP
+ *
+ * PHP 5
+ *
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
+ * @package Cake.Log.Engine
+ * @since CakePHP(tm) v 2.4
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+App::uses('BaseLog', 'Log/Engine');
+
+/**
+ * Syslog stream for Logging. Writes logs to the system logger
+ *
+ * @package Cake.Log.Engine
+ */
+class SyslogLog extends BaseLog {
+
+/**
+ *
+ * By default messages are formatted as:
+ * type: message
+ *
+ * To override the log format (e.g. to add your own info) define the format key when configuring
+ * this logger
+ *
+ * If you wish to include a prefix to all messages, for instance to identify the
+ * application or the web server, then use the prefix option.
+ *
+ * ## Example:
+ *
+ * {{{
+ * CakeLog::config('error', array(
+ * 'engine' => 'SyslogLog',
+ * 'types' => array('emergency', 'alert', 'critical', 'error'),
+ * 'format' => "%s: My-App - %s",
+ * 'prefix' => 'Web Server 01'
+ * ));
+ * }}}
+ *
+ * @var array
+ */
+ protected $_defaults = array(
+ 'format' => '%s: %s',
+ 'flag' => LOG_ODELAY,
+ 'prefix' => '',
+ 'facility' => LOG_USER
+ );
+
+/**
+ *
+ * Used to map the string names back to their LOG_* constants
+ *
+ * @var array
+ */
+ protected $_priorityMap = array(
+ 'emergency' => LOG_EMERG,
+ 'alert' => LOG_ALERT,
+ 'critical' => LOG_CRIT,
+ 'error' => LOG_ERR,
+ 'warning' => LOG_WARNING,
+ 'notice' => LOG_NOTICE,
+ 'info' => LOG_INFO,
+ 'debug' => LOG_DEBUG
+ );
+
+/**
+ * Whether the logger connection is open or not
+ *
+ * @var boolean
+ */
+ protected $_open = false;
+
+/**
+ * Make sure the configuration contains the format parameter, by default it uses
+ * the error number and the type as a prefix to the message
+ *
+ * @param array $config
+ */
+ public function __construct($config = array()) {
+ $config += $this->_defaults;
+ parent::__construct($config);
+ }
+
+/**
+ * Writes a message to syslog
+ *
+ * Map the $type back to a LOG_ constant value, split multi-line messages into multiple
+ * log messages, pass all messages through the format defined in the configuration
+ *
+ * @param string $type The type of log you are making.
+ * @param string $message The message you want to log.
+ * @return boolean success of write.
+ */
+ public function write($type, $message) {
+ if (!$this->_open) {
+ $config = $this->_config;
+ $this->_open($config['prefix'], $config['flag'], $config['facility']);
+ $this->_open = true;
+ }
+
+ $priority = LOG_DEBUG;
+ if (isset($this->_priorityMap[$type])) {
+ $priority = $this->_priorityMap[$type];
+ }
+
+ $messages = explode("\n", $message);
+ foreach ($messages as $message) {
+ $message = sprintf($this->_config['format'], $type, $message);
+ $this->_write($priority, $message);
+ }
+
+ return true;
+ }
+
+/**
+ * Wrapper for openlog call
+ *
+ * @param int $priority
+ * @param sting $output
+ * @return void
+ */
+ public function _open($ident, $options, $facility) {
+ openlog($ident, $options, $facility);
+ }
+
+/**
+ * Wrapper for syslog call
+ *
+ * @param int $priority
+ * @param sting $output
+ * @return bool
+ */
+ protected function _write($priority, $output) {
+ return syslog($priority, $output);
+ }
+
+/**
+ * Closes the logger connection
+ *
+ * @return void
+ **/
+ public function __destruct() {
+ closelog();
+ }
+
+}
@@ -0,0 +1,95 @@
+<?php
+/**
+ * FileLogTest file
+ *
+ * PHP 5
+ *
+ * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice
+ *
+ * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
+ * @package Cake.Test.Case.Log.Engine
+ * @since CakePHP(tm) v 2.4
+ * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
+ */
+App::uses('SyslogLog', 'Log/Engine');
+
+/**
+ * SyslogLogTest class
+ *
+ * @package Cake.Test.Case.Log.Engine
+ */
+class SyslogLogTest extends CakeTestCase {
+
+/**
+ * Tests that the connection to the logger is open with the right arguments
+ *
+ * @return void
+ */
+ public function testOpenLog() {
+ $log = $this->getMock('SyslogLog', array('_open', '_write'));
+ $log->expects($this->once())->method('_open')->with('', LOG_ODELAY, LOG_USER);
+ $log->write('debug', 'message');
+
+ $log = $this->getMock('SyslogLog', array('_open', '_write'));
+ $log->config(array(
+ 'prefix' => 'thing',
+ 'flag' => LOG_NDELAY,
+ 'facility' => LOG_MAIL,
+ 'format' => '%s: %s'
+ ));
+ $log->expects($this->once())->method('_open')
+ ->with('thing', LOG_NDELAY, LOG_MAIL);
+ $log->write('debug', 'message');
+ }
+
+/**
+ * Tests that single lines are written to syslog
+ *
+ * @dataProvider typesProvider
+ * @return void
+ */
+ public function testWriteOneLine($type, $expected) {
+ $log = $this->getMock('SyslogLog', array('_open', '_write'));
+ $log->expects($this->once())->method('_write')->with($expected, $type . ': Foo');
+ $log->write($type, 'Foo');
+ }
+
+/**
+ * Tests that multiple lines are split and logged separately
+ *
+ * @return void
+ */
+ public function testWriteMultiLine() {
+ $log = $this->getMock('SyslogLog', array('_open', '_write'));
+ $log->expects($this->at(1))->method('_write')->with(LOG_DEBUG, 'debug: Foo');
+ $log->expects($this->at(2))->method('_write')->with(LOG_DEBUG, 'debug: Bar');
+ $log->expects($this->exactly(2))->method('_write');
+ $log->write('debug', "Foo\nBar");
+ }
+
+/**
+ * Data provider for the write function test
+ *
+ * @return array
+ */
+ public function typesProvider() {
+ return array(
+ array('emergency', LOG_EMERG),
+ array('alert', LOG_ALERT),
+ array('critical', LOG_CRIT),
+ array('error', LOG_ERR),
+ array('warning', LOG_WARNING),
+ array('notice', LOG_NOTICE),
+ array('info', LOG_INFO),
+ array('debug', LOG_DEBUG)
+ );
+ }
+
+}
+

0 comments on commit 018e5d0

Please sign in to comment.