-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Allow logging to multiple sinks
- Loading branch information
Showing
25 changed files
with
855 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Enum; | ||
|
||
enum LogLevel: string | ||
{ | ||
case TRACE = 'TRACE'; | ||
case DEBUG = 'DEBUG'; | ||
case INFO = 'INFO'; | ||
case WARN = 'WARN'; | ||
case ERROR = 'ERROR'; | ||
case OFF = 'OFF'; | ||
case NONE = 'NONE'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Exception; | ||
|
||
use PhpPact\Exception\BaseException; | ||
|
||
class LogException extends BaseException | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Exception; | ||
|
||
class LoggerApplyException extends LoggerException | ||
{ | ||
public function __construct(int $code) | ||
{ | ||
$message = match ($code) { | ||
-1 => "Can't set logger (applying the logger failed, perhaps because one is applied already).", | ||
default => 'Unknown error', | ||
}; | ||
parent::__construct($message, $code); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Exception; | ||
|
||
class LoggerAttachSinkException extends LoggerException | ||
{ | ||
public function __construct(int $code) | ||
{ | ||
$message = match ($code) { | ||
-1 => "Can't set logger (applying the logger failed, perhaps because one is applied already).", | ||
-2 => 'No logger has been initialized (call `pactffi_logger_init` before any other log function).', | ||
-3 => 'The sink specifier was not UTF-8 encoded.', | ||
-4 => 'The sink type specified is not a known type (known types: "stdout", "stderr", "buffer", or "file /some/path").', | ||
-5 => 'No file path was specified in a file-type sink specification.', | ||
-6 => 'Opening a sink to the specified file path failed (check permissions).', | ||
default => 'Unknown error', | ||
}; | ||
parent::__construct($message, $code); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Exception; | ||
|
||
class LoggerException extends LogException | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Exception; | ||
|
||
class LoggerUnserializeException extends LoggerException | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log; | ||
|
||
use PhpPact\FFI\Client; | ||
use PhpPact\FFI\ClientInterface; | ||
use PhpPact\Log\Enum\LogLevel; | ||
use PhpPact\Log\Exception\LoggerApplyException; | ||
use PhpPact\Log\Exception\LoggerAttachSinkException; | ||
use PhpPact\Log\Exception\LoggerUnserializeException; | ||
use PhpPact\Log\Model\SinkInterface; | ||
|
||
final class Logger implements LoggerInterface | ||
{ | ||
private static ?self $instance = null; | ||
/** | ||
* @var SinkInterface[] | ||
*/ | ||
private array $sinks = []; | ||
private bool $applied = false; | ||
|
||
protected function __construct(private ClientInterface $client) | ||
{ | ||
$this->client->loggerInit(); | ||
} | ||
|
||
protected function __clone(): void | ||
{ | ||
} | ||
|
||
public function __wakeup(): never | ||
{ | ||
throw new LoggerUnserializeException('Cannot unserialize a singleton.'); | ||
} | ||
|
||
public static function instance(?ClientInterface $client = null): Logger | ||
{ | ||
if (!isset(self::$instance)) { | ||
self::$instance = new self($client ?? new Client()); | ||
} | ||
return self::$instance; | ||
} | ||
|
||
public static function tearDown(): void | ||
{ | ||
self::$instance = null; | ||
} | ||
|
||
public function attach(SinkInterface $sink): void | ||
{ | ||
if ($this->applied) { | ||
return; | ||
} | ||
$this->sinks[] = $sink; | ||
} | ||
|
||
public function apply(): void | ||
{ | ||
if ($this->applied) { | ||
return; | ||
} | ||
foreach ($this->sinks as $sink) { | ||
$error = $this->client->loggerAttachSink($sink->getSpecifier(), $this->getLevelFilter($sink->getLevel())); | ||
if ($error) { | ||
throw new LoggerAttachSinkException($error); | ||
} | ||
} | ||
$error = $this->client->loggerApply(); | ||
if ($error) { | ||
throw new LoggerApplyException($error); | ||
} | ||
$this->applied = true; | ||
} | ||
|
||
public function fetchBuffer(): string | ||
{ | ||
return $this->client->fetchLogBuffer(); | ||
} | ||
|
||
private function getLevelFilter(LogLevel $level): int | ||
{ | ||
return match ($level) { | ||
LogLevel::TRACE => $this->client->getLevelFilterTrace(), | ||
LogLevel::DEBUG => $this->client->getLevelFilterDebug(), | ||
LogLevel::INFO => $this->client->getLevelFilterInfo(), | ||
LogLevel::WARN => $this->client->getLevelFilterWarn(), | ||
LogLevel::ERROR => $this->client->getLevelFilterError(), | ||
LogLevel::OFF => $this->client->getLevelFilterOff(), | ||
LogLevel::NONE => $this->client->getLevelFilterOff(), | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log; | ||
|
||
use PhpPact\Log\Model\SinkInterface; | ||
|
||
interface LoggerInterface | ||
{ | ||
public function attach(SinkInterface $sink): void; | ||
|
||
public function apply(): void; | ||
|
||
public function fetchBuffer(): string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Model; | ||
|
||
use PhpPact\Log\Enum\LogLevel; | ||
|
||
abstract class AbstractSink implements SinkInterface | ||
{ | ||
public function __construct(private LogLevel $level) | ||
{ | ||
} | ||
|
||
public function getLevel(): LogLevel | ||
{ | ||
return $this->level; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Model; | ||
|
||
class Buffer extends AbstractSink | ||
{ | ||
public function getSpecifier(): string | ||
{ | ||
return 'buffer'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Model; | ||
|
||
use PhpPact\Log\Enum\LogLevel; | ||
|
||
class File extends AbstractSink | ||
{ | ||
public function __construct(private string $path, LogLevel $level) | ||
{ | ||
parent::__construct($level); | ||
} | ||
|
||
public function getSpecifier(): string | ||
{ | ||
return "file {$this->path}"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Model; | ||
|
||
use PhpPact\Log\Enum\LogLevel; | ||
|
||
interface SinkInterface | ||
{ | ||
public function getLevel(): LogLevel; | ||
|
||
public function getSpecifier(): string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Model; | ||
|
||
class Stderr extends AbstractSink | ||
{ | ||
public function getSpecifier(): string | ||
{ | ||
return 'stderr'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
namespace PhpPact\Log\Model; | ||
|
||
class Stdout extends AbstractSink | ||
{ | ||
public function getSpecifier(): string | ||
{ | ||
return 'stdout'; | ||
} | ||
} |
Oops, something went wrong.