fix: add intelligence implementation (#533)

* feat: add trace query and analyze filter

* feat: add log query

* feat: add metrics query

* feat: add controller layer code; improve the documentation

* feat: operator add intelligence yaml and nacos properties

* fix: transform en
diff --git a/ozhera-intelligence/README.md b/ozhera-intelligence/README.md
index fcbee8e..6df452c 100644
--- a/ozhera-intelligence/README.md
+++ b/ozhera-intelligence/README.md
@@ -30,4 +30,16 @@
 ## ozhera-intelligence-server
 
 + Service to initiate intelligent functionalities.
++ Access to the ozhera-intelligence-server requires the x-token to be included in the header for authorized access to ozhera's data.
 
+## ozhera-intelligence-service
+
++ LogService: Retrieves log data
++ MetricsService: Retrieves monitoring metric data
++ TraceService: Retrieves trace data
+
+# Important Dependencies
+It relies on a Xiaomi open-source [Agent builder platform--m78](https://github.com/XiaoMi/mone/tree/master/m78-all)
+
+# Intelligent Workflow (Sequence Diagram)
+![ozhera-intelligence](../readme/images/ozhera-intelligence.png)
\ No newline at end of file
diff --git a/ozhera-intelligence/README_cn.md b/ozhera-intelligence/README_cn.md
index d1f3e85..d2a448c 100644
--- a/ozhera-intelligence/README_cn.md
+++ b/ozhera-intelligence/README_cn.md
@@ -29,3 +29,17 @@
 ## ozhera-intelligence-server
 
 + 智能化功能启动服务。
++ ozhera-intelligence-server访问需要header中带上x-token,实现有权限的访问ozhera的数据。
+
+## ozhera-intelligence-service
+
++ LogService,取日志数据
++ MetricsService,取监控指标数据
++ TraceService,取链路数据
+
+# 重要依赖
+会依赖小米开源的一款[Agent构建平台——m78](https://github.com/XiaoMi/mone/tree/master/m78-all)
+
+
+# 智能化工作流程(时序图)
+![ozhera-intelligence](../readme/images/ozhera-intelligence.png)
\ No newline at end of file
diff --git a/ozhera-intelligence/ozhera-intelligence-domain/pom.xml b/ozhera-intelligence/ozhera-intelligence-domain/pom.xml
index e1cf6ce..605a031 100644
--- a/ozhera-intelligence/ozhera-intelligence-domain/pom.xml
+++ b/ozhera-intelligence/ozhera-intelligence-domain/pom.xml
@@ -41,6 +41,10 @@
             <artifactId>lombok</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.ozhera</groupId>
+            <artifactId>trace-etl-domain</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
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
new file mode 100644
index 0000000..bca831c
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/HeraRootCaseAnalyseRes.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+import lombok.Data;
+import lombok.ToString;
+
+/**
+ * @author dingtao
+ * @date 2025/1/20 11:26
+ */
+@Data
+@ToString
+public class HeraRootCaseAnalyseRes {
+    private Double maxCpuUsage;
+    private Double maxLoad;
+    private Double maxJvmHeapUsage;
+    private Double maxSTWCost;
+    private Double STWCountOf1m;
+    private Double cpuCount;
+}
diff --git a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/Metric.java b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/Metric.java
new file mode 100644
index 0000000..d3cd46d
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/Metric.java
@@ -0,0 +1,94 @@
+/*
+ * 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;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class Metric implements Serializable {
+    private String application;
+    private String instance;
+    private String ip;
+    private String job;
+
+    private String replica;
+    private String serverIp;
+
+    //dubbo label
+    private String methodName;
+    private String serviceName;
+
+    //sql
+    private String sqlMethod;
+    private String sql;
+    private String dataSource;
+
+    //redis
+    private String host;
+    private String port;
+    private String dbindex;
+    private String method;
+
+    //env
+    private String serverEnv;
+
+    //container info
+    private String container_label_PROJECT_ID;
+    private String name;//container name eg:zzytest-20220323221926067
+    private String container;//container name for k8s eg:youpin-gateway-dingtao-test2-900329(gitGroup-gitName-envId)
+    private String pod;//pod name for k8s eg:91102-dingtao-test-644758f5b4-jk9t7
+    private String namespace;//namespace name for k8s eg:nrme
+
+    private String lastCreateTime;
+
+    private double value;
+
+    private String timestamp;
+
+    private String traceId;
+
+    private String service;
+
+    private String apiid;
+
+    private String serialid;
+
+    private String sceneid;
+
+    private String pod_ip;
+
+    private String calert;
+
+    private String alert_op;
+
+    private String alert_value;
+
+    private String detailRedirectUrl;
+
+    private String __priority__;
+
+    // downstream service information
+    private String clientProjectId;
+    private String clientProjectName;
+    private String clientEnv;
+    private String clientIp;
+
+}
diff --git a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricDataRangeSetVector.java b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricDataRangeSetVector.java
new file mode 100644
index 0000000..eac2481
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricDataRangeSetVector.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@ToString
+public class MetricDataRangeSetVector implements Serializable {
+    private Metric metric;
+    private List<List<String>> values;
+}
+
diff --git a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricDataRangeVector.java b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricDataRangeVector.java
new file mode 100644
index 0000000..8f2e1d2
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricDataRangeVector.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@ToString
+public class MetricDataRangeVector implements Serializable {
+    private String resultType;
+    private List<MetricDataRangeSetVector> result;
+}
diff --git a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricRangeResponseVector.java b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricRangeResponseVector.java
new file mode 100644
index 0000000..70bc934
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricRangeResponseVector.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+import lombok.Data;
+import lombok.ToString;
+
+import java.io.Serializable;
+
+@Data
+@ToString
+public class MetricRangeResponseVector implements Serializable {
+    private String status;
+    private MetricDataRangeVector data;
+}
diff --git a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricsQueryParam.java b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricsQueryParam.java
index 96541b9..98a6448 100644
--- a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricsQueryParam.java
+++ b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/MetricsQueryParam.java
@@ -20,9 +20,11 @@
 
 import lombok.Builder;
 import lombok.Data;
+import lombok.ToString;
 
 @Data
 @Builder
+@ToString
 public class MetricsQueryParam {
 
     private String env;
@@ -33,6 +35,8 @@
 
     private String startTime;
 
+    private String endTime;
+
     private String duration;
 
     // The error margin between the start time and end time,
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 18fdcdf..b9de720 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
@@ -20,13 +20,15 @@
 
 import lombok.Builder;
 import lombok.Data;
+import lombok.ToString;
 
 import java.util.List;
 
 @Data
 @Builder
+@ToString
 public class TraceQueryParam {
     private String traceId;
     private String env;
-    private List<String> timeStamp;
+    private long timeStamp;
 }
diff --git a/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TraceTreeNode.java b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TraceTreeNode.java
new file mode 100644
index 0000000..14998c5
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-domain/src/main/java/org/apache/ozhera/intelligence/domain/rootanalysis/TraceTreeNode.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+import lombok.Data;
+import org.apache.ozhera.trace.etl.domain.tracequery.Span;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class TraceTreeNode {
+
+    private Span span;
+    private List<TraceTreeNode> children;
+
+    public TraceTreeNode(Span span){
+        this.span = span;
+        this.children = new ArrayList<>();
+    }
+
+    public TraceTreeNode(){
+
+    }
+
+    public void addChild(TraceTreeNode child) {
+        children.add(child);
+    }
+}
diff --git a/ozhera-intelligence/ozhera-intelligence-server/pom.xml b/ozhera-intelligence/ozhera-intelligence-server/pom.xml
index 02cdac4..5664c13 100644
--- a/ozhera-intelligence/ozhera-intelligence-server/pom.xml
+++ b/ozhera-intelligence/ozhera-intelligence-server/pom.xml
@@ -80,7 +80,7 @@
                 <artifactId>spring-boot-maven-plugin</artifactId>
                 <version>2.7.15</version>
                 <configuration>
-                    <mainClass>org.apache.ozhera.trace.etl.bootstrap.TraceEtlBootstrap</mainClass>
+                    <mainClass>org.apache.ozhera.intelligence.bootstrap.IntelligenceBootStrap</mainClass>
                 </configuration>
                 <executions>
                     <execution>
diff --git a/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/config/DubboConfiguration.java b/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/config/DubboConfiguration.java
new file mode 100644
index 0000000..f672299
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/config/DubboConfiguration.java
@@ -0,0 +1,71 @@
+/*
+ * 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.config;
+
+import com.alibaba.nacos.api.config.annotation.NacosValue;
+import com.google.common.collect.Maps;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class DubboConfiguration {
+
+    @Value("${dubbo.protocol.port}")
+    private int port;
+
+    @Value("${server.port}")
+    private String httpGateWayPort;
+
+    @NacosValue("${dubbo.registry.address}")
+    private String regAddress;
+
+    @Bean
+    public ApplicationConfig applicationConfig() {
+        ApplicationConfig applicationConfig = new ApplicationConfig();
+        applicationConfig.setName("Trace-etl-manager");
+        applicationConfig.setParameters(Maps.newHashMap());
+        applicationConfig.getParameters().put("http_gateway_port", httpGateWayPort);
+        applicationConfig.getParameters().put("dubbo_version", "1.0");
+        applicationConfig.setQosEnable(false);
+        return applicationConfig;
+    }
+
+    @Bean
+    public RegistryConfig registryConfig() {
+        RegistryConfig registryConfig = new RegistryConfig();
+        registryConfig.setAddress(regAddress);
+        return registryConfig;
+    }
+
+    @Bean
+    public ProtocolConfig protocolConfig() {
+        ProtocolConfig protocolConfig = new ProtocolConfig();
+        protocolConfig.setPort(port);
+        protocolConfig.setTransporter("netty4");
+        protocolConfig.setThreadpool("fixed");
+        protocolConfig.setThreads(800);
+        return protocolConfig;
+    }
+
+}
\ No newline at end of file
diff --git a/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/config/NacosConfiguration.java b/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/config/NacosConfiguration.java
new file mode 100644
index 0000000..cb7d29d
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/config/NacosConfiguration.java
@@ -0,0 +1,31 @@
+/*
+ * 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.config;
+
+import com.alibaba.nacos.api.annotation.NacosProperties;
+import com.alibaba.nacos.spring.context.annotation.config.EnableNacosConfig;
+import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = "${nacos.address}"))
+@NacosPropertySource(dataId = "hera_intelligence_config", autoRefreshed = true)
+public class NacosConfiguration {
+}
\ No newline at end of file
diff --git a/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/controller/RootAnalysisController.java b/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/controller/RootAnalysisController.java
index 62ba03c..aad511c 100644
--- a/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/controller/RootAnalysisController.java
+++ b/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/controller/RootAnalysisController.java
@@ -19,13 +19,23 @@
 package org.apache.ozhera.intelligence.controller;
 
 import com.xiaomi.youpin.infra.rpc.Result;
+import com.xiaomi.youpin.infra.rpc.errors.GeneralCodes;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.ozhera.intelligence.domain.rootanalysis.HeraRootCaseAnalyseRes;
+import org.apache.ozhera.intelligence.domain.rootanalysis.LogParam;
+import org.apache.ozhera.intelligence.domain.rootanalysis.MetricsQueryParam;
+import org.apache.ozhera.intelligence.service.LogService;
+import org.apache.ozhera.intelligence.service.MetricsService;
+import org.apache.ozhera.intelligence.service.TraceService;
+import org.apache.ozhera.trace.etl.domain.tracequery.Span;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.apache.ozhera.intelligence.domain.rootanalysis.TraceQueryParam;
-import org.apache.ozhera.intelligence.service.RootAnalysisService;
+
+import java.util.List;
+import java.util.Map;
 
 @RestController
 @RequestMapping("/analysis")
@@ -33,10 +43,44 @@
 public class RootAnalysisController {
 
     @Autowired
-    private RootAnalysisService rootAnalysisService;
+    private TraceService traceService;
 
-    @GetMapping("/trace")
-    public Result<String> traceRootAnalysis(TraceQueryParam param) {
-        return rootAnalysisService.traceRootAnalysis(param);
+    @Autowired
+    private LogService logService;
+
+    @Autowired
+    private MetricsService metricsService;
+
+    @PostMapping("/trace/sectional/span")
+    public Result<List<Span>> traceRootAnalysis(TraceQueryParam param) {
+        try {
+            List<Span> spans = traceService.queryTraceRootAnalysis(param);
+            return Result.success(spans);
+        }catch (Exception e){
+            log.error("trace analyze error , ", e);
+            return Result.fail(GeneralCodes.InternalError, "trace analyze error");
+        }
+    }
+
+    @PostMapping("/log/condition")
+    public Result<List<Map<String, Object>>> logCondition(LogParam param) {
+        try {
+            List<Map<String, Object>> logs = logService.queryLogRootAnalysis(param);
+            return Result.success(logs);
+        }catch (Exception e){
+            log.error("log analyze error , ", e);
+            return Result.fail(GeneralCodes.InternalError, "log analyze error");
+        }
+    }
+
+    @PostMapping("/metrics")
+    public Result<HeraRootCaseAnalyseRes> metrics(MetricsQueryParam param) {
+        try {
+            HeraRootCaseAnalyseRes metrics = metricsService.queryMetricsRootAnalysis(param);
+            return Result.success(metrics);
+        }catch (Exception e){
+            log.error("metrics analyze error , ", e);
+            return Result.fail(GeneralCodes.InternalError, "metrics analyze error");
+        }
     }
 }
diff --git a/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/filter/TokenValidationFilter.java b/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/filter/TokenValidationFilter.java
new file mode 100644
index 0000000..572da05
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-server/src/main/java/org/apache/ozhera/intelligence/filter/TokenValidationFilter.java
@@ -0,0 +1,53 @@
+/*
+ * 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.filter;
+
+import com.alibaba.nacos.api.config.annotation.NacosValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Component
+public class TokenValidationFilter extends OncePerRequestFilter {
+
+    private static final Logger logger = LoggerFactory.getLogger(TokenValidationFilter.class);
+
+    @NacosValue("${analyze.token}")
+    private String validToken;
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws ServletException, IOException {
+        String token = request.getHeader("x-token");
+
+        if (token != null && token.equals(validToken)) {
+            filterChain.doFilter(request, response);
+        } else {
+            logger.warn("Token incorrect, illegal request!");
+            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+        }
+    }
+}
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 a38e97e..5691905 100644
--- a/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/application.properties
+++ b/ozhera-intelligence/ozhera-intelligence-server/src/main/resources/application.properties
@@ -18,4 +18,15 @@
 server.type=${server.type}
 server.port=${server.port}
 
-log.path=${log.path}
\ No newline at end of file
+log.path=${log.path}
+
+dubbo.group=${dubbo.group}
+dubbo.protocol.id=${dubbo.protocol.id}
+dubbo.protocol.name=${dubbo.protocol.name}
+dubbo.protocol.port=${dubbo.protocol.port}
+trace.query.group=${trace.query.group}
+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
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 5ad085d..08fdc82 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
@@ -18,4 +18,15 @@
 server.type=staging
 server.port=8080
 
-log.path=/tmp/work/log
\ No newline at end of file
+log.path=/tmp/work/log
+
+dubbo.group=staging
+dubbo.protocol.id=dubbo
+dubbo.protocol.name=dubbo
+dubbo.protocol.port=-1
+trace.query.group=staging
+trace.query.version=1.0
+log.query.group=
+log.query.version=1.0
+
+nacos.address=nacos:80
\ No newline at end of file
diff --git a/ozhera-intelligence/ozhera-intelligence-service/pom.xml b/ozhera-intelligence/ozhera-intelligence-service/pom.xml
index e1afc94..fc97b77 100644
--- a/ozhera-intelligence/ozhera-intelligence-service/pom.xml
+++ b/ozhera-intelligence/ozhera-intelligence-service/pom.xml
@@ -72,11 +72,16 @@
             <artifactId>spring-test</artifactId>
         </dependency>
 
-        <!-- trace domain -->
+        <!-- trace api -->
         <dependency>
             <groupId>org.apache.ozhera</groupId>
-            <artifactId>trace-etl-domain</artifactId>
-            <version>2.2.5-incubating</version>
+            <artifactId>trace-etl-api</artifactId>
+        </dependency>
+
+        <!-- log api -->
+        <dependency>
+            <groupId>org.apache.ozhera</groupId>
+            <artifactId>log-api</artifactId>
         </dependency>
 
         <dependency>
@@ -88,6 +93,75 @@
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>run.mone</groupId>
+            <artifactId>dubbo</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.alibaba.spring</groupId>
+                    <artifactId>spring-context-support</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- nacos -->
+        <dependency>
+            <groupId>run.mone</groupId>
+            <artifactId>spring-context-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>run.mone</groupId>
+            <artifactId>nacos-client</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-databind</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>run.mone</groupId>
+            <artifactId>dubbo-registry-nacos</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>spring-context-support</artifactId>
+                    <groupId>com.alibaba.spring</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.nacos</groupId>
+            <artifactId>nacos-spring-context</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-databind</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.alibaba.spring</groupId>
+                    <artifactId>spring-context-support</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- okhttp -->
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
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 4a1075d..a59402f 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
@@ -18,18 +18,54 @@
  */
 package org.apache.ozhera.intelligence.service;
 
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.ozhera.log.api.model.dto.LogFilterOptions;
+import org.apache.ozhera.log.api.service.HeraLogApiService;
 import org.springframework.stereotype.Service;
 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 {
 
+    @DubboReference(interfaceClass = HeraLogApiService.class, group = "${log.query.group}", version = "${log.query.version}")
+    private HeraLogApiService heraLogApiService;
+
     /**
+     * To cover the trace time in the log, we extend the trace time by 5 minutes before and after as a condition to query the log
+     */
+    private static final int LOG_QUERY_TIME_GAP = 1000 * 60 * 5;
+
+
+	/**
      * Query logs based on the specified log query conditions.
+     *
      * @param param
      * @return
      */
-    public String queryLogRootAnalysis(LogParam param){
-        return null;
+    public List<Map<String, Object>> queryLogRootAnalysis(LogParam param) {
+        List<Map<String, Object>> maps = heraLogApiService.queryLogData(buildLogFilterOptions(param));
+        return maps;
     }
-}
+
+
+    private LogFilterOptions buildLogFilterOptions(LogParam param) {
+        LogFilterOptions logFilterOptions = new LogFilterOptions();
+        logFilterOptions.setProjectId(Long.parseLong(param.getApplication()));
+        logFilterOptions.setEnvId(Long.parseLong(param.getEnvId()));
+        logFilterOptions.setTraceId(param.getTraceId());
+        Long startTime = Long.parseLong(param.getStartTime());
+        Long duration = Long.parseLong(param.getDuration());
+        Long endTime = startTime + duration;
+        logFilterOptions.setStartTime(String.valueOf(startTime / 1000 - LOG_QUERY_TIME_GAP));
+        logFilterOptions.setEndTime(String.valueOf(endTime / 1000 + LOG_QUERY_TIME_GAP));
+        logFilterOptions.setLevel(param.getLevel());
+        return logFilterOptions;
+    }
+}
\ No newline at end of file
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 9b17a89..0207be1 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
@@ -18,21 +18,231 @@
  */
 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.http.client.utils.URIBuilder;
+import org.apache.ozhera.intelligence.domain.rootanalysis.HeraRootCaseAnalyseRes;
+import org.apache.ozhera.intelligence.domain.rootanalysis.MetricDataRangeSetVector;
+import org.apache.ozhera.intelligence.domain.rootanalysis.MetricRangeResponseVector;
+import org.apache.ozhera.intelligence.util.HttpClient;
 import org.springframework.stereotype.Service;
 import org.apache.ozhera.intelligence.domain.rootanalysis.MetricsQueryParam;
 
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+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 {
 
+    @NacosValue("${prometheus.api.url}")
+    private String prometheusUrl;
+
+    private static final String URI_QUERY_RANGE = "/api/v1/query_range";
+    private static final String P_QUERY = "query";
+    private static final String P_STEP = "step";
+    private static final String P_START = "start";
+    private static final String P_END = "end";
+
     /**
      * Query metrics based on the specified metric query conditions.
-     * @param param
+     *
+     * @param req
      * @return
      */
-    public String queryMetricsRootAnalysis(MetricsQueryParam param){
-        return null;
+    public HeraRootCaseAnalyseRes queryMetricsRootAnalysis(MetricsQueryParam req) {
+        HeraRootCaseAnalyseRes res = new HeraRootCaseAnalyseRes();
+        try {
+            updateParam(req);
+            log.info("updated param is : " + req);
+            String kubePodInfoPromQl = getKubePodInfoPromQl(req.getIp());
+            log.info("getPodNameByKubePodInfo.kubePodInfoPromQl:{}", kubePodInfoPromQl);
+            MetricRangeResponseVector podPodIpListVector = requestPrometheusRangeV2(kubePodInfoPromQl,
+                    req.getStartTime(), req.getEndTime(), req.getEnv());
+            List<MetricDataRangeSetVector> kubePodInfo = podPodIpListVector.getData().getResult();
+            MetricDataRangeSetVector kubePodInfoMetrics = kubePodInfo.get(kubePodInfo.size() - 1);
+            String podName = kubePodInfoMetrics.getMetric().getPod();
+            String cpuPromQl = "max(rate(container_cpu_user_seconds_total{system=\"mione\",application=\"" + req.getApplication() + "\", pod=\"" + podName + "\", image!=\"\", container =~ \"^(?:\\\\d+-0-\\\\d+|faas-sidecar)$\"}[30s]) * 100)";
+            String loadPromQl = "max(container_cpu_load_average_10s{system=\"mione\",application=\"" + req.getApplication() + "\", pod=\"" + podName + "\", image!=\"\", container =~ \"^(?:\\\\d+-0-\\\\d+|faas-sidecar)$\"} / 1000)";
+            String gcMaxTimes = "max(delta(jvm_gc_pause_seconds_count{serverIp=\"" + req.getIp() + "\", application=\"" + req.getApplication() + "\",containerName=\"main\"}[1m]))";
+            String memoryUsedRate = "avg(sum(jvm_memory_used_bytes{application=\"" + req.getApplication() + "\",area=\"heap\",ip=\"" + req.getIp() + "\",containerName=\"main\"}) / sum(jvm_memory_max_bytes{application=\"" + req.getApplication() + "\",area=\"heap\",ip=\"" + req.getIp() + "\",containerName=\"main\"})) * 100";
+            String maxGCDuration = "max(max_over_time(jvm_gc_pause_seconds_max{serverIp=~\"" + req.getIp() + "\", application=\"" + req.getApplication() + "\",containerName=\"main\"}[1m]))";
+            String cpuCount = "system_cpu_count{serverIp=~\"" + req.getIp() + "\", application=\"" + req.getApplication() + "\",containerName=~\".*\"}";
+            log.info("getPodNameByKubePodInfo.cpuPromQl:{}", cpuPromQl);
+            log.info("getPodNameByKubePodInfo.loadPromQl:{}", loadPromQl);
+            log.info("getPodNameByKubePodInfo.gcMaxTimes:{}", gcMaxTimes);
+            log.info("getPodNameByKubePodInfo.memoryUsedRate:{}", memoryUsedRate);
+            log.info("getPodNameByKubePodInfo.maxGCDuration:{}", maxGCDuration);
+            log.info("getPodNameByKubePodInfo.cpuCount:{}", cpuCount);
+            CompletableFuture<MetricRangeResponseVector> cpuFuture = CompletableFuture.supplyAsync(() -> requestPrometheusRangeV2(cpuPromQl,
+                    req.getStartTime(), req.getEndTime(), req.getEnv()), HERA_SOLUTION_METRICS_POOL);
+            CompletableFuture<MetricRangeResponseVector> loadFuture = CompletableFuture.supplyAsync(() -> requestPrometheusRangeV2(loadPromQl,
+                    req.getStartTime(), req.getEndTime(), req.getEnv()), HERA_SOLUTION_METRICS_POOL);
+            CompletableFuture<MetricRangeResponseVector> gcMaxTimesFuture = CompletableFuture.supplyAsync(() -> requestPrometheusRangeV2(gcMaxTimes,
+                    req.getStartTime(), req.getEndTime(), req.getEnv()), HERA_SOLUTION_METRICS_POOL);
+            CompletableFuture<MetricRangeResponseVector> memoryFuture = CompletableFuture.supplyAsync(() -> requestPrometheusRangeV2(memoryUsedRate,
+                    req.getStartTime(), req.getEndTime(), req.getEnv()), HERA_SOLUTION_METRICS_POOL);
+            CompletableFuture<MetricRangeResponseVector> maxGCFuture = CompletableFuture.supplyAsync(() -> requestPrometheusRangeV2(maxGCDuration,
+                    req.getStartTime(), req.getEndTime(), req.getEnv()), HERA_SOLUTION_METRICS_POOL);
+            CompletableFuture<MetricRangeResponseVector> cpuCountFuture = CompletableFuture.supplyAsync(() -> requestPrometheusRangeV2(cpuCount,
+                    req.getStartTime(), req.getEndTime(), req.getEnv()), HERA_SOLUTION_METRICS_POOL);
+            CompletableFuture<Void> allComplete = CompletableFuture.allOf(cpuFuture, loadFuture, gcMaxTimesFuture, memoryFuture, maxGCFuture);
+            allComplete.get(8000, TimeUnit.MILLISECONDS);
+            MetricRangeResponseVector cpuMetrics = cpuFuture.get();
+            if (cpuMetrics != null) {
+                log.info("getPodNameByKubePodInfo cpuMetrics : " + cpuMetrics);
+                List<MetricDataRangeSetVector> cpuResult = cpuMetrics.getData().getResult();
+                if (cpuResult != null && cpuResult.size() > 0) {
+                    List<List<String>> values = cpuResult.get(0).getValues();
+                    res.setMaxCpuUsage(getMaxValue(values));
+                }
+            }
+            MetricRangeResponseVector loadMetrics = loadFuture.get();
+            if (loadMetrics != null) {
+                log.info("getPodNameByKubePodInfo loadMetrics : " + loadMetrics);
+                List<MetricDataRangeSetVector> loadResult = loadMetrics.getData().getResult();
+                if (loadResult != null && loadResult.size() > 0) {
+                    List<List<String>> values = loadResult.get(0).getValues();
+                    res.setMaxLoad(getMaxValue(values));
+                }
+            }
+            MetricRangeResponseVector gcMaxTimesMetrics = gcMaxTimesFuture.get();
+            if (gcMaxTimesMetrics != null) {
+                log.info("getPodNameByKubePodInfo gcMaxTimesMetrics : " + gcMaxTimesMetrics);
+                List<MetricDataRangeSetVector> gcMaxTimesResult = gcMaxTimesMetrics.getData().getResult();
+                if (gcMaxTimesResult != null && gcMaxTimesResult.size() > 0) {
+                    List<List<String>> values = gcMaxTimesResult.get(0).getValues();
+                    res.setMaxSTWCost(getMaxValue(values));
+                }
+            }
+            MetricRangeResponseVector memoryMetrics = memoryFuture.get();
+            if (memoryMetrics != null) {
+                log.info("getPodNameByKubePodInfo memoryMetrics : " + memoryMetrics);
+                List<MetricDataRangeSetVector> memoryResult = memoryMetrics.getData().getResult();
+                if (memoryResult != null && memoryResult.size() > 0) {
+                    List<List<String>> values = memoryResult.get(0).getValues();
+                    res.setMaxJvmHeapUsage(getMaxValue(values));
+                }
+            }
+            MetricRangeResponseVector maxGCMetrics = maxGCFuture.get();
+            if (maxGCMetrics != null) {
+                log.info("getPodNameByKubePodInfo maxGCMetrics : " + maxGCMetrics);
+                List<MetricDataRangeSetVector> maxGCResult = maxGCMetrics.getData().getResult();
+                if (maxGCResult != null && maxGCResult.size() > 0) {
+                    List<List<String>> values = maxGCResult.get(0).getValues();
+                    res.setSTWCountOf1m(getMaxValue(values));
+                }
+            }
+            MetricRangeResponseVector cpuCountMetrics = cpuCountFuture.get();
+            if (cpuCountMetrics != null) {
+                log.info("getPodNameByKubePodInfo maxGCMetrics : " + cpuCountMetrics);
+                List<MetricDataRangeSetVector> cpuCountResult = cpuCountMetrics.getData().getResult();
+                if (cpuCountResult != null && cpuCountResult.size() > 0) {
+                    List<List<String>> values = cpuCountResult.get(0).getValues();
+                    res.setCpuCount(getMaxValue(values));
+                }
+            }
+        } catch (Exception e) {
+            log.error("get root cause analysis error , ", e);
+        }
+        return res;
     }
-}
+
+    private void updateParam(MetricsQueryParam req) {
+        Long startTime = Long.parseLong(req.getStartTime());
+        Long duration = Long.parseLong(req.getDuration());
+        Long endTime = startTime + duration;
+        Long gap = Long.parseLong(req.getGap());
+        // startTime is in microseconds, convert to milliseconds
+        Long startTimeMs = startTime / 1000;
+        Long endTimeMs = endTime / 1000;
+        req.setStartTime(addGap(startTimeMs, gap * -1));
+        req.setEndTime(addGap(endTimeMs, gap));
+        req.setApplication(convertApp(req.getApplication()));
+    }
+
+    private String getKubePodInfoPromQl(String hostIp) {
+        return "count(kube_pod_info{system=\"mione\",pod_ip=~\"" + hostIp + "\"})  by (pod_ip,pod)";
+    }
+
+    private MetricRangeResponseVector requestPrometheusRangeV2(String promQl, String startTime, String endTime, String env) {
+        try {
+            Map<String, String> map = new HashMap<>();
+            map.put(P_QUERY, promQl);  // Metric parameter
+            // step: 1h = 15, 2h = 2 * 15
+            Long multi = (Long.parseLong(endTime) - Long.parseLong(startTime)) / 3600;
+            if (multi < 1) {
+                multi = 1L;
+
+            }
+            map.put(P_STEP, String.valueOf(multi * 15));
+            map.put(P_START, startTime);
+            map.put(P_END, endTime);
+            String url = completeQueryUrl(prometheusUrl, URI_QUERY_RANGE, promQl, map);
+            System.out.println(url);
+            Map<String, String> headers = new HashMap<>();
+            headers.put("Accept", "*/*");
+            log.info("queryPrometheusRangeResponse :  {}", url.toString());
+            String data = HttpClient.get(url.toString(), headers);
+            MetricRangeResponseVector metricResult = new Gson().fromJson(data, MetricRangeResponseVector.class);
+            if (metricResult == null || !"success".equals(metricResult.getStatus())) {
+                return null;
+            } else {
+                return metricResult;
+            }
+        } catch (Exception e) {
+            log.error("requestPrometheusRange err", e);
+            return null;
+        }
+    }
+
+    private String completeQueryUrl(String domain, String path, String query, Map<String, String> map) {
+        URIBuilder builder = new URIBuilder();
+        builder.setScheme("http");
+        builder.setHost(domain);
+        builder.setPath(path);
+        map.forEach(builder::addParameter);
+        URL url = null;
+        try {
+            url = builder.build().toURL();
+        } catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+        return url.toString();
+    }
+
+    private double getMaxValue(List<List<String>> values) {
+        List<Double> temValues = new ArrayList<>();
+        for (List<String> value : values) {
+            temValues.add(Double.valueOf(value.get(1)));
+        }
+        Collections.sort(temValues);
+        return temValues.get(temValues.size() - 1);
+    }
+
+    private String addGap(long time, long gap) {
+        // After calculating the time interval, convert ms to s
+        return String.valueOf((time + gap) / 1000);
+    }
+
+    private String convertApp(String application) {
+        return application.replaceAll("-", "_");
+    }
+}
\ 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 0705d04..b2ec745 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
@@ -18,18 +18,298 @@
  */
 package org.apache.ozhera.intelligence.service;
 
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.ozhera.intelligence.domain.rootanalysis.TraceTreeNode;
+import org.apache.ozhera.trace.etl.api.service.TraceQueryService;
+import org.apache.ozhera.trace.etl.domain.jaegeres.JaegerAttribute;
+import org.apache.ozhera.trace.etl.domain.tracequery.Span;
+import org.apache.ozhera.trace.etl.domain.tracequery.Trace;
+import org.apache.ozhera.trace.etl.domain.tracequery.TraceIdQueryVo;
 import org.springframework.stereotype.Service;
 import org.apache.ozhera.intelligence.domain.rootanalysis.TraceQueryParam;
+import org.apache.ozhera.trace.etl.domain.jaegeres.JaegerProcess;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author dingtao
+ * @date 2025/1/20 11:26
+ */
 @Service
 public class TraceService {
 
     /**
+     * call trace-etl-manager TraceQueryService, The group and version in Dubbo should be consistent with the group and version in TraceQueryServiceImpl in trace-etl-manager.
+     */
+    @DubboReference(interfaceClass = TraceQueryService.class, group = "${trace.query.group}", version = "${trace.query.version}")
+    private TraceQueryService traceQueryService;
+
+    /**
+     * The time range threshold for querying before and after the given timestamp.
+     * The actual query range is calculated by subtracting and adding QUERY_TIME_RANGE to the given timestamp.
+     */
+    private static final long QUERY_TIME_RANGE = 30 * 60 * 1000;
+
+    /**
+     * The maximum depth of the analyzed trace to be retrieved.
+     */
+    private static final int TRACE_DEEP = 5;
+
+
+    private static final String SERVICE_ENV_ID_KEY = "service.env.id";
+    private static final List<String> NOT_RETAIN_SPAN_NAMES = List.of("UDS");
+    private static final List<String> RETAIN_TAGS = Arrays.asList("net.sock.peer.addr", "span.kind", "net.sock.peer.port", "http.target", "net.host.name", "net.peer.name", "net.peer.port", "rpc.service", "rpc.method", "rpc.system", "db.statement", "error", "http.url");
+    private static final List<String> RETAIN_PROCESS_TAGS = Arrays.asList(SERVICE_ENV_ID_KEY, "ip", "service.env", "service.env.id", "service.container.name", "host.name");
+
+    /**
      * Query trace based on the specified trace query conditions.
+     *
      * @param param
      * @return
      */
-    public String queryTraceRootAnalysis(TraceQueryParam param){
-        return null;
+    public List<Span> queryTraceRootAnalysis(TraceQueryParam param) {
+        Trace traceResult = traceQueryService.getByTraceId(buildTraceIdQueryVo(param));
+        List<Span> result = new ArrayList<>();
+        if (traceResult != null && traceResult.getSpans() != null && !traceResult.getSpans().isEmpty()) {
+            // analyze and cut span
+            List<Span> analyze = analyzeTrace(traceResult.getSpans(), TRACE_DEEP);
+            result = getSpansFilter(analyze);
+        }
+        return result;
     }
-}
+
+    /**
+     * Analyze trace information and return a list of key Spans
+     * <p>
+     * This method first builds a TraceTreeNode tree, then analyzes the trace information based on whether errors exist.
+     * If there are errors, it will find and return the most recent error node and its child nodes.
+     * If there are no errors, it will search for time-consuming nodes.
+     *
+     * @param spans The list of Spans to be analyzed
+     * @param N     The number of child nodes to return in case of errors
+     * @return A list containing key Spans, representing error nodes or time-consuming nodes
+     */
+    public List<Span> analyzeTrace(List<Span> spans, int N) {
+        // Build TraceTreeNode tree
+
+        // Build TraceTreeNode tree
+        Map<String, TraceTreeNode> nodeMap = new HashMap<>();
+        boolean hasError = false;
+        for (Span span : spans) {
+            if (hasException(span)) {
+                hasError = true;
+            }
+            TraceTreeNode node = new TraceTreeNode(span);
+
+            nodeMap.put(span.getSpanID(), node);
+        }
+        List<TraceTreeNode> roots = new ArrayList<>();
+        for (TraceTreeNode node : nodeMap.values()) {
+            if (node.getSpan().getReferences().isEmpty() ||
+                    !nodeMap.containsKey(node.getSpan().getReferences().get(0).getSpanID())) {
+                roots.add(node);
+            } else {
+                TraceTreeNode parentNode = nodeMap.get(node.getSpan().getReferences().get(0).getSpanID());
+                parentNode.addChild(node);
+            }
+        }
+        // Sort sibling nodes by startTime
+        for (TraceTreeNode root : roots) {
+            sortChildren(root);
+        }
+        List<Span> result = new ArrayList<>();
+        if (hasError) {
+            // Find error nodes
+            List<TraceTreeNode> errorNodes = new ArrayList<>();
+            for (TraceTreeNode root : roots) {
+                findErrorTargetNode(root, errorNodes);
+                if (errorNodes != null && errorNodes.size() > 0) {
+                    int currentChildCount = 0;
+                    // Sort by Span.startTime, analyze the Span with the latest start time, which is likely the most relevant
+                    errorNodes.sort(Comparator.comparing(s -> s.getSpan().getStartTime()));
+                    TraceTreeNode lastErrorNode = errorNodes.get(errorNodes.size() - 1);
+                    result.add(lastErrorNode.getSpan());
+                    addNChild(result, lastErrorNode, N, currentChildCount);
+                }
+            }
+        } else {
+            // Finding time-consuming nodes is more complex. We start with the root node's duration as a baseline,
+            // and search level by level until there are no more child nodes or no child nodes with significantly high duration.
+            List<TraceTreeNode> slowNodes = new ArrayList<>();
+            for (TraceTreeNode root : roots) {
+                long rootDuration = root.getSpan().getDuration();
+                slowNodes.add(root);
+                findSlowNode(root, slowNodes, rootDuration);
+                for (TraceTreeNode node : slowNodes) {
+                    result.add(node.getSpan());
+
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Filter and process the given list of Spans
+     *
+     * @param spans The list of Spans to be processed
+     * @return The filtered and processed list of Spans
+     * <p>
+     * This method mainly performs the following operations:
+     * 1. Filters out Spans that don't need to be retained based on NOT_RETAIN_SPAN_NAMES
+     * 2. For retained Spans, only keeps tags specified in RETAIN_TAGS
+     * 3. For each Span's Process, only keeps tags specified in RETAIN_PROCESS_TAGS
+     * If the input spans is null or empty, it returns the original spans directly
+     */
+    private List<Span> getSpansFilter(List<Span> spans) {
+        if (spans != null && spans.size() > 0) {
+            List<Span> newSpans = new ArrayList<>();
+            for (Span span : spans) {
+                String operationName = span.getOperationName();
+
+                boolean isRetain = true;
+                for (String filter : NOT_RETAIN_SPAN_NAMES) {
+                    if (operationName.contains(filter)) {
+                        isRetain = false;
+                    }
+                }
+                if (isRetain) {
+                    newSpans.add(span);
+                }
+            }
+            for (Span span : newSpans) {
+                List<JaegerAttribute> newTags = new ArrayList<>();
+                for (JaegerAttribute attribute : span.getTags()) {
+                    if (RETAIN_TAGS.contains(attribute.getKey())) {
+                        newTags.add(attribute);
+                    }
+                }
+                span.setTags(newTags);
+                List<JaegerAttribute> newProcessTags = new ArrayList<>();
+                JaegerProcess process = span.getProcess();
+                List<JaegerAttribute> processTags = process.getTags();
+                for (JaegerAttribute processTag : processTags) {
+                    if (RETAIN_PROCESS_TAGS.contains(processTag.getKey())) {
+                        newProcessTags.add(processTag);
+                    }
+                }
+                process.setTags(newProcessTags);
+            }
+            return newSpans;
+        }
+        return spans;
+    }
+
+    private boolean hasException(Span span) {
+        // Determine if the span contains any errors based on the actual situation
+        for (JaegerAttribute tag : span.getTags()) {
+            if ("error".equals(tag.getKey())) {
+                return true;
+
+
+            }
+        }
+        return false;
+    }
+
+    private void sortChildren(TraceTreeNode node) {
+        if (node.getChildren() != null) {
+            node.getChildren().sort(Comparator.comparingLong(n -> n.getSpan().getStartTime()));
+            for (TraceTreeNode child : node.getChildren()) {
+                sortChildren(child);
+            }
+        }
+    }
+
+    private void findSlowNode(TraceTreeNode root, List<TraceTreeNode> slowNodes, long rootDuration) {
+        // Find nodes with duration greater than 80% of the parent node's duration.
+        // If none found, look for 50%, then 30%, 20%, and finally 10%.
+        if (!root.getChildren().isEmpty()) {
+            for (TraceTreeNode childNode : root.getChildren()) {
+                if (findByPercent(childNode, slowNodes, rootDuration, 0.8)) {
+
+                    findSlowNode(childNode, slowNodes, childNode.getSpan().getDuration());
+                } else if (findByPercent(childNode, slowNodes, rootDuration, 0.5)) {
+                    findSlowNode(childNode, slowNodes, childNode.getSpan().getDuration());
+                } else if (findByPercent(childNode, slowNodes, rootDuration, 0.3)) {
+                    findSlowNode(childNode, slowNodes, childNode.getSpan().getDuration());
+                } else if (findByPercent(childNode, slowNodes, rootDuration, 0.2)) {
+                    findSlowNode(childNode, slowNodes, childNode.getSpan().getDuration());
+                } else if (findByPercent(childNode, slowNodes, rootDuration, 0.1)) {
+                    findSlowNode(childNode, slowNodes, childNode.getSpan().getDuration());
+                }
+            }
+        }
+    }
+
+    private boolean findByPercent(TraceTreeNode parent, List<TraceTreeNode> slowNodes, long rootDuration, double percent) {
+        boolean result = false;
+        for (TraceTreeNode childNode : parent.getChildren()) {
+            if (childNode.getSpan().getDuration() > rootDuration * percent) {
+                result = true;
+                slowNodes.add(childNode);
+            }
+        }
+        return result;
+    }
+
+    private void findErrorTargetNode(TraceTreeNode node, List<TraceTreeNode> errorNodes) {
+        if (hasException(node.getSpan())) {
+            errorNodes.add(node);
+        }
+
+        if (node.getChildren() != null) {
+            for (TraceTreeNode child : node.getChildren()) {
+                findErrorTargetNode(child, errorNodes);
+            }
+        }
+    }
+
+    /**
+     * Add the specified number of child nodes of the targetNode to the result.
+     * First, add the first-level child nodes; if the quantity is not sufficient,
+     * then add the second-level child nodes. If the number of child nodes exceeds afterNumber,
+     * or if there are no more child nodes, the method returns.
+     *
+     * @param result      List to store the resulting Span objects
+     * @param targetNode
+     * @param afterNumber
+     */
+    private void addNChild(List<Span> result, TraceTreeNode targetNode, int afterNumber, int currentChildCount) {
+        List<TraceTreeNode> children = targetNode.getChildren();
+        if (!children.isEmpty()) {
+            List<TraceTreeNode> childs = new ArrayList<>();
+            for (TraceTreeNode treeNode : children) {
+                result.add(treeNode.getSpan());
+                currentChildCount++;
+                if (currentChildCount >= afterNumber) {
+                    return;
+                }
+                if (!treeNode.getChildren().isEmpty()) {
+                    childs.add(treeNode);
+                }
+            }
+            // If the number of first-level child nodes is less than afterNumber, continue adding second-level child nodes
+            for (TraceTreeNode secondChild : childs) {
+                addNChild(result, secondChild, afterNumber, currentChildCount);
+            }
+        }
+    }
+
+    private TraceIdQueryVo buildTraceIdQueryVo(TraceQueryParam param) {
+
+        TraceIdQueryVo vo = new TraceIdQueryVo();
+        vo.setTraceId(param.getTraceId());
+        long startTime = param.getTimeStamp() - QUERY_TIME_RANGE;
+        long endTime = param.getTimeStamp() + QUERY_TIME_RANGE;
+        vo.setStartTime(startTime);
+        vo.setEndTime(endTime);
+        return vo;
+    }
+}
\ No newline at end of file
diff --git a/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/util/CommitPoolUtil.java b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/util/CommitPoolUtil.java
new file mode 100644
index 0000000..ce873e9
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/util/CommitPoolUtil.java
@@ -0,0 +1,48 @@
+/*
+ * 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.util;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class CommitPoolUtil {
+
+    public static final ThreadPoolExecutor HERA_SOLUTION_METRICS_POOL;
+    private static final BlockingQueue<Runnable> heraSolutionMetricsQueue = new ArrayBlockingQueue<>(30);
+    private static final AtomicInteger heraSolutionThreadNumber = new AtomicInteger(1);
+
+    static {
+        HERA_SOLUTION_METRICS_POOL = new ThreadPoolExecutor(15, 20,
+                0L, TimeUnit.MILLISECONDS,
+                heraSolutionMetricsQueue, new ThreadFactory() {
+            @Override
+            public Thread newThread(Runnable r) {
+                Thread thread = new Thread(r);
+                thread.setDaemon(false);
+                thread.setName("hera-solution-metrics" + heraSolutionThreadNumber.getAndIncrement());
+                return thread;
+            }
+        });
+    }
+
+}
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
new file mode 100644
index 0000000..f250ff1
--- /dev/null
+++ b/ozhera-intelligence/ozhera-intelligence-service/src/main/java/org/apache/ozhera/intelligence/util/HttpClient.java
@@ -0,0 +1,92 @@
+/*
+ * 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.util;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+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 {
+
+    private static final OkHttpClient client;
+
+    static {
+        client = new OkHttpClient.Builder()
+                .connectTimeout(10, TimeUnit.SECONDS)
+                .writeTimeout(10, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+    }
+
+    public static JsonObject postRequest(String url, JsonObject jsonObject) {
+        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+        RequestBody body = RequestBody.create(JSON, jsonObject.toString());
+        Request request = new Request.Builder()
+                .url(url)
+                .post(body)
+                .build();
+        try (Response response = client.newCall(request).execute()) {
+            if (!response.isSuccessful()) {
+                throw new IOException("Unexpected code " + response);
+            }
+            return new JsonParser().parse(response.body().string()).getAsJsonObject();
+        } catch (Exception e) {
+            log.error("HttpClient post error, ", e);
+            return null;
+        }
+    }
+
+
+    public static String get(String url, Map<String, String> headers) {
+        Request.Builder requestBuilder = new Request.Builder().url(url);
+
+        if (headers != null) {
+            for (Map.Entry<String, String> entry : headers.entrySet()) {
+                requestBuilder.addHeader(entry.getKey(), entry.getValue());
+            }
+        }
+
+        Request request = requestBuilder.build();
+
+        try (Response response = client.newCall(request).execute()) {
+            if (!response.isSuccessful()) {
+                throw new IOException("Unexpected code " + response);
+            }
+            return response.body().string();
+        } catch (Exception e) {
+            log.error("HttpClient get error, ", e);
+            return null;
+        }
+
+    }
+}
diff --git a/ozhera-intelligence/pom.xml b/ozhera-intelligence/pom.xml
index 3f3c5ac..1a6d9b6 100644
--- a/ozhera-intelligence/pom.xml
+++ b/ozhera-intelligence/pom.xml
@@ -68,6 +68,21 @@
                 <artifactId>trace-etl-domain</artifactId>
                 <version>2.2.5-incubating</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.ozhera</groupId>
+                <artifactId>trace-etl-api</artifactId>
+                <version>2.2.5-incubating</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.ozhera</groupId>
+                <artifactId>log-api</artifactId>
+                <version>2.2.5-incubating</version>
+            </dependency>
+            <dependency>
+                <groupId>com.squareup.okhttp3</groupId>
+                <artifactId>okhttp</artifactId>
+                <version>4.12.0</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/intelligence/ozhera_intelligence.yml b/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/intelligence/ozhera_intelligence.yml
new file mode 100644
index 0000000..90cb38a
--- /dev/null
+++ b/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/intelligence/ozhera_intelligence.yml
@@ -0,0 +1,41 @@
+# 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.
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: ozhera-intelligence
+  namespace: ozhera-namespace
+  labels:
+    app: ozhera-intelligence
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: ozhera-intelligence
+  template:
+    metadata:
+      labels:
+        app: ozhera-intelligence
+    spec:
+      containers:
+      - name: ozhera-intelligence-container
+        image: herahub/opensource-pub:ozhera-intelligence-2.2.5-incubating-beta-v1
+        imagePullPolicy: Always
+        ports:
+        - containerPort: 4446
+        resources:
+          limits:
+            cpu: '500m'
+            memory: 1Gi
diff --git "a/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/nacos/config/hera_intelligence_config_\043_DEFAULT_GROUP.properties" "b/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/nacos/config/hera_intelligence_config_\043_DEFAULT_GROUP.properties"
new file mode 100644
index 0000000..5bf79da
--- /dev/null
+++ "b/ozhera-operator/ozhera-operator-server/src/main/resources/ozhera_init/nacos/config/hera_intelligence_config_\043_DEFAULT_GROUP.properties"
@@ -0,0 +1,17 @@
+# 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.
+analyze.token=
+dubbo.registry.address=nacos://${hera.nacos.address}
+prometheus.api.url=${hera.prometheus.url}
diff --git a/readme/images/ozhera-intelligence.png b/readme/images/ozhera-intelligence.png
new file mode 100644
index 0000000..79d9020
--- /dev/null
+++ b/readme/images/ozhera-intelligence.png
Binary files differ
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
new file mode 100644
index 0000000..d657d5d
--- /dev/null
+++ b/trace-etl/trace-etl-api/src/main/java/org/apache/ozhera/trace/etl/api/service/TraceQueryService.java
@@ -0,0 +1,36 @@
+/*
+ * 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.trace.etl.api.service;
+
+import org.apache.ozhera.trace.etl.domain.tracequery.Trace;
+import org.apache.ozhera.trace.etl.domain.tracequery.TraceIdQueryVo;
+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);
+
+    Trace getByTraceId(TraceIdQueryVo vo);
+}
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
new file mode 100644
index 0000000..bc8bc30
--- /dev/null
+++ b/trace-etl/trace-etl-manager/src/main/java/org/apache/ozhera/trace/etl/manager/dubbo/TraceQueryServiceImpl.java
@@ -0,0 +1,61 @@
+/*
+ * 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.trace.etl.manager.dubbo;
+
+import org.apache.dubbo.config.annotation.Service;
+import org.apache.ozhera.trace.etl.api.service.DataSourceService;
+import org.apache.ozhera.trace.etl.api.service.TraceQueryService;
+import org.apache.ozhera.trace.etl.domain.tracequery.Trace;
+import org.apache.ozhera.trace.etl.domain.tracequery.TraceIdQueryVo;
+import org.apache.ozhera.trace.etl.domain.tracequery.TraceListQueryVo;
+import org.apache.ozhera.trace.etl.domain.tracequery.TraceQueryResult;
+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 {
+
+    @Autowired
+    private DataSourceService dataSourceService;
+
+    @Override
+    public List<Trace> getList(TraceListQueryVo vo) {
+        TraceQueryResult<List<Trace>> result = dataSourceService.getList(vo);
+        if (result != null) {
+            return result.getData();
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public Trace getByTraceId(TraceIdQueryVo vo) {
+        TraceQueryResult<List<Trace>> result = dataSourceService.getByTraceId(vo);
+        if (result != null) {
+            return result.getData().getFirst();
+        } else {
+            return null;
+        }
+    }
+}