在实际项目中,通知我们需要记录一些日志,方便问题核查。但是日志多了就很容易混乱,请求,响应,执行中的日志无法对应,这时就需要为请求进行标记唯一ID来进行跟踪。


/**
* 记录请求日志
*
* Class ApiLog
* @package App\Library\Components\Elog
*/
class ApiLog
{
static $logPath; private static $singleton; /**
* 单例
* @return ApiLog
*/
public static function singleton()
{ if (false == self::$singleton instanceof ApiLog) {
self::$singleton = new static();
} return self::$singleton;
} protected function __construct($logPath = '')
{
if (empty($logPath)) {
self::$logPath = ROOT_PATH . 'logs/request/';
} else {
self::$logPath = ROOT_PATH . $logPath;
} if (!is_dir(self::$logPath)) {
mkdir(self::$logPath, 0777, true);
}
} public function record($action, $request = [], $type = 'requestLog')
{
$headers = [];
if (!function_exists('getallheaders')) {
foreach ($_SERVER as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') {
$headers[str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($name, 5))))] = $value;
}
}
} else {
$headers = getallheaders();
} //============== 加密用户登录密码
if (isset($request['password'])) {
$request['password'] = md5(md5($request['password']));
} //============== 加密邮箱
if (isset($request['email'])) {
$request['email'] = encrypt_email($request['email']);
}
// ...... 日志中对关键信息进行加密 // 请求日志记录详细一点
if ('requestLog' == $type) {
$data = [
'action' => $action,
'platform' => PHONE_SYSTEM,
'ip' => real_ip(),
'request' => $request,
'REQUEST_URI' => isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '',
'headers' => $headers,
];
} else {
$data = [
'action' => $action,
'response' => $request
];
} $this->write($data, $type);
} protected function write($logData, $type)
{ $minutes = date('i'); $file = date('Y-m-d-H') . '-v' . (intval($minutes / 10)) . '.log'; $logData = ['request_id' => static::getRequestId(), 'add_time' => time(), 'type' => $type, 'content' => $logData]; file_put_contents(self::$logPath . $file, json_encode($logData) . PHP_EOL, FILE_APPEND);
} protected static function getRequestId()
{
static $requestId = ''; if (!empty($requestId)) {
return $requestId;
} if (function_exists('session_create_id')) {
$hash = session_create_id();
} else {
$uid = uniqid('', true);
$data = '';
$data .= isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : '';
$data .= isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
$data .= isset($_SERVER['LOCAL_ADDR']) ? $_SERVER['LOCAL_ADDR'] : '';
$data .= isset($_SERVER['LOCAL_PORT']) ? $_SERVER['LOCAL_PORT'] : '';
$data .= isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
$data .= isset($_SERVER['REMOTE_PORT']) ? $_SERVER['REMOTE_PORT'] : '';
$hash = hash('ripemd128', $uid . md5($data));
} $hash = strtoupper($hash); return $requestId = substr($hash, 0, 8) . '-' . substr($hash, 8, 4) . '-' . substr($hash, 12, 4) . '-' . substr($hash, 16, 4) . '-' . substr($hash, 20, 12);
}
}

使用单例,保证一次请求的ID一致



ApiLog::singleton()->record($action,$request);

ApiLog::singleton()->record($action,$actionData,'createOrder');

ApiLog::singleton()->record($action,$errorMessage,'errorHandler');

ApiLog::singleton()->record($action,$response,'ResponseLog');

原文地址:https://segmentfault.com/a/1190000016675975

通过唯一ID实现简单的日志跟踪实现的更多相关文章

  1. 高并发分布式环境中获取全局唯一ID[分布式数据库全局唯一主键生成]

    需求说明 在过去单机系统中,生成唯一ID比较简单,可以使用MySQL的自增主键或者Oracle中的sequence, 在现在的大型高并发分布式系统中,以上策略就会有问题了,因为不同的数据库会部署到不同 ...

  2. 如何检索Android设备的唯一ID

    关于本文档 Android的开发者在一些特定情况下都需要知道手机中的唯一设备ID.例如,跟踪应用程序的安装,生成用于复制保护的DRM时需要使用设备的唯一ID.在本文档结尾处提供了作为参考的示例代码片段 ...

  3. 全局唯一ID发号器的几个思路

    标识(ID / Identifier)是无处不在的,生成标识的主体是人,那么它就是一个命名过程,如果是计算机,那么它就是一个生成过程.如何保证分布式系统下,并行生成标识的唯一与标识的命名空间有着密不可 ...

  4. Redis的n种妙用,分布式锁,分布式唯一id,消息队列,抽奖……

    介绍 redis是键值对的数据库,常用的五种数据类型为字符串类型(string),散列类型(hash),列表类型(list),集合类型(set),有序集合类型(zset) Redis用作缓存,主要两个 ...

  5. 高性能高可用的分布式唯一ID服务——mooon-uniq-id

    目录 目录 1 1. 前言 1 2. 名词 1 3. 功能 1 4. 唯一性原理 2 5. 系统结构 2 5.1. mooon-uniq-agent 2 5.2. mooon-uniq-master ...

  6. 用ELK搭建简单的日志收集分析系统【转】

    缘起 在微服务开发过程中,一般都会利用多台服务器做分布式部署,如何能够把分散在各个服务器中的日志归集起来做分析处理,是一个微服务服务需要考虑的一个因素. 搭建一个日志系统 搭建一个日志系统需要考虑一下 ...

  7. Android 如何检索Android设备的唯一ID

    关于本文档 Android的开发者在一些特定情况下都需要知道手机中的唯一设备ID.例如,跟踪应用程序的安装,生成用于复制保护的DRM时需要使用设备的唯一ID.在本文档结尾处提供了作为参考的示例代码片段 ...

  8. 百度开源的分布式唯一ID生成器UidGenerator,解决了时钟回拨问题

    UidGenerator是百度开源的Java语言实现,基于Snowflake算法的唯一ID生成器.而且,它非常适合虚拟环境,比如:Docker.另外,它通过消费未来时间克服了雪花算法的并发限制.Uid ...

  9. 关于分布式唯一ID,snowflake的一些思考及改进(完美解决时钟回拨问题)

    1.写唯一ID生成器的原由 在阅读工程源码的时候,发现有一个工具职责生成一个消息ID,方便进行全链路的查询,实现方式特别简单,核心源码不过两行,根据时间戳以及随机数生成一个ID,这种算法ID在分布式系 ...

随机推荐

  1. C# 基础复习 三 XML操作

    XML 可扩展标记语言(所有标签都是自己定义,没有固定格式) 如果要给XML规定格式,可以使用dtd (dtd是什么?你不会自己百度吗) XML主要用来存储数据 XML的要求:     根节点只能有一 ...

  2. 利用after和before伪元素在文字两边写横线

    示例: 代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  3. pythone 学习笔记(粗略)

    文档目录 概述 安装 基本语法 数据结构 4.1 数字和字符串类型 4.2 元祖 4.3 列表 4.4 字典 流程语句 5.1 分支结构 5.2 逻辑运算符(if) 5.3 循环 5.3.1 for ...

  4. HDU 1047 Integer Inquiry( 高精度加法水 )

    链接:传送门 思路:高精度水题 /************************************************************************* > File ...

  5. FZU 1692 Key problem( 循环矩阵优化 + 矩阵快速幂)

    链接:传送门 题意: n个小朋友围成一个环( 2 <= n <= 100 )然后进行m次的游戏. 一开始,第 i 个小朋友有 Ai 个苹果. 定义游戏的规则为:每一次游戏处于 i 位置的小 ...

  6. pyqt5的QWebEngineView 使用方法

    说明1:关于QWebEngineView pyqt5 已经抛弃 QtWebKit和QtWebKitWidgets,而使用最新的QtWebEngineWidgets. QtWebEngineWidget ...

  7. html全屏显示

    JavaScript代码: function toggleFullScreen() { if (!document.fullscreenElement && // alternativ ...

  8. Laravel源码解析之从入口开始

    前言 提升能力的方法并非使用更多工具,而是解刨自己所使用的工具.今天我们从Laravel启动的第一步开始讲起. 入口文件 laravel是单入口框架,所有请求必将经过index.php define( ...

  9. django-7-django模型系统

    <<<常用的模型字段类型>>>https://docs.djangoproject.com/en/2.1/ref/models/fields/#field-type ...

  10. ASP.NET-HTML.Helper常用方法

    Html.ActionLink方法 Html.ActionLink("linkText","actionName") Html.ActionLink(" ...