diff --git a/pom.xml b/pom.xml
index 88b5cfe31..7765d69e7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,7 @@
1.5.10
6.2.2.Final
1.3.2
+ 0.16.0
1.14.3
0.10.7
9.1.6
@@ -114,6 +115,7 @@
1.2.17
2.17.1
1.7.36
+ 9.0.108
false
@@ -378,6 +380,29 @@
druid-spring-boot-starter
${druid-spring-boot-starter.version}
+
+
+ io.prometheus
+ simpleclient
+ ${prometheus.simpleclient.version}
+
+
+ io.prometheus
+ simpleclient_common
+ ${prometheus.simpleclient.version}
+
+
+
+ io.prometheus
+ simpleclient_hotspot
+ ${prometheus.simpleclient.version}
+
+
+
+ io.prometheus
+ simpleclient_httpserver
+ ${prometheus.simpleclient.version}
+
org.hibernate.validator
@@ -549,6 +574,12 @@
compile
+
+ org.apache.tomcat.embed
+ tomcat-embed-core
+ ${tomcat-embed-core.version}
+
+
org.apache.seatunnel
datasource-s3
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-jdbc-db2/pom.xml b/seatunnel-datasource/seatunnel-datasource-plugins/datasource-jdbc-db2/pom.xml
index a13423735..881f03151 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-jdbc-db2/pom.xml
+++ b/seatunnel-datasource/seatunnel-datasource-plugins/datasource-jdbc-db2/pom.xml
@@ -63,10 +63,6 @@
db2jcc
db2jcc4
-
- org.apache.seatunnel
- seatunnel-api
-
diff --git a/seatunnel-server/seatunnel-app/pom.xml b/seatunnel-server/seatunnel-app/pom.xml
index cc7578e1f..59d4fa3ae 100644
--- a/seatunnel-server/seatunnel-app/pom.xml
+++ b/seatunnel-server/seatunnel-app/pom.xml
@@ -325,6 +325,11 @@
spring-security-ldap
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
com.baomidou
mybatis-plus-boot-starter
@@ -391,6 +396,24 @@
h2
+
+
+ io.prometheus
+ simpleclient
+
+
+ io.prometheus
+ simpleclient_common
+
+
+ io.prometheus
+ simpleclient_hotspot
+
+
+ io.prometheus
+ simpleclient_httpserver
+
+
org.springframework.boot
spring-boot-starter-test
@@ -440,6 +463,11 @@
+
+ org.apache.tomcat.embed
+ tomcat-embed-core
+
+
org.apache.seatunnel
datasource-kafka
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/adapter/SeatunnelWebAdapter.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/adapter/SeatunnelWebAdapter.java
index 0974e4562..8b81a90eb 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/adapter/SeatunnelWebAdapter.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/adapter/SeatunnelWebAdapter.java
@@ -44,6 +44,7 @@ public class SeatunnelWebAdapter implements WebMvcConfigurer {
public static final String REGISTER_PATH_PATTERN = "/users/register";
private static final String RESOURCE_NAME_PATH_PATTERN =
"/seatunnel/api/v1/resources/workspace";
+ private static final String METRIC_PATH_PATTERN = "/metrics";
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
@@ -77,6 +78,7 @@ public void addInterceptors(InterceptorRegistry registry) {
LOGIN_PATH_PATTERN,
REGISTER_PATH_PATTERN,
RESOURCE_NAME_PATH_PATTERN,
+ METRIC_PATH_PATTERN,
"/swagger-resources/**",
"/webjars/**",
"/v2/**",
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobDefinitionController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobDefinitionController.java
index 3da3bf7ca..d9bb2766b 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobDefinitionController.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobDefinitionController.java
@@ -22,6 +22,8 @@
import org.apache.seatunnel.app.domain.request.job.JobReq;
import org.apache.seatunnel.app.domain.response.PageInfo;
import org.apache.seatunnel.app.domain.response.job.JobDefinitionRes;
+import org.apache.seatunnel.app.metrics.annotations.Counted;
+import org.apache.seatunnel.app.metrics.annotations.Timed;
import org.apache.seatunnel.app.service.IJobDefinitionService;
import org.apache.seatunnel.app.service.IJobTaskService;
import org.apache.seatunnel.server.common.CodeGenerateUtils;
@@ -54,6 +56,12 @@ public class JobDefinitionController {
*
* @return created job id
*/
+ @Counted(
+ name = "create_job_definition_request",
+ help = "Total number of create job definition requests")
+ @Timed(
+ name = "create_job_definition_request_latency",
+ help = "Latency of create job definition API in seconds")
@PostMapping
@ApiOperation(value = "create job definition", httpMethod = "POST")
Result createJobDefinition(@RequestBody JobReq jobReq)
@@ -65,6 +73,9 @@ Result createJobDefinition(@RequestBody JobReq jobReq)
}
}
+ @Counted(
+ name = "get_job_definitions_request",
+ help = "Total number of get job definitions request")
@GetMapping
@ApiOperation(value = "get job definition", httpMethod = "GET")
Result> getJobDefinition(
@@ -75,12 +86,21 @@ Result> getJobDefinition(
return Result.success(jobService.getJob(searchName, pageNo, pageSize, jobMode));
}
+ @Counted(
+ name = "get_job_definition_by_id_request",
+ help = "Total number of get job definition by id requests")
@GetMapping("/{jobId}")
@ApiOperation(value = "get job definition", httpMethod = "GET")
Result getJobDefinition(@PathVariable long jobId) {
return Result.success(jobService.getJobDefinitionByJobId(jobId));
}
+ @Counted(
+ name = "delete_job_definition_request",
+ help = "Total number of delete job definition requests")
+ @Timed(
+ name = "delete_job_definition_request_latency",
+ help = "Latency of delete job definition API in seconds")
@DeleteMapping
@ApiOperation(value = "delete job definition", httpMethod = "DELETE")
Result deleteJobDefinition(
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobExecutorController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobExecutorController.java
index b88224288..9393ec9c5 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobExecutorController.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobExecutorController.java
@@ -22,6 +22,7 @@
import org.apache.seatunnel.app.domain.request.job.JobExecParam;
import org.apache.seatunnel.app.domain.response.executor.JobExecutionStatus;
import org.apache.seatunnel.app.domain.response.executor.JobExecutorRes;
+import org.apache.seatunnel.app.metrics.annotations.Counted;
import org.apache.seatunnel.app.service.IJobExecutorService;
import org.apache.seatunnel.app.service.IJobInstanceService;
import org.apache.seatunnel.app.service.ITaskInstanceService;
@@ -53,6 +54,7 @@ public class JobExecutorController {
@Resource private IJobInstanceService jobInstanceService;
@Resource private ITaskInstanceService taskInstanceService;
+ @Counted(name = "execute_job_request", help = "Total number of execute job requests")
@PostMapping("/execute")
@ApiOperation(value = "Execute synchronization tasks", httpMethod = "POST")
public Result jobExecutor(
@@ -77,6 +79,7 @@ public Result resource(
}
}
+ @Counted(name = "pause_job_request", help = "Total number of pause job requests")
@GetMapping("/pause")
public Result jobPause(
@ApiParam(value = "jobInstanceId", required = true) @RequestParam Long jobInstanceId) {
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobTaskController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobTaskController.java
index 0e2fd1e9f..49d81c0ee 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobTaskController.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/JobTaskController.java
@@ -22,6 +22,8 @@
import org.apache.seatunnel.app.domain.request.job.JobTaskInfo;
import org.apache.seatunnel.app.domain.request.job.PluginConfig;
import org.apache.seatunnel.app.domain.response.job.JobTaskCheckRes;
+import org.apache.seatunnel.app.metrics.annotations.Counted;
+import org.apache.seatunnel.app.metrics.annotations.Timed;
import org.apache.seatunnel.app.service.IJobTaskService;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -44,6 +46,10 @@ public class JobTaskController {
@Resource private IJobTaskService jobTaskService;
+ @Counted(name = "save_job_dag_request", help = "Total number of save job dag requests")
+ @Timed(
+ name = "save_job_dag_request_latency",
+ help = "Latency of save job dag request in seconds")
@PostMapping("/dag/{jobVersionId}")
@ApiOperation(value = "save job dag", httpMethod = "POST")
Result saveJobDAG(
@@ -59,6 +65,10 @@ Result getJob(
return Result.success(jobTaskService.getTaskConfig(jobVersionId));
}
+ @Counted(name = "save_job_task_request", help = "Total number of save job task requests")
+ @Timed(
+ name = "save_job_task_request_latency",
+ help = "Latency of save job task request in seconds")
@PostMapping("/task/{jobVersionId}")
@ApiOperation(value = "save or update single task", httpMethod = "POST")
Result saveSingleTask(
@@ -77,6 +87,10 @@ Result getSingleTask(
return Result.success(jobTaskService.getSingleTask(jobVersionId, pluginId));
}
+ @Counted(name = "delete_job_task_request", help = "Total number of delete job task requests")
+ @Timed(
+ name = "delete_job_task_request_latency",
+ help = "Latency of delete job task request in seconds")
@DeleteMapping("/task/{jobVersionId}")
@ApiOperation(value = "delete single task", httpMethod = "DELETE")
Result deleteSingleTask(
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceController.java
index 85da2ac5a..673c7d381 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceController.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceController.java
@@ -29,6 +29,8 @@
import org.apache.seatunnel.app.domain.response.PageInfo;
import org.apache.seatunnel.app.domain.response.datasource.DatasourceDetailRes;
import org.apache.seatunnel.app.domain.response.datasource.DatasourceRes;
+import org.apache.seatunnel.app.metrics.annotations.Counted;
+import org.apache.seatunnel.app.metrics.annotations.Timed;
import org.apache.seatunnel.app.service.IDatasourceService;
import org.apache.seatunnel.app.utils.CartesianProductUtils;
import org.apache.seatunnel.app.utils.PropertyUtils;
@@ -80,6 +82,8 @@ public class SeatunnelDatasourceController extends BaseController {
private static final List wsSupportDatasources =
PropertyUtils.getList(Constants.WS_SUPPORT_DATASOURCES, Constants.COMMA);
+ @Counted(name = "create_datasource_requests", help = "Number of create datasource requests")
+ @Timed(name = "create_datasource_latency", help = "Latency of create datasource API")
@ApiOperation(value = "create datasource", notes = "create datasource")
@ApiImplicitParams({
@ApiImplicitParam(
@@ -120,6 +124,10 @@ Result createDatasource(@RequestBody DatasourceReq req) {
stringStringMap));
}
+ @Counted(
+ name = "test_connection_requests",
+ help = "Number of test datasource connection requests")
+ @Timed(name = "test_connection_latency", help = "Latency of check datasource connection API")
@ApiOperation(value = "test datasource connection", notes = "test datasource connection")
@ApiImplicitParams({
@ApiImplicitParam(
@@ -142,6 +150,8 @@ Result testConnect(@RequestBody DatasourceCheckReq req) {
req.getPluginName(), DEFAULT_PLUGIN_VERSION, req.getDatasourceConfig()));
}
+ @Counted(name = "update_datasource_requests", help = "Number of update datasource requests")
+ @Timed(name = "update_datasource_latency", help = "Latency of update datasource API")
@ApiOperation(value = "update datasource", notes = "update datasource")
@ApiImplicitParams({
@ApiImplicitParam(
@@ -176,6 +186,8 @@ Result updateDatasource(
stringStringMap));
}
+ @Counted(name = "delete_datasource_requests", help = "Number of delete datasource requests")
+ @Timed(name = "delete_datasource_latency", help = "Latency of delete datasource API")
@ApiOperation(value = "delete datasource by id", notes = "delete datasource by id")
@DeleteMapping("/{id}")
Result deleteDatasource(@PathVariable("id") String id) {
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/TaskInstanceController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/TaskInstanceController.java
index 128c2e61b..acbab8826 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/TaskInstanceController.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/TaskInstanceController.java
@@ -19,6 +19,8 @@
import org.apache.seatunnel.app.common.Result;
import org.apache.seatunnel.app.domain.dto.job.SeaTunnelJobInstanceDto;
+import org.apache.seatunnel.app.metrics.annotations.Counted;
+import org.apache.seatunnel.app.metrics.annotations.Timed;
import org.apache.seatunnel.app.service.ITaskInstanceService;
import org.apache.seatunnel.app.utils.PageInfo;
import org.apache.seatunnel.common.constants.JobMode;
@@ -37,6 +39,8 @@ public class TaskInstanceController {
@Autowired ITaskInstanceService taskInstanceService;
+ @Counted(name = "number_of_job_metric_request", help = "total number of job metrics request")
+ @Timed(name = "job_metric_request_latency", help = "Latency of job metric api in seconds")
@GetMapping("/jobMetrics")
@ApiOperation(value = "get the jobMetrics list ", httpMethod = "GET")
public Result> getTaskInstanceList(
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/UserController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/UserController.java
index 59c68ab4b..cf1ff2e0f 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/UserController.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/UserController.java
@@ -25,6 +25,8 @@
import org.apache.seatunnel.app.domain.response.PageInfo;
import org.apache.seatunnel.app.domain.response.user.AddUserRes;
import org.apache.seatunnel.app.domain.response.user.UserSimpleInfoRes;
+import org.apache.seatunnel.app.metrics.annotations.Counted;
+import org.apache.seatunnel.app.metrics.annotations.Timed;
import org.apache.seatunnel.app.service.IUserService;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -110,6 +112,8 @@ public Result disable(
return Result.success();
}
+ @Counted(name = "user_login", help = "total number of user login request")
+ @Timed(name = "user_login_request_latency", help = "Latency of login request in seconds")
@PostMapping("/login")
public Result login(
@RequestBody UserLoginReq req,
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/annotations/Counted.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/annotations/Counted.java
new file mode 100644
index 000000000..bce1ecfe2
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/annotations/Counted.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.seatunnel.app.metrics.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Counted {
+ String name();
+
+ String help() default "";
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/annotations/Timed.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/annotations/Timed.java
new file mode 100644
index 000000000..e8fe2ad09
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/annotations/Timed.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.seatunnel.app.metrics.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Timed {
+ String name();
+
+ String help() default "";
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/aop/MetricsAspect.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/aop/MetricsAspect.java
new file mode 100644
index 000000000..3833dcd17
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/aop/MetricsAspect.java
@@ -0,0 +1,88 @@
+/*
+ * 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.seatunnel.app.metrics.aop;
+
+import org.apache.seatunnel.app.metrics.annotations.Counted;
+import org.apache.seatunnel.app.metrics.annotations.Timed;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+
+import io.prometheus.client.CollectorRegistry;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Summary;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Aspect
+@Component
+@ConditionalOnProperty(name = "seatunnel-web.telemetry.enabled", havingValue = "true")
+public class MetricsAspect {
+
+ private final CollectorRegistry collectorRegistry;
+
+ private final Map counters = new ConcurrentHashMap<>();
+ private final Map summaries = new ConcurrentHashMap<>();
+
+ @Autowired
+ public MetricsAspect(CollectorRegistry collectorRegistry) {
+ this.collectorRegistry = collectorRegistry;
+ }
+
+ @Before("@annotation(counted)")
+ public void beforeCounted(Counted counted) {
+ String name = counted.name();
+ String help = counted.help();
+
+ Counter counter =
+ counters.computeIfAbsent(
+ name,
+ key ->
+ Counter.build()
+ .name(key)
+ .help(help.isEmpty() ? "Counter for " + key : help)
+ .register(collectorRegistry));
+
+ counter.inc();
+ }
+
+ @Around("@annotation(timed)")
+ public Object aroundTimed(ProceedingJoinPoint joinPoint, Timed timed) throws Throwable {
+ String name = timed.name();
+ String help = timed.help();
+
+ Summary summary =
+ summaries.computeIfAbsent(
+ name,
+ key ->
+ Summary.build()
+ .name(key)
+ .help(help.isEmpty() ? "Summary for " + key : help)
+ .register(collectorRegistry));
+
+ try (Summary.Timer ignored = summary.startTimer()) {
+ return joinPoint.proceed();
+ }
+ }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/config/MetricsFilter.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/config/MetricsFilter.java
new file mode 100644
index 000000000..fcce318a4
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/config/MetricsFilter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.seatunnel.app.metrics.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import java.io.IOException;
+
+@Component
+public class MetricsFilter implements Filter {
+
+ @Value("${seatunnel-web.telemetry.port:8802}")
+ private String telemetryPort;
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ HttpServletRequest httpRequest = (HttpServletRequest) request;
+ if (httpRequest.getLocalPort() == Integer.parseInt(telemetryPort)
+ && "/metrics".equals(httpRequest.getRequestURI())) {
+ chain.doFilter(request, response); // Allow metrics requests
+ } else if (httpRequest.getLocalPort() == Integer.parseInt(telemetryPort)) {
+ response.getWriter().write("Access Denied");
+ response.getWriter().flush();
+ } else {
+ chain.doFilter(request, response); // Allow other requests on the default port
+ }
+ }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/config/MetricsPortConfig.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/config/MetricsPortConfig.java
new file mode 100644
index 000000000..1a32bc69e
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/config/MetricsPortConfig.java
@@ -0,0 +1,44 @@
+/*
+ * 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.seatunnel.app.metrics.config;
+
+import org.apache.catalina.connector.Connector;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MetricsPortConfig {
+
+ @Value("${seatunnel-web.telemetry.port:8802}")
+ private String telemetryPort;
+
+ @Bean
+ public WebServerFactoryCustomizer metricsConnectorCustomizer() {
+ return factory -> {
+ Connector metricsConnector =
+ new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
+ metricsConnector.setPort(
+ Integer.parseInt(telemetryPort)); // Set the desired port for metrics
+ factory.addAdditionalTomcatConnectors(metricsConnector);
+ };
+ }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/config/PrometheusConfig.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/config/PrometheusConfig.java
new file mode 100644
index 000000000..645328e15
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/config/PrometheusConfig.java
@@ -0,0 +1,42 @@
+/*
+ * 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.seatunnel.app.metrics.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import io.prometheus.client.CollectorRegistry;
+import io.prometheus.client.hotspot.DefaultExports;
+
+import javax.annotation.PostConstruct;
+
+@Configuration
+@ConditionalOnProperty(name = "seatunnel-web.telemetry.enabled", havingValue = "true")
+public class PrometheusConfig {
+
+ @PostConstruct
+ public void init() {
+ DefaultExports.initialize();
+ }
+
+ @Bean
+ public CollectorRegistry collectorRegistry() {
+ return CollectorRegistry.defaultRegistry;
+ }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/controller/MetricsController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/controller/MetricsController.java
new file mode 100644
index 000000000..713b487ed
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/metrics/controller/MetricsController.java
@@ -0,0 +1,49 @@
+/*
+ * 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.seatunnel.app.metrics.controller;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.prometheus.client.CollectorRegistry;
+import io.prometheus.client.exporter.common.TextFormat;
+
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+import java.io.Writer;
+
+@RestController
+@ConditionalOnProperty(name = "seatunnel-web.telemetry.enabled", havingValue = "true")
+public class MetricsController {
+
+ private final CollectorRegistry collectorRegistry;
+
+ public MetricsController(CollectorRegistry collectorRegistry) {
+ this.collectorRegistry = collectorRegistry;
+ }
+
+ @GetMapping("/metrics")
+ public void scrape(HttpServletResponse response) throws IOException {
+ response.setContentType(TextFormat.CONTENT_TYPE_004);
+ try (Writer writer = response.getWriter()) {
+ TextFormat.write004(writer, collectorRegistry.metricFamilySamples());
+ }
+ }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/resources/application.yml b/seatunnel-server/seatunnel-app/src/main/resources/application.yml
index 57117794e..e67dd0c9b 100644
--- a/seatunnel-server/seatunnel-app/src/main/resources/application.yml
+++ b/seatunnel-server/seatunnel-app/src/main/resources/application.yml
@@ -60,6 +60,9 @@ seatunnel-web:
- password
- auth
access-controller-class: org.apache.seatunnel.app.permission.SeatunnelAccessControllerDefaultImpl
+ telemetry:
+ enabled: false
+ port: 8802
---
spring:
config:
diff --git a/seatunnel-web-it/src/test/resources/application.yml b/seatunnel-web-it/src/test/resources/application.yml
index d691a7127..bf258a084 100644
--- a/seatunnel-web-it/src/test/resources/application.yml
+++ b/seatunnel-web-it/src/test/resources/application.yml
@@ -56,6 +56,9 @@ seatunnel-web:
- password
- auth
access-controller-class: org.apache.seatunnel.app.common.AccessControllerTestingImp
+ telemetry:
+ enabled: false
+ port: 8803
---
spring:
diff --git a/tools/dependencies/known-dependencies.txt b/tools/dependencies/known-dependencies.txt
index d9b7e900e..89c1f7452 100644
--- a/tools/dependencies/known-dependencies.txt
+++ b/tools/dependencies/known-dependencies.txt
@@ -168,7 +168,8 @@ simpleclient_httpserver-0.16.0.jar
simpleclient_tracer_common-0.16.0.jar
simpleclient_tracer_otel-0.16.0.jar
simpleclient_tracer_otel_agent-0.16.0.jar
-
+tomcat-annotations-api-9.0.108.jar
+tomcat-embed-core-9.0.108.jar