Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ Example
-------

```php
use util\log\LogCategory;
use util\log\ConsoleAppender;
use util\log\Logging;
use util\ServiceNotAvailableException;
use lang\Throwable;

$logger= (new LogCategory())->withAppender(new ConsoleAppender());
$logger= Logging::named('service')->toConsole();
$logger->info('Starting application');

try {
Expand Down
12 changes: 9 additions & 3 deletions src/main/php/util/log/FileAppender.class.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php namespace util\log;

use io\File;

/**
* Appender which appends data to a file
*
Expand All @@ -23,10 +25,14 @@ class FileAppender extends Appender {
/**
* Constructor
*
* @param string $filename default 'php://stderr' filename to log to
* @param string|io.Path|io.File $file
*/
public function __construct($filename= 'php://stderr') {
$this->filename= $filename;
public function __construct($file= 'php://stderr') {
if ($file instanceof File) {
$this->filename= $file->getURI();
} else {
$this->filename= (string)$file;
}
}

/**
Expand Down
128 changes: 128 additions & 0 deletions src/main/php/util/log/LogSetup.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php namespace util\log;

use util\log\layout\DefaultLayout;
use lang\Value;
use util\Objects;

/**
* Logging DSL
*
* @test xp://util.log.unittest.LoggingTest
*/
class LogSetup implements Value {
private $category= null;
private $level= LogLevel::ALL;
private $layout= null;

/**
* Sets category
*
* @param string $category
* @return self
*/
public function named($category) {
$this->category= $category;
return $this;
}

/**
* Sets level
*
* @param string $level
* @return self
*/
public function of($level) {
$this->level= $level;
return $this;
}

/**
* Sets layout
*
* @param util.log.Layout $layout
* @return self
*/
public function using(Layout $layout) {
$this->layout= $layout;
return $this;
}

/**
* Returns a logging category with all specified appenders attached
*
* @param util.log.Appender... $appenders
* @return util.log.LogCategory
*/
public function to(...$appenders) {
$cat= new LogCategory($this->category, $this->level);
$layout= $this->layout ?: new DefaultLayout();
foreach ($appenders as $appender) {
$cat->addAppender($appender->withLayout($layout));
}
return $cat;
}

/**
* Returns a logging category with a console appender attached
*
* @param bool $colors
* @return util.log.LogCategory
*/
public function toConsole($colors= true) {
return self::to($colors ? new ColoredConsoleAppender() : new ConsoleAppender());
}

/**
* Returns a logging category with a file appender attached
*
* @param string|io.Path|io.File $file
* @return util.log.LogCategory
*/
public function toFile($file) {
return self::to(new FileAppender($file));
}

/**
* Returns a logging category with a syslog appender attached
*
* @see php://openlog
* @param int $facility
* @param string $identifier if omitted, uses main class
* @return util.log.LogCategory
*/
public function toSyslog($facility= LOG_USER, $identifier= null) {
return self::to(new SyslogAppender($identifier ?: $_SERVER['argv'][0], $facility));
}

/** @return string */
public function toString() {
return sprintf(
'%s(category= %s, level= %s, layout= %s)',
nameof($this),
$this->category ?: '(default)',
LogLevel::nameOf($this->level),
$this->layout ? nameof($this->layout) : '(default)'
);
}

/** @return string */
public function hashCode() {
return Objects::hashOf([$this->category, $this->level, $this->layout]);
}

/**
* Compares
*
* @param var $value
* @return int
*/
public function compareTo($value) {
return $value instanceof self
? Objects::compare(
[$this->category, $this->level, $this->layout],
[$value->category, $value->level, $value->layout]
)
: 1
;
}
}
48 changes: 48 additions & 0 deletions src/main/php/util/log/Logging.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php namespace util\log;

/**
* Logging DSL
*
* @test xp://util.log.unittest.LoggingTest
*/
abstract class Logging {

/**
* Returns a logging setup with all loglevels
*
* @return util.log.LogSetup
*/
public static function all() {
return new LogSetup();
}

/**
* Returns a logging setup with a given category
*
* @param string $category
* @return util.log.LogSetup
*/
public static function named($category) {
return (new LogSetup())->named($category);
}

/**
* Returns a logging setup with a given log level
*
* @param int $level
* @return util.log.LogSetup
*/
public static function of($level) {
return (new LogSetup())->of($level);
}

/**
* Returns a logging setup with a given layout
*
* @param util.log.Layout $layout
* @return util.log.LogSetup
*/
public static function using(Layout $layout) {
return (new LogSetup())->using($layout);
}
}
62 changes: 62 additions & 0 deletions src/test/php/util/log/unittest/LoggingTest.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php namespace util\log\unittest;

use util\log\Logging;
use util\log\LogCategory;
use util\log\LogLevel;
use util\log\FileAppender;
use util\log\ConsoleAppender;
use util\log\ColoredConsoleAppender;
use util\log\SyslogAppender;
use util\log\layout\PatternLayout;
use io\File;
use io\Path;

class LoggingTest extends \unittest\TestCase {

#[@test]
public function to() {
$appenders= [new ColoredConsoleAppender(), new FileAppender('test.log')];
$this->assertEquals($appenders, Logging::all()->to(...$appenders)->getAppenders());
}

#[@test]
public function to_console() {
$this->assertInstanceOf(ColoredConsoleAppender::class, Logging::all()->toConsole()->getAppenders()[0]);
}

#[@test]
public function to_console_without_colors() {
$this->assertInstanceOf(ConsoleAppender::class, Logging::all()->toConsole(false)->getAppenders()[0]);
}

#[@test, @values([
# ['test.log'],
# [new Path('test.log')],
# [new File('test.log')]
#])]
public function to_file($file) {
$this->assertInstanceOf(FileAppender::class, Logging::all()->toFile($file)->getAppenders()[0]);
}

#[@test]
public function to_syslog() {
$this->assertInstanceOf(SyslogAppender::class, Logging::all()->toSyslog()->getAppenders()[0]);
}

#[@test]
public function named() {
$this->assertEquals('sql', Logging::named('sql')->to(new ConsoleAppender())->identifier);
}

#[@test]
public function of() {
$level= LogLevel::WARN | LogLevel::ERROR;
$this->assertEquals($level, Logging::of($level)->to(new ConsoleAppender())->flags);
}

#[@test]
public function using() {
$layout= new PatternLayout('%m');
$this->assertEquals($layout, Logging::using($layout)->to(new ConsoleAppender())->getAppenders()[0]->getLayout());
}
}