Merge pull request #415 from limingxinleo/1.0-logger

Added handlers config for logger.
This commit is contained in:
李铭昕 2019-08-17 23:50:36 +08:00 committed by GitHub
commit 3ee382a896
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 199 additions and 81 deletions

View File

@ -3,6 +3,7 @@
## Added
- [#405](https://github.com/hyperf-cloud/hyperf/pull/405) Added Context::override() method.
- [#415](https://github.com/hyperf-cloud/hyperf/pull/415) Added handlers configuration for logger, now you could config multiple handlers to logger.
## Fixed
- [#414](https://github.com/hyperf-cloud/hyperf/pull/414) Fixed WebSocketExceptionHandler typo

View File

@ -1,5 +1,15 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://doc.hyperf.io
* @contact group@hyperf.io
* @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
*/
# source: grpc.proto
namespace GPBMetadata;
@ -8,22 +18,22 @@ class Grpc
{
public static $is_initialized = false;
public static function initOnce() {
public static function initOnce()
{
$pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
if (static::$is_initialized == true) {
return;
return;
}
$pool->internalAddGeneratedFile(hex2bin(
"0aae010a0a677270632e70726f746f12046772706322200a04496e666f12" .
"0a0a026964180120012805120c0a046e616d6518022001280922360a0955" .
"7365725265706c79120f0a076d65737361676518012001280912180a0469" .
"6e666f18022001280b320a2e677270632e496e666f32380a0c757365725f" .
"7365727669636512280a0767657455736572120a2e677270632e496e666f" .
"1a0f2e677270632e557365725265706c792200620670726f746f33"
'0aae010a0a677270632e70726f746f12046772706322200a04496e666f12' .
'0a0a026964180120012805120c0a046e616d6518022001280922360a0955' .
'7365725265706c79120f0a076d65737361676518012001280912180a0469' .
'6e666f18022001280b320a2e677270632e496e666f32380a0c757365725f' .
'7365727669636512280a0767657455736572120a2e677270632e496e666f' .
'1a0f2e677270632e557365725265706c792200620670726f746f33'
));
static::$is_initialized = true;
}
}

View File

@ -1,24 +1,33 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://doc.hyperf.io
* @contact group@hyperf.io
* @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
*/
# source: grpc.proto
namespace Grpc;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>grpc.Info</code>
* Generated from protobuf message <code>grpc.Info</code>.
*/
class Info extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>int32 id = 1;</code>
* Generated from protobuf field <code>int32 id = 1;</code>.
*/
private $id = 0;
/**
* Generated from protobuf field <code>string name = 2;</code>
* Generated from protobuf field <code>string name = 2;</code>.
*/
private $name = '';
@ -26,19 +35,20 @@ class Info extends \Google\Protobuf\Internal\Message
* Constructor.
*
* @param array $data {
* Optional. Data for populating the Message object.
* Optional. Data for populating the Message object.
*
* @type int $id
* @type string $name
* @var int $id
* @var string $name
* }
*/
public function __construct($data = NULL) {
public function __construct($data = null)
{
\GPBMetadata\Grpc::initOnce();
parent::__construct($data);
}
/**
* Generated from protobuf field <code>int32 id = 1;</code>
* Generated from protobuf field <code>int32 id = 1;</code>.
* @return int
*/
public function getId()
@ -47,7 +57,7 @@ class Info extends \Google\Protobuf\Internal\Message
}
/**
* Generated from protobuf field <code>int32 id = 1;</code>
* Generated from protobuf field <code>int32 id = 1;</code>.
* @param int $var
* @return $this
*/
@ -60,7 +70,7 @@ class Info extends \Google\Protobuf\Internal\Message
}
/**
* Generated from protobuf field <code>string name = 2;</code>
* Generated from protobuf field <code>string name = 2;</code>.
* @return string
*/
public function getName()
@ -69,17 +79,15 @@ class Info extends \Google\Protobuf\Internal\Message
}
/**
* Generated from protobuf field <code>string name = 2;</code>
* Generated from protobuf field <code>string name = 2;</code>.
* @param string $var
* @return $this
*/
public function setName($var)
{
GPBUtil::checkString($var, True);
GPBUtil::checkString($var, true);
$this->name = $var;
return $this;
}
}

View File

@ -1,44 +1,54 @@
<?php
# Generated by the protocol buffer compiler. DO NOT EDIT!
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://doc.hyperf.io
* @contact group@hyperf.io
* @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
*/
# source: grpc.proto
namespace Grpc;
use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;
/**
* Generated from protobuf message <code>grpc.UserReply</code>
* Generated from protobuf message <code>grpc.UserReply</code>.
*/
class UserReply extends \Google\Protobuf\Internal\Message
{
/**
* Generated from protobuf field <code>string message = 1;</code>
* Generated from protobuf field <code>string message = 1;</code>.
*/
private $message = '';
/**
* Generated from protobuf field <code>.grpc.Info info = 2;</code>
* Generated from protobuf field <code>.grpc.Info info = 2;</code>.
*/
private $info = null;
private $info;
/**
* Constructor.
*
* @param array $data {
* Optional. Data for populating the Message object.
* Optional. Data for populating the Message object.
*
* @type string $message
* @type \Grpc\Info $info
* @var string $message
* @var \Grpc\Info $info
* }
*/
public function __construct($data = NULL) {
public function __construct($data = null)
{
\GPBMetadata\Grpc::initOnce();
parent::__construct($data);
}
/**
* Generated from protobuf field <code>string message = 1;</code>
* Generated from protobuf field <code>string message = 1;</code>.
* @return string
*/
public function getMessage()
@ -47,20 +57,20 @@ class UserReply extends \Google\Protobuf\Internal\Message
}
/**
* Generated from protobuf field <code>string message = 1;</code>
* Generated from protobuf field <code>string message = 1;</code>.
* @param string $var
* @return $this
*/
public function setMessage($var)
{
GPBUtil::checkString($var, True);
GPBUtil::checkString($var, true);
$this->message = $var;
return $this;
}
/**
* Generated from protobuf field <code>.grpc.Info info = 2;</code>
* Generated from protobuf field <code>.grpc.Info info = 2;</code>.
* @return \Grpc\Info
*/
public function getInfo()
@ -69,7 +79,7 @@ class UserReply extends \Google\Protobuf\Internal\Message
}
/**
* Generated from protobuf field <code>.grpc.Info info = 2;</code>
* Generated from protobuf field <code>.grpc.Info info = 2;</code>.
* @param \Grpc\Info $var
* @return $this
*/
@ -80,6 +90,4 @@ class UserReply extends \Google\Protobuf\Internal\Message
return $this;
}
}

View File

@ -26,10 +26,9 @@ class RequestTest extends TestCase
public function testRequest()
{
$request = new Request($path = 'grpc.service/path', $info = new Info());
$this->assertSame([
'content-type' => 'application/grpc+proto',
'user-agent' => 'grpc-php-hyperf/1.0 (hyperf-grpc-client/dev-master)',
], $request->headers);
$this->assertSame(2, count($request->headers));
$this->assertSame('application/grpc+proto', $request->headers['content-type']);
$this->assertRegExp('/^grpc-php-hyperf\/1.0 \(hyperf-grpc-client\/.*\)$/', $request->headers['user-agent']);
$this->assertSame($path, $request->path);
$this->assertSame(Parser::serializeMessage($info), $request->data);
}
@ -37,10 +36,9 @@ class RequestTest extends TestCase
public function testGetDefaultHeaders()
{
$request = new Request($path = 'grpc.service/path', $info = new Info());
$this->assertSame([
'content-type' => 'application/grpc+proto',
'user-agent' => 'grpc-php-hyperf/1.0 (hyperf-grpc-client/dev-master)',
], $request->getDefaultHeaders());
$this->assertSame(2, count($request->getDefaultHeaders()));
$this->assertSame('application/grpc+proto', $request->getDefaultHeaders()['content-type']);
$this->assertRegExp('/^grpc-php-hyperf\/1.0 \(hyperf-grpc-client\/.*\)$/', $request->getDefaultHeaders()['user-agent']);
}
public function testUserDefinedHeaders()
@ -49,10 +47,10 @@ class RequestTest extends TestCase
'content-type' => 'application/grpc',
'foo' => 'bar',
]);
$this->assertSame([
'content-type' => 'application/grpc',
'user-agent' => 'grpc-php-hyperf/1.0 (hyperf-grpc-client/dev-master)',
'foo' => 'bar',
], $request->headers);
$this->assertSame(3, count($request->headers));
$this->assertSame('application/grpc', $request->headers['content-type']);
$this->assertRegExp('/^grpc-php-hyperf\/1.0 \(hyperf-grpc-client\/.*\)$/', $request->headers['user-agent']);
$this->assertSame('bar', $request->headers['foo']);
}
}

View File

@ -12,16 +12,18 @@ declare(strict_types=1);
return [
'default' => [
'handler' => [
'class' => \Monolog\Handler\StreamHandler::class,
'constructor' => [
'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
'level' => \Monolog\Logger::DEBUG,
'handlers' => [
[
'class' => Monolog\Handler\StreamHandler::class,
'constructor' => [
'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
'level' => Monolog\Logger::DEBUG,
],
'formatter' => [
'class' => Monolog\Formatter\LineFormatter::class,
'constructor' => [],
],
],
],
'formatter' => [
'class' => \Monolog\Formatter\LineFormatter::class,
'constructor' => [],
],
],
];

View File

@ -14,8 +14,11 @@ namespace Hyperf\Logger;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Logger\Exception\InvalidConfigException;
use Hyperf\Utils\Arr;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\HandlerInterface;
use Monolog\Handler\StreamHandler;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
@ -50,11 +53,11 @@ class LoggerFactory
}
$config = $config[$group];
$handler = $this->handler($config);
$handlers = $this->handlers($config);
return make(Logger::class, [
'name' => $name,
'handlers' => [$handler],
'handlers' => $handlers,
]);
}
@ -67,16 +70,55 @@ class LoggerFactory
return $this->loggers[$name] = $this->make($name, $group);
}
protected function handler(array $config): HandlerInterface
protected function getDefaultFormatterConfig($config)
{
$handlerClass = $config['handler']['class'];
$handlerConstructor = $config['handler']['constructor'];
$formatterClass = Arr::get($config, 'formatter.class', LineFormatter::class);
$formatterConstructor = Arr::get($config, 'formatter.constructor', []);
return [
'class' => $formatterClass,
'constructor' => $formatterConstructor,
];
}
protected function getDefaultHandlerConfig($config)
{
$handlerClass = Arr::get($config, 'handler.class', StreamHandler::class);
$handlerConstructor = Arr::get($config, 'handler.constructor', [
'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
'level' => Logger::DEBUG,
]);
return [
'class' => $handlerClass,
'constructor' => $handlerConstructor,
];
}
protected function handlers(array $config): array
{
$handlerConfigs = $config['handlers'] ?? [[]];
$handlers = [];
$defaultHandlerConfig = $this->getDefaultHandlerConfig($config);
$defaultFormatterConfig = $this->getDefaultFormatterConfig($config);
foreach ($handlerConfigs as $value) {
$class = $value['class'] ?? $defaultHandlerConfig['class'];
$constructor = $value['constructor'] ?? $defaultHandlerConfig['constructor'];
$formatterConfig = $value['formatter'] ?? $defaultFormatterConfig;
$handlers[] = $this->handler($class, $constructor, $formatterConfig);
}
return $handlers;
}
protected function handler($class, $constructor, $formatterConfig): HandlerInterface
{
/** @var HandlerInterface $handler */
$handler = make($handlerClass, $handlerConstructor);
$handler = make($class, $constructor);
$formatterClass = $config['formatter']['class'];
$formatterConstructor = $config['formatter']['constructor'];
$formatterClass = $formatterConfig['class'];
$formatterConstructor = $formatterConfig['constructor'];
/** @var FormatterInterface $formatter */
$formatter = make($formatterClass, $formatterConstructor);

View File

@ -18,10 +18,13 @@ use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Utils\ApplicationContext;
use Mockery;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\TestHandler;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use ReflectionClass;
/**
* @internal
@ -47,17 +50,43 @@ class LoggerFactoryTest extends TestCase
ApplicationContext::setContainer($container);
$factory = $container->get(LoggerFactory::class);
$logger = $factory->get('hyperf');
$this->assertInstanceOf(StdoutLoggerInterface::class, $logger);
$this->assertInstanceOf(LoggerInterface::class, $logger);
$this->assertInstanceOf(Logger::class, $logger);
$this->assertInstanceOf(\Hyperf\Logger\Logger::class, $logger);
}
private function mockContainer()
public function testHandlerConfig()
{
$container = $this->mockContainer();
$factory = $container->get(LoggerFactory::class);
$logger = $factory->get('hyperf', 'default');
$this->assertInstanceOf(\Hyperf\Logger\Logger::class, $logger);
$reflectionClass = new ReflectionClass($logger);
$handlersProperty = $reflectionClass->getProperty('handlers');
$handlersProperty->setAccessible(true);
$handlers = $handlersProperty->getValue($logger);
$this->assertCount(1, $handlers);
$this->assertInstanceOf(StreamHandler::class, current($handlers));
}
public function testHandlersConfig()
{
$container = $this->mockContainer();
$factory = $container->get(LoggerFactory::class);
$logger = $factory->get('hyperf', 'default-handlers');
$this->assertInstanceOf(\Hyperf\Logger\Logger::class, $logger);
$reflectionClass = new ReflectionClass($logger);
$handlersProperty = $reflectionClass->getProperty('handlers');
$handlersProperty->setAccessible(true);
$handlers = $handlersProperty->getValue($logger);
$this->assertCount(2, $handlers);
$this->assertInstanceOf(StreamHandler::class, $handlers[0]);
$this->assertInstanceOf(TestHandler::class, $handlers[1]);
}
private function mockContainer(): ContainerInterface
{
$container = Mockery::mock(ContainerInterface::class);
$container->shouldReceive('get')->once()->with(ConfigInterface::class)->andReturn(new Config([
$container->shouldReceive('get')->with(ConfigInterface::class)->andReturn(new Config([
'logger' => [
'default' => [
'handler' => [
@ -72,11 +101,31 @@ class LoggerFactoryTest extends TestCase
'constructor' => [],
],
],
'default-handlers' => [
'handlers' => [
[
'class' => \Monolog\Handler\StreamHandler::class,
'constructor' => [
'stream' => BASE_PATH . '/runtime/logs/hyperf.log',
'level' => \Monolog\Logger::DEBUG,
],
],
[
'class' => \Monolog\Handler\TestHandler::class,
'constructor' => [
'level' => \Monolog\Logger::DEBUG,
],
]
],
'formatter' => [
'class' => \Monolog\Formatter\LineFormatter::class,
'constructor' => [],
],
],
],
]));
$container->shouldReceive('get')
->once()
->with(LoggerFactory::class)
->andReturn(new LoggerFactory($container));