Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patternlayout: %d for dates #1

Merged
merged 3 commits into from
Aug 22, 2015
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ supported:
* `%c` - Category name
* `%l` - Log level - lowercase
* `%L` - Log level - uppercase
* `%d` - Date in YYYY-MM-DD
* `%t` - Time in HH:MM:SS
* `%p` - Process ID
* `%%` - A literal percent sign (%)
Expand Down
42 changes: 24 additions & 18 deletions src/main/php/util/log/layout/PatternLayout.class.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<?php namespace util\log\layout;

use lang\IllegalArgumentException;
use util\log\LoggingEvent;
use util\log\LogLevel;

/**
* Pattern layout
*
Expand All @@ -8,17 +12,17 @@
* The format string consists of format tokens preceded by a percent
* sign (%) and any other character. The following format tokens are
* supported:
* <ul>
* <li>%m - Message</li>
* <li>%c - Category name</li>
* <li>%l - Log level - lowercase</li>
* <li>%L - Log level - uppercase</li>
* <li>%t - Time in HH:MM:SS</li>
* <li>%p - Process ID</li>
* <li>%% - A literal percent sign (%)</li>
* <li>%n - A line break</li>
* <li>%x - Context information, if available</li>
* </ul>
*
* - %m - Message
* - %c - Category name
* - %l - Log level - lowercase
* - %L - Log level - uppercase
* - %d - Date in YYYY-MM-DD
* - %t - Time in HH:MM:SS
* - %p - Process ID
* - %% - A literal percent sign (%)
* - %n - A line break
* - %x - Context information, if available
*
* @test xp://net.xp_framework.unittest.logging.PatternLayoutTest
*/
Expand All @@ -28,13 +32,14 @@ class PatternLayout extends \util\log\Layout {
/**
* Creates a new pattern layout
*
* @param string format
* @param string $format
* @throws lang.IllegalArgumentException
*/
public function __construct($format) {
for ($i= 0, $s= strlen($format); $i < $s; $i++) {
if ('%' === $format{$i}) {
if (++$i >= $s) {
throw new \lang\IllegalArgumentException('Not enough input at position '.($i - 1));
throw new IllegalArgumentException('Not enough input at position '.($i - 1));
}
switch ($format{$i}) {
case '%': { // Literal percent
Expand All @@ -46,8 +51,8 @@ public function __construct($format) {
break;
}
default: { // Any other character - verify it's supported
if (!strspn($format{$i}, 'mclLtpx')) {
throw new \lang\IllegalArgumentException('Unknown format token "'.$format{$i}.'"');
if (!strspn($format{$i}, 'mclLtdpx')) {
throw new IllegalArgumentException('Unknown format token "'.$format{$i}.'"');
}
$this->format[]= '%'.$format{$i};
}
Expand All @@ -64,15 +69,16 @@ public function __construct($format) {
* @param util.log.LoggingEvent event
* @return string
*/
public function format(\util\log\LoggingEvent $event) {
public function format(LoggingEvent $event) {
$out= '';
foreach ($this->format as $token) {
switch ($token) {
case '%m': $out.= implode(' ', array_map([$this, 'stringOf'], $event->getArguments())); break;
case '%t': $out.= gmdate('H:i:s', $event->getTimestamp()); break;
case '%d': $out.= gmdate('Y-m-d', $event->getTimestamp()); break;
case '%c': $out.= $event->getCategory()->identifier; break;
case '%l': $out.= strtolower(\util\log\LogLevel::nameOf($event->getLevel())); break;
case '%L': $out.= strtoupper(\util\log\LogLevel::nameOf($event->getLevel())); break;
case '%l': $out.= strtolower(LogLevel::nameOf($event->getLevel())); break;
case '%L': $out.= strtoupper(LogLevel::nameOf($event->getLevel())); break;
case '%p': $out.= $event->getProcessId(); break;
case '%x': $out.= null == ($context= $event->getContext()) ? '' : $context->format(); break;
default: $out.= $token;
Expand Down
50 changes: 23 additions & 27 deletions src/test/php/util/log/unittest/PatternLayoutTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,20 @@
class PatternLayoutTest extends \unittest\TestCase {

/**
* Creates a new logging event
* Formats a given logging event
*
* @param string $pattern
* @param util.log.LogCategory $cat
* @return util.log.LoggingEvent
* @return string
*/
private function newLoggingEvent($cat= null) {
return new LoggingEvent(
private function format($pattern, $cat= null) {
return (new PatternLayout($pattern))->format(new LoggingEvent(
$cat ?: new LogCategory('default'),
1258733284,
1214,
LogLevel::WARN,
['Hello']
);
));
}

#[@test, @expect(IllegalArgumentException::class)]
Expand All @@ -37,74 +38,69 @@ public function unterminated_format_token() {

#[@test]
public function message() {
$this->assertEquals('Hello', (new PatternLayout('%m'))->format($this->newLoggingEvent()));
$this->assertEquals('Hello', $this->format('%m'));
}

#[@test]
public function category_name() {
$this->assertEquals('default', (new PatternLayout('%c'))->format($this->newLoggingEvent()));
$this->assertEquals('default', $this->format('%c'));
}

#[@test]
public function lowercase_loglevel() {
$this->assertEquals('warn', (new PatternLayout('%l'))->format($this->newLoggingEvent()));
$this->assertEquals('warn', $this->format('%l'));
}

#[@test]
public function uppercase_loglevel() {
$this->assertEquals('WARN', (new PatternLayout('%L'))->format($this->newLoggingEvent()));
$this->assertEquals('WARN', $this->format('%L'));
}

#[@test]
public function date_in_YYYY_MM_DD() {
$this->assertEquals('2009-11-20', $this->format('%d'));
}

#[@test]
public function time_in_HH_MM_SS() {
$this->assertEquals('16:08:04', (new PatternLayout('%t'))->format($this->newLoggingEvent()));
$this->assertEquals('16:08:04', $this->format('%t'));
}

#[@test]
public function process_id() {
$this->assertEquals('1214', (new PatternLayout('%p'))->format($this->newLoggingEvent()));
$this->assertEquals('1214', $this->format('%p'));
}

#[@test]
public function literal_percent() {
$this->assertEquals('100%', (new PatternLayout('100%%'))->format($this->newLoggingEvent()));
$this->assertEquals('100%', $this->format('100%%'));
}

#[@test]
public function line_break() {
$this->assertEquals("\n", (new PatternLayout('%n'))->format($this->newLoggingEvent()));
$this->assertEquals("\n", $this->format('%n'));
}

#[@test]
public function context_when_not_available() {
$this->assertEquals('', (new PatternLayout('%x'))->format($this->newLoggingEvent()));
$this->assertEquals('', $this->format('%x'));
}

#[@test]
public function context() {
$context= new MappedLogContext();
$context->put('key1', 'val1');

$this->assertEquals(
'key1=val1',
(new PatternLayout('%x'))->format($this->newLoggingEvent(new LogCategory('default', LogLevel::ALL, $context)))
);
$this->assertEquals('key1=val1', $this->format('%x', new LogCategory('default', LogLevel::ALL, $context)));
}

#[@test]
public function simple_format() {
$this->assertEquals(
'WARN [default] Hello',
(new PatternLayout('%L [%c] %m'))->format($this->newLoggingEvent())
);
$this->assertEquals('WARN [default] Hello', $this->format('%L [%c] %m'));
}

#[@test]
public function default_format() {
$this->assertEquals(
'[16:08:04 1214 warn] Hello',
(new PatternLayout('[%t %p %l] %m'))->format($this->newLoggingEvent())
);
$this->assertEquals('[16:08:04 1214 warn] Hello', $this->format('[%t %p %l] %m'));
}

}