在实际项目中,通知我们需要记录一些日志,方便问题核查。但是日志多了就很容易混乱,请求,响应,执行中的日志无法对应,这时就需要为请求进行标记唯一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. Eclipse中修改GIT分支名称

    修改GIT分支名称: 1.切换到要修改名称的分支: 2.右击项目——Team——Advanced——Rename Branch…: 3.在弹出的Branch Rename框中选中要修改名的分支——Re ...

  2. HDU1027 Ignatius and the Princess II( 逆康托展开 )

    链接:传送门 题意:给出一个 n ,求 1 - n 全排列的第 m 个排列情况 思路:经典逆康托展开,需要注意的时要在原来逆康托展开的模板上改动一些地方. 分析:已知 1 <= M <= ...

  3. 为什么在index.jsp里面引入了common.js,在item-add.jsp以及其他一些jsp文件里面就不需要引入common.jsne ?

    那是因为,index.jsp页面的根节点是body,hrml.是一个完整的网页.那我们再看item-add.jsp页面,他节点是div,只是一个html的片段,并不是一个完整的网页,在easyUI中, ...

  4. shell试题

    1.按单词出现频率降序排序! 2.按字母出现频率降序排序! The months of learning in Old Boy education are the few months that I ...

  5. DML语句(添加、更新和删除记录)

       a.添加记录(一次插入一行记录)     insert into 表名(字段名,字段名...)     values (字段值,字段值...)       insert into person ...

  6. 匿名訪问之(一)web application级别

    假设用SharePoint做一个对外开放的公共站点,比方公司展示站点.那么浏览站点的人不须要注冊和登陆.就应该能看到内容.这个时候就须要对站点开启匿名訪问. SharePoint的匿名訪问是从上而下的 ...

  7. 【JavaEE WEB 开发】Tomcat 具体解释 Servlet 入门

    转载请注明出处 :  http://blog.csdn.net/shulianghan/article/details/47146817 一. Tomcat 下载安装配置 1. Tomcat 下载 T ...

  8. 设计网页录入信息与自己定义server数据接收

    需求:设计一个注冊网页用于录入username和登录password.并将数据传入server并显示出来. 1.前言:网页提交的 get 和 post 两种方式. (1)对于get提交方式,以本文中样 ...

  9. 仿hibernate,spring框架手动写

    近期学习了hibernate底层技术和spring 的底层技术,认为非常不错,所以想分享下,要是说的不够具体.能够去下载资源自己查看下载链接 技术的体现是在实际中的.如今大体介绍一下吧 首先介绍hib ...

  10. Java多线程之~~~线程安全容器的非堵塞容器

    在并发编程中,会常常遇到使用容器.可是假设一个容器不是线程安全的.那么他在多线程的插入或者删除的过程 中就会出现各种问题.就是不同步的问题.所以JDK提供了线程安全的容器,他能保证容器在多线程的情况下 ...