default logging to console (#899)

Rather than log nothing by default, log warnings and greater to console.
By providing a psr-3 logger, users can gain greater control over logging, including disabling it (via NullLogger)
This commit is contained in:
Brett McBride 2022-12-22 09:39:27 +11:00 committed by GitHub
parent c98866b3fa
commit 558e7ce30e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 104 additions and 11 deletions

View File

@ -5,14 +5,14 @@ require __DIR__ . '/../../../vendor/autoload.php';
use Monolog\Handler\StreamHandler; use Monolog\Handler\StreamHandler;
use Monolog\Logger; use Monolog\Logger;
use OpenTelemetry\SDK\Common\Log\LoggerHolder; use OpenTelemetry\API\Common\Log\LoggerHolder;
use OpenTelemetry\SDK\Trace\TracerProviderFactory; use OpenTelemetry\SDK\Trace\TracerProviderFactory;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
echo 'Starting SettingUpLogging example' . PHP_EOL; echo 'Starting SettingUpLogging example' . PHP_EOL;
//create a Logger, and register it with library's logger holder. The library will use this logger //By default, opentelemetry's internal logging (errors, warnings, etc) will be output to console.
//for all of its internal logging (errors, warnings, etc) //You can instead provide a psr-3 logger to provide greater control of logging output:
LoggerHolder::set( LoggerHolder::set(
new Logger('otel-php', [new StreamHandler(STDOUT, LogLevel::DEBUG)]) new Logger('otel-php', [new StreamHandler(STDOUT, LogLevel::DEBUG)])
); );

View File

@ -9,10 +9,40 @@ use Psr\Log\LogLevel;
trait LogsMessagesTrait trait LogsMessagesTrait
{ {
private static function shouldLog(string $level): bool
{
return in_array($level, [LogLevel::ERROR, LogLevel::WARNING, LogLevel::CRITICAL, LogLevel::EMERGENCY]);
}
private static function map(string $level)
{
switch ($level) {
case LogLevel::WARNING:
return E_USER_WARNING;
case LogLevel::ERROR:
case LogLevel::CRITICAL:
case LogLevel::EMERGENCY:
return E_USER_ERROR;
default:
return E_USER_NOTICE;
}
}
private static function doLog(string $level, string $message, array $context): void private static function doLog(string $level, string $message, array $context): void
{ {
$context['source'] = get_called_class(); $logger = LoggerHolder::get();
LoggerHolder::get()->log($level, $message, $context); if ($logger !== null) {
$context['source'] = get_called_class();
$logger->log($level, $message, $context);
} elseif (self::shouldLog($level)) {
$message = sprintf(
'%s: %s in %s',
$message,
(array_key_exists('exception', $context) && $context['exception'] instanceof \Throwable) ? $context['exception']->getMessage() : '',
get_called_class()
);
trigger_error($message, self::map($level));
}
} }
protected static function logDebug(string $message, array $context = []): void protected static function logDebug(string $message, array $context = []): void

View File

@ -21,13 +21,14 @@ final class LoggerHolder
/** /**
* @suppress PhanTypeMismatchReturnNullable * @suppress PhanTypeMismatchReturnNullable
* @internal
*/ */
public static function get(): LoggerInterface public static function get(): ?LoggerInterface
{ {
return self::$logger ?? new NullLogger(); return self::$logger;
} }
public static function set(LoggerInterface $logger): void public static function set(?LoggerInterface $logger): void
{ {
self::$logger = $logger; self::$logger = $logger;
} }

View File

@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace OpenTelemetry\Tests\Unit\SDK\Behavior; namespace OpenTelemetry\Tests\Unit\API\Behavior;
use OpenTelemetry\API\Behavior\LogsMessagesTrait; use OpenTelemetry\API\Behavior\LogsMessagesTrait;
use OpenTelemetry\API\Common\Log\LoggerHolder; use OpenTelemetry\API\Common\Log\LoggerHolder;
@ -30,6 +30,30 @@ class LogsMessagesTraitTest extends TestCase
LoggerHolder::unset(); LoggerHolder::unset();
} }
public function test_defaults_to_trigger_error_with_warning(): void
{
$message = 'something went wrong';
LoggerHolder::unset();
$this->assertFalse(LoggerHolder::isSet());
$instance = $this->createInstance();
$this->expectWarning();
$this->expectWarningMessageMatches(sprintf('/%s/', $message));
$instance->run('logWarning', 'foo', ['exception' => new \Exception($message)]);
}
public function test_defaults_to_trigger_error_with_error(): void
{
$message = 'something went wrong';
LoggerHolder::unset();
$this->assertFalse(LoggerHolder::isSet());
$instance = $this->createInstance();
$this->expectError();
$this->expectErrorMessageMatches(sprintf('/%s/', $message));
$instance->run('logError', 'foo', ['exception' => new \Exception($message)]);
}
/** /**
* @testdox Proxies logging methods through to logger * @testdox Proxies logging methods through to logger
* @dataProvider logLevelProvider * @dataProvider logLevelProvider
@ -60,9 +84,9 @@ class LogsMessagesTraitTest extends TestCase
return new class() { return new class() {
use LogsMessagesTrait; use LogsMessagesTrait;
//accessor for protected trait methods //accessor for protected trait methods
public function run(string $method, string $message): void public function run(string $method, string $message, array $context = []): void
{ {
$this->{$method}($message); $this->{$method}($message, $context);
} }
}; };
} }

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace OpenTelemetry\Tests\Unit\API\Trace\Propagation; namespace OpenTelemetry\Tests\Unit\API\Trace\Propagation;
use OpenTelemetry\API\Common\Log\LoggerHolder;
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
use OpenTelemetry\API\Trace\SpanContext; use OpenTelemetry\API\Trace\SpanContext;
use OpenTelemetry\API\Trace\SpanContextInterface; use OpenTelemetry\API\Trace\SpanContextInterface;
@ -14,6 +15,7 @@ use OpenTelemetry\Context\Context;
use OpenTelemetry\Context\ContextInterface; use OpenTelemetry\Context\ContextInterface;
use OpenTelemetry\SDK\Trace\Span; use OpenTelemetry\SDK\Trace\Span;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
/** /**
* @covers \OpenTelemetry\API\Trace\Propagation\TraceContextPropagator * @covers \OpenTelemetry\API\Trace\Propagation\TraceContextPropagator
@ -32,6 +34,7 @@ class TraceContextPropagatorTest extends TestCase
protected function setUp(): void protected function setUp(): void
{ {
LoggerHolder::set(new NullLogger());
$this->traceContextPropagator = TraceContextPropagator::getInstance(); $this->traceContextPropagator = TraceContextPropagator::getInstance();
$this->traceState = (new TraceState())->with('bar', 'baz')->with('foo', 'bar'); $this->traceState = (new TraceState())->with('bar', 'baz')->with('foo', 'bar');
} }

View File

@ -4,8 +4,10 @@ declare(strict_types=1);
namespace OpenTelemetry\Tests\API\Unit\Trace; namespace OpenTelemetry\Tests\API\Unit\Trace;
use OpenTelemetry\API\Common\Log\LoggerHolder;
use OpenTelemetry\API\Trace\TraceState; use OpenTelemetry\API\Trace\TraceState;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
use function str_repeat; use function str_repeat;
use function strlen; use function strlen;
@ -14,6 +16,11 @@ use function strlen;
*/ */
class TraceStateTest extends TestCase class TraceStateTest extends TestCase
{ {
public function setUp(): void
{
LoggerHolder::set(new NullLogger());
}
public function test_get_tracestate_value(): void public function test_get_tracestate_value(): void
{ {
$tracestate = new TraceState('vendor1=value1'); $tracestate = new TraceState('vendor1=value1');

View File

@ -5,11 +5,13 @@ declare(strict_types=1);
namespace OpenTelemetry\Example\Unit\SDK\Metrics; namespace OpenTelemetry\Example\Unit\SDK\Metrics;
use AssertWell\PHPUnitGlobalState\EnvironmentVariables; use AssertWell\PHPUnitGlobalState\EnvironmentVariables;
use OpenTelemetry\API\Common\Log\LoggerHolder;
use OpenTelemetry\API\Metrics\MeterInterface; use OpenTelemetry\API\Metrics\MeterInterface;
use OpenTelemetry\SDK\Common\Configuration\KnownValues; use OpenTelemetry\SDK\Common\Configuration\KnownValues;
use OpenTelemetry\SDK\Common\Configuration\Variables; use OpenTelemetry\SDK\Common\Configuration\Variables;
use OpenTelemetry\SDK\Metrics\MeterProviderFactory; use OpenTelemetry\SDK\Metrics\MeterProviderFactory;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
/** /**
* @covers \OpenTelemetry\SDK\Metrics\MeterProviderFactory * @covers \OpenTelemetry\SDK\Metrics\MeterProviderFactory
@ -18,6 +20,11 @@ class MeterProviderFactoryTest extends TestCase
{ {
use EnvironmentVariables; use EnvironmentVariables;
public function setUp(): void
{
LoggerHolder::set(new NullLogger());
}
public function tearDown(): void public function tearDown(): void
{ {
$this->restoreEnvironmentVariables(); $this->restoreEnvironmentVariables();

View File

@ -6,6 +6,7 @@ namespace OpenTelemetry\Tests\Unit\SDK\Propagation;
use AssertWell\PHPUnitGlobalState\EnvironmentVariables; use AssertWell\PHPUnitGlobalState\EnvironmentVariables;
use OpenTelemetry\API\Baggage\Propagation\BaggagePropagator; use OpenTelemetry\API\Baggage\Propagation\BaggagePropagator;
use OpenTelemetry\API\Common\Log\LoggerHolder;
use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator; use OpenTelemetry\API\Trace\Propagation\TraceContextPropagator;
use OpenTelemetry\Context\Propagation\MultiTextMapPropagator; use OpenTelemetry\Context\Propagation\MultiTextMapPropagator;
use OpenTelemetry\Context\Propagation\NoopTextMapPropagator; use OpenTelemetry\Context\Propagation\NoopTextMapPropagator;
@ -14,6 +15,7 @@ use OpenTelemetry\SDK\Common\Configuration\KnownValues;
use OpenTelemetry\SDK\Common\Configuration\Variables; use OpenTelemetry\SDK\Common\Configuration\Variables;
use OpenTelemetry\SDK\Propagation\PropagatorFactory; use OpenTelemetry\SDK\Propagation\PropagatorFactory;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
/** /**
* @covers OpenTelemetry\SDK\Propagation\PropagatorFactory * @covers OpenTelemetry\SDK\Propagation\PropagatorFactory
@ -22,6 +24,11 @@ class PropagatorFactoryTest extends TestCase
{ {
use EnvironmentVariables; use EnvironmentVariables;
public function setUp(): void
{
LoggerHolder::set(new NullLogger());
}
public function tearDown(): void public function tearDown(): void
{ {
$this->restoreEnvironmentVariables(); $this->restoreEnvironmentVariables();

View File

@ -5,9 +5,11 @@ declare(strict_types=1);
namespace OpenTelemetry\Tests\Unit\SDK; namespace OpenTelemetry\Tests\Unit\SDK;
use AssertWell\PHPUnitGlobalState\EnvironmentVariables; use AssertWell\PHPUnitGlobalState\EnvironmentVariables;
use OpenTelemetry\API\Common\Log\LoggerHolder;
use OpenTelemetry\SDK\Common\Configuration\Variables; use OpenTelemetry\SDK\Common\Configuration\Variables;
use OpenTelemetry\SDK\SdkAutoloader; use OpenTelemetry\SDK\SdkAutoloader;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
/** /**
* @covers \OpenTelemetry\SDK\SdkAutoloader * @covers \OpenTelemetry\SDK\SdkAutoloader
@ -16,6 +18,11 @@ class SdkAutoloaderTest extends TestCase
{ {
use EnvironmentVariables; use EnvironmentVariables;
public function setUp(): void
{
LoggerHolder::set(new NullLogger());
}
public function tearDown(): void public function tearDown(): void
{ {
SdkAutoloader::shutdown(); SdkAutoloader::shutdown();

View File

@ -6,12 +6,14 @@ namespace OpenTelemetry\Tests\Unit\SDK\Trace\SpanExporter;
use Mockery; use Mockery;
use Mockery\Adapter\Phpunit\MockeryTestCase; use Mockery\Adapter\Phpunit\MockeryTestCase;
use OpenTelemetry\API\Common\Log\LoggerHolder;
use OpenTelemetry\SDK\Common\Export\TransportInterface; use OpenTelemetry\SDK\Common\Export\TransportInterface;
use OpenTelemetry\SDK\Common\Future\CompletedFuture; use OpenTelemetry\SDK\Common\Future\CompletedFuture;
use OpenTelemetry\SDK\Common\Future\ErrorFuture; use OpenTelemetry\SDK\Common\Future\ErrorFuture;
use OpenTelemetry\SDK\Common\Future\FutureInterface; use OpenTelemetry\SDK\Common\Future\FutureInterface;
use OpenTelemetry\SDK\Trace\SpanExporterInterface; use OpenTelemetry\SDK\Trace\SpanExporterInterface;
use OpenTelemetry\Tests\Unit\SDK\Util\SpanData; use OpenTelemetry\Tests\Unit\SDK\Util\SpanData;
use Psr\Log\NullLogger;
/** /**
* @psalm-suppress UndefinedInterfaceMethod * @psalm-suppress UndefinedInterfaceMethod
@ -23,6 +25,7 @@ abstract class AbstractExporterTest extends MockeryTestCase
public function setUp(): void public function setUp(): void
{ {
LoggerHolder::set(new NullLogger());
$this->future = Mockery::mock(FutureInterface::class); $this->future = Mockery::mock(FutureInterface::class);
$this->future->allows([ $this->future->allows([
'map' => $this->future, 'map' => $this->future,

View File

@ -31,6 +31,7 @@ use OpenTelemetry\SDK\Trace\SpanProcessorInterface;
use OpenTelemetry\Tests\Unit\SDK\Util\TestClock; use OpenTelemetry\Tests\Unit\SDK\Util\TestClock;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Psr\Log\NullLogger;
/** /**
* @covers \OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessor * @covers \OpenTelemetry\SDK\Trace\SpanProcessor\BatchSpanProcessor
@ -41,6 +42,7 @@ class BatchSpanProcessorTest extends MockeryTestCase
protected function setUp(): void protected function setUp(): void
{ {
LoggerHolder::set(new NullLogger());
$this->testClock = new TestClock(); $this->testClock = new TestClock();
ClockFactory::setDefault($this->testClock); ClockFactory::setDefault($this->testClock);

View File

@ -21,6 +21,7 @@ use OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor;
use OpenTelemetry\Tests\Unit\SDK\Util\SpanData; use OpenTelemetry\Tests\Unit\SDK\Util\SpanData;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Psr\Log\NullLogger;
/** /**
* @covers OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor * @covers OpenTelemetry\SDK\Trace\SpanProcessor\SimpleSpanProcessor
@ -43,6 +44,7 @@ class SimpleSpanProcessorTest extends MockeryTestCase
protected function setUp(): void protected function setUp(): void
{ {
LoggerHolder::set(new NullLogger());
$this->readWriteSpan = Mockery::mock(ReadWriteSpanInterface::class); $this->readWriteSpan = Mockery::mock(ReadWriteSpanInterface::class);
$this->readableSpan = Mockery::mock(ReadableSpanInterface::class); $this->readableSpan = Mockery::mock(ReadableSpanInterface::class);