SpringBoot教程(三十二) SpringBoot集成Skywalking鏈路跟蹤

SpringBoot教程(三十二) | SpringBoot集成Skywalking鏈路跟蹤
  • 一、Skywalking是什么?
  • 二、Skywalking與JDK版本的對應關系
  • 三、Skywalking下載
  • 四、Skywalking 數據存儲
  • 五、Skywalking 的啟動
  • 六、部署探針
    • 前提: Agents 8.9.0 放入 項目工程
    • 方式一:IDEA 部署探針
    • 方式二:Java 命令行啟動方式
    • 方式三:編寫sh腳本啟動(linux環境)
  • 七、Springboot 的啟動
    • IDEA 部署探針方式啟動
    • Skywalking 進行日志配置
    • 實現入參、返參都可查看
      • 方式一:通過 Agent 配置實現 (有缺點)
      • 方式二:通過 trace 和 Filter 實現
      • 方式三:通過 trace 和 Aop 去實現

一、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/
在這里插入圖片描述

  • 其他的版本的 APM 地址
    https://archive.apache.org/dist/skywalking/

  • 其他的java 版本的 Agents 地址
    https://archive.apache.org/dist/skywalking/java-agent/

注意點:
7.x及以下版本 APM 包里面有包括 Agents,但是8.x的就發現被分開了,所以8.x的及以上的 就需要 Agents 也得下載

目前該文選擇 下載 APM 8.9.1 和 Agents 8.9.0 后解壓
在這里插入圖片描述

四、Skywalking 數據存儲

Skywalking 存在多種數據存儲

  1. h2(默認的存儲方式,重啟后數據會丟失)
  2. Elasticsearch (最常用的數據存儲方式)
  3. MySQL
  4. TiDB

相關文件OAP 配置文件(config/application.yml)
我只截取了關于設置存儲方式的部分

storage:selector: ${SW_STORAGE:h2}elasticsearch:namespace: ${SW_NAMESPACE:""}clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}connectTimeout: ${SW_STORAGE_ES_CONNECT_TIMEOUT:500}socketTimeout: ${SW_STORAGE_ES_SOCKET_TIMEOUT:30000}numHttpClientThread: ${SW_STORAGE_ES_NUM_HTTP_CLIENT_THREAD:0}user: ${SW_ES_USER:""}password: ${SW_ES_PASSWORD:""}trustStorePath: ${SW_STORAGE_ES_SSL_JKS_PATH:""}trustStorePass: ${SW_STORAGE_ES_SSL_JKS_PASS:""}secretsManagementFile: ${SW_ES_SECRETS_MANAGEMENT_FILE:""} # Secrets management file in the properties format includes the username, password, which are managed by 3rd party tool.dayStep: ${SW_STORAGE_DAY_STEP:1} # Represent the number of days in the one minute/hour/day index.indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:1} # Shard number of new indexesindexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:1} # Replicas number of new indexes# 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.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 0superDatasetIndexShardsFactor: ${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.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.indexTemplateOrder: ${SW_STORAGE_ES_INDEX_TEMPLATE_ORDER:0} # the order of index templatebulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:5000} # Execute the async bulk record data every ${SW_STORAGE_ES_BULK_ACTIONS} requests# flush the bulk every 10 seconds whatever the number of requests# INT(flushInterval * 2/3) would be used for index refresh period.flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:15}concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number of concurrent requestsresultWindowMaxSize: ${SW_STORAGE_ES_QUERY_MAX_WINDOW_SIZE:10000}metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:5000}segmentQueryMaxSize: ${SW_STORAGE_ES_QUERY_SEGMENT_SIZE:200}profileTaskQueryMaxSize: ${SW_STORAGE_ES_QUERY_PROFILE_TASK_SIZE:200}oapAnalyzer: ${SW_STORAGE_ES_OAP_ANALYZER:"{"analyzer":{"oap_analyzer":{"type":"stop"}}}"} # the oap analyzer.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.advanced: ${SW_STORAGE_ES_ADVANCED:""}h2:driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db;DB_CLOSE_DELAY=-1}user: ${SW_STORAGE_H2_USER:sa}metadataQueryMaxSize: ${SW_STORAGE_H2_QUERY_MAX_SIZE:5000}maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:100}asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:1}mysql:properties:jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:3306/swtest?rewriteBatchedStatements=true"}dataSource.user: ${SW_DATA_SOURCE_USER:root}dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root@1234}dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}tidb:properties:jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:4000/tidbswtest?rewriteBatchedStatements=true"}dataSource.user: ${SW_DATA_SOURCE_USER:root}dataSource.password: ${SW_DATA_SOURCE_PASSWORD:""}dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}dataSource.useAffectedRows: ${SW_DATA_SOURCE_USE_AFFECTED_ROWS:true}metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}influxdb:# InfluxDB configurationurl: ${SW_STORAGE_INFLUXDB_URL:http://localhost:8086}user: ${SW_STORAGE_INFLUXDB_USER:root}password: ${SW_STORAGE_INFLUXDB_PASSWORD:}database: ${SW_STORAGE_INFLUXDB_DATABASE:skywalking}actions: ${SW_STORAGE_INFLUXDB_ACTIONS:1000} # the number of actions to collectduration: ${SW_STORAGE_INFLUXDB_DURATION:1000} # the time to wait at most (milliseconds)batchEnabled: ${SW_STORAGE_INFLUXDB_BATCH_ENABLED:true}fetchTaskLogMaxSize: ${SW_STORAGE_INFLUXDB_FETCH_TASK_LOG_MAX_SIZE:5000} # the max number of fetch task log in a requestconnectionResponseFormat: ${SW_STORAGE_INFLUXDB_CONNECTION_RESPONSE_FORMAT:MSGPACK} # the response format of connection to influxDB, cannot be anything but MSGPACK or JSON.postgresql:properties:jdbcUrl: ${SW_JDBC_URL:"jdbc:postgresql://localhost:5432/skywalking"}dataSource.user: ${SW_DATA_SOURCE_USER:postgres}dataSource.password: ${SW_DATA_SOURCE_PASSWORD:123456}dataSource.cachePrepStmts: ${SW_DATA_SOURCE_CACHE_PREP_STMTS:true}dataSource.prepStmtCacheSize: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_SIZE:250}dataSource.prepStmtCacheSqlLimit: ${SW_DATA_SOURCE_PREP_STMT_CACHE_SQL_LIMIT:2048}dataSource.useServerPrepStmts: ${SW_DATA_SOURCE_USE_SERVER_PREP_STMTS:true}metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}zipkin-elasticsearch:namespace: ${SW_NAMESPACE:""}clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}trustStorePath: ${SW_STORAGE_ES_SSL_JKS_PATH:""}trustStorePass: ${SW_STORAGE_ES_SSL_JKS_PASS:""}dayStep: ${SW_STORAGE_DAY_STEP:1} # Represent the number of days in the one minute/hour/day index.indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:1} # Shard number of new indexesindexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:1} # Replicas number of new indexes# 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.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 0superDatasetIndexShardsFactor: ${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.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.user: ${SW_ES_USER:""}password: ${SW_ES_PASSWORD:""}secretsManagementFile: ${SW_ES_SECRETS_MANAGEMENT_FILE:""} # Secrets management file in the properties format includes the username, password, which are managed by 3rd party tool.bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:5000} # Execute the async bulk record data every ${SW_STORAGE_ES_BULK_ACTIONS} requests# flush the bulk every 10 seconds whatever the number of requests# INT(flushInterval * 2/3) would be used for index refresh period.flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:15}concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number of concurrent requestsresultWindowMaxSize: ${SW_STORAGE_ES_QUERY_MAX_WINDOW_SIZE:10000}metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:5000}segmentQueryMaxSize: ${SW_STORAGE_ES_QUERY_SEGMENT_SIZE:200}profileTaskQueryMaxSize: ${SW_STORAGE_ES_QUERY_PROFILE_TASK_SIZE:200}oapAnalyzer: ${SW_STORAGE_ES_OAP_ANALYZER:"{"analyzer":{"oap_analyzer":{"type":"stop"}}}"} # the oap analyzer.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.advanced: ${SW_STORAGE_ES_ADVANCED:""}iotdb:host: ${SW_STORAGE_IOTDB_HOST:127.0.0.1}rpcPort: ${SW_STORAGE_IOTDB_RPC_PORT:6667}username: ${SW_STORAGE_IOTDB_USERNAME:root}password: ${SW_STORAGE_IOTDB_PASSWORD:root}storageGroup: ${SW_STORAGE_IOTDB_STORAGE_GROUP:root.skywalking}sessionPoolSize: ${SW_STORAGE_IOTDB_SESSIONPOOL_SIZE:16}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(用管理員方式啟動),會開啟兩個命令行窗口。

  • (1)Skywalking-Collector:追蹤信息收集器,通過 gRPC/Http 收集客戶端的采集信息 。Http默認端口 12800,gRPC默認端口 11800。(如需要修改,可前往 apache-skywalking-apm-binconfigapplicaiton.yml 進行修改)
  • (2)Skywalking-Webapp:管理平臺頁面 默認端口 8080 (如需要修改,可前往 apache-skywalking-apm-binwebappwebapp.yml 進行修改)

啟動圖如下:
在這里插入圖片描述

接著瀏覽器Skywalking訪問:http://localhost:8080/
這個右邊有個自動刷新的按鈕,一定要啟動起來
不然到時候,springboot工程啟動以后,你以為沒有連接成功(F5刷新頁面是沒有用的)
在這里插入圖片描述

六、部署探針

前提: Agents 8.9.0 放入 項目工程

也不說放其他位置不好,不過放到項目里面更好一點,后面你就能感受到便利了

在這里插入圖片描述

方式一:IDEA 部署探針

修改啟動類的 VM options(虛擬機選項)配置
在這里插入圖片描述

在這里插入圖片描述
配置的jvm參數如下:

-javaagent:D:ideaObjectreactBootspringboot-fullsrcmainskywalking-agentskywalking-agent.jar
-Dskywalking.agent.service_name=woqu-ndy
-Dskywalking.collector.backend_service=127.0.0.1:11800
  • javaagent: 表示 skywalking‐agent.jar的本地磁盤的路徑
    (我這邊是放到項目里面了)
    -Dskywalking.agent.service_name:表示在skywalking上顯示的服務名
    -Dskywalking.collector.backend_service:表示skywalking的collector服務的IP及端口
  • 注意:-Dskywalking.collector.backend_service 可以指定遠程地址, 但是 javaagent 必須綁定你本機物理路徑的 skywalking-agent.jar

方式二:Java 命令行啟動方式

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環境)

#!/bin/bash  # 設置 SkyWalking Agent 的路徑  
AGENT_PATH="/home/yourusername/Desktop/apache-skywalking-apm-6.6.0/apache-skywalking-apm-bin/agent"  # 設置 Java 應用的 JAR 文件路徑  
JAR_PATH="/path/to/your/service-myapp.jar"  # 設置 SkyWalking 服務名稱和 Collector 后端服務地址  
SERVICE_NAME="service-myapp"  
COLLECTOR_BACKEND_SERVICE="localhost:11800"  # 構造 Java Agent 參數  
JAVA_AGENT="-javaagent:$AGENT_PATH/skywalking-agent.jar   -Dskywalking.agent.service_name=$SERVICE_NAME   -Dskywalking.collector.backend_service=$COLLECTOR_BACKEND_SERVICE"  # 啟動 Java 應用  
java $JAVA_AGENT -jar $JAR_PATH

七、Springboot 的啟動

IDEA 部署探針方式啟動

啟動后,控制臺日志輸出開頭出現了以下的記錄,就表示連接上Skywalking了
在這里插入圖片描述
再看 Skywalking(http://localhost:8080/) 頁面那邊,你就會發現有個這個圖(表示連接上了)
在這里插入圖片描述
我們再請求一下 Controller 的接口,就會發現捕獲了相關接口記錄
(但是目前,還是沒有接口具體詳細的日志入參或者出參的)
在這里插入圖片描述
在這里插入圖片描述

Skywalking 進行日志配置

為log日志增加 skywalking的 traceId(追蹤ID)。便于排查

首先引入maven依賴

 <!-- SkyWalking 的日志工具包 -->
<dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-logback-1.x</artifactId><version>9.0.0</version>
</dependency>

接著在 resources文件夾下創建 logback-spring.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false"><!--定義日志文件的存儲地址 勿在 LogBack 的配置中使用相對路徑--><property name="LOG_HOME" value="D:/logs/" ></property><!-- 彩色日志 --><conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /><!--控制臺日志, 控制臺輸出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符--><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></layout></encoder></appender><!--文件日志, 按照每天生成日志文件 (只能是 由 Logger 或者 LoggerFactory 記錄的日志消息哦)--><!--以下關于 日志文件的pattern 需要去掉顏色,防止出現 ANSI轉義序列--><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件輸出的文件名--><FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/pro.log</FileNamePattern><!--日志文件保留天數--><MaxHistory>30</MaxHistory></rollingPolicy><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符--><!--            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%-10.10thread] %-5level %-50.50logger{50}:%-3L - %msg%n</pattern></layout></encoder><!--日志文件最大的大小--><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><MaxFileSize>10MB</MaxFileSize></triggeringPolicy></appender><!--skywalking grpc 日志收集--><appender name="grpc" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender"><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout"><Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{tid}] [%thread] %-5level %logger{36} -%msg%n</Pattern></layout></encoder></appender><!-- 日志輸出級別 --><root level="INFO"><appender-ref ref="STDOUT" ></appender-ref><appender-ref ref="FILE" ></appender-ref><appender-ref ref="grpc"/></root>
</configuration>

請求接口就可以發現TID的輸出
(在這里是882c67dc859046c398fbfc5725df9de0.109.17288962842340001)
在這里插入圖片描述

然后把它放到 追蹤 欄目的追蹤id ,可以查到記錄

在這里插入圖片描述
然后把它放到 日志 欄目的追蹤id ,可以查到記錄
在這里插入圖片描述

實現入參、返參都可查看

方式一:通過 Agent 配置實現 (有缺點)

首先,你需要確認SkyWalking的Agent配置。
SkyWalking的Agent在啟動時會讀取配置文件,通常是agent.config。
默認情況下,請求參數的采集是關閉的,你需要手動開啟。
具體步驟如下:
在你的SkyWalking Agent配置文件agent.config中,找到plugin部分,確保以下配置項設置為true:

plugin.tomcat.collect_http_params=${SW_PLUGIN_TOMCAT_COLLECT_HTTP_PARAMS:true}
plugin.springmvc.collect_http_params=${SW_PLUGIN_SPRINGMVC_COLLECT_HTTP_PARAMS:true}
plugin.httpclient.collect_http_params=${SW_PLUGIN_HTTPCLIENT_COLLECT_HTTP_PARAMS:true}

缺點:可是以上設置,只能開啟get請求的入參采集,post無法獲取到,這個方式不怎么好

方式二:通過 trace 和 Filter 實現

一、引入追蹤工具包

<!-- SkyWalking 追蹤工具包 -->
<dependency><groupId>org.apache.skywalking</groupId><artifactId>apm-toolkit-trace</artifactId><version>9.0.0</version>
</dependency>

二、使用 HttpFilter 和 ContentCachingRequestWrapper

知識小貼士:為什么不用HttpServletRequest?
如果直接把HttpServletRequest中的InputStream讀取后輸出日志,會導致后續業務邏輯讀取不到InputStream中的內容,因為流只能讀取一次。

package com.example.springbootfull.quartztest.Filter;import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;@Slf4j
@Component
public class ApmHttpInfo extends HttpFilter {//被忽略的頭部信息  private static final Set<String> IGNORED_HEADERS;static {Set<String> ignoredHeaders = new HashSet<>();ignoredHeaders.addAll(java.util.Arrays.asList("Content-Type","User-Agent","Accept","Cache-Control","Postman-Token","Host","Accept-Encoding","Connection","Content-Length").stream().map(String::toUpperCase).collect(Collectors.toList()));IGNORED_HEADERS = ignoredHeaders;}@Overridepublic 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());}//構造headerEnumeration<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("'");}}//獲取bodyString body = new String(requestWrapper.getContentAsByteArray(), StandardCharsets.UTF_8);if (StringUtils.hasLength(body)) {sb.append(" -d '").append(body).append("'");}//輸出到inputActiveSpan.tag("input", sb.toString());//獲取返回值bodyString responseBody = new String(responseWrapper.getContentAsByteArray(), StandardCharsets.UTF_8);//輸出到outputActiveSpan.tag("output", responseBody);} catch (Exception e) {log.warn("fail to build http log", e);} finally {//這一行必須添加,否則就一直不返回responseWrapper.copyBodyToResponse();}}}
}

效果如下(get請求):
在這里插入圖片描述
效果如下(post請求):
在這里插入圖片描述

方式三:通過 trace 和 Aop 去實現

在此就不細說了,這個也是一種方案

參考文章
【1】skywalking環境搭建(windows)
【2】windows下安裝skywalking 9.2
【3】skywalking9.1結合logback配置日志收集
【4】SpringBoot集成Skywalking日志收集
【5】skywalking展示http請求和響應

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/62266.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/62266.shtml
英文地址,請注明出處:http://en.pswp.cn/web/62266.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

flask創建templates目錄存放html文件

首先&#xff0c;創建flask項目&#xff0c;在pycharm中File --> New Project&#xff0c;選擇Flask項目。 然后&#xff0c;在某一目錄下&#xff0c;新建名為templates的文件夾&#xff0c;這時會是一個普通的文件夾。 然后右擊templates文件夾&#xff0c;選擇Unmark as …

Java進階(注解,設計模式,對象克隆)

Java進階(注解&#xff0c;設計模式&#xff0c;對象克隆) 一. 注解 1.1 什么是注解 java中注解(Annotation)&#xff0c;又稱java標注&#xff0c;是一種特殊的注釋 可以添加在包&#xff0c;類&#xff0c;成員變量&#xff0c;方法&#xff0c;參數等內容上 注解會隨同…

部署loki,grafana 以及springcloud用法舉例

文章目錄 場景docker 部署grafanadocker-compose部署loki維護配置文件 local-config.yaml維護docker-compose.yml配置啟動 grafana 添加loki數據源springcloud用法舉例查看loki的explore,查看日志 場景 小公司缺少運維崗位&#xff0c;需要研發自己部署日志系統&#xff0c;elk…

keil報錯---connection refused due to device mismatch

解決辦法如下&#xff1a; 記得改成1 把Enable取消

第三節、電機定速轉動【51單片機-TB6600驅動器-步進電機教程】

摘要&#xff1a;本節介紹用定時器定時的方式&#xff0c;精準控制脈沖時間&#xff0c;從而控制步進電機速度 一、計算過程 1.1 電機每一步的角速度等于走這一步所花費的時間&#xff0c;走一步角度等于步距角&#xff0c;走一步的時間等于一個脈沖的時間 w s t e p t … ……

vue中pdf.js的使用,包括pdf顯示,跳轉指定頁面,高亮關鍵詞

目錄 一、下載pdf.js 二、引入到本地的項目中 三、實現預覽pdf 四、跳轉到指定頁面 五、利用pdf里面的find查找關鍵詞 六、修改頁面大小為實際大小 一、下載pdf.js https://github.com/mozilla/pdf.js 里面有很多的版本&#xff0c; 高版本的可能瀏覽器不兼容或者還要考…

OD B卷【連續字母長度】

題目 給定一個字符串&#xff0c;只包含大寫字母&#xff0c;求在包含同一字母的子串中&#xff0c;長度第k長的子串的長度&#xff0c;相同字母只取最長的那個子串。 輸入描述&#xff1a; 第一行輸入一個子串&#xff08;長【1,100】&#xff09;&#xff0c;只包含大寫字母…

python中的 Pydantic 框架介紹

Pydantic 框架介紹 Pydantic 是一個用于數據驗證和設置管理的 Python 庫。它主要通過數據模型類的定義來處理 JSON 數據、解析請求和響應數據&#xff0c;并提供自動化的驗證和轉換。Pydantic 主要用于處理 Python 類型的安全性和驗證&#xff0c;尤其在 FastAPI 等現代 Pytho…

橋接模式和組合模式的區別

橋接模式&#xff08;Bridge Pattern&#xff09;和組合模式&#xff08;Composite Pattern&#xff09;都是結構型設計模式&#xff0c;旨在解決對象結構的復雜性問題&#xff0c;但它們的應用場景和目的有所不同。以下是它們的區別&#xff1a; 1. 定義與目的 橋接模式&…

Qt 小項目 學生管理信息系統

主要是對數據庫的增刪查改的操作 登錄/注冊界面&#xff1a; 主頁面&#xff1a; 添加信息&#xff1a; 刪除信息&#xff1a; 刪除第一行&#xff08;支持多行刪除&#xff09; 需求分析&#xff1a; 用QT實現一個學生管理信息系統&#xff0c;數據庫為MySQL 要求&#xf…

14.數據容器-set集合

特點 無序的&#xff0c;元素不重復&#xff0c;自帶去重功能。 可以容納不同類型的元素數據。 # 定義一個空set my_set {} your_set set() my_set {aa, bb, bb, aa} # {aa, bb} print(my_set) 因為set集合是無序的&#xff0c;所以集合不支持下標索引訪問。所以set集合…

“量子躍遷與數據織網:深入探索K最近鄰算法在高維空間中的優化路徑、神經網絡融合技術及未來機器學習生態系統的構建“

&#x1f3bc;個人主頁&#xff1a;【Y小夜】 &#x1f60e;作者簡介&#xff1a;一位雙非學校的大二學生&#xff0c;編程愛好者&#xff0c; 專注于基礎和實戰分享&#xff0c;歡迎私信咨詢&#xff01; &#x1f386;入門專欄&#xff1a;&#x1f387;【MySQL&#xff0…

硬件選型規則

光源選型: 先用型號中帶H的&#xff0c;沒有的選標準的. 光源和光源控制器的搭配需要確保接口一致。 根據型號表中的最佳工作距離和相機的尺寸。 光源控制器選型&#xff1a; 首先選擇海康風格系列光源控制器考慮與光源的接口匹配。功率應該滿足接近光源功率。檢查是否退市…

【QNX+Android虛擬化方案】135 - QNX側如何Dump 88Q5152 MIBS報文計數

【QNX+Android虛擬化方案】135 - QNX側如何Dump 88Q5152 MIBS報文計數 一、讀取 88Q5152 MIBS 計數二、讀取 88Q5152 WDT 相關寄存器基于原生純凈代碼,自學總結 純技術分享,不會也不敢涉項目、不泄密、不傳播代碼文檔!!! 本文禁止轉載分享 !!! 匯總鏈接:《【QNX+Andro…

C#核心(15)繼承中的構造函數

前言 我們之前學過構造函數是什么東西&#xff0c;今天的內容也和構造函數緊密相關&#xff0c;一個繼承了父親的子類里面構造函數的規則是什么樣的&#xff0c;今天內容很簡單&#xff0c;請聽我慢慢講來。 基本概念 特點&#xff1a;當申明一個子類時&#xff0c;先執行父…

TVbox源貢獻指南

歡迎各路大佬踴躍提PR&#xff0c;分享爬蟲代碼。 源碼倉庫地址 https://github.com/lushunming/AndroidCatVodSpider 快速開始 本工程是一個完整的AndroidStudio工程&#xff0c;請你用AS打開編輯。 工程調試完畢后要需要導出生成jar文件配合軟件使用&#xff0c;執行根目…

FastAPI快速入門

文章目錄 了解FastAPI程序結構第一步&#xff0c;導入FastAPI第二步&#xff0c;創建一個app實例第三步&#xff0c;編寫一個 路徑操作裝飾器第五步、運行開發服務器uvicorn main:app --reload即可訪問api鏈接。符案例 聲明路徑參數聲明路徑參數的類型get請求查詢參數請求體如何…

云計算.運維.面試題

1、計算機能直接識別的語言( C )。 A、匯編語言 B、自然語言 C、機器語言 D、高級語言 2、應用軟件是指( D )。 A、所有能夠使用的軟件 B、能被各應用單位共同使用的某種軟件 C、所有計算機上都應使用的基本軟件D、專門為某一應用目的而編制的軟件 3、計算機的顯示器是一…

如何優雅地實現單例模式?內部靜態類還是雙重檢查鎖定?

在最近的一個項目中&#xff0c;我需要為一個核心配置類實現單例模式。在設計過程中&#xff0c;我發現要同時滿足延遲加載和線程安全這兩個要求&#xff0c;常見的實現方式有兩種&#xff1a;內部靜態類和雙重檢查鎖定&#xff08;Double-Checked Locking, DCL&#xff09;。 …

【計算機網絡】 —— 數據鏈路層(壹)

文章目錄 前言 一、概述 1. 基本概念 2. 數據鏈路層的三個主要問題 二、封裝成幀 1. 概念 2. 幀頭、幀尾的作用 3. 透明傳輸 4. 提高效率 三、差錯檢測 1. 概念 2. 奇偶校驗 3. 循環冗余校驗CRC 1. 步驟 2. 生成多項式 3. 例題 4. 總結 四、可靠傳輸 1. 基本…