都快2202年了,你还不会用RequestId看日志 ?

对某数藏app逆向安全分析 昨晚我群里有个老哥在问移动端滑块怎么分析因为大多app端的滑块都是加载在webview上的我当时突然就想到才没几天搞定的一个app,也有webview部分的操作,因为是用uni打包的,所以实际走的还是webview。而uni相关的其实之前发过一篇对uni-app开发的某app逆向分析不过今天这个app有点不同,我感觉是值得记录的,所以准备再写一篇有关这个的工作避坑&内推(仅成都)、技术交流、商务合作、技术交流群geekbyte。 阅读详情

引言

在日常的后端开发工作中,最常见的操作之一就是看日志排查问题,对于大项目一般使用类似ELK的技术栈统一搜集日志,小项目就直接把日志打印到日志文件。那不管对于大项目或者小项目,查看日志都需要通过某个关键字进行搜索,从而快速定位到异常日志的位置来进一步排查问题。

对于后端初学者来说,日志的关键字可能就是直接打印某个业务的说明加上业务标识,如果出现问题直接搜索对应的说明或者标识。例如下单场景,可能就直接打印:创建订单,订单编号:xxxx,当有问题的时候,则直接搜索订单编号或者创建订单。在这种方式下,经常会搜索出多条日志,增加问题的排查时长。

所以,今天我们就来说一说这个关键字的设计,这里我们使用RequestId进行精确定位问题日志的位置从而解决问题。

需求

目标: 帮助开发快速定位日志位置

思路:当前端进行一次请求的时候,在进行业务逻辑处理之前我们需要生成一个唯一的RequestId,在业务逻辑处理过程中涉及到日志打印我们都需要带上这个RequestId,最后响应给前端的数据结构同样需要带上RequestId。 这样,每次请求都会有一个RequestId,当某个接口异常则通过前端反馈的RequestId,后端即可快速定位异常的日志位置。

总结下我们的需求:

  • 一次请求生成一次RequestId,并且RequestId唯一
  • 一次请求响应给前端,都需要返回RequestId字段,接口正常、业务异常、系统异常,都需要返回该字段
  • 一次请求在控制台或者日志文件打印的日志,都需要显示RequestId
  • 一次请求的入参和出参都需要打印
  • 对于异步操作,需要在异步线程的日志同样显示RequestId

实现

  1. 实现生成和存储RequestId的工具类
public class RequestIdUtils {
    private static final ThreadLocal<UUID> requestIdHolder = new ThreadLocal<>();
    private RequestIdUtils() {
    }
    public static void generateRequestId() {
        requestIdHolder.set(UUID.randomUUID());
    }
    public static void generateRequestId(UUID uuid) {
        requestIdHolder.set(uuid);
    }
    public static UUID getRequestId() {
        return (UUID)requestIdHolder.get();
    }
    public static void removeRequestId() {
        requestIdHolder.remove();
    }
}

因为我们一次请求会生成一次RequestId,并且RequestId唯一,所以这里我们使用使用UUID来生成RequestId,并且用ThreadLocal进行存储。

  1. 实现一个AOP,拦截所有的Controller的方法,这里是主要的处理逻辑
@Aspect
@Order
@Slf4j
public class ApiMessageAdvisor {


    @Around("execution(public * org.anyin.gitee.shiro.controller..*Controller.*(..))")
    public Object invokeAPI(ProceedingJoinPoint pjp) {
        String apiName = this.getApiName(pjp);
        // 生成RequestId
        String requestId = this.getRequestId();
        // 配置日志文件打印 REQUEST_ID
        MDC.put("REQUEST_ID", requestId);
        Object returnValue = null;
        try{
            // 打印请求参数
            this.printRequestParam(apiName, pjp);
            returnValue = pjp.proceed();
            // 处理RequestId
            this.handleRequestId(returnValue);
        }catch (BusinessException ex){
            // 业务异常
            returnValue = this.handleBusinessException(apiName, ex);
        }catch (Throwable ex){
            // 系统异常        
            returnValue = this.handleSystemException(apiName, ex);
        }finally {
            // 打印响应参数
            this.printResponse(apiName, returnValue);
            RequestIdUtils.removeRequestId();
            MDC.clear();
        }
        return returnValue;
    }

    /**
     * 处理系统异常
     * @param apiName 接口名称
     * @param ex 系统异常
     * @return 返回参数
     */
    private Response handleSystemException(String apiName, Throwable ex){
        log.error("@Meet unknown error when do " + apiName + ":" + ex.getMessage(), ex);
        Response response = new Response(BusinessCodeEnum.UNKNOWN_ERROR.getCode(), BusinessCodeEnum.UNKNOWN_ERROR.getMsg());
        response.setRequestId(RequestIdUtils.getRequestId().toString());
        return response;
    }

    /**
     * 处理业务异常
     * @param apiName 接口名称
     * @param ex 业务异常
     * @return 返回参数
     */
    private Response handleBusinessException(String apiName, BusinessException ex){
        log.error("@Meet error when do " + apiName + "[" + ex.getCode() + "]:" + ex.getMsg(), ex);
        Response response = new Response(ex.getCode(), ex.getMsg());
        response.setRequestId(RequestIdUtils.getRequestId().toString());
        return response;
    }

    /**
     * 填充RequestId
     * @param returnValue 返回参数
     */
    private void handleRequestId(Object returnValue){
        if(returnValue instanceof Response){
            Response response = (Response)returnValue;
            response.setRequestId(RequestIdUtils.getRequestId().toString());
        }
    }

    /**
     * 打印响应参数信息
     * @param apiName 接口名称
     * @param returnValue 返回值
     */
    private void printResponse(String apiName, Object returnValue){
        if (log.isInfoEnabled()) {
            log.info("@@{} done, response: {}", apiName, JSONUtil.toJsonStr(returnValue));
        }
    }

    /**
     * 打印请求参数信息
     * @param apiName 接口名称
     * @param pjp 切点
     */
    private void printRequestParam(String apiName, ProceedingJoinPoint pjp){
        Object[] args = pjp.getArgs();
        if(log.isInfoEnabled() && args != null&& args.length > 0){
            for(Object o : args) {
                if(!(o instanceof HttpServletRequest) && !(o instanceof HttpServletResponse) && !(o instanceof CommonsMultipartFile)) {
                    log.info("@@{} started, request: {}", apiName, JSONUtil.toJsonStr(o));
                }
            }
        }
    }

    /**
     * 获取RequestId
     * 优先从header头获取,如果没有则自己生成
     * @return RequestId
     */
    private String getRequestId(){
        // 因为如果有网关,则一般会从网关传递过来,所以优先从header头获取
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(attributes != null && StringUtils.hasText(attributes.getRequest().getHeader("x-request-id"))) {
            HttpServletRequest request = attributes.getRequest();
            String requestId = request.getHeader("x-request-id");
            UUID uuid = UUID.fromString(requestId);
            RequestIdUtils.generateRequestId(uuid);
            return requestId;
        }
        UUID existUUID = RequestIdUtils.getRequestId();
        if(existUUID != null){
            return existUUID.toString();
        }
        RequestIdUtils.generateRequestId();
        return RequestIdUtils.getRequestId().toString();
    }

    /**
     * 获取当前接口对应的类名和方法名
     * @param pjp 切点
     * @return apiName
     */
    private String getApiName(ProceedingJoinPoint pjp){
        String apiClassName = pjp.getTarget().getClass().getSimpleName();
        String methodName = pjp.getSignature().getName();
        return apiClassName.concat(":").concat(methodName);
    }
}

简单说明:

  • 对于RequestId的获取方法 getRequestId,我们优先从header头获取,有网关的场景下一般会从网关传递过来;其次判断是否已经存在,如果存在则直接返回,这里是为了兼容有过滤器并且在过滤器生成了RequestId的场景;最后之前2中场景都未找到RequestId,则自己生成,并且返回
  • MDC.put("REQUEST_ID", requestId) 在我们生成RequestId之后,需要设置到日志系统中,这样子日志文件才能打印RequestId
  • printRequestParam 和 printResponse 是打印请求参数和响应参数,如果是高并发或者参数很多的场景下,最好不要打印
  • handleRequestId 、 handleBusinessException 、 handleSystemException 这三个方法分别是在接口正常、接口业务异常、接口系统异常的场景下设置RequestId
  1. 日志文件配置
<contextName>logback</contextName>
<springProperty scope="context" name="level" source="logging.level.root"/>
<springProperty scope="context" name="path" source="logging.file.path"/>


<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
    <Target>System.out</Target>
   <filter class="ch.qos.logback.classic.filter.ThresholdFilter" >
        <level>DEBUG</level>
    </filter>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{REQUEST_ID}] [%thread] [%-5level] [%logger{0}:%L] : %msg%n</pattern>
    </encoder>
</appender>

<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${path}</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
    </rollingPolicy>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{REQUEST_ID}] [%thread] [%-5level] [%logger{0}:%L] : %msg%n</pattern>
    </encoder>
</appender>

<root level="${level}">
    <appender-ref ref="console"/>
    <appender-ref ref="file"/>
</root>

这里是一个简单的日志格式配置文件,主要是关注[%X{REQUEST_ID}], 这里主要是把RequestId在日志文件中打印出来

  1. 解决线程异步场景下RequestId的打印问题
public class MdcExecutor implements Executor {
    private Executor executor;
    public MdcExecutor(Executor executor) {
        this.executor = executor;
    }
    @Override
    public void execute(Runnable command) {
        final String requestId = MDC.get("REQUEST_ID");
        executor.execute(() -> {
            MDC.put("REQUEST_ID", requestId);
            try {
                command.run();
            } finally {
                MDC.remove("REQUEST_ID");
            }
        });
    }
}

这里是一个简单的代理模式,代理了Executor,在真正执行的run方法之前设置RequestId到日志系统中,这样子异步线程的日志同样可以打印我们想要的RequestId

测试效果

  • 登录效果

不会吧,你还不会用RequestId看日志 ?

不会吧,你还不会用RequestId看日志 ?

  • 正常的业务处理

不会吧,你还不会用RequestId看日志 ?

不会吧,你还不会用RequestId看日志 ?

  • 发生业务异常

不会吧,你还不会用RequestId看日志 ?

不会吧,你还不会用RequestId看日志 ?

  • 发生系统异常

不会吧,你还不会用RequestId看日志 ?

不会吧,你还不会用RequestId看日志 ?

  • 异步线程

不会吧,你还不会用RequestId看日志 ?

不会吧,你还不会用RequestId看日志 ?

最后

通过以上骚操作,同学,你知道怎么使用RequestId看日志了吗?

微服务中的请求追踪与日志记录 - `requestId`(请求ID)和 `traceId`(跟踪ID) 在微服务架构中,请求的追踪和日志记录是非常关键的,能够帮助我们更好地理解系统的行为、排查问题、优化性能。requestId(请求ID)和traceId(跟踪ID)。 阅读详情

相关推荐

request-id.js:允许您通过添加X-Request-Id的响应标头来识别非顺序日志(例如Syslog)内的客户端请求。 允许通过查询参数或请求标头设置值。 对于Koa和Express

请求编号 通过添加X-Request-Id的响应标头,允许您在非顺序日志(例如Syslog)中标识客户端请求。 允许通过查询参数或请求标头设置值。 对于Koa和Express。 $ npm install request-id 用法 快速入门(考阿或特快) # koa var requestId = require('request-id'); var app = require('koa')(); app.use(requestId()); # express var requestId = require('request-id/express'); var app = require('express')(); app.use(requestId()); 随机编号 % curl example.com //=> X-Client-ID: a37cacc3-71d5-40f0-a

对Request-ID的一些认识

为什么要使用Request Id 1. Request Id 是为了解决下面问题 问题一: 客户端访问的Web服务时,如何将客户端请求与服务端日志关联 问题二: 微服务架构下,访问日志如何查询 问题三: 不同项目交互出现异常,如何做日志关联 2. Request Id Vs 没有Request Id 没有Request Id 请求,只能根据调用函数日志关键,在根据用户的输入的参数,时间...

yongwan5637的博客 3万+

3D Slicer中文教程(三)—数据加载及保存方式

1.打开数据与保存数据 (1)打开数据 ——可以将数据拖拽到3D Slicer应用窗口或者从菜单栏工具栏打开。 ——多种方式加载大量数据。 有关DICOM数据,请参阅DICOM模块文档。 对于几乎所有其他(包括场景),您可以使用添加数据对话框。 有关支持的数据格式的列表,请参阅此列表。 请注意,仅部分支持列出的某些格式。 ——对于一些更复杂的格式(特别是DWI),建议首先使用DICOM到n...

weixin_33676492的博客 5534

为什么很多网站每次的请求都有一个requestid?具体如何实现?使用场景是什么?底层原理是什么?

使用requestid是一种有效的方法,可以提高系统的可维护性和可调试性。通过在请求中生成并传递requestid,可以方便地进行日志记录、错误报告、性能监控和分布式系统跟踪。理解requestid的工作原理和实现方法有助于开发者设计出更加健壮和易于管理的Web应用。

长风破浪会有时的博客 9276

windows11 远程桌面连接 通过代理连接RDP桌面报错 错误代码0x904 拓展错误代码0x7

打开windows Defender防火墙设置--允许应用通过防火墙更改设置--允许其他应用浏览--进入C:\WINDOWS\system32目录选择mstsc.exe进入C:\Windows\SysWOW64目录h'qmstsc.exe添加后列表里多了一个远程桌面连接,还有一个Remote Desktop Connection,配置网络权限后保存连接成功。

weixin_43978891的博客 1万+

基于51单片机的多功能计算器全套设计

当今社会,随着人们物质生活的不断提高,电子产品已经走进了家家户户,无论是生活或学习,还是娱乐和消遣几乎样样都离不开电子产品,大型复杂的计算能力是人脑所不能胜任的,而且人脑比较容易出错。计算器作为一种快速通用的计算工具方便了用户的使用。计算器可谓是我们最亲密的电子伙伴之一。本设计着重在于分析计算器设计开发过程中的环节和步骤,并从实践经验出发对计算器设计做了详细的分析和研究。 本设计是以STC89C52单片机为核心的计算器模拟系统设计,输入采用5×8矩阵键盘,可以进行加、减、乘、除等十几种数字运算,同时支持括号

runweipa的博客 1742

2021-08-28

你应该知道的RPC原理   在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示。这些程序的特点是服务消费方和服务提供方是本地调用关系。   而一旦踏入公司尤其是大型互联网公司就会发现,公司的系统都由成千上万大大小小的服务组成,各服务部署在不同的机器上,由不同的团队负责。这时就会遇到两个问题:1)要搭建一个新服务,免不了需要依赖他人的服务,而现在他人的服务都在远端,怎么调用?2)其它团队要使用我们的新服务,我们的服务该怎么发布以便他人调用?下文将对这两个问题展开探

wr_java的博客 9109

PCIe Crosslink

PCIe Crosslink(交叉连接)是一种特殊的PCIe链路连接方式,允许两个PCIe设备(通常是Root Complex或Endpoint)是指两个PCIe设备(如两个CPU、两个FPGA或两个GPU)通过PCIe链路直接连接,形成点对点(P2P)通信通道。:两个Intel/AMD CPU通过PCIe Crosslink直接通信(替代UPI/Infinity Fabric)。:主板需提供PCIe Crosslink连接(如特定插槽支持x16/x8 Crosslink)。

zly8865372的博客 1636

logback日志(requestId(请求ID))(processId(进程ID))

添加requestId、processId分别为请求id和进程id 添加拦截器拦截每次请求并把请求id和进程id存入mdc在logback.xml中调用并在控制台打印 MDC是log4j和 logback 支持的一种方便在多线程条件下记录追踪日志的功能 统一日志格式这里希望在打印日志时,每行数据都有一个请求ID,这样就很方面追踪日志,slf4j有个MDC的类,是ThreadLocal的实现,保存在这里的变量会绑定到某个请求线程,于是在该请求的线程里的日志代码都可以使用设入的变量,在项目里定义一个拦..

陈一一同学的博客 1万+

告别GUI点点点:Formality形式化验证的TCL脚本自动化实战(附完整脚本)

本文详细介绍了如何通过TCL脚本实现Formality形式化验证的全流程自动化,显著提升验证效率并降低错误率。内容涵盖脚本框架解析、参数化设计、验证报告生成及团队协作策略,特别适合芯片设计工程师摆脱传统GUI操作,实现300%以上的效率提升。

weixin_33737134的博客 282

机器视觉避坑指南:为什么你的Halcon划痕检测总漏检?(附优化方案)

本文深入剖析了Halcon在表面划痕检测中漏检率高的常见原因,如灰度值波动、噪声干扰及形态学参数设置不当。针对复杂背景与低对比度划痕,提出了超越官方例程的多尺度纹理分析与特征融合优化方案,旨在帮助开发者构建更鲁棒、稳定的机器视觉检测流程,有效提升检出率。

weixin_29057163的博客 234

查找RequestID的方法

今天中午收到金山云的告警短信,发现有几个服务器的CPU飙升,如图:这个服务器的用途是用户上传云录像到云存储的,登陆到服务器,使用#curl http://127.0.0.1:9030/online/detect/test 之后,发现已经没有任何的反应,在日志里筛选关键词cost后得到的内容如下:看见此时的cost值特别高,表明很多录像在上传云存储的时候出现了困难,再详细筛选一...

weixin_34259159的博客 5283

Vue - 最新详细实现滑块拖动拼图验证,网站登录验证滑块验证功能,拖动滑块到图片缺口的位置即为成功,滑块验证安全检测(详细示例代码,一键复制运行)

您一定见过很多系统都“配备”了滑块验证、拼图验证、找不同等,本质上都是为了验证登录系统的是人还是机器(代码),如下图所示效果: 您打开项目根目录,终端执行如下命令:拼图式拖动滑块验证 验证拖动滑块验证,滑动拼图/图片点选验证 接下来,在中加入以下代码: 如下图所示: 更多配置示例和参数详见官方文档,以下便是如上效果图的代码:.........

🏆 前端领域优质创作者 1万+

http 请求增加 X-Request-ID

namespace log\processor; use Request; class RequestProcessor { public function __invoke($record) { $extra = [ 'method' => Request::method(), 'path' => Request::pathinfo() ]; if (Request::head

黎明 5687

手把手教你学Simulink——基于通信协议与标准的场景实例:卫星通信中的网络安全协议(IPSec)仿真

随着卫星通信在国防、金融、应急指挥、能源管网等关键领域的广泛应用,其安全性已成为系统设计的核心要求。然而,卫星链路具有广播特性、长距离传输、地面站分布广等特点,极易遭受窃听、篡改、重放、中间人攻击等网络威胁。传统的“信任链路层安全”已不足以应对现代网络攻击。为此,国际标准组织(如IETF、ETSI、CCSDS)推荐在卫星通信中部署协议,实现端到端的数据机密性、完整性、身份认证和抗重放保护。本文将手把手教你如何在中构建一个符合标准的仿真系统,涵盖从明文传输到加密隧道的完整安全链路建模。本文完整实现了。

MHD0815的博客 148

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

各种request_id唯一ID在不同场景的应用

最后项目接受到nginx传送的以$request_id 作为traceId的字符串,实现nginx和tomcat的链路串联。这里的 唯一ID proxy_set_header x-request-id $http_x_request_id;这里网关入口的日志配置 :核心配置 p-request-id=[$request_id]在运维场景中 存在需要唯一ID的情况,很多时候不知道什么时候采取唯一ID比较合适。

剑哥是个运维工程师 会点python和JAVA ,最近研究AI和GPU 2584

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

不会吧,你还不会用RequestId看日志 ?

引言 在日常的后端开发工作中,最常见的操作之一就是看日志排查问题,对于大项目一般使用类似ELK的技术栈统一搜集日志,小项目就直接把日志打印到日志文件。那不管对于大项目或者小项目,查看日志都需要通过某个关键字进行搜索,从而快速定位到异常日志的位置来进一步排查问题。 对于后端初学者来说,日志的关键字可能就是直接打印某个业务的说明加上业务标识,如果出现问题直接搜索对应的说明或者标识。例如下单场景,可能就直接打印:创建订单,订单编号:xxxx,当有问题的时候,则直接搜索订单编号或者创建订单。在这种方式下,经常会

欢迎来到我的博客 2558

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

php request id,PHP生成唯一RequestID类

这篇文章主要介绍了PHP生成唯一RequestID类,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下本文介绍PHP生成唯一RequestID类,使用session_create_id()与uniqid()方法,保证唯一性,提供完整代码及演示,方便大家学习使用。现在的系统设计一般使用分布式系统,一个请求可能要调用几个微服务处理,最后再把结果返回。当请求出现问题时,我们很难去跟踪是哪个微...

weixin_29888579的博客 2138

对Request-ID的一些认识(*)

为什么要使用Request Id Request Id 是为了解决下面问题 问题一: 客户端访问的Web服务时,如何将客户端请求与服务端日志关联 问题二: 微服务架构下,访问日志如何查询 问题三: 不同项目交互出现异常,如何做日志关联 Request Id Vs 没有Request Id 没有Request Id 请求,只能根据调用函数日志关键,在根据用户的输入的参数,时间来确定相关的日志。 如果项目是以分布式,微服务架构来实现, 上面查日志方式帮助很小。原因如下 代码层层封装后,无法通过日志关

weixin_42408447的博客 6737

request('id')语句,返回的是什么类型的数据

request('id')语句,返回的是什么类型的数据 问:在做网页数据库时碰到的问题,数据库字段aticleid唯一表示一条记录,点击该记录名称,打开新窗口,地址栏应显示http://***.***.**.**/viewarticle.asp?id=***** 若articleid=0015555,则点击打开后只能显示静态页面部分,地址栏...

weixin_34346099的博客 1202

Request ID,Trace(x-tt-logid),Span,Resource ID,Logid,TaskID

RequestId:一次 HTTP 调用(会变)TraceId(x-tt-logid):一次用户操作全程不变(全局唯一)Span:每一段内部调用(分段)日志 logid:每条日志一个(单条)resourceId :管被操作的资源关于logId的备注:狭义:单条日志行的唯一 ID,即本文中所提到的 logId广义:日常口语中常说的logid常与 TraceId 同义,用来把同一次请求的所有后端日志(Nginx、网关、服务 A、服务 B、DB、MQ…) 绑定在一起。

m0_44956937的博客 467

网络多线程

1. Netty 原理 Netty 是一个高性能、异步事件驱动的 NIO 框架,基于 JAVA NIO 提供的 API 实现。它提供了对TCP、UDP 和文件传输的支持,作为一个异步 NIO 框架,Netty 的所有 IO 操作都是异步非阻塞的,通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得 IO 操作结果。 2. Netty 高性能 在 IO 编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者 IO 多路复用技术进行处理。IO 多路复用技术通过把多个

m0_53080414的博客 603

在Logback中配置`requestId`进行日志追踪的实践与应用

Logback 是一个高效、灵活的Java日志框架,广泛用于Spring Boot项目中。它支持多种日志输出格式和策略,允许用户灵活配置日志级别、输出格式、目标位置等。requestIdMDC(映射诊断上下文)是slf4j提供的一种机制,允许在多线程环境中存储和共享上下文信息(例如requestIdMDC数据与当前线程相关联,因此能够有效区分和跟踪多线程环境中的日志。通过在Spring Boot应用中正确配置Logback、MDC和线程池,我们可以确保每个请求的日志都能包含一个唯一的requestId。

乙壳虫的博客 2107

Gin中间件:requestid——为Gin Web框架添加请求ID功能

Gin中间件:requestid——为Gin Web框架添加请求ID功能 项目介绍 gin-contrib/requestid 是一个为基于 Gin 的Web应用程序提供唯一请求ID生成的中间件。这个开源项目使得开发者能够轻松地在应用程序的日志中追踪每个HTTP请求,增强调试和监控能力。通过为每个请求附加唯一的ID,开发者可以在分布式系统中更容易地关联日志条目,从而简化问题诊断过程。 项目快速启动...

gitblog_00428的博客 1233

[2017-11-07]相应头 X-ReqId

公共相应头相应头 X-ReqId在Nginx中实现作用:上传请求的唯一 ID。通过该 ID 可快速定位用户请求的相关日志。要求: nginx version v1.11以上 配置方法:1.在http内部添加mapmap $http_x_request_id $reqid { default $http_x_request_id; "" $request_id; }2

enutter的专栏 2243
上一篇: 阿里二面:main 方法可以继承吗?
下一篇: 年末福利,TCP/IP 协议终于被人讲的明明白白了
superjava_
博客等级 码龄5年 254粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值