This is an automated email from the ASF dual-hosted git repository.
psxjoy pushed a commit to branch intelligence-front-end
in repository https://gitbox.apache.org/repos/asf/ozhera.git
The following commit(s) were added to refs/heads/intelligence-front-end by this
push:
new 5f31d053 feat: add trace analysis service (#590)
5f31d053 is described below
commit 5f31d05374be6dbe29793c132154fb1b557627a9
Author: EricDing <[email protected]>
AuthorDate: Fri Jun 20 15:23:13 2025 +0800
feat: add trace analysis service (#590)
* feat: add trace analysis service
* fix: delete author
---
.../client/bootstrap/HeraDemoClientBootstrap.java | 3 -
ozhera-intelligence/README.md | 29 +-
ozhera-intelligence/README_cn.md | 15 +-
.../rootanalysis/HeraRootCaseAnalyseRes.java | 4 -
.../domain/rootanalysis/LogPromptResult.java | 6 +
.../domain/rootanalysis/MetricsPromptResult.java | 4 +
.../domain/rootanalysis/TracePromptResult.java | 13 +
.../domain/rootanalysis/TraceQueryParam.java | 2 +-
.../domain/rootanalysis/constant/Prompts.java | 175 ++++++++++++
.../rootanalysis/constant}/RootAnalysisConst.java | 2 +-
.../src/main/resources/application.properties | 5 +-
.../resources/config/opensource-outer.properties | 4 +-
.../intelligence/agents/config/AgentConfig.java | 20 +-
.../agents/function/TraceAnalysisFunction.java | 31 ++-
.../ozhera/intelligence/service/LogService.java | 4 -
.../intelligence/service/MetricsService.java | 4 -
.../ozhera/intelligence/service/PromptService.java | 160 +++++++++--
.../intelligence/service/TraceAnalysisService.java | 250 ++++++++++++++++-
.../ozhera/intelligence/service/TraceService.java | 24 +-
.../ozhera/intelligence/util/HttpClient.java | 4 -
.../intelligence/service/PromptServiceTest.java | 295 +++++++++++++++++++++
..._intelligence_config_#_DEFAULT_GROUP.properties | 2 +
.../agent/bootstrap/PrometheusAgentBootstrap.java | 3 -
.../java/org/apache/ozhera/webhook/Bootstrap.java | 3 -
.../webhook/controller/HeraWebhookController.java | 4 -
.../trace/etl/api/service/TraceQueryService.java | 4 -
.../etl/es/bootstrap/TraceEtlEsBootstrap.java | 3 -
.../trace/etl/es/consumer/ConsumerService.java | 5 -
.../bootstrap/TraceEtlManagerBootstrap.java | 3 -
.../etl/manager/dubbo/TraceQueryServiceImpl.java | 4 -
.../bootstrap/TraceEtlMetadataBootstrap.java | 3 -
.../nginx/bootstrap/TraceEtlNginxBootstrap.java | 3 -
.../trace/etl/bootstrap/TraceEtlBootstrap.java | 3 -
.../etl/consumer/RocketMQConsumerService.java | 5 -
34 files changed, 989 insertions(+), 110 deletions(-)
diff --git
a/ozhera-demo-client/ozhera-demo-client-server/src/main/java/org/apache/ozhera/demo/client/bootstrap/HeraDemoClientBootstrap.java
b/ozhera-demo-client/ozhera-demo-client-server/src/main/java/org/apache/ozhera/demo/client/bootstrap/HeraDemoClientBootstrap.java
index 76e4204c..29490a9f 100644
---
a/ozhera-demo-client/ozhera-demo-client-server/src/main/java/org/apache/ozhera/demo/client/bootstrap/HeraDemoClientBootstrap.java
+++
b/ozhera-demo-client/ozhera-demo-client-server/src/main/java/org/apache/ozhera/demo/client/bootstrap/HeraDemoClientBootstrap.java
@@ -26,9 +26,6 @@ import
org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
-/**
- * @author dingtao
- */
@EnableAutoConfiguration(exclude= {DataSourceAutoConfiguration.class})
@ComponentScan(basePackages = {"org.apache.ozhera.demo.client"})
@DubboComponentScan(basePackages = "org.apache.ozhera.demo.client")
diff --git a/ozhera-intelligence/README.md b/ozhera-intelligence/README.md
index 6df452c4..e3bc9e9b 100644
--- a/ozhera-intelligence/README.md
+++ b/ozhera-intelligence/README.md
@@ -42,4 +42,31 @@
It relies on a Xiaomi open-source [Agent builder
platform--m78](https://github.com/XiaoMi/mone/tree/master/m78-all)
# Intelligent Workflow (Sequence Diagram)
-
\ No newline at end of file
+
+
+# LLM Environment Variables
+Currently, the LLM class is used for invoking large language models (LLMs).
The required environment variables (env vars) are defined in the LLMProvider
class.
+
+## Prerequisite:
+A base LLM_PROVIDER env var must be set to specify the desired LLMProvider.
+
+## Example:
+To use **DeepSeek**, follow these steps:
+
+Set LLM_PROVIDER=DEEPSEEK.
+
+Refer to the LLMProvider class for DeepSeek's specific requirements. In this
case, DEEPSEEK_API_KEY is mandatory.
+Configure the API key:
+
+DEEPSEEK_API_KEY=xxx-xxxxx
+
+## Recommended Models
+Given that this use case involves **large-scale data analysis** with
significant logical reasoning and analytical processing, it is advisable to
leverage high-performance inference-optimized models or models with strong
code-generation capabilities available on the market.
+
+## Suggested Criteria:
+
+- High accuracy in complex reasoning tasks.
+- Robust contextual understanding for analytical workflows.
+- Efficient handling of long-context prompts (if applicable).
+
+Examples include models fine-tuned for reasoning-intensive workloads or those
excelling in programmatic problem-solving.
\ No newline at end of file
diff --git a/ozhera-intelligence/README_cn.md b/ozhera-intelligence/README_cn.md
index d2a448c2..8e167bab 100644
--- a/ozhera-intelligence/README_cn.md
+++ b/ozhera-intelligence/README_cn.md
@@ -42,4 +42,17 @@
# 智能化工作流程(时序图)
-
\ No newline at end of file
+
+
+# 启动依赖
+## LLM环境变量
+目前使用LLM类进行大模型调用,它所需要的env都在LLMProvider类中,首先需要一个基础的LLM_PROVIDER的env,来指定使用的LLMProvider。
+
+**示例**:
+比如想要使用DEEPSEEK
+
+首先需要设置LLM_PROVIDER=DEEPSEEK
+然后再根据LLMProvider类中的DEEPSEEK,看他需要哪些环境变量。这里DEEPSEEK需要使用DEEPSEEK_API_KEY,所以我们还需要设置DEEPSEEK_API_KEY=xxx-xxxxx
+
+## 推荐使用的模型
+由于这里可能会分析大量数据,而且具有大量的逻辑推理、分析,使用市面上比较好的推理模型或者代码能力较强的模型会比较好
\ No newline at end of file
diff --git
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/HeraRootCaseAnalyseRes.java
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/HeraRootCaseAnalyseRes.java
index bca831c3..f02da0c5 100644
---
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/HeraRootCaseAnalyseRes.java
+++
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/HeraRootCaseAnalyseRes.java
@@ -21,10 +21,6 @@ package org.apache.ozhera.intelligence.domain.rootanalysis;
import lombok.Data;
import lombok.ToString;
-/**
- * @author dingtao
- * @date 2025/1/20 11:26
- */
@Data
@ToString
public class HeraRootCaseAnalyseRes {
diff --git
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/LogPromptResult.java
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/LogPromptResult.java
index 2df12701..e22794d8 100644
---
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/LogPromptResult.java
+++
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/LogPromptResult.java
@@ -18,11 +18,17 @@
*/
package org.apache.ozhera.intelligence.domain.rootanalysis;
+import lombok.Builder;
import lombok.Data;
@Data
+@Builder
public class LogPromptResult {
+
private boolean root;
private String logReason;
+
+ public static final String ROOT = "root";
+ public static final String LOG_REASON = "logReason";
}
diff --git
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricsPromptResult.java
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricsPromptResult.java
index 7c6a65df..4d2dd581 100644
---
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricsPromptResult.java
+++
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricsPromptResult.java
@@ -18,13 +18,17 @@
*/
package org.apache.ozhera.intelligence.domain.rootanalysis;
+import lombok.Builder;
import lombok.Data;
@Data
+@Builder
public class MetricsPromptResult {
private boolean root;
private String metricsReason;
+ public static final String ROOT = "root";
+ public static final String METRICS_REASON = "metricsReason";
}
diff --git
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TracePromptResult.java
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TracePromptResult.java
index 664c0d76..1c3f3b58 100644
---
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TracePromptResult.java
+++
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TracePromptResult.java
@@ -18,10 +18,13 @@
*/
package org.apache.ozhera.intelligence.domain.rootanalysis;
+import lombok.Builder;
import lombok.Data;
@Data
+@Builder
public class TracePromptResult {
+
// Detailed description of the exception reason, using professional
Chinese terminology
private String traceReason;
@@ -49,4 +52,14 @@ public class TracePromptResult {
// Value of process.ip for the node where the spanId is located
private String ip;
+
+ public static final String TRACE_REASON_KEY = "traceReason";
+ public static final String APPLICATION = "application";
+ public static final String ROOT = "root";
+ public static final String PROJECT_ID = "projectId";
+ public static final String ENV_ID = "envId";
+ public static final String START_TIME = "startTime";
+ public static final String DURATION = "duration";
+ public static final String SPAN_ID = "spanId";
+ public static final String IP = "ip";
}
diff --git
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TraceQueryParam.java
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TraceQueryParam.java
index b9de7208..d9b8c196 100644
---
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TraceQueryParam.java
+++
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TraceQueryParam.java
@@ -30,5 +30,5 @@ import java.util.List;
public class TraceQueryParam {
private String traceId;
private String env;
- private long timeStamp;
+ private Long timeStamp;
}
diff --git
a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/constant/Prompts.java
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/constant/Prompts.java
new file mode 100644
index 00000000..30860208
--- /dev/null
+++
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/constant/Prompts.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.intelligence.domain.rootanalysis.constant;
+
+public class Prompts {
+ public static final String TRACE_ANALYSIS_PROMPT = """
+
作为一位经验丰富的Java开发工程师,你负责分析请求链路中各个节点的Span信息,并确定导致异常或慢查询的根本原因。我们会提供一个包含请求链路全部节点的数据集。你的任务是:
+
+ 1. 确认服务之间的调用关系和依赖,从而确定每个节点在链路中的依赖层级。可以通过节点中的 references.spanID
来确认当前节点的父节点。
+ 2. 识别存在的异常,并判断其是否为最底层节点。
+ 3. 如果没有异常节点,则判断当前链路总耗时是否大于一秒。若大于一秒,分析当前链路中层级最深、耗时最长的节点,该节点一般为根因节点。
+ 4. 分析这些节点信息,查找导致异常或慢查询的根本原因,判断异常或超时是否发生在服务接口调用、数据库操作等环节。
+ 5. 如果 span.kind 是 client 节点,并且报服务调用超时异常,请判断其调用的 server 节点的耗时,若
server 节点耗时过高,则根本原因是 server 节点而非 client 节点。
+ 6. 如果最底层原因是 "biz result code exception",认为该情况需要通过日志进行进一步分析,并返回
"root": false。
+ 7. 如果无法通过 Span 信息直接识别根本原因,且需要查看日志或其他指标数据,则返回疑似问题节点的信息,并同样设置
"root": false。
+ 8. 如果只有一个 Span,那么这个 Span 是根本原因,若不存在异常,则判断其是否耗时大于一秒,若耗时大于一秒,则该 Span
是链路慢查询的根本原因。
+
+ 请使用以下 XML 格式返回分析结果,包括问题描述、发生问题的应用、是否为根本原因、项目ID、环境ID、异常开始和结束时间等信息:
+ ```xml
+ <result>
+ <traceReason>异常原因的详细描述,使用专业术语</traceReason>
+ <application>引发异常的应用名称,从问题节点的 process.serviceName
获取</application>
+ <root>true|false, 是否为根本原因,根据分析设定</root>
+ <projectId>应用的项目ID,从问题节点的 process.serviceName 按 '-'
分割后取第一部分</projectId>
+ <envId>应用的环境ID,从问题节点的 process.tags 中 key 为 service.env.id
的值获取</envId>
+ <startTime>异常开始时间,从问题节点的 startTime,取整数值</startTime>
+ <duration>异常结束时间,从问题节点的 duration,取整数值</duration>
+ <spanId>根因节点的 spanId</spanId>
+ <ip>根因节点的 process.ip 的值</ip>
+ </result>
+ ```
+
+ 请确保结果为有效的 XML 数据。如果传入的 data 数据为空,则返回以下固定的内容:
+ ```xml
+ <result>
+ <traceReason>trace数据为空,请确认</traceReason>
+ <root>true</root>
+ </result>
+ ```
+
+ ## 返回结果示例:
+ ### 当返回结果需要查看日志时,返回root为false
+ ```xml
+ <result>
+
<traceReason>在调用com.demo.service.order.MemberService/getRefundInfo接口时发生业务异常,返回错误码500。该异常发生在服务端,可能是由于系统内部错误或业务逻辑异常导致的。建议查看服务端日志以获取更详细的错误信息。</traceReason>
+ <application>123-demo-service</application>
+ <root>false</root>
+ <projectId>123</projectId>
+ <envId>456</envId>
+ <startTime>1735884072289000</startTime>
+ <duration>35149</duration>
+ <spanId>a291ab32156dca70</spanId>
+ <ip>10.112.113.114</ip>
+ </result>
+ ```
+
+ 以下是提供的数据集:
+ """;
+
+ public static final String LOG_ANALYSIS_PROMPT = """
+ 你是一名拥有众多工作经验的Java开发工程师专家,在对Web服务的请求响应日志分析方面非常精通。请仔细分析我提供的Java
Web服务请求日志信息,该信息以数组的形式给出。你的任务是找出日志中展示的问题的根原因。你需要给出一段详细的描述,详细描述要使用中文,并包含专业术语,来解释异常的根本原因。
+
+
在你的分析完成后,需要返回一个XML格式的数据结构,其中包含两个关键字段:'logReason'和'root'。'Logreason'字段应包含你的问题分析,而'root'字段应代表本次分析是否触及到了根本原因。如果你确定从日志信息中发现了问题的根本原因,请设定'root'字段为true。如果你需要其他监控指标数据(metrics)来进行更深入的分析,当前日志信息不足以确立根本原因时,请将'root'字段设置为false,并在'logReason'字段中说明为什么需要更多数据。如果传入的日志信息为空,则设定'root'字段为false,设定'logReason'为'由于日志信息为空,无法根据日志判断根因'。
+
+ 请根据以下格式返回XML响应:
+
+ <result>
+ <logReason>这里填写问题分析</logReason>
+ <root>true|false, 根据是否为根本原因来设定</root>
+ </result>
+
+ 请根据提供的日志信息数组按上述要求给出你的分析和XML格式的响应。
+
+ """;
+
+ public static final String METRICS_ANALYSIS_PROMPT = """
+ 作为一名Java开发工程师专家,你拥有对Java
Web服务实例指标进行分析的能力。你现在需要对提供的监控指标数据进行仔细分析,以找出服务中存在的异常或慢查询的根本原因。监控指标数据格式如下:
+
+ {
+ "maxCpuUsage": "<最大CPU使用率,数值类型>",
+ "maxLoad": "<最大系统负载,数值类型>",
+ "maxJvmHeapUsage": "<最大JVM堆内存使用率,数值类型>",
+ "maxSTWCost": "<最大Stop-The-World(STW)暂停耗时,毫秒单位,数值类型>",
+ "STWCountOf1m": "<一分钟内最大STW次数,数值类型>",
+ "cpuCount": "<容器CPU数量,数值类型>"
+ }
+
+ 请针对以下各指标进行分析:
+
+ 当maxCpuUsage超过(100 * cpuCount) * 0.8时,确定是否存在CPU使用率异常。
+ 当maxLoad超过cpuCount,且尤其当超过cpuCount * 2时,确定系统负载是否过高。
+ 当maxJvmHeapUsage超过80时,判断JVM堆内存是否过度使用。
+ 当maxSTWCost超过200ms时,判断是否有长时间的GC暂停问题。
+ 当STWCountOf1m超过10时,判断STW次数是否异常。
+
+ 分析的结果应以XML格式返回,其中包含以下字段:
+
+ metricsReason:包含问题分析的描述,使用中文和专业术语说明。如果分析结果不足以确定根本原因,则说明原因并填写空字符串。
+
root:一个布尔值,标明是否确定根本原因。仅当你根据日志信息确定了问题的根本原因时,设定为true;如果分析结果不足以确立根本原因,设定为false并在metricsReason中说明需要更多数据的理由。
+
+ XML响应格式应为:
+ <result>
+ <metricsReason>问题分析描述</metricsReason>
+ <root>true|false</root>
+ </result>
+
+ 你的分析应基于以下提供的监控指标数据,请按上述要求给出你的结果:
+ """;
+
+ public static final String RESULT_COLLECT_PROMPT = """
+ 基于以下提供的信息,请详细分析系统出现问题的根本原因,并以简明扼要的方式描述它。输入包含以下部分:
+ - 应用名称(application)
+ - 链路追踪分析得出的原因(traceReason)
+ - 业务日志分析得出的原因(logReason)
+ - 指标监控分析得出的原因(metricsReason)
+
+ 详细分析如下:
+ ""\"
+ application:
+ ${application}
+
+ traceReason:
+ ${traceReason}
+
+ logReason:
+ ${logReason}
+
+ metricsReason:
+ ${metricsReason}
+ ""\"
+
+ 请根据这些分析生成一个XML格式的返回结果,其中包含字段“simpleReason”,该字段总结问题的根本原因。格式如下:
+
+ <result>
+ <application>${application}</application>
+ <simpleReason>简明扼要的分析原因</simpleReason>
+ </result>
+
+ 注意:
+ 1. 如果traceReason为空,则不用进行分析,'simpleReason'字段设定为'trace数据为空'。
+ 2.
如果traceReason不为空,请综合traceReason、logReason和metricsReason给出一个简明扼要的总结。
+
+ 示例:
+
+ 输入:
+ ""\"
+ application:Shopify
+ traceReason:在TestService中发生业务逻辑异常,返回了500错误码
+ logReason:日志显示在TestService的252行发生了空指针异常
+ metricsReason:一切正常
+ ""\"
+
+ 输出:
+ <result>
+ <application>Shopify</application>
+ <simpleReason>在TestService的252行发生空指针异常,导致返回了500错误码</simpleReason>
+ </result>
+ """;
+}
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/RootAnalysisConst.java
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/constant/RootAnalysisConst.java
similarity index 93%
rename from
ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/RootAnalysisConst.java
rename to
ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/constant/RootAnalysisConst.java
index 07ebedf2..7d342798 100644
---
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/RootAnalysisConst.java
+++
b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/constant/RootAnalysisConst.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.ozhera.intelligence.service;
+package org.apache.ozhera.intelligence.domain.rootanalysis.constant;
public class RootAnalysisConst {
diff --git
a/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/application.properties
b/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/application.properties
index 56919051..8bebaee4 100644
---
a/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/application.properties
+++
b/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/application.properties
@@ -29,4 +29,7 @@ trace.query.version=${trace.query.version}
log.query.group=${log.query.group}
log.query.version=${log.query.version}
-nacos.address=${nacos.address}
\ No newline at end of file
+nacos.address=${nacos.address}
+
+# agents name
+trace.agent.name=${trace.agent.name}
\ No newline at end of file
diff --git
a/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/config/opensource-outer.properties
b/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/config/opensource-outer.properties
index 08fdc828..88360392 100644
---
a/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/config/opensource-outer.properties
+++
b/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/config/opensource-outer.properties
@@ -29,4 +29,6 @@ trace.query.version=1.0
log.query.group=
log.query.version=1.0
-nacos.address=nacos:80
\ No newline at end of file
+nacos.address=nacos:80
+
+trace.agent.name=trace-analysis
\ No newline at end of file
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/agents/config/AgentConfig.java
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/agents/config/AgentConfig.java
index 32d3cc98..a5b0cae2 100644
---
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/agents/config/AgentConfig.java
+++
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/agents/config/AgentConfig.java
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
package org.apache.ozhera.intelligence.agents.config;
import com.google.common.collect.Lists;
@@ -19,7 +37,7 @@ import run.mone.hive.roles.tool.TextToSpeechTool;
@Configuration
public class AgentConfig {
- @Value("${mcp.agent.name}")
+ @Value("${trace.agent.name}")
private String agentName;
@Autowired
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/agents/function/TraceAnalysisFunction.java
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/agents/function/TraceAnalysisFunction.java
index d988e908..450219dc 100644
---
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/agents/function/TraceAnalysisFunction.java
+++
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/agents/function/TraceAnalysisFunction.java
@@ -1,7 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
package org.apache.ozhera.intelligence.agents.function;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
+import org.apache.ozhera.intelligence.domain.rootanalysis.TraceQueryParam;
import org.apache.ozhera.intelligence.service.TraceAnalysisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -22,7 +41,7 @@ public class TraceAnalysisFunction implements McpFunction {
private String name = "stream_hera_analysis";
- private String desc = "根据traceId分析trace链路上异常或者慢查询出现的根本原因";
+ private String desc = "Analyze the root cause of exceptions or slow
queries in the trace chain based on traceId";
private String chaosToolSchema = """
{
@@ -30,7 +49,7 @@ public class TraceAnalysisFunction implements McpFunction {
"properties": {
"traceId": {
"type": "string",
- "description": "traceId,为32位0-9和a-f组成的随机字符串"
+ "description": "traceId, a random string consisting of
32 characters from 0-9 and a-f"
}
},
"required": ["traceId"]
@@ -45,16 +64,16 @@ public class TraceAnalysisFunction implements McpFunction {
String traceId = getStringParam(args, "traceId");
if (traceId.isEmpty()) {
- log.warn("traceId 为空");
+ log.warn("traceId is empty");
}
- String result = traceAnalysisService.analyzeTraceRoot(traceId,
"online");
+ String result =
traceAnalysisService.analyzeTraceRoot(TraceQueryParam.builder().traceId(traceId).env("online").build());
return createSuccessFlux(result);
} catch (Exception e) {
- log.error("执行混沌操作失败", e);
+ log.error("Failed to execute chaos operation", e);
return Flux.just(new McpSchema.CallToolResult(
- List.of(new McpSchema.TextContent("操作失败:" +
e.getMessage())), true));
+ List.of(new McpSchema.TextContent("Operation failed: " +
e.getMessage())), true));
}
});
}
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/LogService.java
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/LogService.java
index a59402f2..7502c4a8 100644
---
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/LogService.java
+++
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/LogService.java
@@ -27,10 +27,6 @@ import
org.apache.ozhera.intelligence.domain.rootanalysis.LogParam;
import java.util.List;
import java.util.Map;
-/**
- * @author dingtao
- * @date 2025/1/20 11:26
- */
@Service
public class LogService {
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/MetricsService.java
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/MetricsService.java
index 0207be19..506fdf38 100644
---
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/MetricsService.java
+++
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/MetricsService.java
@@ -42,10 +42,6 @@ import java.util.concurrent.TimeUnit;
import static
org.apache.ozhera.intelligence.util.CommitPoolUtil.HERA_SOLUTION_METRICS_POOL;
-/**
- * @author dingtao
- * @date 2025/1/20 11:26
- */
@Service
@Slf4j
public class MetricsService {
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/PromptService.java
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/PromptService.java
index 470810c7..1456dcdd 100644
---
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/PromptService.java
+++
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/PromptService.java
@@ -18,59 +18,165 @@
*/
package org.apache.ozhera.intelligence.service;
-import org.springframework.stereotype.Service;
+import com.google.common.collect.ImmutableMap;
import org.apache.ozhera.intelligence.domain.rootanalysis.LogPromptResult;
import org.apache.ozhera.intelligence.domain.rootanalysis.MetricsPromptResult;
import org.apache.ozhera.intelligence.domain.rootanalysis.TracePromptResult;
+import org.apache.ozhera.intelligence.domain.rootanalysis.constant.Prompts;
+import org.springframework.stereotype.Service;
+import run.mone.hive.common.AiTemplate;
+import run.mone.hive.common.MultiXmlParser;
+import run.mone.hive.common.ToolDataInfo;
+import run.mone.hive.configs.LLMConfig;
+import run.mone.hive.llm.LLM;
+import run.mone.hive.llm.LLMProvider;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.Map;
@Service
public class PromptService {
+ private LLM llm;
+
+ @PostConstruct
+ private void init() {
+ llm = new
LLM(LLMConfig.builder().llmProvider(LLMProvider.valueOf(System.getenv("LLM_PROVIDER"))).build());
+ }
+
/**
- * Conduct large model analysis based on trace data
+ * Perform LLM analysis based on trace data
*
- * @param trace
- * @return
+ * @param trace trace link data
+ * @return TracePromptResult analysis result
*/
public TracePromptResult traceAnalysis(String trace) {
- // Retrieve the corresponding prompt
- // Invoke the large model for analysis
- return null;
+ // Get the corresponding prompt
+ String prompt = Prompts.TRACE_ANALYSIS_PROMPT + "\n" + trace;
+
+ // Call LLM for analysis
+ String llmRes = llm.chat(prompt);
+
+ // Parse the XML result returned by LLM
+ List<ToolDataInfo> tools = new MultiXmlParser().parse(llmRes);
+ if (tools == null || tools.isEmpty()) {
+ // If parsing result is empty, return default error message
+ return TracePromptResult.builder()
+ .traceReason("Failed to parse LLM result")
+ .root(false)
+ .build();
+ }
+
+ Map<String, String> keyValuePairs = tools.get(0).getKeyValuePairs();
+
+ // Build and return complete TracePromptResult object
+ return TracePromptResult.builder()
+
.traceReason(keyValuePairs.get(TracePromptResult.TRACE_REASON_KEY))
+ .application(keyValuePairs.get(TracePromptResult.APPLICATION))
+
.root(Boolean.parseBoolean(keyValuePairs.get(TracePromptResult.ROOT)))
+ .envId(keyValuePairs.get(TracePromptResult.ENV_ID))
+ .startTime(keyValuePairs.get(TracePromptResult.START_TIME))
+ .duration(keyValuePairs.get(TracePromptResult.DURATION))
+ .spanId(keyValuePairs.get(TracePromptResult.SPAN_ID))
+ .ip(keyValuePairs.get(TracePromptResult.IP))
+ .build();
}
/**
- * Conduct large model analysis based on log data
+ * Perform LLM analysis based on log data
*
- * @param log
- * @return
+ * @param log log data
+ * @return LogPromptResult analysis result
*/
public LogPromptResult logAnalysis(String log) {
- // Retrieve the corresponding prompt
- // Invoke the large model for analysis
- return null;
+ // Get the corresponding prompt
+ String prompt = Prompts.LOG_ANALYSIS_PROMPT + "\n" + log;
+
+ // Call LLM for analysis
+ String llmRes = llm.chat(prompt);
+
+ // Parse the XML result returned by LLM
+ List<ToolDataInfo> tools = new MultiXmlParser().parse(llmRes);
+ if (tools == null || tools.isEmpty()) {
+ // If parsing result is empty, return default error message
+ return LogPromptResult.builder()
+ .logReason("Failed to parse LLM result")
+ .root(false)
+ .build();
+ }
+
+ Map<String, String> keyValuePairs = tools.get(0).getKeyValuePairs();
+
+ // Build and return complete LogPromptResult object
+ return LogPromptResult.builder()
+ .logReason(keyValuePairs.get(LogPromptResult.LOG_REASON))
+
.root(Boolean.parseBoolean(keyValuePairs.get(LogPromptResult.ROOT)))
+ .build();
}
/**
- * Conduct large model analysis based on metrics data
+ * Perform LLM analysis based on metrics data
*
- * @param metrics
- * @return
+ * @param metrics metrics data
+ * @return MetricsPromptResult analysis result
*/
public MetricsPromptResult metricsAnalysis(String metrics) {
- // Retrieve the corresponding prompt
- // Invoke the large model for analysis
- return null;
+ // Get the corresponding prompt, replace data placeholder
+ String prompt = Prompts.METRICS_ANALYSIS_PROMPT + "\n" + metrics;
+
+ // Call LLM for analysis
+ String llmRes = llm.chat(prompt);
+
+ // Parse the XML result returned by LLM
+ List<ToolDataInfo> tools = new MultiXmlParser().parse(llmRes);
+ if (tools == null || tools.isEmpty()) {
+ // If parsing result is empty, return default error message
+ return MetricsPromptResult.builder()
+ .metricsReason("Failed to parse LLM result")
+ .root(false)
+ .build();
+ }
+
+ Map<String, String> keyValuePairs = tools.get(0).getKeyValuePairs();
+
+ // Build and return complete MetricsPromptResult object
+ return MetricsPromptResult.builder()
+
.metricsReason(keyValuePairs.get(MetricsPromptResult.METRICS_REASON))
+
.root(Boolean.parseBoolean(keyValuePairs.get(MetricsPromptResult.ROOT)))
+ .build();
}
/**
- * Summarize a clear and concise root cause based on the analysis results
from trace, log, and metrics.
- * @param traceReason
- * @param logReason
- * @param metricsReason
- * @return
+ * Based on the analysis results of trace, log and metrics,
comprehensively derive clear and concise root cause analysis
+ *
+ * @param application application name
+ * @param traceReason trace analysis result
+ * @param logReason log analysis result
+ * @param metricsReason metrics analysis result
+ * @return String comprehensive analysis result
*/
- public String getSimpleReason(String traceReason, String logReason, String
metricsReason) {
- // Invoke the large model for analysis
- return null;
+ public String getSimpleReason(String application, String traceReason,
String logReason, String metricsReason) {
+ // Build prompt, replace placeholders
+ String prompt =
AiTemplate.renderTemplate(Prompts.RESULT_COLLECT_PROMPT,
+ ImmutableMap.of("application", application != null ?
application : "",
+ "traceReason", traceReason != null ? traceReason : "",
+ "logReason", logReason != null ? logReason : "",
+ "metricsReason", metricsReason != null ? metricsReason
: ""));
+
+ // Call LLM for analysis
+ String llmRes = llm.chat(prompt);
+
+ // Parse the XML result returned by LLM
+ List<ToolDataInfo> tools = new MultiXmlParser().parse(llmRes);
+ if (tools == null || tools.isEmpty()) {
+ // If parsing result is empty, return default error message
+ return "Failed to parse LLM result";
+ }
+
+ Map<String, String> keyValuePairs = tools.get(0).getKeyValuePairs();
+
+ // Return simplified analysis result
+ return keyValuePairs.get("simpleReason");
}
}
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/TraceAnalysisService.java
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/TraceAnalysisService.java
index 489a14f7..12cafa7b 100644
---
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/TraceAnalysisService.java
+++
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/TraceAnalysisService.java
@@ -1,15 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
package org.apache.ozhera.intelligence.service;
+import com.alibaba.nacos.api.config.annotation.NacosValue;
+import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
+import org.apache.ozhera.intelligence.domain.rootanalysis.*;
+import org.apache.ozhera.trace.etl.domain.tracequery.Span;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Trace analysis service
+ */
@Slf4j
@Service
public class TraceAnalysisService {
+ @NacosValue("${hera.trace.url}")
+ private String heraTraceUrl;
+
+ @Autowired
+ private TraceService traceService;
+
+ @Autowired
+ private PromptService promptService;
+
+ @Autowired
+ private LogService logService;
+
+ @Autowired
+ private MetricsService metricsService;
+
+ private final Gson gson = new Gson();
+
+ /**
+ * Analyze trace root cause
+ * Performs trace analysis based on input parameters. If trace analysis
doesn't find root cause,
+ * continues with log analysis. If log analysis also doesn't find root
cause, performs metrics analysis,
+ * and finally generates comprehensive analysis report.
+ *
+ * @param param trace query parameters
+ * @return analysis result report
+ */
+ public String analyzeTraceRoot(TraceQueryParam param) {
+ try {
+ log.info("Starting trace root cause analysis, parameters: {}",
param);
+
+ // Step 1: Query trace data
+ List<Span> spans = traceService.queryTraceRootAnalysis(param);
+ if (spans == null || spans.isEmpty()) {
+ log.warn("No trace data found, traceId: {}",
param.getTraceId());
+ return "No related trace data found";
+ }
+
+ // Step 2: Call trace analysis AI model
+ String traceData = gson.toJson(spans);
+ TracePromptResult traceResult =
promptService.traceAnalysis(traceData);
+ log.info("Trace analysis result: {}", traceResult);
+
+ // Check if trace analysis found root cause
+ if (traceResult != null && traceResult.isRoot()) {
+ log.info("Trace analysis found root cause, returning
comprehensive report directly");
+ return generateFinalReport(traceResult, null, null, param);
+ }
+
+ // Step 3: Trace didn't find root cause, perform log analysis
+ log.info("Trace analysis didn't find root cause, starting log
analysis");
+
+ // Check if trace analysis result contains necessary information
for further analysis
+ if (traceResult == null) {
+ log.warn("Trace analysis result is empty, cannot continue with
log and metrics analysis");
+ return "Trace analysis failed, unable to obtain necessary
analysis information";
+ }
+
+ LogParam logParam = buildLogParam(traceResult, param);
+ List<Map<String, Object>> logs =
logService.queryLogRootAnalysis(logParam);
+
+ LogPromptResult logResult = null;
+ if (logs != null && !logs.isEmpty()) {
+ String logData = gson.toJson(logs);
+ logResult = promptService.logAnalysis(logData);
+ log.info("Log analysis result: {}", logResult);
+
+ // Check if log analysis found root cause
+ if (logResult != null && logResult.isRoot()) {
+ log.info("Log analysis found root cause, returning
comprehensive report directly");
+ return generateFinalReport(traceResult, logResult, null,
param);
+ }
+ } else {
+ log.warn("No related log data found");
+ }
+
+ // Step 4: Log analysis also didn't find root cause, perform
metrics analysis
+ log.info("Log analysis didn't find root cause, starting metrics
analysis");
+ MetricsQueryParam metricsParam = buildMetricsParam(traceResult,
param);
+ HeraRootCaseAnalyseRes metricsData =
metricsService.queryMetricsRootAnalysis(metricsParam);
+
+ MetricsPromptResult metricsResult = null;
+ if (metricsData != null) {
+ String metricsJsonData = gson.toJson(metricsData);
+ metricsResult = promptService.metricsAnalysis(metricsJsonData);
+ log.info("Metrics analysis result: {}", metricsResult);
+ } else {
+ log.warn("No related metrics data found");
+ }
+
+ // Step 5: Generate final comprehensive report
+ return generateFinalReport(traceResult, logResult, metricsResult,
param);
+
+ } catch (Exception e) {
+ log.error("Exception occurred during trace root cause analysis",
e);
+ return "Exception occurred during analysis: " + e.getMessage();
+ }
+ }
+
+ /**
+ * Generate final comprehensive analysis report
+ *
+ * @param traceResult trace analysis result
+ * @param logResult log analysis result
+ * @param metricsResult metrics analysis result
+ * @param param original query parameters
+ * @return comprehensive analysis report
+ */
+ private String generateFinalReport(TracePromptResult traceResult,
LogPromptResult logResult,
+ MetricsPromptResult metricsResult,
TraceQueryParam param) {
+ // Get simplified root cause analysis results
+ String application = traceResult != null ?
traceResult.getApplication() : "";
+ String traceReason = traceResult != null ?
traceResult.getTraceReason() : "";
+ String logReason = logResult != null ? logResult.getLogReason() : "";
+ String metricsReason = metricsResult != null ?
metricsResult.getMetricsReason() : "";
+
+ String simpleReason = promptService.getSimpleReason(application,
traceReason, logReason, metricsReason);
+
+ // Build MarkDownParam parameters
+ MarkDownParam markDownParam = MarkDownParam.builder()
+ .application(application)
+ .traceReason(traceReason)
+ .logReason(logReason)
+ .metricsReason(metricsReason)
+ .simpleReason(simpleReason)
+ .traceId(param.getTraceId())
+ .timestamp(param.getTimeStamp() != null ?
param.getTimeStamp().toString() : "")
+ .build();
+
+ // Generate and return comprehensive report
+ return assembleReport(markDownParam);
+ }
- public String analyzeTraceRoot(String traceId, String env) {
- return null;
+ /**
+ * Build log query parameters based on trace analysis result
+ *
+ * @param traceResult trace analysis result
+ * @param param original query parameters
+ * @return log query parameters
+ */
+ private LogParam buildLogParam(TracePromptResult traceResult,
TraceQueryParam param) {
+ return LogParam.builder()
+ .application(traceResult.getApplication() != null ?
traceResult.getApplication() : "")
+ .envId(traceResult.getEnvId() != null ? traceResult.getEnvId()
: "")
+ .traceId(param.getTraceId())
+ .startTime(traceResult.getStartTime() != null ?
traceResult.getStartTime() : "")
+ .duration(traceResult.getDuration() != null ?
traceResult.getDuration() : "")
+ .level("ERROR") // Default to query ERROR level logs
+ .build();
}
+ /**
+ * Build metrics query parameters based on trace analysis result
+ *
+ * @param traceResult trace analysis result
+ * @param param original query parameters
+ * @return metrics query parameters
+ */
+ private MetricsQueryParam buildMetricsParam(TracePromptResult traceResult,
TraceQueryParam param) {
+ return MetricsQueryParam.builder()
+ .application(traceResult.getApplication() != null ?
traceResult.getApplication() : "")
+ .ip(traceResult.getIp() != null ? traceResult.getIp() : "")
+ .startTime(traceResult.getStartTime() != null ?
traceResult.getStartTime() : "")
+ .duration(traceResult.getDuration() != null ?
traceResult.getDuration() : "")
+ .gap("300000") // Default 5-minute time interval
+ .build();
+ }
+
+ /**
+ * Execute root cause analysis and generate comprehensive report
+ * Based on various analysis results input, generates formatted root cause
analysis report
+ *
+ * @param param parameter object containing various analysis results
+ * @return formatted root cause analysis report
+ */
+ public String assembleReport(MarkDownParam param) {
+ // Get various analysis results from parameter object, use default
values if empty
+ String traceReason = param.getTraceReason() == null ? "" :
param.getTraceReason();
+ String application = param.getApplication() == null ? "未获取到应用" :
param.getApplication();
+ String logReason = param.getLogReason() == null ? "" :
param.getLogReason();
+ String metricsReason = param.getMetricsReason() == null ? "" :
param.getMetricsReason();
+ String simpleReason = param.getSimpleReason() == null ? "" :
param.getSimpleReason();
+ String traceId = param.getTraceId() == null ? "" : param.getTraceId();
+ String timestamp = param.getTimestamp() == null ? "" :
param.getTimestamp();
+
+
+ // Build comprehensive analysis report
+ StringBuilder sb = new StringBuilder();
+ sb.append("根本原因在于应用:**")
+ .append(application)
+ .append("**,\n原因:**")
+ .append(simpleReason)
+ .append("**\n\n");
+
+ sb.append("---\n")
+ .append("通过链路追踪分析的详细原因:\n\n")
+ .append(traceReason)
+ .append("\n\n");
+
+ sb.append("---\n")
+ .append("通过日志分析的详细原因:\n\n")
+ .append(logReason)
+ .append("\n\n");
+
+ sb.append("---\n")
+ .append("通过指标监控分析的详细原因:\n\n")
+ .append(metricsReason)
+ .append("\n\n");
+
+ // Build trace link
+ sb.append("---\n")
+ .append("链路追踪:<")
+ .append(heraTraceUrl)
+ .append(traceId);
+ if (!"".equals(timestamp)) {
+ sb.append("?startTime=").append(timestamp);
+ sb.append("&endTime=").append(timestamp);
+ }
+ sb.append(">\n");
+
+ // Return result
+ return sb.toString();
+ }
}
\ No newline at end of file
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/TraceService.java
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/TraceService.java
index b2ec745e..d2740da8 100644
---
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/TraceService.java
+++
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/service/TraceService.java
@@ -36,10 +36,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-/**
- * @author dingtao
- * @date 2025/1/20 11:26
- */
@Service
public class TraceService {
@@ -306,8 +302,24 @@ public class TraceService {
TraceIdQueryVo vo = new TraceIdQueryVo();
vo.setTraceId(param.getTraceId());
- long startTime = param.getTimeStamp() - QUERY_TIME_RANGE;
- long endTime = param.getTimeStamp() + QUERY_TIME_RANGE;
+
+ long startTime;
+ long endTime;
+
+ // If timeStamp is null, set it to the start and end times of the
current day
+ if (param.getTimeStamp() == null) {
+ java.time.LocalDate today = java.time.LocalDate.now();
+ java.time.LocalDateTime startOfDay = today.atStartOfDay();
+ java.time.LocalDateTime endOfDay = today.atTime(23, 59, 59,
999_999_999);
+
+ startTime =
startOfDay.atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli();
+ endTime =
endOfDay.atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli();
+ } else {
+ // Use the original logic to query within QUERY_TIME_RANGE before
and after the specified timestamp
+ startTime = param.getTimeStamp() - QUERY_TIME_RANGE;
+ endTime = param.getTimeStamp() + QUERY_TIME_RANGE;
+ }
+
vo.setStartTime(startTime);
vo.setEndTime(endTime);
return vo;
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/util/HttpClient.java
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/util/HttpClient.java
index f250ff1f..d56c5749 100644
---
a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/util/HttpClient.java
+++
b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/util/HttpClient.java
@@ -31,10 +31,6 @@ import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
-/**
- * @author dingtao
- * @date 2025/1/20 11:26
- */
@Slf4j
public class HttpClient {
diff --git
a/ozhera-intelligence/ozhera-intelligence-service/src/test/java/org/apache/ozhera/intelligence/service/PromptServiceTest.java
b/ozhera-intelligence/ozhera-intelligence-service/src/test/java/org/apache/ozhera/intelligence/service/PromptServiceTest.java
new file mode 100644
index 00000000..026360e3
--- /dev/null
+++
b/ozhera-intelligence/ozhera-intelligence-service/src/test/java/org/apache/ozhera/intelligence/service/PromptServiceTest.java
@@ -0,0 +1,295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ozhera.intelligence.service;
+
+import org.apache.ozhera.intelligence.domain.rootanalysis.LogPromptResult;
+import org.apache.ozhera.intelligence.domain.rootanalysis.MetricsPromptResult;
+import org.apache.ozhera.intelligence.domain.rootanalysis.TracePromptResult;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import run.mone.hive.configs.LLMConfig;
+import run.mone.hive.llm.LLM;
+import run.mone.hive.llm.LLMProvider;
+
+import java.lang.reflect.Field;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * PromptService unit test class
+ * Test the basic functionality of various methods in PromptService
+ */
+class PromptServiceTest {
+
+ private PromptService promptService;
+
+ /**
+ * Preparation before testing
+ * Initialize PromptService instance
+ */
+ @BeforeEach
+ void setUp() throws Exception {
+ promptService = new PromptService();
+
+ // Create a test LLM instance (using environment variables or default
values)
+ String llmProvider = System.getenv("LLM_PROVIDER");
+
+ try {
+ LLM llm = new
LLM(LLMConfig.builder().llmProvider(LLMProvider.valueOf(llmProvider)).build());
+
+ // Set private field llm through reflection
+ Field llmField = PromptService.class.getDeclaredField("llm");
+ llmField.setAccessible(true);
+ llmField.set(promptService, llm);
+ } catch (Exception e) {
+ // If LLM initialization fails, skip the test or use empty
implementation
+ System.out.println("Warning: LLM initialization failed, tests may
not run properly: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test traceAnalysis method
+ * Verify that the method can be called normally and returns
TracePromptResult object
+ */
+ @Test
+ void testTraceAnalysis() {
+ // Prepare test data
+ String traceData = """
+ {
+ "traceID": "test-trace-123",
+ "spans": [
+ {
+ "spanID": "span-001",
+ "operationName": "database-query",
+ "duration": 5000,
+ "tags": [
+ {"key": "error", "value": "true"},
+ {"key": "db.statement", "value": "SELECT * FROM users"}
+ ]
+ }
+ ]
+ }
+ """;
+
+ try {
+ // Execute test method
+ TracePromptResult result = promptService.traceAnalysis(traceData);
+
+ // Verify result is not null
+ assertNotNull(result, "TracePromptResult should not be null");
+
+ // Verify basic fields exist
+ assertNotNull(result.getTraceReason(), "traceReason field should
not be null");
+
+ // Print results for debugging
+ System.out.println("Trace analysis result:");
+ System.out.println("- Reason: " + result.getTraceReason());
+ System.out.println("- Application: " + result.getApplication());
+ System.out.println("- Is root: " + result.isRoot());
+ System.out.println("- Environment ID: " + result.getEnvId());
+
+ } catch (Exception e) {
+ // If call fails, at least verify the method exists and is callable
+ System.out.println("Trace analysis call exception (possibly LLM
configuration issue): " + e.getMessage());
+ assertNotNull(promptService, "PromptService instance should
exist");
+ }
+ }
+
+ /**
+ * Test logAnalysis method
+ * Verify that the method can be called normally and returns
LogPromptResult object
+ */
+ @Test
+ void testLogAnalysis() {
+ // Prepare test data
+ String logData = """
+ [
+ {
+ "timestamp": "2024-01-01 10:00:00",
+ "level": "ERROR",
+ "message": "java.lang.NullPointerException at
com.example.service.UserService.getUserById(UserService.java:45)",
+ "thread": "http-nio-8080-exec-1"
+ },
+ {
+ "timestamp": "2024-01-01 10:00:01",
+ "level": "ERROR",
+ "message": "Failed to process user request",
+ "thread": "http-nio-8080-exec-1"
+ }
+ ]
+ """;
+
+ try {
+ // Execute test method
+ LogPromptResult result = promptService.logAnalysis(logData);
+
+ // Verify result is not null
+ assertNotNull(result, "LogPromptResult should not be null");
+
+ // Verify basic fields exist
+ assertNotNull(result.getLogReason(), "logReason field should not
be null");
+
+ // Print results for debugging
+ System.out.println("Log analysis result:");
+ System.out.println("- Reason: " + result.getLogReason());
+ System.out.println("- Is root: " + result.isRoot());
+
+ } catch (Exception e) {
+ // If call fails, at least verify the method exists and is callable
+ System.out.println("Log analysis call exception (possibly LLM
configuration issue): " + e.getMessage());
+ assertNotNull(promptService, "PromptService instance should
exist");
+ }
+ }
+
+ /**
+ * Test metricsAnalysis method
+ * Verify that the method can be called normally and returns
MetricsPromptResult object
+ */
+ @Test
+ void testMetricsAnalysis() {
+ // Prepare test data
+ String metricsData = """
+ {
+ "maxCpuUsage": 95.5,
+ "maxLoad": 8.2,
+ "maxJvmHeapUsage": 85.0,
+ "maxSTWCost": 250,
+ "STWCountOf1m": 12,
+ "cpuCount": 4
+ }
+ """;
+
+ try {
+ // Execute test method
+ MetricsPromptResult result =
promptService.metricsAnalysis(metricsData);
+
+ // Verify result is not null
+ assertNotNull(result, "MetricsPromptResult should not be null");
+
+ // Verify basic fields exist
+ assertNotNull(result.getMetricsReason(), "metricsReason field
should not be null");
+
+ // Print results for debugging
+ System.out.println("Metrics analysis result:");
+ System.out.println("- Reason: " + result.getMetricsReason());
+ System.out.println("- Is root: " + result.isRoot());
+
+ } catch (Exception e) {
+ // If call fails, at least verify the method exists and is callable
+ System.out.println("Metrics analysis call exception (possibly LLM
configuration issue): " + e.getMessage());
+ assertNotNull(promptService, "PromptService instance should
exist");
+ }
+ }
+
+ /**
+ * Test getSimpleReason method
+ * Verify that the method can be called normally and returns comprehensive
analysis result
+ */
+ @Test
+ void testGetSimpleReason() {
+ // Prepare test data
+ String application = "UserService";
+ String traceReason = "Database query timeout, took 5 seconds";
+ String logReason = "NullPointerException occurred at line 45 in
UserService.getUserById method";
+ String metricsReason = "CPU usage reached 95.5%, system load is too
high";
+
+ try {
+ // Execute test method
+ String result = promptService.getSimpleReason(application,
traceReason, logReason, metricsReason);
+
+ // Verify result is not null
+ assertNotNull(result, "Comprehensive analysis result should not be
null");
+ assertFalse(result.trim().isEmpty(), "Comprehensive analysis
result should not be empty string");
+
+ // Print results for debugging
+ System.out.println("Comprehensive analysis result:");
+ System.out.println(result);
+
+ } catch (Exception e) {
+ // If call fails, at least verify the method exists and is callable
+ System.out.println("Comprehensive analysis call exception
(possibly LLM configuration issue): " + e.getMessage());
+ assertNotNull(promptService, "PromptService instance should
exist");
+ }
+ }
+
+ /**
+ * Test handling of empty input parameters
+ * Verify the method's ability to handle empty inputs
+ */
+ @Test
+ void testWithEmptyInputs() {
+ try {
+ // Test empty string input
+ TracePromptResult traceResult = promptService.traceAnalysis("");
+ assertNotNull(traceResult, "Trace analysis result with empty input
should not be null");
+
+ LogPromptResult logResult = promptService.logAnalysis("");
+ assertNotNull(logResult, "Log analysis result with empty input
should not be null");
+
+ MetricsPromptResult metricsResult =
promptService.metricsAnalysis("");
+ assertNotNull(metricsResult, "Metrics analysis result with empty
input should not be null");
+
+ // Test comprehensive analysis with null parameters
+ String simpleReason = promptService.getSimpleReason(null, null,
null, null);
+ assertNotNull(simpleReason, "Comprehensive analysis result with
null parameters should not be null");
+
+ System.out.println("Empty input test passed");
+
+ } catch (Exception e) {
+ System.out.println("Empty input test exception: " +
e.getMessage());
+ // Even if exception occurs, ensure service instance exists
+ assertNotNull(promptService, "PromptService instance should
exist");
+ }
+ }
+
+ /**
+ * Test method parameter validation
+ * Verify basic parameter handling of each method
+ */
+ @Test
+ void testMethodParameterHandling() {
+ // Verify PromptService instance exists
+ assertNotNull(promptService, "PromptService instance should not be
null");
+
+ // Verify methods exist (check through reflection)
+ try {
+ // Check traceAnalysis method
+ assertNotNull(promptService.getClass().getMethod("traceAnalysis",
String.class),
+ "traceAnalysis method should exist");
+
+ // Check logAnalysis method
+ assertNotNull(promptService.getClass().getMethod("logAnalysis",
String.class),
+ "logAnalysis method should exist");
+
+ // Check metricsAnalysis method
+
assertNotNull(promptService.getClass().getMethod("metricsAnalysis",
String.class),
+ "metricsAnalysis method should exist");
+
+ // Check getSimpleReason method
+
assertNotNull(promptService.getClass().getMethod("getSimpleReason",
+ String.class, String.class, String.class, String.class),
+ "getSimpleReason method should exist");
+
+ System.out.println("All method signature validation passed");
+
+ } catch (NoSuchMethodException e) {
+ fail("Method signature validation failed: " + e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git
a/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/nacos/config/hera_intelligence_config_#_DEFAULT_GROUP.properties
b/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/nacos/config/hera_intelligence_config_#_DEFAULT_GROUP.properties
index 5bf79dad..94f6fd7e 100644
---
a/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/nacos/config/hera_intelligence_config_#_DEFAULT_GROUP.properties
+++
b/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/nacos/config/hera_intelligence_config_#_DEFAULT_GROUP.properties
@@ -12,6 +12,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
analyze.token=
dubbo.registry.address=nacos://${hera.nacos.address}
prometheus.api.url=${hera.prometheus.url}
+hera.trace.url=http://${hera.homepage.url}/project-hera-tracing/traceid/
diff --git
a/ozhera-prometheus-agent/ozhera-prometheus-agent-server/src/main/java/org/apache/ozhera/prometheus/agent/bootstrap/PrometheusAgentBootstrap.java
b/ozhera-prometheus-agent/ozhera-prometheus-agent-server/src/main/java/org/apache/ozhera/prometheus/agent/bootstrap/PrometheusAgentBootstrap.java
index dd0cb696..a06568c7 100644
---
a/ozhera-prometheus-agent/ozhera-prometheus-agent-server/src/main/java/org/apache/ozhera/prometheus/agent/bootstrap/PrometheusAgentBootstrap.java
+++
b/ozhera-prometheus-agent/ozhera-prometheus-agent-server/src/main/java/org/apache/ozhera/prometheus/agent/bootstrap/PrometheusAgentBootstrap.java
@@ -27,9 +27,6 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
-/**
- * @author dingtao
- */
@EnableAutoConfiguration
@ComponentScan(basePackages = {"org.apache.ozhera.prometheus.agent",
"com.xiaomi.youpin"})
@DubboComponentScan(basePackages = "org.apache.ozhera.prometheus.agent")
diff --git
a/ozhera-webhook/ozhera-webhook-server/src/main/java/org/apache/ozhera/webhook/Bootstrap.java
b/ozhera-webhook/ozhera-webhook-server/src/main/java/org/apache/ozhera/webhook/Bootstrap.java
index 0b0f0053..22fca6dc 100644
---
a/ozhera-webhook/ozhera-webhook-server/src/main/java/org/apache/ozhera/webhook/Bootstrap.java
+++
b/ozhera-webhook/ozhera-webhook-server/src/main/java/org/apache/ozhera/webhook/Bootstrap.java
@@ -37,9 +37,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
-/**
- * @author dingtao
- */
@EnableAutoConfiguration
@ComponentScan(basePackages = {"org.apache.ozhera.webhook"})
@Slf4j
diff --git
a/ozhera-webhook/ozhera-webhook-server/src/main/java/org/apache/ozhera/webhook/controller/HeraWebhookController.java
b/ozhera-webhook/ozhera-webhook-server/src/main/java/org/apache/ozhera/webhook/controller/HeraWebhookController.java
index f96407ad..1dbc4d39 100644
---
a/ozhera-webhook/ozhera-webhook-server/src/main/java/org/apache/ozhera/webhook/controller/HeraWebhookController.java
+++
b/ozhera-webhook/ozhera-webhook-server/src/main/java/org/apache/ozhera/webhook/controller/HeraWebhookController.java
@@ -37,10 +37,6 @@ import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
-/**
- * @author dingtao
- * @date 2023/4/11 14:40
- */
@RestController
@Slf4j
public class HeraWebhookController {
diff --git
a/trace-etl/trace-etl-api/src/main/java/org/apache/ozhera/trace/etl/api/service/TraceQueryService.java
b/trace-etl/trace-etl-api/src/main/java/org/apache/ozhera/trace/etl/api/service/TraceQueryService.java
index d657d5d7..71e5ed15 100644
---
a/trace-etl/trace-etl-api/src/main/java/org/apache/ozhera/trace/etl/api/service/TraceQueryService.java
+++
b/trace-etl/trace-etl-api/src/main/java/org/apache/ozhera/trace/etl/api/service/TraceQueryService.java
@@ -24,10 +24,6 @@ import
org.apache.ozhera.trace.etl.domain.tracequery.TraceListQueryVo;
import java.util.List;
-/**
- * @author dingtao
- * @date 2025/1/20 11:26
- */
public interface TraceQueryService {
List<Trace> getList(TraceListQueryVo vo);
diff --git
a/trace-etl/trace-etl-es/src/main/java/org/apache/ozhera/trace/etl/es/bootstrap/TraceEtlEsBootstrap.java
b/trace-etl/trace-etl-es/src/main/java/org/apache/ozhera/trace/etl/es/bootstrap/TraceEtlEsBootstrap.java
index 1daff2f7..499230c6 100644
---
a/trace-etl/trace-etl-es/src/main/java/org/apache/ozhera/trace/etl/es/bootstrap/TraceEtlEsBootstrap.java
+++
b/trace-etl/trace-etl-es/src/main/java/org/apache/ozhera/trace/etl/es/bootstrap/TraceEtlEsBootstrap.java
@@ -26,9 +26,6 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
-/**
- * @author dingtao
- */
@EnableAutoConfiguration
@ComponentScan(basePackages = {"org.apache.ozhera.trace.etl.es",
"org.apache.ozhera.trace.etl", "com.xiaomi.data.push.redis",
"run.mone.trace.etl"})
@DubboComponentScan(basePackages = "org.apache.ozhera.trace.etl.es.dubbo")
diff --git
a/trace-etl/trace-etl-es/src/main/java/org/apache/ozhera/trace/etl/es/consumer/ConsumerService.java
b/trace-etl/trace-etl-es/src/main/java/org/apache/ozhera/trace/etl/es/consumer/ConsumerService.java
index 03c313fc..1c215aa9 100644
---
a/trace-etl/trace-etl-es/src/main/java/org/apache/ozhera/trace/etl/es/consumer/ConsumerService.java
+++
b/trace-etl/trace-etl-es/src/main/java/org/apache/ozhera/trace/etl/es/consumer/ConsumerService.java
@@ -51,11 +51,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
-/**
- * @author dingtao
- * @Description
- * @date 2021/9/29 2:47 pm
- */
@Service
@Slf4j
public class ConsumerService {
diff --git
a/trace-etl/trace-etl-manager/src/main/java/org/apache/ozhera/trace/etl/manager/bootstrap/TraceEtlManagerBootstrap.java
b/trace-etl/trace-etl-manager/src/main/java/org/apache/ozhera/trace/etl/manager/bootstrap/TraceEtlManagerBootstrap.java
index ec875758..388341d5 100644
---
a/trace-etl/trace-etl-manager/src/main/java/org/apache/ozhera/trace/etl/manager/bootstrap/TraceEtlManagerBootstrap.java
+++
b/trace-etl/trace-etl-manager/src/main/java/org/apache/ozhera/trace/etl/manager/bootstrap/TraceEtlManagerBootstrap.java
@@ -25,9 +25,6 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
-/**
- * @author dingtao
- */
@EnableAutoConfiguration
@ComponentScan(basePackages = {"org.apache.ozhera.trace.etl",
"run.mone.trace.etl"})
@DubboComponentScan(basePackages = "org.apache.ozhera.trace.etl")
diff --git
a/trace-etl/trace-etl-manager/src/main/java/org/apache/ozhera/trace/etl/manager/dubbo/TraceQueryServiceImpl.java
b/trace-etl/trace-etl-manager/src/main/java/org/apache/ozhera/trace/etl/manager/dubbo/TraceQueryServiceImpl.java
index bc8bc30c..c0954ad2 100644
---
a/trace-etl/trace-etl-manager/src/main/java/org/apache/ozhera/trace/etl/manager/dubbo/TraceQueryServiceImpl.java
+++
b/trace-etl/trace-etl-manager/src/main/java/org/apache/ozhera/trace/etl/manager/dubbo/TraceQueryServiceImpl.java
@@ -29,10 +29,6 @@ import
org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
-/**
- * @author dingtao
- * @date 2025/1/20 11:26
- */
@Service(interfaceClass = TraceQueryService.class, group = "${dubbo.group}",
version = "1.0")
public class TraceQueryServiceImpl implements TraceQueryService {
diff --git
a/trace-etl/trace-etl-metadata/src/main/java/org/apache/ozhera/trace/etl/metadata/bootstrap/TraceEtlMetadataBootstrap.java
b/trace-etl/trace-etl-metadata/src/main/java/org/apache/ozhera/trace/etl/metadata/bootstrap/TraceEtlMetadataBootstrap.java
index 89975a99..b2e636c4 100644
---
a/trace-etl/trace-etl-metadata/src/main/java/org/apache/ozhera/trace/etl/metadata/bootstrap/TraceEtlMetadataBootstrap.java
+++
b/trace-etl/trace-etl-metadata/src/main/java/org/apache/ozhera/trace/etl/metadata/bootstrap/TraceEtlMetadataBootstrap.java
@@ -26,9 +26,6 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
-/**
- * @author dingtao
- */
@EnableAutoConfiguration
@ComponentScan(basePackages = {"com.xiaomi.hera.trace.etl",
"run.mone.trace.etl"})
@DubboComponentScan(basePackages = "run.mone.trace.etl")
diff --git
a/trace-etl/trace-etl-nginx/src/main/java/org/apache/ozhera/trace/etl/nginx/bootstrap/TraceEtlNginxBootstrap.java
b/trace-etl/trace-etl-nginx/src/main/java/org/apache/ozhera/trace/etl/nginx/bootstrap/TraceEtlNginxBootstrap.java
index 62d57ef2..8ccb3cd5 100644
---
a/trace-etl/trace-etl-nginx/src/main/java/org/apache/ozhera/trace/etl/nginx/bootstrap/TraceEtlNginxBootstrap.java
+++
b/trace-etl/trace-etl-nginx/src/main/java/org/apache/ozhera/trace/etl/nginx/bootstrap/TraceEtlNginxBootstrap.java
@@ -26,9 +26,6 @@ import
org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
-/**
- * @author dingtao
- */
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@ComponentScan(basePackages = {"org.apache.ozhera.trace.etl.nginx"})
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
diff --git
a/trace-etl/trace-etl-server/src/main/java/org/apache/ozhera/trace/etl/bootstrap/TraceEtlBootstrap.java
b/trace-etl/trace-etl-server/src/main/java/org/apache/ozhera/trace/etl/bootstrap/TraceEtlBootstrap.java
index 9f054dfc..0251e9db 100644
---
a/trace-etl/trace-etl-server/src/main/java/org/apache/ozhera/trace/etl/bootstrap/TraceEtlBootstrap.java
+++
b/trace-etl/trace-etl-server/src/main/java/org/apache/ozhera/trace/etl/bootstrap/TraceEtlBootstrap.java
@@ -26,9 +26,6 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
-/**
- * @author dingtao
- */
@EnableAutoConfiguration
@ComponentScan(basePackages = {"org.apache.ozhera.trace.etl",
"com.xiaomi.data.push.redis", "run.mone.trace.etl"})
@DubboComponentScan(basePackages = "org.apache.ozhera.trace.etl.dubbo")
diff --git
a/trace-etl/trace-etl-server/src/main/java/org/apache/ozhera/trace/etl/consumer/RocketMQConsumerService.java
b/trace-etl/trace-etl-server/src/main/java/org/apache/ozhera/trace/etl/consumer/RocketMQConsumerService.java
index 804f2972..1778d4bd 100644
---
a/trace-etl/trace-etl-server/src/main/java/org/apache/ozhera/trace/etl/consumer/RocketMQConsumerService.java
+++
b/trace-etl/trace-etl-server/src/main/java/org/apache/ozhera/trace/etl/consumer/RocketMQConsumerService.java
@@ -38,11 +38,6 @@ import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
-/**
- * @author dingtao
- * @Description
- * @date 2021/9/29 2:47 下午
- */
@Service
@ConditionalOnProperty(name = "mq.type", havingValue = "rocketMQ")
@Slf4j
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]