Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"psr/http-message": "^1.0",
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0",
"psr/log": "^1.1"
"psr/log": "^1.1 || ^2.0 || ^3.0"
Comment thread
tsoslow marked this conversation as resolved.
Comment thread
tsoslow marked this conversation as resolved.
},
"autoload": {
"psr-4": {
Expand Down
14 changes: 13 additions & 1 deletion src/StderrLogger.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,16 @@ public function __construct(string $minLevel = LogLevel::WARNING, $stream = 'php
}
}

public function log($level, $message, array $context = [])
public function log($level, $message, array $context = []): void
{
if (!is_string($level)) {
if (is_object($level) && method_exists($level, '__toString')) {
$level = (string) $level;
} else {
throw new InvalidArgumentException('Invalid log level: must be a string');
}
Comment thread
tsoslow marked this conversation as resolved.
}

if (!isset(self::LOG_LEVEL_MAP[$level])) {
throw new InvalidArgumentException("Invalid log level: {$level}");
Comment thread
tsoslow marked this conversation as resolved.
}
Expand All @@ -67,6 +75,10 @@ public function log($level, $message, array $context = [])
$context['exception'] = explode("\n", (string) $exception);
}

if (is_object($message) && method_exists($message, '__toString')) {
$message = (string) $message;
}

fwrite($this->stream, json_encode(compact('level', 'message', 'context')) . "\n");
Comment thread
tsoslow marked this conversation as resolved.
Outdated
}
}
2 changes: 1 addition & 1 deletion tests/Integration/IntegTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ protected function createHttpServer(ServerRequestInterface $request): HttpServer

protected function failOnLoggedErrors(): void
{
$this->logger->method('error')->willReturnCallback(function (string $message, array $context) {
$this->logger->method('error')->willReturnCallback(function ($message, array $context = []) {
$message = "Logged an error: {$message}\nContext:\n";
foreach ($context as $key => $value) {
$message .= "- {$key}: {$value}\n";
Expand Down
43 changes: 43 additions & 0 deletions tests/Integration/StderrLoggerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace SlackPhp\Framework\Tests\Integration;

use PHPUnit\Framework\TestCase;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
use SlackPhp\Framework\StderrLogger;

class StderrLoggerTest extends TestCase
{
public function testStringableMessageIsRenderedAsStringInJsonLog(): void
{
$stream = fopen('php://temp', 'a+');
$logger = new StderrLogger(LogLevel::DEBUG, $stream);

$message = new class() {
public function __toString(): string
{
return 'stringable-message';
}
};

$logger->log(LogLevel::ERROR, $message, ['foo' => 'bar']);

rewind($stream);
$line = trim((string) stream_get_contents($stream));
$payload = json_decode($line, true);

$this->assertSame('stringable-message', $payload['message']);
$this->assertSame(LogLevel::ERROR, $payload['level']);
$this->assertSame(['foo' => 'bar'], $payload['context']);
}

public function testNonStringLevelThrowsInvalidArgumentException(): void
{
$stream = fopen('php://temp', 'a+');
$logger = new StderrLogger(LogLevel::DEBUG, $stream);

$this->expectException(InvalidArgumentException::class);
$logger->log([], 'hello');
}
}
Loading