Wenn ich eine Lib oder ein Framework sehe, kommt bei mir immer die Frage auf: "Wie macht man so etwas?" Das gipfelte heute darin, dass ich ein kleines Logging-Framework geschrieben habe. Etwas an
Log4j erinnernd aber erst einmal nur mit Output in eine Datei. Andere Outputs könnte man noch integrieren durch Appender-Types.
Die LoggerFactory
class XWLoggerFactory{
private static $config=[];
private static $appenderCache=[];
/**
* @return XWLogger
* @param string $clazz
*/
public static function getLogger($clazz){
if(count(self::$config)==0 && file_exists("system/config/log.json")){
self::$config=json_decode(file_get_contents("system/config/log.json"),true);
foreach(self::$config["appenders"] as $appender){
self::$appenderCache[$appender["name"]]=$appender;
}
}
$appenders=[];
$levels=[];
foreach(self::$config["classes"] as $cla){
if(preg_match("/^".$cla["name"]."/i", $clazz)){
foreach($cla["appenders"] as $app){
$appenders[]=self::$appenderCache[$app["name"]];
$levels[]=$app["level"];
}
}
}
return new XWLogger($clazz, $appenders, $levels);
}
}
Der Logger
class XWLogger{
const ALERT="alert";
const CRITICAL="critical";
const ERROR="error";
const WARNING="warning";
const INFO="info";
const NOTICE="notice";
const DEBUG="debug";
private $clazz="";
private $appenders=[];
private $levels=[];
private $values=[
"alert" => 6,
"critical" => 5,
"error" => 4,
"warning" => 3,
"info" => 2,
"notice" => 1,
"debug" => 0,
];
public function __construct($clazz, $appenders, $levels){
$this->clazz=$clazz;
$this->appenders=$appenders;
$this->levels=$levels;
}
/**
*
* @param string $type
* @param string $msg
* @param \Exception $e
*/
public function log($type, $msg, \Exception $e=null){
foreach($this->appenders as $key => $app){
if($this->values[$this->levels[$key]] >= $this->values[strtolower($type)]){
$dateFormat="Y-m-d h:i:s";
if(isset($app["dateformat"])){
$dateFormat=$app["dateformat"];
}
$ip="";
if(isset($app["remoteip"]) && ($app["remoteip"]===true || $app["remoteip"]=="true")){
$ip=" [".$_SERVER["REMOTE_ADDR"]."]";
}
$content = strtoupper($type).$ip." [".date($dateFormat)."]: ".$msg;
if($e!=null && $app["exceptionFullStackTrace"]){
$content.="\n".$e->getTraceAsString();
}
if(!file_exists($app["filename"])){
if(!file_exists(preg_replace("/[a-zA-Z0-9_.]+$/Uis", "", $app["filename"]))){
mkdir(preg_replace("/[a-zA-Z0-9_.]+$/Uis", "", $app["filename"]));
}
}
file_put_contents($app["filename"], $content."\n", FILE_APPEND);
}
}
}
}
Die Config-Datei (
system/config/log.json) for den aoop-PageLoader
{
"appenders":[
{
"name":"default",
"filename":"system/log/aoop.log",
"dateformat":"H-m-y h:i:s",
"remoteip":"true"
}
],
"classes":[
{
"name":"XWFastPostProPageLoader",
"appenders":[
{
"name":"default",
"level":"warning"
}
]
}
]
}
Eine Nutzung mit einer einfachen Warning
XWLoggerFactory::getLogger(self:class)->log(XWLogger::Warning, "a warning!");