feat(ZP-560): Add syslog option for logging

Support for syslog (local) and rsyslog (remote).
For me it's pretty usefull with docker containers or if you have
multiple instances and want to have all the log at the same place.
Signed-off-by: 's avatarFrancisco Miguel Biete &lt;fbiete@gmail.com&gt; <fmbiete@gmail.com>
parent 119acfdc
......@@ -106,6 +106,16 @@
define('LOGUSERLEVEL', LOGLEVEL_DEVICEID);
$specialLogUsers = array();
// If you want to disable log to file, and log to syslog instead
define('LOG_SYSLOG_ENABLED', false);
// false will log to local syslog, otherwise put the remote syslog IP here
define('LOG_SYSLOG_HOST', false);
// Syslog port
define('LOG_SYSLOG_PORT', 514);
// Program showed in the syslog. Useful if you have more than one instance login to the same syslog
define('LOG_SYSLOG_PROGRAM', '[z-push]');
// Location of the trusted CA, e.g. '/etc/ssl/certs/EmailCA.pem'
// Uncomment and modify the following line if the validation of the certificates fails.
// define('CAINFO', '/etc/ssl/certs/EmailCA.pem');
......
......@@ -63,6 +63,7 @@ include_once('lib/core/asdevice.php');
include_once('lib/core/statemanager.php');
include_once('lib/core/devicemanager.php');
include_once('lib/core/zpush.php');
include_once('lib/core/zsyslog.php');
include_once('lib/core/zlog.php');
include_once('lib/core/paddingfilter.php');
include_once('lib/interface/ibackend.php');
......
......@@ -50,6 +50,7 @@ class ZLog {
static private $lastLogs = array();
static private $userLog = false;
static private $unAuthCache = array();
static private $syslogEnabled = false;
/**
* Initializes the logging
......@@ -60,6 +61,11 @@ class ZLog {
static public function Initialize() {
global $specialLogUsers;
if (defined('LOG_SYSLOG_ENABLED') && LOG_SYSLOG_ENABLED) {
self::$syslogEnabled = true;
ZSyslog::Initialize();
}
// define some constants for the logging
if (!defined('LOGUSERLEVEL'))
define('LOGUSERLEVEL', LOGLEVEL_OFF);
......@@ -111,7 +117,7 @@ class ZLog {
$data = self::buildLogString($loglevel) . $message . "\n";
if ($loglevel <= LOGLEVEL) {
@file_put_contents(LOGFILE, $data, FILE_APPEND);
self::writeToLog($loglevel, $data, LOGFILE);
}
// should we write this into the user log?
......@@ -123,11 +129,11 @@ class ZLog {
if (self::logToUserFile()) {
// something was logged before the user was authenticated, write this to the log
if (!empty(self::$unAuthCache)) {
@file_put_contents(LOGFILEDIR . self::logToUserFile() . ".log", implode('', self::$unAuthCache), FILE_APPEND);
self::writeToLog($loglevel, implode('', self::$unAuthCache), LOGFILEDIR . self::logToUserFile() . ".log");
self::$unAuthCache = array();
}
// only use plain old a-z characters for the generic log file
@file_put_contents(LOGFILEDIR . self::logToUserFile() . ".log", $data, FILE_APPEND);
self::writeToLog($loglevel, $data, LOGFILEDIR . self::logToUserFile() . ".log");
}
// the user is not authenticated yet, we save the log into memory for now
else {
......@@ -136,7 +142,7 @@ class ZLog {
}
if (($loglevel & LOGLEVEL_FATAL) || ($loglevel & LOGLEVEL_ERROR)) {
@file_put_contents(LOGERRORFILE, $data, FILE_APPEND);
self::writeToLog($loglevel, $data, LOGERRORFILE);
}
if ($loglevel & LOGLEVEL_WBXMLSTACK) {
......@@ -205,7 +211,10 @@ class ZLog {
if (!isset(self::$devid))
self::$devid = '';
return Utils::GetFormattedTime() ." ". self::$pidstr . self::getLogLevelString($loglevel, (LOGLEVEL > LOGLEVEL_INFO)) ." ". self::$user . self::$devid;
if (self::$syslogEnabled)
return self::$pidstr . self::getLogLevelString($loglevel, (LOGLEVEL > LOGLEVEL_INFO)) . " " . self::$user . self::$devid;
else
return Utils::GetFormattedTime() . " " . self::$pidstr . self::getLogLevelString($loglevel, (LOGLEVEL > LOGLEVEL_INFO)) . " " . self::$user . self::$devid;
}
/**
......@@ -233,6 +242,31 @@ class ZLog {
case LOGLEVEL_WBXMLSTACK: return "[WBXMLSTACK]"; break;
}
}
/**
* Write the message to the log facility.
*
* @param int $loglevel
* @param string $data
* @param string $logfile
*
* @access private
* @return void
*/
static private function writeToLog($loglevel, $data, $logfile = null) {
if (self::$syslogEnabled) {
if (ZSyslog::send($loglevel, $data) === false) {
error_log("Unable to send to syslog");
error_log($data);
}
}
else {
if (@file_put_contents($logfile, $data, FILE_APPEND) === false) {
error_log(sprintf("Unable to write in %s", $logfile));
error_log($data);
}
}
}
}
/**----------------------------------------------------------------------------------------------------------
......
<?php
// local, remote and papertrail compatible syslogclass
// https://gist.github.com/coderofsalvation/11325307
class ZSyslog {
private static $hostname = false;
private static $port = 514;
private static $program = "[z-push]";
/**
* Initializes the logging
*
* @access public
* @return boolean
*/
public static function Initialize() {
if (defined('LOG_SYSLOG_HOST'))
self::$hostname = LOG_SYSLOG_HOST;
if (defined('LOG_SYSLOG_PORT'))
self::$port = LOG_SYSLOG_PORT;
if (defined('LOG_SYSLOG_PROGRAM'))
self::$program = LOG_SYSLOG_PROGRAM;
}
/**
* Send a message in the syslog facility.
*
* @params int $zlog_level Z-Push LogLevel
* @params string $message
*
* @access public
* @return boolean
*/
public static function send($zlog_level, $message) {
$level = self::zlogLevel2SyslogLevel($zlog_level);
if ($level === false) {
return false;
}
if (self::$hostname === false) {
return syslog($level, $message);
}
else {
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$facility = 1; // user level
$pri = ($facility*8) + $level; // multiplying the Facility number by 8 + adding the level
foreach (explode("\n", $message) as $line) {
if (strlen(trim($line)) > 0) {
$syslog_message = "<{$pri}>" . date('M d H:i:s ') . self::$program . ': ' . $line;
socket_sendto($sock, $syslog_message, strlen($syslog_message), 0, self::$hostname, self::$port);
}
}
socket_close($sock);
}
return true;
}
/**
* Converts the ZLog level to SYSLOG level.
*
* @params int $loglevel Z-Push LogLevel
*
* @access private
* @return SYSLOG_LEVEL or false
*/
private static function zlogLevel2SyslogLevel($loglevel) {
switch($loglevel) {
case LOGLEVEL_OFF: return false; break;
case LOGLEVEL_FATAL: return LOG_ALERT; break;
case LOGLEVEL_ERROR: return LOG_ERR; break;
case LOGLEVEL_WARN: return LOG_WARNING; break;
case LOGLEVEL_INFO: return LOG_INFO; break;
case LOGLEVEL_DEBUG: return LOG_DEBUG; break;
case LOGLEVEL_WBXML: return LOG_DEBUG; break;
case LOGLEVEL_DEVICEID: return LOG_DEBUG; break;
case LOGLEVEL_WBXMLSTACK: return LOG_DEBUG; break;
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment