skywalking手动上报一些指标信息

文章提供了手动上报异常信息和SQL信息到Skywalking的示例,包括在全局异常处理器中利用切面拦截异常并上报,以及通过Mybatis拦截器补全SQL信息进行上报,便于链路追踪和问题排查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

skywalking的相关概念我就不介绍了,有兴趣可以参看官网文档
以下提供以下简单示例手工上报一些对问题排查比较有用的一些信息。当然这些内容你也可以写成探针插件的形式,怎么开发探针插件也自行参考官方文档。此处仅在项目框架层面提供一些简单的示例,助于你快速入门。

手动上报异常信息

一般我们在项目中都会做全局异常拦截处理,最早我的方案是在gateway统一拦截封装,这样skywalking的agent组件就会不会到对应的异常信息进行上报到skywalkingserver端。但是接手了个没有gateway的微服务项目,统一由nginx进行转发,此时我们如果不将异常收敛在当前服务处理,异常信息势必会被抛到前端页面,显然是很不友好的行为。所以此时我们就得在当前服务内处理skywalking的异常信息上报。
正常我们的全局异常拦截处理类如下

@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
@Slf4j
public class GlobalExceptionHandler implements ExcetionHandler {
    
    @ExceptionHandler(value = Exception.class)
    public JsonResult unhandledException(HttpServletResponse resp, Exception e){
        log.error("未处理异常:", e);
        JsonResult result = new JsonResult();
        result.setMessage(ErrorCode.UNCATCH_EXCEPTION.getMsg());
        result.setCode(ErrorCode.UNCATCH_EXCEPTION.getCode());
        return result;
    }
    
}

此时由于异常被收敛在这个类统一处理,所以我们可以写个切面横切这个类的所有方法,拿到异常信息手动上报给skywalking组件,当然也可以写出插件的形式。不用在框架代码中手动上报。

切面代码如下:

@Aspect
public class ExceptionHandlerAspect {
    
    @Around(value = "@annotation(org.springframework.web.bind.annotation.ExceptionHandler)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof Throwable) {
                ActiveSpan.error((Throwable)arg);
            }
        }
        return joinPoint.proceed();
    }
}

是不是很简单。此处我们处理拦截异常之外,我们还可以对sql进行拦截,并将sql信息补全之后也统一上报给skywalking。这样出现业务问题时假如没有异常而是数据等问题,我们很容易可以通过链路追踪到对应的sql信息,除了sql我们还可以跟踪mq信息缓存信息等等都是一样的道理

手动上报sql信息

sql上报,sql上报我们可以写个sql拦截器,拦截statmentHander阶段或者拦截ParameterHandler阶段这两个阶段都是可以进行sql补全的。

ParameterHandler代码如下

@Intercepts({
        @Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class})
}
)
public class MybatisLogInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        PreparedStatement statement = (PreparedStatement) invocation.getArgs()[0];
        PreparedStatement sql = null;
        Object proceed = invocation.proceed();
        if (Proxy.isProxyClass(statement.getClass())) {
            InvocationHandler handler = Proxy.getInvocationHandler(statement);
            if (handler.getClass().getName().endsWith(".PreparedStatementLogger")) {
                Field field = handler.getClass().getDeclaredField("statement");
                field.setAccessible(true);
                sql = (PreparedStatement) field.get(handler);
            }
        }

        ActiveSpan.tag(SpanConstant.ORM_TYPE, "mybatis");
        ActiveSpan.tag(SpanConstant.SQL_STATEMENT, sql);

        return proceed;
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}

StatmentHander代码如下

@Intercepts(
    @Signature(
        type = StatementHandler.class,
        method = "parameterize",
        args = Statement.class
    )
)
public class MybatisTraceInterceptor implements Interceptor {
    private final static Logger log= LoggerFactory.getLogger(MybatisTraceInterceptor.class);
    
    public static <T> T realTarget(Object target) {
        if (Proxy.isProxyClass(target.getClass())) {
            MetaObject metaObject = SystemMetaObject.forObject(target);
            return realTarget(metaObject.getValue("h"));
        }
        return (T) target;
    }
    
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object proceed = null;
        String sql=null;
        Statement statement = (Statement) invocation.getArgs()[0];
        proceed = invocation.proceed();
        try {
            PreparedStatementLogger psl = realTarget(statement);
            PreparedStatement ps = psl.getPreparedStatement();
            String pss = ps.toString();
            sql = pss.substring(pss.indexOf(":") + 1);
            ActiveSpan.tag(SpanConstant.ORM_TYPE, "mybatis");
            ActiveSpan.tag(SpanConstant.SQL_STATEMENT, sql);
        }catch (Exception e){
            log.error("sql上报skyWalking异常",e.getMessage());
        }
        return proceed;
    }
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    
    @Override
    public void setProperties(Properties properties) {
    }
}

手动上报出入参信息

这里同样有两种方案,一个使用切面的方式进行处理,一个使用Filter或者拦截器的方式进行处理,但是后两个阶段存在一个问题就是流的读取问题,所以如果选择后两者进行操作,还需要进行流的缓存封装,是比较不可取的方案。代码都差不多,这个我就不贴了。

注意:
过滤器和拦截器一般我们用来处理头部信息会比较好点。

<think>首先,用户的问题是关于部署SkyWalking Agent的指导。用户说:“我想在环境中部署SkyWalking Agent的指导 请问如何部署SkyWalking Agent”。所以,我需要基于系统指令和提供的引用内容来回答。 系统指令关键点: - 所有行内数学表达式用$...$格式。 - 独立公式用$$...$$单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 参考站内引用:引用[1]到[4]。 提供的引用内容: - [^1]:手动挂载SkyWalking Agent的方式。 - [^2]:启动命令中添加参数javaagent。 - [^3]:Docker部署,包括配置agent.config。 - [^4]:k8s部署,使用daemonset,挂载hostPath。 用户的问题是关于部署SkyWalking Agent的指导,所以我需要覆盖各种部署方式。引用中提到Docker、k8s和一般方式。 结构化回答: 1. **介绍**:简要解释SkyWalking Agent是什么。 2. **部署方式**:基于引用,分步解释不同方式。 - 方式一:手动挂载(引用[^1])。 - 方式二:启动命令添加参数(引用[^2])。 - Docker部署(引用[^3])。 - k8s部署(引用[^4])。 3. **步骤细节**:为每种方式提供清晰的步骤。 4. **生成相关问题**:在回答末尾添加相关问题。 5. **引用标识**:在相关部分末尾添加引用。 确保使用中文回答。 生成相关问题: - 基于主题,如优化、性能分析、应用场景等。 - 例如: 1. SkyWalking Agent的配置选项有哪些? 2. 如何监控部署后的SkyWalking Agent? 3. SkyWalking与其他APM工具的比较? 数学表达式:用户问题中没有数学内容,但系统指令说所有行内数学表达式用$...$。如果回答中涉及数学,就用它。但部署SkyWalking Agent可能不涉及数学,所以可能不需要。如果有,如涉及公式,就用LaTeX格式。 回答结构: - 开头:确认问题并概述。 - 主体:分步骤解释部署方式。 - 结尾:总结并添加相关问题。 参考引用: - 在解释每个方式时,引用相关部分。 - 如:在手动挂载部分,添加[^1]。 最终输出格式: - 使用清晰标题。 - 代码块用```...```。 - 相关问题用§§相关问题§§部分。</think>### SkyWalking Agent 部署指南 SkyWalking Agent 是一个轻量级的应用性能监控(APM)代理,用于收集 Java 应用的链路追踪和指标数据。部署时,需要将 Agent 集成到目标应用中,并通过配置连接到 SkyWalking OAP 服务器。以下是基于常见环境的逐步部署方法,确保过程可靠且易于操作。部署前,请确保已安装 SkyWalking OAP 和 UI 组件(如未安装,可参考官方文档)。 #### 方式一:手动挂载 SkyWalking Agent(适用于 Docker 或本地环境) 此方法通过挂载 Agent 文件到应用容器中实现集成,适合 Docker 化应用。 1. **下载并解压 SkyWalking Agent**: 从 [Apache SkyWalking 官网](https://skywalking.apache.org/) 下载最新 Agent 包,解压到本地目录,如 `/usr/local/skywalking-agent`。 2. **修改 Agent 配置**: 编辑 `agent/config/agent.config` 文件,设置 OAP 服务器地址和端口: ```bash cd agent/config vi agent.config # 修改以下配置项: # agent.service_name=your_service_name # 设置服务名称 # collector.backend_service=oap-server-ip:11800 # 替换为实际 OAP IP 和端口 ``` 如果不配置,需在启动命令中指定参数[^3]。 3. **挂载到 Docker 容器**: 在 Docker 运行命令中添加挂载卷,将 Agent 目录绑定到容器内: ```bash docker run -d \ -v /usr/local/skywalking-agent:/skywalking/agent \ # 挂载 Agent 目录 -e JAVA_OPTS="-javaagent:/skywalking/agent/skywalking-agent.jar" \ # 设置 JVM 参数 your_application_image ``` 此方式避免重复打包 Agent,减少镜像大小[^1]。 #### 方式二:启动命令添加参数(适用于本地或非容器化应用) 直接在应用启动命令中嵌入 Agent 参数,简单快捷。 1. **下载 Agent**: 获取 Agent JAR 包(如 `skywalking-agent.jar`),存放于应用服务器路径,如 `/opt/skywalking-agent/`。 2. **修改启动脚本**: 在 Java 应用的启动命令中添加 `-javaagent` 参数: ```bash java -javaagent:/opt/skywalking-agent/skywalking-agent.jar \ -Dskywalking.agent.service_name=your_service_name \ # 设置服务名 -Dskywalking.collector.backend_service=oap-server-ip:11800 \ # 指定 OAP 地址 -jar your_application.jar ``` 参数 `-Dskywalking.agent.service_name` 可覆盖配置文件中的设置[^2]。 3. **验证部署**: 启动应用后,访问 SkyWalking UI(默认端口 8080),检查是否收集到调用信息。若无数据,检查网络连接和 OAP 状态[^2]。 #### 方式三:Docker 集成部署(优化容器化方案) 针对 Docker 环境,结合挂载和参数配置,提高灵活性。 1. **准备 Agent 配置文件**: 在主机上创建 Agent 目录并配置 `agent.config`(同方式一)。 2. **运行容器**: 使用 `docker run` 命令同时挂载目录和设置环境变量: ```bash docker run -d \ -v /path/to/skywalking-agent:/agent \ # 挂载配置目录 -e SW_AGENT_NAME=your_service_name \ # 环境变量设置服务名 -e SW_AGENT_COLLECTOR_BACKEND_SERVICES=oap-server-ip:11800 \ # 设置 OAP your_application_image ``` 环境变量优先级高于配置文件,便于动态调整[^3]。 #### 方式四:Kubernetes 部署(使用 DaemonSet) 在 k8s 集群中,通过 DaemonSet 将 Agent 挂载到所有节点,避免每个 Pod 重复包含 Agent。 1. **创建 DaemonSet**: 定义 DaemonSet YAML 文件,使用 `hostPath` 挂载 Agent 目录到节点: ```yaml apiVersion: apps/v1 kind: DaemonSet metadata: name: skywalking-agent spec: selector: matchLabels: app: skywalking-agent template: metadata: labels: app: skywalking-agent spec: containers: - name: agent image: busybox # 使用轻量镜像作为占位 volumeMounts: - name: sky-agent mountPath: /agent volumes: - name: sky-agent hostPath: path: /usr/local/skywalking-agent # 主机上的 Agent 路径 type: Directory ``` 应用此配置:`kubectl apply -f daemonset.yaml`。 2. **在应用 Pod 中使用挂载**: 在 Java 应用的 Deployment 中,添加 volume 和启动参数: ```yaml spec: containers: - name: app image: your_app_image volumeMounts: - name: sky-agent mountPath: /agent # 挂载到容器内 env: - name: JAVA_OPTS value: "-javaagent:/agent/skywalking-agent.jar -Dskywalking.agent.service_name=your_service" ``` 此方法减少容器大小,简化管理[^4]。 3. **验证与监控**: 部署后,检查 SkyWalking UI 的拓扑图和服务指标。常见问题排查: - 确保 OAP 服务可达(测试:`telnet oap-server-ip 11800`)。 - 检查 Agent 日志(路径:`agent/logs/skywalking-api.log`)。 #### 总结与注意事项 - **通用步骤**:所有方式需确保 OAP 服务器运行正常(默认端口 11800)。部署后,Agent 会自动上报数据到 OAP。 - **最佳实践**: - 测试环境优先验证配置。 - 使用环境变量(如 `SW_AGENT_NAME`)动态覆盖配置,增强可移植性。 - 监控 Agent 资源消耗(CPU 和内存),避免影响应用性能[^2][^4]。 - **故障处理**: 若数据未上报,检查 Agent 日志或使用 SkyWalking CLI 工具诊断连接问题。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值