ToB企服应用市场:ToB评测及商务社交产业平台

标题: SpringBoot教程(三十二) SpringBoot集成Skywalking链路跟踪 [打印本页]

作者: 温锦文欧普厨电及净水器总代理    时间: 2024-12-8 13:41
标题: SpringBoot教程(三十二) SpringBoot集成Skywalking链路跟踪
SpringBoot教程(三十二) | SpringBoot集成Skywalking链路跟踪


一、Skywalking是什么?

SkyWalking是一个开源的、用于观测分布式系统(特别是微服务、云原生和容器化应用)的平台。
它提供了对分布式系统的追踪、监控和诊断能力。
二、Skywalking与JDK版本的对应关系

SkyWalking 8.x版本要求Java版本至少为8(即JDK 1.8),
SkyWalking 9.x版本则要求Java版本至少为11(即JDK 11)
以是选择的时间需要留意一下JDK版本。
三、Skywalking下载

Skywalking 官网下载地址 https://skywalking.apache.org/downloads/


   留意点:
7.x及以下版本 APM 包里面有包罗 Agents,但是8.x的就发现被分开了,以是8.x的及以上的 就需要 Agents 也得下载
  目前该文选择 下载 APM 8.9.1 和 Agents 8.9.0 后解压

四、Skywalking 数据存储

Skywalking 存在多种数据存储
相关文件OAP 配置文件(config/application.yml)
我只截取了关于设置存储方式的部分
  1. storage:
  2.   selector: ${SW_STORAGE:h2}
  3.   elasticsearch:
  4.     namespace: ${SW_NAMESPACE:""}
  5.     clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
  6.     protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}
  7.     connectTimeout: ${SW_STORAGE_ES_CONNECT_TIMEOUT:500}
  8.     socketTimeout: ${SW_STORAGE_ES_SOCKET_TIMEOUT:30000}
  9.     numHttpClientThread: ${SW_STORAGE_ES_NUM_HTTP_CLIENT_THREAD:0}
  10.     user: ${SW_ES_USER:""}
  11.     password: ${SW_ES_PASSWORD:""}
  12.     trustStorePath: ${SW_STORAGE_ES_SSL_JKS_PATH:""}
  13.     trustStorePass: ${SW_STORAGE_ES_SSL_JKS_PASS:""}
  14.     secretsManagementFile: ${SW_ES_SECRETS_MANAGEMENT_FILE:""} # Secrets management file in the properties format includes the username, password, which are managed by 3rd party tool.
  15.     dayStep: ${SW_STORAGE_DAY_STEP:1} # Represent the number of days in the one minute/hour/day index.
  16.     indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:1} # Shard number of new indexes
  17.     indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:1} # Replicas number of new indexes
  18.     # Super data set has been defined in the codes, such as trace segments.The following 3 config would be improve es performance when storage super size data in es.
  19.     superDatasetDayStep: ${SW_SUPERDATASET_STORAGE_DAY_STEP:-1} # Represent the number of days in the super size dataset record index, the default value is the same as dayStep when the value is less than 0
  20.     superDatasetIndexShardsFactor: ${SW_STORAGE_ES_SUPER_DATASET_INDEX_SHARDS_FACTOR:5} #  This factor provides more shards for the super data set, shards number = indexShardsNumber * superDatasetIndexShardsFactor. Also, this factor effects Zipkin and Jaeger traces.
  21.     superDatasetIndexReplicasNumber: ${SW_STORAGE_ES_SUPER_DATASET_INDEX_REPLICAS_NUMBER:0} # Represent the replicas number in the super size dataset record index, the default value is 0.
  22.     indexTemplateOrder: ${SW_STORAGE_ES_INDEX_TEMPLATE_ORDER:0} # the order of index template
  23.     bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:5000} # Execute the async bulk record data every ${SW_STORAGE_ES_BULK_ACTIONS} requests
  24.     # flush the bulk every 10 seconds whatever the number of requests
  25.     # INT(flushInterval * 2/3) would be used for index refresh period.
  26.     flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:15}
  27.     concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number of concurrent requests
  28.     resultWindowMaxSize: ${SW_STORAGE_ES_QUERY_MAX_WINDOW_SIZE:10000}
  29.     metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:5000}
  30.     segmentQueryMaxSize: ${SW_STORAGE_ES_QUERY_SEGMENT_SIZE:200}
  31.     profileTaskQueryMaxSize: ${SW_STORAGE_ES_QUERY_PROFILE_TASK_SIZE:200}
  32.     oapAnalyzer: ${SW_STORAGE_ES_OAP_ANALYZER:"{"analyzer":{"oap_analyzer":{"type":"stop"}}}"} # the oap analyzer.
  33.     oapLogAnalyzer: ${SW_STORAGE_ES_OAP_LOG_ANALYZER:"{"analyzer":{"oap_log_analyzer":{"type":"standard"}}}"} # the oap log analyzer. It could be customized by the ES analyzer configuration to support more language log formats, such as Chinese log, Japanese log and etc.
  34.     advanced: ${SW_STORAGE_ES_ADVANCED:""}
  35.   h2:
  36.     driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}
  37.     url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db;DB_CLOSE_DELAY=-1}
  38.     user: ${SW_STORAGE_H2_USER:sa}
  39.     metadataQueryMaxSize: ${SW_STORAGE_H2_QUERY_MAX_SIZE:5000}
  40.     maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}
  41.     numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}
  42.     maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:100}
  43.     asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:1}
  44.   mysql:
  45.     properties:
  46.       jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/swtest?rewriteBatchedStatements=true"}
  47.       dataSource.user: ${SW_DATA_SOURCE_USER:root}
  48.       dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root@1234}
  49.       dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}
  50.       dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}
  51.       dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}
  52.       dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}
  53.     metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}
  54.     maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}
  55.     numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}
  56.     maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}
  57.     asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}
  58.   tidb:
  59.     properties:
  60.       jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:4000/tidbswtest?rewriteBatchedStatements=true"}
  61.       dataSource.user: ${SW_DATA_SOURCE_USER:root}
  62.       dataSource.password: ${SW_DATA_SOURCE_PASSWORD:""}
  63.       dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}
  64.       dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}
  65.       dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}
  66.       dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}
  67.       dataSource.useAffectedRows: ${SW_DATA_SOURCE_USE_AFFECTED_ROWS:true}
  68.     metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}
  69.     maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}
  70.     numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}
  71.     maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}
  72.     asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}
  73.   influxdb:
  74.     # InfluxDB configuration
  75.     url: ${SW_STORAGE_INFLUXDB_URL:http://localhost:8086}
  76.     user: ${SW_STORAGE_INFLUXDB_USER:root}
  77.     password: ${SW_STORAGE_INFLUXDB_PASSWORD:}
  78.     database: ${SW_STORAGE_INFLUXDB_DATABASE:skywalking}
  79.     actions: ${SW_STORAGE_INFLUXDB_ACTIONS:1000} # the number of actions to collect
  80.     duration: ${SW_STORAGE_INFLUXDB_DURATION:1000} # the time to wait at most (milliseconds)
  81.     batchEnabled: ${SW_STORAGE_INFLUXDB_BATCH_ENABLED:true}
  82.     fetchTaskLogMaxSize: ${SW_STORAGE_INFLUXDB_FETCH_TASK_LOG_MAX_SIZE:5000} # the max number of fetch task log in a request
  83.     connectionResponseFormat: ${SW_STORAGE_INFLUXDB_CONNECTION_RESPONSE_FORMAT:MSGPACK} # the response format of connection to influxDB, cannot be anything but MSGPACK or JSON.
  84.   postgresql:
  85.     properties:
  86.       jdbcUrl: ${SW_JDBC_URL:"jdbc:postgresql://localhost:5432/skywalking"}
  87.       dataSource.user: ${SW_DATA_SOURCE_USER:postgres}
  88.       dataSource.password: ${SW_DATA_SOURCE_PASSWORD:123456}
  89.       dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}
  90.       dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}
  91.       dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}
  92.       dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}
  93.     metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}
  94.     maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}
  95.     numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}
  96.     maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}
  97.     asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}
  98.   zipkin-elasticsearch:
  99.     namespace: ${SW_NAMESPACE:""}
  100.     clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
  101.     protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}
  102.     trustStorePath: ${SW_STORAGE_ES_SSL_JKS_PATH:""}
  103.     trustStorePass: ${SW_STORAGE_ES_SSL_JKS_PASS:""}
  104.     dayStep: ${SW_STORAGE_DAY_STEP:1} # Represent the number of days in the one minute/hour/day index.
  105.     indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:1} # Shard number of new indexes
  106.     indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:1} # Replicas number of new indexes
  107.     # Super data set has been defined in the codes, such as trace segments.The following 3 config would be improve es performance when storage super size data in es.
  108.     superDatasetDayStep: ${SW_SUPERDATASET_STORAGE_DAY_STEP:-1} # Represent the number of days in the super size dataset record index, the default value is the same as dayStep when the value is less than 0
  109.     superDatasetIndexShardsFactor: ${SW_STORAGE_ES_SUPER_DATASET_INDEX_SHARDS_FACTOR:5} #  This factor provides more shards for the super data set, shards number = indexShardsNumber * superDatasetIndexShardsFactor. Also, this factor effects Zipkin and Jaeger traces.
  110.     superDatasetIndexReplicasNumber: ${SW_STORAGE_ES_SUPER_DATASET_INDEX_REPLICAS_NUMBER:0} # Represent the replicas number in the super size dataset record index, the default value is 0.
  111.     user: ${SW_ES_USER:""}
  112.     password: ${SW_ES_PASSWORD:""}
  113.     secretsManagementFile: ${SW_ES_SECRETS_MANAGEMENT_FILE:""} # Secrets management file in the properties format includes the username, password, which are managed by 3rd party tool.
  114.     bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:5000} # Execute the async bulk record data every ${SW_STORAGE_ES_BULK_ACTIONS} requests
  115.     # flush the bulk every 10 seconds whatever the number of requests
  116.     # INT(flushInterval * 2/3) would be used for index refresh period.
  117.     flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:15}
  118.     concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number of concurrent requests
  119.     resultWindowMaxSize: ${SW_STORAGE_ES_QUERY_MAX_WINDOW_SIZE:10000}
  120.     metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:5000}
  121.     segmentQueryMaxSize: ${SW_STORAGE_ES_QUERY_SEGMENT_SIZE:200}
  122.     profileTaskQueryMaxSize: ${SW_STORAGE_ES_QUERY_PROFILE_TASK_SIZE:200}
  123.     oapAnalyzer: ${SW_STORAGE_ES_OAP_ANALYZER:"{"analyzer":{"oap_analyzer":{"type":"stop"}}}"} # the oap analyzer.
  124.     oapLogAnalyzer: ${SW_STORAGE_ES_OAP_LOG_ANALYZER:"{"analyzer":{"oap_log_analyzer":{"type":"standard"}}}"} # the oap log analyzer. It could be customized by the ES analyzer configuration to support more language log formats, such as Chinese log, Japanese log and etc.
  125.     advanced: ${SW_STORAGE_ES_ADVANCED:""}
  126.   iotdb:
  127.     host: ${SW_STORAGE_IOTDB_HOST:127.0.0.1}
  128.     rpcPort: ${SW_STORAGE_IOTDB_RPC_PORT:6667}
  129.     username: ${SW_STORAGE_IOTDB_USERNAME:root}
  130.     password: ${SW_STORAGE_IOTDB_PASSWORD:root}
  131.     storageGroup: ${SW_STORAGE_IOTDB_STORAGE_GROUP:root.skywalking}
  132.     sessionPoolSize: ${SW_STORAGE_IOTDB_SESSIONPOOL_SIZE:16}
  133.     fetchTaskLogMaxSize: ${SW_STORAGE_IOTDB_FETCH_TASK_LOG_MAX_SIZE:1000} # the max number of fetch task log in a request
复制代码
五、Skywalking 的启动

进入 D:apache-skywalking-apm-8.9.1apache-skywalking-apm-binin ,双击运行 startup.bat(用管理员方式启动),会开启两个下令行窗口。

启动图如下:

接着欣赏器Skywalking访问:http://localhost:8080/
这个右边有个自动刷新的按钮,肯定要启动起来
不然到时间,springboot工程启动以后,你以为没有连接乐成(F5刷新页面是没有效的)

六、部署探针

前提: Agents 8.9.0 放入 项目工程

   也不说放其他位置欠好,不过放到项目里面更好一点,后面你就能感受到便利了
  

方式一:IDEA 部署探针

修改启动类的 VM options(虚拟机选项)配置


配置的jvm参数如下:
  1. -javaagent:D:ideaObjectreactBootspringboot-fullsrcmainskywalking-agentskywalking-agent.jar
  2. -Dskywalking.agent.service_name=woqu-ndy
  3. -Dskywalking.collector.backend_service=127.0.0.1:11800
复制代码
  
  方式二:Java 下令行启动方式

  1. java -javaagent:D:ideaObjectreactBootspringboot-fullsrcmainskywalking-agentskywalking-agent.jar=-Dskywalking.agent.service_name=service-myapp,-Dskywalking.collector.backend_service=localhost:11800 -jar service-myapp.jar
复制代码
方式三:编写sh脚本启动(linux环境)

  1. #!/bin/bash  
  2. # 设置 SkyWalking Agent 的路径  
  3. AGENT_PATH="/home/yourusername/Desktop/apache-skywalking-apm-6.6.0/apache-skywalking-apm-bin/agent"  
  4. # 设置 Java 应用的 JAR 文件路径  
  5. JAR_PATH="/path/to/your/service-myapp.jar"  
  6. # 设置 SkyWalking 服务名称和 Collector 后端服务地址  
  7. SERVICE_NAME="service-myapp"  
  8. COLLECTOR_BACKEND_SERVICE="localhost:11800"  
  9. # 构造 Java Agent 参数  
  10. JAVA_AGENT="-javaagent:$AGENT_PATH/skywalking-agent.jar   
  11.             -Dskywalking.agent.service_name=$SERVICE_NAME   
  12.             -Dskywalking.collector.backend_service=$COLLECTOR_BACKEND_SERVICE"  
  13.   
  14. # 启动 Java 应用  
  15. java $JAVA_AGENT -jar $JAR_PATH
复制代码
七、Springboot 的启动

IDEA 部署探针方式启动

启动后,控制台日志输出开头出现了以下的记录,就表示连接上Skywalking了

再看 Skywalking(http://localhost:8080/) 页面那里,你就会发现有个这个图(表示连接上了)

我们再请求一下 Controller 的接口,就会发现捕获了相关接口记录
(但是目前,还是没有接口具体详细的日志入参或者出参的)


Skywalking 进行日志配置

为log日志增加 skywalking的 traceId(追踪ID)。便于排查
起首引入maven依赖
  1. <!-- SkyWalking 的日志工具包 -->
  2. <dependency>
  3.    <groupId>org.apache.skywalking</groupId>
  4.    <artifactId>apm-toolkit-logback-1.x</artifactId>
  5.    <version>9.0.0</version>
  6. </dependency>
复制代码
接着在 resources文件夹下创建 logback-spring.xml文件
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration debug="false">
  3.     <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
  4.     <property name="LOG_HOME" value="D:/logs/" ></property>
  5.     <!-- 彩色日志 -->
  6.     <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
  7.     <!--控制台日志, 控制台输出 -->
  8.     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  9.         <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  10.             <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
  11.                 <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
  12.                 <pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} [%X{tid}] %clr([%-10.10thread]){faint} %clr(%-5level) %clr(%-50.50logger{50}:%-3L){cyan} %clr(-){faint} %msg%n</pattern>
  13.             </layout>
  14.         </encoder>
  15.     </appender>
  16.     <!--文件日志, 按照每天生成日志文件 (只能是 由 Logger 或者 LoggerFactory 记录的日志消息哦)-->
  17.     <!--以下关于 日志文件的pattern 需要去掉颜色,防止出现 ANSI转义序列-->
  18.     <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  19.         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
  20.             <!--日志文件输出的文件名-->
  21.             <FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/pro.log</FileNamePattern>
  22.             <!--日志文件保留天数-->
  23.             <MaxHistory>30</MaxHistory>
  24.         </rollingPolicy>
  25.         <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  26.             <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
  27.                 <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
  28.                 <!--            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>-->
  29.                 <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%-10.10thread] %-5level %-50.50logger{50}:%-3L - %msg%n</pattern>
  30.             </layout>
  31.         </encoder>
  32.         <!--日志文件最大的大小-->
  33.         <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
  34.             <MaxFileSize>10MB</MaxFileSize>
  35.         </triggeringPolicy>
  36.     </appender>
  37.     <!--skywalking grpc 日志收集-->
  38.     <appender name="grpc" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
  39.         <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  40.             <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
  41.                 <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern>
  42.             </layout>
  43.         </encoder>
  44.     </appender>
  45.     <!-- 日志输出级别 -->
  46.     <root level="INFO">
  47.         <appender-ref ref="STDOUT" ></appender-ref>
  48.         <appender-ref ref="FILE" ></appender-ref>
  49.         <appender-ref ref="grpc"/>
  50.     </root>
  51. </configuration>
复制代码
请求接口就可以发现TID的输出
(在这里是882c67dc859046c398fbfc5725df9de0.109.17288962842340001)

然后把它放到 追踪 栏目标追踪id ,可以查到记录

然后把它放到 日志 栏目标追踪id ,可以查到记录

实现入参、返参都可检察

方式一:通过 Agent 配置实现 (有缺点)

起首,你需要确认SkyWalking的Agent配置。
SkyWalking的Agent在启动时会读取配置文件,通常是agent.config。
默认情况下,请求参数的采集是关闭的,你需要手动开启。
具体步调如下:
在你的SkyWalking Agent配置文件agent.config中,找到plugin部分,确保以下配置项设置为true:
  1. plugin.tomcat.collect_http_params=${SW_PLUGIN_TOMCAT_COLLECT_HTTP_PARAMS:true}
  2. plugin.springmvc.collect_http_params=${SW_PLUGIN_SPRINGMVC_COLLECT_HTTP_PARAMS:true}
  3. plugin.httpclient.collect_http_params=${SW_PLUGIN_HTTPCLIENT_COLLECT_HTTP_PARAMS:true}
复制代码
缺点:可是以上设置,只能开启get请求的入参采集,post无法获取到,这个方式不怎么好
方式二:通过 trace 和 Filter 实现

一、引入追踪工具包
  1. <!-- SkyWalking 追踪工具包 -->
  2. <dependency>
  3.    <groupId>org.apache.skywalking</groupId>
  4.    <artifactId>apm-toolkit-trace</artifactId>
  5.    <version>9.0.0</version>
  6. </dependency>
复制代码
二、使用 HttpFilter 和 ContentCachingRequestWrapper
   知识小贴士:为什么不消HttpServletRequest?
如果直接把HttpServletRequest中的InputStream读取后输出日志,会导致后续业务逻辑读取不到InputStream中的内容,因为流只能读取一次。
  1. package com.example.springbootfull.quartztest.Filter;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
  4. import org.springframework.stereotype.Component;
  5. import org.springframework.util.StringUtils;
  6. import org.springframework.web.util.ContentCachingRequestWrapper;
  7. import org.springframework.web.util.ContentCachingResponseWrapper;
  8. import javax.servlet.FilterChain;
  9. import javax.servlet.ServletException;
  10. import javax.servlet.http.HttpFilter;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13. import java.io.IOException;
  14. import java.nio.charset.StandardCharsets;
  15. import java.util.Enumeration;
  16. import java.util.HashSet;
  17. import java.util.Set;
  18. import java.util.stream.Collectors;
  19. @Slf4j
  20. @Component
  21. public class ApmHttpInfo extends HttpFilter {
  22.     //被忽略的头部信息  
  23.     private static final Set<String> IGNORED_HEADERS;
  24.     static {
  25.         Set<String> ignoredHeaders = new HashSet<>();
  26.         ignoredHeaders.addAll(
  27.                 java.util.Arrays.asList(
  28.                         "Content-Type",
  29.                         "User-Agent",
  30.                         "Accept",
  31.                         "Cache-Control",
  32.                         "Postman-Token",
  33.                         "Host",
  34.                         "Accept-Encoding",
  35.                         "Connection",
  36.                         "Content-Length"
  37.                 ).stream()
  38.                         .map(String::toUpperCase)
  39.                         .collect(Collectors.toList())
  40.         );
  41.         IGNORED_HEADERS = ignoredHeaders;
  42.     }
  43.     @Override
  44.     public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
  45.         ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
  46.         ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
  47.         try {
  48.             filterChain.doFilter(requestWrapper, responseWrapper);
  49.         } finally {
  50.             try {
  51.                 //构造请求信息: 比如 curl -X GET http://localhost:18080/getPerson?id=1 -H 'token: me-token' -d '{ "name": "hello" }'
  52.                 //构造请求的方法&URL&参数
  53.                 StringBuilder sb = new StringBuilder("curl")
  54.                         .append(" -X ").append(request.getMethod())
  55.                         .append(" ").append(request.getRequestURL().toString());
  56.                 if (StringUtils.hasLength(request.getQueryString())) {
  57.                     sb.append("?").append(request.getQueryString());
  58.                 }
  59.                 //构造header
  60.                 Enumeration<String> headerNames = request.getHeaderNames();
  61.                 while (headerNames.hasMoreElements()) {
  62.                     String headerName = headerNames.nextElement();
  63.                     if (!IGNORED_HEADERS.contains(headerName.toUpperCase())) {
  64.                         sb.append(" -H '").append(headerName).append(": ").append(request.getHeader(headerName)).append("'");
  65.                     }
  66.                 }
  67.                 //获取body
  68.                 String body = new String(requestWrapper.getContentAsByteArray(), StandardCharsets.UTF_8);
  69.                 if (StringUtils.hasLength(body)) {
  70.                     sb.append(" -d '").append(body).append("'");
  71.                 }
  72.                 //输出到input
  73.                 ActiveSpan.tag("input", sb.toString());
  74.                 //获取返回值body
  75.                 String responseBody = new String(responseWrapper.getContentAsByteArray(), StandardCharsets.UTF_8);
  76.                 //输出到output
  77.                 ActiveSpan.tag("output", responseBody);
  78.             } catch (Exception e) {
  79.                 log.warn("fail to build http log", e);
  80.             } finally {
  81.                 //这一行必须添加,否则就一直不返回
  82.                 responseWrapper.copyBodyToResponse();
  83.             }
  84.         }
  85.     }
  86. }
复制代码
效果如下(get请求):

效果如下(post请求):

方式三:通过 trace 和 Aop 去实现

在此就不细说了,这个也是一种方案
参考文章
【1】skywalking环境搭建(windows)
【2】windows下安装skywalking 9.2
【3】skywalking9.1联合logback配置日志收集
【4】SpringBoot集成Skywalking日志收集
【5】skywalking展示http请求和响应

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4