异常与日志处理

框架中提供基础错误处理,可以集中式处理各种异常。日志存储在 runtime/logs 中,可以通过业务需求,讲日志集中发送到一个日志服务器中,FastD 正在研发解决方案,敬请期待: LogViewer

异常

框架中的异常会通过 json 的形式返回到客户端,输出具体的错误信息

  1. HTTP 404 Not Found
  1. {
  2. "msg": "Route \"/d\" is not found.",
  3. "code": 404,
  4. "file": "../RouteCollection.php",
  5. "line": 273,
  6. "trace": [
  7. ]
  8. }

当我们框架执行出现异常时候,并且不希望将敏感信息输出到客户端,那么可以通过 config/app.php 进行配置屏蔽,如:

  1. <?php
  2. return [
  3. // ...
  4. 'exception' => [
  5. 'response' => function (Exception $e) {
  6. return [
  7. 'msg' => $e->getMessage(),
  8. 'code' => $e->getCode(),
  9. // 'file' => $e->getFile(),
  10. // 'line' => $e->getLine(),
  11. // 'trace' => explode("\n", $e->getTraceAsString()),
  12. ];
  13. },
  14. ],
  15. // ...
  16. ];

实现原理非常简单:

  1. <?php
  2. // ...
  3. $handle = config()->get('exception.handle');
  4. $response = json($handle($e), $statusCode);
  5. // ...

日志处理

日志服务依赖于 monolog,当应用程序发生异常时,程序会将异常信息记录在日志中。

3.1 开始日志配置增强至数组处理,支持自定义日志格式和传输

配置:

  1. <?php
  2. return [
  3. 'log' => [
  4. [\Monolog\Handler\StreamHandler::class, 'error.log', \Monolog\Logger::ERROR]
  5. ],
  6. ];

数组接受 4 个参数,分别解析成: handler, log file, level, formatter

实现原理:

  1. <?php
  2. $logger = new \Monolog\Logger(app()->getName());
  3. list($handle, $name, $level, $format) = array_pad([\Monolog\Handler\StreamHandler::class, 'error.log', \Monolog\Logger::ERROR], 4, null);
  4. if (is_string($handle)) {
  5. $handle = new $handle($path.'/'.$name, $level);
  6. }
  7. null !== $format && $handle->setFormatter(is_string($format) ? new \Monolog\Formatter\LineFormatter($format) : $format);
  8. $logger->pushHandler($handle);

集中式日志处理

当我们应用分布过多的时候,就需要考虑如何将日志集中管理起来,方便排查,分析。如果利用 Swoole 即将是一件容易实现的事情。启动我们的日志服务器,然后将每个应用日志都投递到日志服务器中。

应用中仅需要提交数据,数据处理就可以在日志服务器中完成。monolog 中可以使用 monolog-reader 进行解析。

  1. <?php
  2. return [
  3. 'log' => [
  4. [new \Monolog\Handler\SocketHandler('schema://host:port'), 'error.log', \Monolog\Logger::ERROR]
  5. ],
  6. ];

服务器接收提交信息后,对日志进行解析,批量入库,然后对应做响应的处理即可。

下一节: 应用配置