mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
Merge pull request #101 from Combodo/feature/faf_log_modularity
Feature/faf log modularity
This commit is contained in:
@@ -99,6 +99,14 @@ class Config
|
||||
* @since 2.7.0 export_pdf_font param
|
||||
*/
|
||||
protected $m_aSettings = array(
|
||||
'log_level_min' => array(
|
||||
'type' => 'array',
|
||||
'description' => 'Optional min log level per channel',
|
||||
'default' => '',
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'app_env_label' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'Label displayed to describe the current application environment, defaults to the environment name (e.g. "production")',
|
||||
|
||||
@@ -199,28 +199,36 @@ class FileLog
|
||||
}
|
||||
}
|
||||
|
||||
public function Error($sText)
|
||||
public function Error($sText, $sChannel = '', $aContext = array())
|
||||
{
|
||||
$this->Write('Error | '.$sText);
|
||||
$this->Write($sText, __FUNCTION__, $sChannel, $aContext);
|
||||
}
|
||||
|
||||
public function Warning($sText)
|
||||
public function Warning($sText, $sChannel = '', $aContext = array())
|
||||
{
|
||||
$this->Write('Warning | '.$sText);
|
||||
$this->Write($sText, __FUNCTION__, $sChannel, $aContext);
|
||||
}
|
||||
|
||||
public function Info($sText)
|
||||
public function Info($sText, $sChannel = '', $aContext = array())
|
||||
{
|
||||
$this->Write('Info | '.$sText);
|
||||
$this->Write($sText, __FUNCTION__, $sChannel, $aContext);
|
||||
}
|
||||
|
||||
public function Ok($sText)
|
||||
public function Ok($sText, $sChannel = '', $aContext = array())
|
||||
{
|
||||
$this->Write('Ok | '.$sText);
|
||||
$this->Write($sText, __FUNCTION__, $sChannel, $aContext);
|
||||
}
|
||||
|
||||
protected function Write($sText)
|
||||
public function Debug($sText, $sChannel = '', $aContext = array())
|
||||
{
|
||||
$this->Write($sText, __FUNCTION__, $sChannel, $aContext);
|
||||
}
|
||||
|
||||
protected function Write($sText, $sLevel = '', $sChannel = '', $aContext = array())
|
||||
{
|
||||
$sTextPrefix = empty($sLevel) ? '' : (str_pad($sLevel, 7).' | ');
|
||||
$sTextSuffix = empty($sChannel) ? '' : " | $sChannel";
|
||||
$sText = "{$sTextPrefix}{$sText}{$sTextSuffix}";
|
||||
$sLogFilePath = $this->oFileNameBuilder->GetLogFilePath();
|
||||
|
||||
if (empty($sLogFilePath))
|
||||
@@ -233,6 +241,15 @@ class FileLog
|
||||
{
|
||||
flock($hLogFile, LOCK_EX);
|
||||
$sDate = date('Y-m-d H:i:s');
|
||||
if (empty($aContext))
|
||||
{
|
||||
fwrite($hLogFile, "$sDate | $sText\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
$sContext = var_export($aContext, true);
|
||||
fwrite($hLogFile, "$sDate | $sText\n$sContext\n");
|
||||
}
|
||||
fwrite($hLogFile, "$sDate | $sText\n");
|
||||
fflush($hLogFile);
|
||||
flock($hLogFile, LOCK_UN);
|
||||
@@ -243,53 +260,161 @@ class FileLog
|
||||
|
||||
abstract class LogAPI
|
||||
{
|
||||
const CHANNEL_DEFAULT = '';
|
||||
|
||||
const LEVEL_DEBUG = 'Debug';
|
||||
const LEVEL_OK = 'Ok';
|
||||
const LEVEL_INFO = 'Info';
|
||||
const LEVEL_WARNING = 'Warning';
|
||||
const LEVEL_ERROR = 'Error';
|
||||
// const LEVEL_CRITICAL = 'Critical';
|
||||
// const LEVEL_ALERT = 'Alert';
|
||||
// const LEVEL_EMERGENCY = 'Emergency';
|
||||
|
||||
protected static $m_oMockMetaModelConfig = null;
|
||||
|
||||
protected static $aLevelsPriority = array(
|
||||
self::LEVEL_DEBUG => 100,
|
||||
self::LEVEL_OK => 150,
|
||||
self::LEVEL_INFO => 200,
|
||||
self::LEVEL_WARNING => 300,
|
||||
self::LEVEL_ERROR => 400,
|
||||
);
|
||||
|
||||
public static function Enable($sTargetFile)
|
||||
{
|
||||
// m_oFileLog is not defined as a class attribute so that each impl will have its own
|
||||
static::$m_oFileLog = new FileLog($sTargetFile);
|
||||
}
|
||||
|
||||
public static function Error($sText)
|
||||
public static function MockStaticObjects($oFileLog, $oMetaModelConfig=null)
|
||||
{
|
||||
if (static::$m_oFileLog)
|
||||
{
|
||||
static::$m_oFileLog->Error($sText);
|
||||
}
|
||||
static::$m_oFileLog = $oFileLog;
|
||||
static::$m_oMockMetaModelConfig = $oMetaModelConfig;
|
||||
}
|
||||
public static function Warning($sText)
|
||||
|
||||
public static function Error($sMessage, $sChannel = null, $aContext = array())
|
||||
{
|
||||
if (static::$m_oFileLog)
|
||||
{
|
||||
static::$m_oFileLog->Warning($sText);
|
||||
}
|
||||
static::Log(self::LEVEL_ERROR, $sMessage, $sChannel, $aContext);
|
||||
}
|
||||
public static function Info($sText)
|
||||
|
||||
public static function Warning($sMessage, $sChannel = null, $aContext = array())
|
||||
{
|
||||
if (static::$m_oFileLog)
|
||||
{
|
||||
static::$m_oFileLog->Info($sText);
|
||||
}
|
||||
static::Log(self::LEVEL_WARNING, $sMessage, $sChannel, $aContext);
|
||||
}
|
||||
public static function Ok($sText)
|
||||
|
||||
public static function Info($sMessage, $sChannel = null, $aContext = array())
|
||||
{
|
||||
if (static::$m_oFileLog)
|
||||
{
|
||||
static::$m_oFileLog->Ok($sText);
|
||||
}
|
||||
static::Log(self::LEVEL_INFO, $sMessage, $sChannel, $aContext);
|
||||
}
|
||||
|
||||
public static function Ok($sMessage, $sChannel = null, $aContext = array())
|
||||
{
|
||||
static::Log(self::LEVEL_OK, $sMessage, $sChannel, $aContext);
|
||||
}
|
||||
|
||||
public static function Debug($sMessage, $sChannel = null, $aContext = array())
|
||||
{
|
||||
static::Log(self::LEVEL_DEBUG, $sMessage, $sChannel, $aContext);
|
||||
}
|
||||
|
||||
public static function Log($sLevel, $sMessage, $sChannel = null, $aContext = array())
|
||||
{
|
||||
if (! static::$m_oFileLog)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (! isset(self::$aLevelsPriority[$sLevel]))
|
||||
{
|
||||
IssueLog::Error("invalid log level '{$sLevel}'");
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_null($sChannel))
|
||||
{
|
||||
$sChannel = static::CHANNEL_DEFAULT;
|
||||
}
|
||||
|
||||
$sMinLogLevel = self::GetMinLogLevel($sChannel);
|
||||
|
||||
if ($sMinLogLevel === false || $sMinLogLevel === 'false')
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (is_string($sMinLogLevel))
|
||||
{
|
||||
if (! isset(self::$aLevelsPriority[$sMinLogLevel]))
|
||||
{
|
||||
throw new Exception("invalid configuration for log_level '{$sMinLogLevel}' is not within the list: ".implode(',', array_keys(self::$aLevelsPriority)));
|
||||
}
|
||||
elseif (self::$aLevelsPriority[$sLevel] < self::$aLevelsPriority[$sMinLogLevel])
|
||||
{
|
||||
//priority too low regarding the conf, do not log this
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static::$m_oFileLog->$sLevel($sMessage, $sChannel, $aContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sChannel
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
private static function GetMinLogLevel($sChannel)
|
||||
{
|
||||
$oConfig = (static::$m_oMockMetaModelConfig !== null) ? static::$m_oMockMetaModelConfig : \MetaModel::GetConfig();
|
||||
if (!$oConfig instanceof Config)
|
||||
{
|
||||
return self::LEVEL_OK;
|
||||
}
|
||||
|
||||
$sLogLevelMin = $oConfig->Get('log_level_min');
|
||||
|
||||
if (empty($sLogLevelMin))
|
||||
{
|
||||
return self::LEVEL_OK;
|
||||
}
|
||||
|
||||
if (!is_array($sLogLevelMin))
|
||||
{
|
||||
return $sLogLevelMin;
|
||||
}
|
||||
|
||||
if (isset($sLogLevelMin[$sChannel]))
|
||||
{
|
||||
return $sLogLevelMin[$sChannel];
|
||||
}
|
||||
|
||||
if (isset($sLogLevelMin[static::CHANNEL_DEFAULT]))
|
||||
{
|
||||
return $sLogLevelMin[$sChannel];
|
||||
}
|
||||
|
||||
return self::LEVEL_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SetupLog extends LogAPI
|
||||
{
|
||||
const CHANNEL_DEFAULT = 'SetupLog';
|
||||
|
||||
protected static $m_oFileLog = null;
|
||||
}
|
||||
|
||||
class IssueLog extends LogAPI
|
||||
{
|
||||
const CHANNEL_DEFAULT = 'IssueLog';
|
||||
|
||||
protected static $m_oFileLog = null;
|
||||
}
|
||||
|
||||
class ToolsLog extends LogAPI
|
||||
{
|
||||
const CHANNEL_DEFAULT = 'ToolsLog';
|
||||
|
||||
protected static $m_oFileLog = null;
|
||||
}
|
||||
|
||||
161
test/core/LogAPITest.php
Normal file
161
test/core/LogAPITest.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Eric
|
||||
* Date: 31/08/2018
|
||||
* Time: 17:03
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Core;
|
||||
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class LogAPITest extends ItopTestCase
|
||||
{
|
||||
private $mockFileLog;
|
||||
private $oMetaModelConfig;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockFileLog = $this->createMock('FileLog');
|
||||
$this->oMetaModelConfig = $this->createMock('Config');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dataProvider LogApiProvider
|
||||
* @test
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
public function TestLogApi($oConfigObject, $sMessage, $Channel, $sExpectedLevel, $sExpectedMessage, $sExpectedChannel = '')
|
||||
{
|
||||
\IssueLog::MockStaticObjects($this->mockFileLog, $oConfigObject);
|
||||
|
||||
$this->mockFileLog->expects($this->exactly(1))
|
||||
->method($sExpectedLevel)
|
||||
->with($sExpectedMessage, $sExpectedChannel);
|
||||
|
||||
\IssueLog::Error($sMessage, $Channel);
|
||||
}
|
||||
|
||||
public function LogApiProvider()
|
||||
{
|
||||
return [
|
||||
[ $this->oMetaModelConfig, "log msg", '' , "Error", "log msg"],
|
||||
[ $this->oMetaModelConfig, "log msg", 'PoudlardChannel' , "Error", "log msg", 'PoudlardChannel'],
|
||||
[ array(), "log msg", '' , "Error", "log msg"], // Bruno?
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
public function TestUnknownLevel()
|
||||
{
|
||||
$this->mockFileLog->expects($this->exactly(1))
|
||||
->method("Error")
|
||||
->with("invalid log level 'TotoLevel'");
|
||||
|
||||
\IssueLog::Log('TotoLevel', "log msg");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider LogWarningWithASpecificChannelProvider
|
||||
* @test
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
public function TestLogWarningWithASpecificChannel($expectedCallNb, $sExpectedLevel, $ConfigReturnedObject, $bExceptionRaised=false)
|
||||
{
|
||||
$this->oMetaModelConfig
|
||||
->method("Get")
|
||||
->with('log_level_min')
|
||||
->willReturn($ConfigReturnedObject);
|
||||
|
||||
\IssueLog::MockStaticObjects($this->mockFileLog, $this->oMetaModelConfig);
|
||||
|
||||
$this->mockFileLog->expects($this->exactly($expectedCallNb))
|
||||
->method($sExpectedLevel)
|
||||
->with("log msg", "GaBuZoMeuChannel");
|
||||
|
||||
try{
|
||||
\IssueLog::Warning("log msg", "GaBuZoMeuChannel");
|
||||
if ($bExceptionRaised)
|
||||
{
|
||||
$this->fail("raised should have been raised");
|
||||
}
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
if (!$bExceptionRaised)
|
||||
{
|
||||
$this->fail("raised should NOT have been raised");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function LogWarningWithASpecificChannelProvider()
|
||||
{
|
||||
return [
|
||||
"empty config" => [ 0, "Ok", ''],
|
||||
"Default Unknown Level" => [ 0, "Ok", 'TotoLevel', true],
|
||||
"Info as Default Level" => [ 1 , "Warning", 'Info'],
|
||||
"Error as Default Level" => [ 0, "Warning", 'Error'],
|
||||
"Empty array" => [ 0, "Ok", array()],
|
||||
"Channel configured on an undefined level" => [ 0, "Ok", ["GaBuZoMeuChannel" => "TotoLevel"], true],
|
||||
"Channel defined with Error" => [ 0, "Warning", ["GaBuZoMeuChannel" => "Error"]],
|
||||
"Channel defined with Info" => [ 1, "Warning", ["GaBuZoMeuChannel" => "Info"]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider LogOkWithASpecificChannel
|
||||
* @test
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
public function TestLogOkWithASpecificChannel($expectedCallNb, $sExpectedLevel, $ConfigReturnedObject, $bExceptionRaised=false)
|
||||
{
|
||||
$this->oMetaModelConfig
|
||||
->method("Get")
|
||||
->with('log_level_min')
|
||||
->willReturn($ConfigReturnedObject);
|
||||
|
||||
\IssueLog::MockStaticObjects($this->mockFileLog, $this->oMetaModelConfig);
|
||||
|
||||
$this->mockFileLog->expects($this->exactly($expectedCallNb))
|
||||
->method($sExpectedLevel)
|
||||
->with("log msg", "GaBuZoMeuChannel");
|
||||
|
||||
try{
|
||||
\IssueLog::Ok("log msg", "GaBuZoMeuChannel");
|
||||
if ($bExceptionRaised)
|
||||
{
|
||||
$this->fail("raised should have been raised");
|
||||
}
|
||||
}
|
||||
catch(\Exception $e)
|
||||
{
|
||||
if (!$bExceptionRaised)
|
||||
{
|
||||
$this->fail("raised should NOT have been raised");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function LogOkWithASpecificChannel()
|
||||
{
|
||||
return [
|
||||
"empty config" => [ 1, "Ok", ''],
|
||||
"Empty array" => [ 1, "Ok", array()],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user