36 protected bool $logDebug;
38 private string $format = TextFormat::AQUA .
"[%s] " . TextFormat::RESET .
"%s[%s/%s]: %s" . TextFormat::RESET;
39 private bool $useFormattingCodes =
false;
40 private string $mainThreadName;
41 private string $timezone;
47 public function __construct(?
string $logFile,
bool $useFormattingCodes,
string $mainThreadName, \DateTimeZone $timezone,
bool $logDebug =
false, ?
string $logArchiveDir =
null){
48 parent::__construct();
49 $this->logDebug = $logDebug;
51 $this->useFormattingCodes = $useFormattingCodes;
52 $this->mainThreadName = $mainThreadName;
53 $this->timezone = $timezone->getName();
55 if($logFile !==
null){
57 $this->logWriterThread->start(NativeThread::INHERIT_NONE);
80 $this->format = $format;
84 $this->send($message, \LogLevel::EMERGENCY,
"EMERGENCY", TextFormat::RED);
87 public function alert($message){
88 $this->send($message, \LogLevel::ALERT,
"ALERT", TextFormat::RED);
92 $this->send($message, \LogLevel::CRITICAL,
"CRITICAL", TextFormat::RED);
95 public function error($message){
96 $this->send($message, \LogLevel::ERROR,
"ERROR", TextFormat::DARK_RED);
100 $this->send($message, \LogLevel::WARNING,
"WARNING", TextFormat::YELLOW);
104 $this->send($message, \LogLevel::NOTICE,
"NOTICE", TextFormat::AQUA);
107 public function info($message){
108 $this->send($message, \LogLevel::INFO,
"INFO", TextFormat::WHITE);
111 public function debug($message,
bool $force =
false){
112 if(!$this->logDebug && !$force){
115 $this->send($message, \LogLevel::DEBUG,
"DEBUG", TextFormat::GRAY);
118 public function setLogDebug(
bool $logDebug) : void{
119 $this->logDebug = $logDebug;
129 $this->critical(implode(
"\n", Utils::printableExceptionInfo($e, $trace)));
131 $this->syncFlushBuffer();
134 public function log($level, $message){
136 case \LogLevel::EMERGENCY:
137 $this->emergency($message);
139 case \LogLevel::ALERT:
140 $this->alert($message);
142 case \LogLevel::CRITICAL:
143 $this->critical($message);
145 case \LogLevel::ERROR:
146 $this->error($message);
148 case \LogLevel::WARNING:
149 $this->warning($message);
151 case \LogLevel::NOTICE:
152 $this->notice($message);
154 case \LogLevel::INFO:
155 $this->info($message);
157 case \LogLevel::DEBUG:
158 $this->debug($message);
166 public function buffer(\Closure $c) : void{
167 $this->synchronized($c);
170 public function shutdownLogWriterThread() : void{
171 if($this->logWriterThread !== null){
172 if(NativeThread::getCurrentThreadId() === $this->logWriterThread->getCreatorId()){
173 $this->logWriterThread->shutdown();
175 throw new \LogicException(
"Only the creator thread can shutdown the logger thread");
180 protected function send(
string $message,
string $level,
string $prefix,
string $color) : void{
181 $time = new \DateTime(
'now', new \DateTimeZone($this->timezone));
183 $thread = NativeThread::getCurrentThread();
184 if($thread ===
null){
185 $threadName = $this->mainThreadName .
" thread";
186 }elseif($thread instanceof Thread || $thread instanceof Worker){
187 $threadName = $thread->getThreadName() .
" thread";
189 $threadName = (new \ReflectionClass($thread))->getShortName() .
" thread";
192 $message = sprintf($this->format, $time->format(
"H:i:s.v"), $color, $threadName, $prefix, TextFormat::addBase($color, TextFormat::clean($message,
false)));
194 if(!Terminal::isInit()){
195 Terminal::init($this->useFormattingCodes);
198 $this->
synchronized(
function() use ($message, $level, $time) : void{
199 Terminal::writeLine($message);
200 if($this->logWriterThread !==
null){
201 $this->logWriterThread->write($time->format(
"Y-m-d") .
" " . TextFormat::clean($message) . PHP_EOL);
207 foreach($this->attachments as $attachment){
208 $attachment->log($level, $message);
213 public function syncFlushBuffer() : void{
214 $this->logWriterThread?->syncFlushBuffer();
217 public function __destruct(){
218 if($this->logWriterThread !==
null && !$this->logWriterThread->isJoined() && NativeThread::getCurrentThreadId() === $this->logWriterThread->getCreatorId()){
219 $this->shutdownLogWriterThread();
setFormat(string $format)
__construct(?string $logFile, bool $useFormattingCodes, string $mainThreadName, \DateTimeZone $timezone, bool $logDebug=false, ?string $logArchiveDir=null)
logException(\Throwable $e, $trace=null)