296 lines
6.9 KiB
PHP
296 lines
6.9 KiB
PHP
<?php
|
|
/**
|
|
* @brief Log Class
|
|
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
|
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
|
* @license http://www.invisionpower.com/legal/standards/
|
|
* @package IPS Social Suite
|
|
* @since 07 Nov 2013
|
|
* @version SVN_VERSION_NUMBER
|
|
*/
|
|
|
|
namespace IPS;
|
|
|
|
/* To prevent PHP errors (extending class does not exist) revealing path */
|
|
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
|
{
|
|
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Log Class
|
|
*/
|
|
abstract class _Log
|
|
{
|
|
/**
|
|
* @brief Multitons
|
|
*/
|
|
protected static $instances = array();
|
|
|
|
/**
|
|
* @brief Configuration
|
|
*/
|
|
protected static $configuration = NULL;
|
|
|
|
/**
|
|
* Log
|
|
*
|
|
* Severity constants
|
|
* @li LOG_EMERG system is unusable
|
|
* @li LOG_ALERT action must be taken immediately
|
|
* @li LOG_CRIT critical conditions
|
|
* @li LOG_ERR error conditions
|
|
* @li LOG_WARNING warning conditions
|
|
* @li LOG_NOTICE normal, but significant, condition
|
|
* @li LOG_INFO informational message
|
|
* @li LOG_DEBUG debug-level message
|
|
*
|
|
* LOG_METHOD example JSON object
|
|
* [
|
|
* {
|
|
* 'levels': [0,1,2,3,4,5],
|
|
* 'method': 'disk'
|
|
* },
|
|
* {
|
|
* 'levels': [6,7],
|
|
* 'method': 'email',
|
|
* 'config': { 'to': 'sales@invisionpower.com', 'subject': 'New error log from My Community' }
|
|
* }
|
|
* ]
|
|
*
|
|
* Acceptable methods are "disk", "email" and "syslog".
|
|
*
|
|
* Caveats:
|
|
* @li Email method falls back to PHPs 'mail' command if using the framework fails (critical DB error, etc). If your server cannot use
|
|
* PHPs mail, then do not use the email method.
|
|
*
|
|
* Any missing levels (between 0 and 6) are populated by 'disk' method. 7 is debug and can be left blank
|
|
*
|
|
* @param int|string $key PHP syslog constant (int) or method name (string)
|
|
* @return object \IPS\Log
|
|
*
|
|
* @see <a href='http://tools.ietf.org/html/rfc5424'>RFC 5424</a>
|
|
* @see <a href='http://php.net/syslog'>PHP's syslog</a>
|
|
*/
|
|
public static function i( $key )
|
|
{
|
|
if ( is_string( $key ) )
|
|
{
|
|
$severity = static::getSeverityFromMethod( $key );
|
|
}
|
|
else
|
|
{
|
|
$severity = intval( $key );
|
|
}
|
|
|
|
$config = static::getConfiguration();
|
|
|
|
if ( !isset( static::$instances[ $severity ] ) )
|
|
{
|
|
$classname = '\IPS\Log\\' . ucfirst( $config[ $severity ]['method'] );
|
|
static::$instances[ $severity ] = new $classname( $config[ $severity ]['config'], $severity );
|
|
}
|
|
|
|
/* One method can have multiple severities, so lets set the current severity for this call */
|
|
static::$instances[ $severity ]->setSeverity( $severity );
|
|
|
|
return static::$instances[ $severity ];
|
|
}
|
|
|
|
/**
|
|
* Return a severity level based on method name (disk, syslog, etc)
|
|
*
|
|
* @param string $method Method name (disk, syslog, etc)
|
|
* @return int
|
|
*/
|
|
public static function getSeverityFromMethod( $method )
|
|
{
|
|
foreach( static::getUsedMethods() as $method => $levels )
|
|
{
|
|
$severity = array_pop( $levels );
|
|
return $severity;
|
|
}
|
|
|
|
return LOG_DEBUG;
|
|
}
|
|
|
|
/**
|
|
* Return an array of used methods with the severity levels assigned
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function getUsedMethods()
|
|
{
|
|
$config = static::getConfiguration();
|
|
$methods = array();
|
|
|
|
foreach( $config as $level => $data )
|
|
{
|
|
$methods[ $data['method'] ][] = $level;
|
|
}
|
|
|
|
return $methods;
|
|
}
|
|
|
|
/**
|
|
* Returns the configuration from LOG_METHOD parsed and checked
|
|
*
|
|
* @return array
|
|
*/
|
|
protected static function getConfiguration()
|
|
{
|
|
if ( static::$configuration === NULL )
|
|
{
|
|
$json = @json_decode( LOG_METHOD, TRUE );
|
|
|
|
if ( is_array( $json ) )
|
|
{
|
|
foreach( $json as $row )
|
|
{
|
|
if ( isset( $row['levels'] ) AND isset( $row['method'] ) AND is_array( $row['levels'] ) )
|
|
{
|
|
foreach( $row['levels'] as $level )
|
|
{
|
|
static::$configuration[ $level ]['method'] = $row['method'];
|
|
static::$configuration[ $level ]['config'] = ( isset( $row['config'] ) ) ? $row['config'] : NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Ensure everything except DEBUG has a value */
|
|
foreach( range( 0, 6 ) as $level )
|
|
{
|
|
if ( ! isset( static::$configuration[ $level ] ) )
|
|
{
|
|
static::$configuration[ $level ]['method'] = 'disk';
|
|
static::$configuration[ $level ]['config'] = NULL;
|
|
}
|
|
}
|
|
|
|
/* And then make sure DEBUG has a value set to None if not already set */
|
|
if ( ! isset( static::$configuration[ 7 ] ) )
|
|
{
|
|
static::$configuration[ 7 ]['method'] = 'none';
|
|
static::$configuration[ 7 ]['config'] = NULL;
|
|
}
|
|
}
|
|
|
|
return static::$configuration;
|
|
}
|
|
|
|
/**
|
|
* Prune logs where possible
|
|
*
|
|
* @param int $days Older than (days) to prune
|
|
* @return void
|
|
*/
|
|
public static function pruneLogs( $days )
|
|
{
|
|
if ( ! $days )
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach( static::getUsedMethods() as $method => $levels )
|
|
{
|
|
\IPS\Log::i( $method )->prune( $days );
|
|
}
|
|
}
|
|
|
|
/* @Brief Configuration array */
|
|
protected $config = NULL;
|
|
|
|
/* @Brief Severity level */
|
|
protected $severity = NULL;
|
|
|
|
/**
|
|
* The constructor
|
|
*
|
|
* @param array|null $config
|
|
* @param int $severity
|
|
* @return void
|
|
*/
|
|
public function __construct( $config, $severity )
|
|
{
|
|
$this->config = $config;
|
|
$this->setSeverity( $severity );
|
|
}
|
|
|
|
/**
|
|
* Store the severity for this call
|
|
*
|
|
* @param int $severity Severity
|
|
* @return \IPS\Log
|
|
*/
|
|
public function setSeverity( $severity )
|
|
{
|
|
$this->severity = $severity;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @brief IP address to use or NULL to retrieve from Request class
|
|
*/
|
|
protected $ipAddress = NULL;
|
|
|
|
/**
|
|
* Set the IP address
|
|
*
|
|
* @param string $ip IP address
|
|
* @return \IPS\Log
|
|
* @note This method is designed so that we can bypass issues with \IPS\Settings not loaded yet for instance when logging cache-related calls (since settings are stored in cache)
|
|
*/
|
|
public function setIpAddress( $ip )
|
|
{
|
|
$this->ipAddress = $ip;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the IP address
|
|
*
|
|
* @return string
|
|
* @note This call will reset the stored IP address every time so that other log requests use the correct IP
|
|
*/
|
|
public function getIpAddress()
|
|
{
|
|
$result = ( $this->ipAddress !== NULL ) ? $this->ipAddress : \IPS\Request::i()->ipAddress();
|
|
$this->ipAddress = NULL;
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Get the most recent log titles
|
|
*
|
|
* @param int $limit
|
|
* @return array array( array( 'date' => unixTimeStamp, 'title' => title, 'suffix' => suffix ), ... );
|
|
*/
|
|
public function getMostRecentLogsTitles( $limit=50 )
|
|
{
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Get latest logs
|
|
*
|
|
* @param \IPS\DateTime $date Limit only to logs after this date
|
|
* @return array array( array( 'date' => unixTimeStamp, 'title' => title, 'suffix' => suffix ), ... );
|
|
*/
|
|
public function getLatestTitles( \IPS\DateTime $date )
|
|
{
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Prune logs
|
|
*
|
|
* @param int $days Older than (days) to prune
|
|
* @return void
|
|
*/
|
|
public function prune( $days )
|
|
{
|
|
|
|
}
|
|
} |