Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >skywalking展示http请求和响应

skywalking展示http请求和响应

作者头像
十毛
发布于 2021-11-24 05:26:38
发布于 2021-11-24 05:26:38
3K10
代码可运行
举报
运行总次数:0
代码可运行

使用skywalking跟踪请求的时候,是看不到http请求的参数的,这样不方便定位问题。本文通过自定义的方式(ActiveSpan.tag),实现了http请求和响应的输出,方便快速定位问题

效果图

可以在请求中看到自定义请求信息input和返回值output,方便快速定位问题

实现请求和响应的输出

  • 添加依赖
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-trace</artifactId>
    <version>8.7.0</version>
    <scope>provided</scope>
</dependency>
  • 使用ActiveSpan.tag输出到skywalking
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ActiveSpan.tag("input", sb.toString());
  • 实现http请求和返回值的的输出

因为HttpServletRequestHttpServletResponse中的body只能读取一次,如果在Filte中读取的话,应用本身就读取不到,所以需要使用ContentCachingRequestWrapperContentCachingResponseWrapper

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Slf4j
@Component
public class ApmHttpInfo extends HttpFilter {
    private static final ImmutableSet<String> IGNORED_HEADERS;
    static {
        Set<String> ignoredHeaders = ImmutableSet.of(
                        "Content-Type",
                        "User-Agent",
                        "Accept",
                        "Cache-Control",
                        "Postman-Token",
                        "Host",
                        "Accept-Encoding",
                        "Connection",
                        "Content-Length")
                .stream()
                .map(String::toUpperCase)
                .collect(Collectors.toSet());
        IGNORED_HEADERS = ImmutableSet.copyOf(ignoredHeaders);
    }

    @Override
    public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
        ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);

        try {
            filterChain.doFilter(requestWrapper, responseWrapper);
        } finally {
            try {
                //构造请求信息: 比如 curl -X GET http://localhost:18080/getPerson?id=1 -H 'token: me-token' -d '{ "name": "hello" }'
                //构造请求的方法&URL&参数
                StringBuilder sb = new StringBuilder("curl")
                        .append(" -X ").append(request.getMethod())
                        .append(" ").append(request.getRequestURL().toString());
                if (StringUtils.hasLength(request.getQueryString())) {
                    sb.append("?").append(request.getQueryString());
                }

                //构造header
                Enumeration<String> headerNames = request.getHeaderNames();
                while (headerNames.hasMoreElements()) {
                    String headerName = headerNames.nextElement();
                    if (!IGNORED_HEADERS.contains(headerName.toUpperCase())) {
                        sb.append(" -H '").append(headerName).append(": ").append(request.getHeader(headerName)).append("'");
                    }
                }

                //获取body
                String body = new String(requestWrapper.getContentAsByteArray(), StandardCharsets.UTF_8);
                if (StringUtils.hasLength(body)) {
                    sb.append(" -d '").append(body).append("'");
                }
                //输出到input
                ActiveSpan.tag("input", sb.toString());

                //获取返回值body
                String responseBody = new String(responseWrapper.getContentAsByteArray(), StandardCharsets.UTF_8);
                //输出到output
                ActiveSpan.tag("output", responseBody);
            } catch (Exception e) {
                log.warn("fail to build http log", e);
            } finally {
                //这一行必须添加,否则就一直不返回
                responseWrapper.copyBodyToResponse();
            }
        }
    }
}

参考

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/10/21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
1 条评论
热度
最新
毛哥,有个问题,如果是一个文件上传的接口,那记录的内容是不是太多了?
毛哥,有个问题,如果是一个文件上传的接口,那记录的内容是不是太多了?
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
微系列:8、在Centos系统中,搭建Skywalking服务
OAP:收集tracing和metric信息通过analysis core模块将数据放入持久化容器中(ES,H2(内存数据库),mysql等等),并进行二次统计和监控告警
老张的哲学
2023/01/09
1.3K0
微系列:8、在Centos系统中,搭建Skywalking服务
SkyWalking集成与案例
在容器内,会生成skyapm-2022xxxx.log文件,会有详细的连接信息和推送信息。 同时要检查下是否包含skyapm.json文件。
老张的哲学
2022/04/11
1.4K0
Spring参数错误时输出Http内容
Spring应用中,一般使用Aop进行请求参数和返回值的日志输出,但是这里有一个前提,就是用户请求的参数一定好可以转换为方法参数,但是经常前端请求是一个错误的Json格式,参数转换失败,并不会进入AOP所以也就看不到请求参数。只会看到org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error。这就导致定位问题比较困难,所以后台需要一个更好的办法来输出请求参数。
十毛
2020/11/26
6980
springboot优雅的改进你的输出日志,让你快速的定位问题 超详细的初始化教程
一个好的项目,一定会输出很多的日志,来让开发者,快速的去定位一些问题。下面我将带来一些在springboot中,你可以选择做的初始化技巧。这些都是比较通用的,可以直接进行复制使用,所以我这里不做过多的讲解。
用户10143704
2024/04/13
2700
Filter 实现过滤符合条件的请求并落库
这个配置类定义了一个过滤器,名为logFilter,它在每个请求上只执行一次(由其实现的OncePerRequestFilter接口保证)。
绿毛龟
2024/02/09
3290
Filter 实现过滤符合条件的请求并落库
如何优雅记录 http 请求/ 响应数据?
作者:fredalxin 地址:https://fredal.xin/http-body-recorder
Java技术栈
2021/04/22
1.2K0
Spring cached 的 wrapper 类读取请求响应内容
Servlet 的 request body 以及 response body 一旦流被读取了,就无法再次被读取了,因此这对于有些要做拦截业务请求来说,比较麻烦。那么如何处理这个业务场景呢?利用 filter,然后重写 HttpServletRequest 和 HttpServletResponse 包装一层,然后 proceed,最后 response 完之后在把cached 的 body 设置回原始响应。
BUG弄潮儿
2021/05/17
3.6K0
使用springboot自带的请求、响应缓存实现请求响应打印
在日常的开发中,日志往往是我们用来排查问题的重要依据,请求和响应也是其中重要的组成部分。也看到了很多业务系统记录日志的方式:
shigen
2024/12/24
3431
请求录制 | 巧用filter
Filter能够在一个请求到达servlet之前预处理用户请求, 也可以在离开servlet时处理http响应.
一个架构师
2022/06/27
5010
Spring Boot 记录请求响应日志的常用手段
很多网关设施都具有httptrace的功能,可以帮助我们集中记录请求流量的情况。Orange、Kong、Apache Apisix这些基于Nginx的网关都具有该能力,就连Nginx本身也提供了记录httptrace日志的能力。
码农小胖哥
2021/08/13
6K0
屏蔽词过滤器
黑发不知勤学早,白首方恨读书迟。 ——颜真卿 我们可能想使用本地配置词库、过滤器的方式去做全局屏蔽词处理 这里针对三种参数情况 1.requestParam传参:http://localhost:
阿超
2022/08/17
7280
屏蔽词过滤器
聊聊nacos的DistroFilter
nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/web/CanDistro.java
code4it
2019/09/11
6470
聊聊nacos的DistroFilter
用户输入的虎狼之词,怎么校验之后不见了?
不知道你们有没有对用户输入的东西进行过敏感校验,如果不进行校验,用户属于一些攻击脚本,那么我们的服务就挂逼啦!所以我们首先需要通过过滤器将用户的数据读出来进行安全校验,这里面涉及到一个动作,就是需要将用户的数据在过滤器中读出来,进行校验,通过之后再放行。
一个程序员的成长
2020/11/25
6710
spring boot实现超轻量级网关(反向代理、转发)
在我们的rest服务中,需要暴露一个中间件的接口给用户,但是需要经过rest服务的认证,这是典型的网关使用场景。可以引入网关组件来搞定,但是引入zuul等中间件会增加系统复杂性,这里实现一个超轻量级的网关,只实现请求转发,认证等由rest服务的spring security来搞定。
JadePeng
2020/11/24
4.6K0
【第三篇】开始和SpringSecurity的简单交往-处理请求的本质
分析SpringSecurity的核心原理,那么我们从哪开始分析?以及我们要分析哪些内容?
用户4919348
2022/05/10
3110
【第三篇】开始和SpringSecurity的简单交往-处理请求的本质
日志输出filter
因为默认的response获取了响应结果就没了,因此我们需要封装一个ResponseWrapper
阿超
2022/08/17
5580
java在filter中修改一个http请求出入参内容
response保存了请求的返回信息,里面有个outputstream,你要返回给页面的流,都在这个地方保存. 之前遇到一个问题,想把outputstream修改一下.因为这是个输出流,想要改这个里面的东西不是这么简单的. sun为我们提供了这么一个工具HttpServletResponseWrapper抽象类,利用这个类的子类把servletresponse包装一下,在过滤器中使用,就可以去除response的文件流,对其作出修改.给出一个实现:
天涯泪小武
2021/12/09
1.7K0
如何在过滤器中修改http请求体和响应体
在一些业务场景中,需要对http的请求体和响应体做加解密的操作,如果在controller中来调用加解密函数,会增加代码的耦合度,同时也会增加调试的难度。
砒霜拌辣椒
2023/08/23
1.2K1
如何在过滤器中修改http请求体和响应体
我的开发日记(五)
今天主要学习使用了比较常用的功能:1:更新数据时从其他表读取数据(这里有个问题,有个更好的办法是inner join,但是我这个更新涉及到了修改关联项apiId,不能使用这个方法)2:处理list属性批量插入
FunTester
2020/06/24
3410
物联网控制台数据同步--客户端java脚本(Spring Boot)
用户的个性化业务需求需要将产品下所有设备上报的数据传输至用户自有的服务器上进行处理,平台提供了 HTTP 转发服务,将设备上报数据实时 POST 到用户的 HTTP 服务器的能力。
loganydxie
2021/12/31
7672
推荐阅读
相关推荐
微系列:8、在Centos系统中,搭建Skywalking服务
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验