You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@inlong.apache.org by he...@apache.org on 2022/09/02 02:53:03 UTC

[inlong] branch master updated: [INLONG-5765][Manager] Add heartbeat API in the manager client (#5766)

This is an automated email from the ASF dual-hosted git repository.

healchow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git


The following commit(s) were added to refs/heads/master by this push:
     new cb9d97f08 [INLONG-5765][Manager] Add heartbeat API in the manager client (#5766)
cb9d97f08 is described below

commit cb9d97f08ee9cb2753e458d404af20db0916dab2
Author: haifxu <xh...@gmail.com>
AuthorDate: Fri Sep 2 10:52:58 2022 +0800

    [INLONG-5765][Manager] Add heartbeat API in the manager client (#5766)
---
 .../inlong/manager/client/api/Heartbeat.java       |  79 ++++++++
 .../manager/client/api/impl/HeartbeatImpl.java     | 100 ++++++++++
 .../client/api/inner/client/ClientFactory.java     |   3 +
 .../client/api/inner/client/HeartbeatClient.java   | 146 +++++++++++++++
 .../manager/client/api/service/HeartbeatApi.java   |  53 ++++++
 .../client/api/inner/HeartbeatClientTest.java      | 204 +++++++++++++++++++++
 .../pojo/heartbeat/ComponentHeartbeatResponse.java |   6 +
 .../pojo/heartbeat/GroupHeartbeatResponse.java     |   6 +
 .../pojo/heartbeat/StreamHeartbeatResponse.java    |   6 +
 9 files changed, 603 insertions(+)

diff --git a/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/Heartbeat.java b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/Heartbeat.java
new file mode 100644
index 000000000..0bb40c148
--- /dev/null
+++ b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/Heartbeat.java
@@ -0,0 +1,79 @@
+/*
+ * 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.inlong.manager.client.api;
+
+import org.apache.inlong.manager.pojo.common.PageResult;
+import org.apache.inlong.manager.pojo.heartbeat.ComponentHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.GroupHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatPageRequest;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatQueryRequest;
+import org.apache.inlong.manager.pojo.heartbeat.StreamHeartbeatResponse;
+
+/**
+ * Heartbeat interface.
+ */
+public interface Heartbeat {
+
+    /**
+     * Get component heartbeat
+     *
+     * @param request query request of heartbeat
+     * @return component heartbeat
+     */
+    ComponentHeartbeatResponse getComponentHeartbeat(HeartbeatQueryRequest request);
+
+    /**
+     * Get inlong group heartbeat
+     *
+     * @param request query request of heartbeat
+     * @return group heartbeat
+     */
+    GroupHeartbeatResponse getGroupHeartbeat(HeartbeatQueryRequest request);
+
+    /**
+     * Get inlong stream heartbeat
+     *
+     * @param request query request of heartbeat
+     * @return stream heartbeat
+     */
+    StreamHeartbeatResponse getStreamHeartbeat(HeartbeatQueryRequest request);
+
+    /**
+     * List component heartbeat by page
+     *
+     * @param request paging query request
+     * @return list of component heartbeat
+     */
+    PageResult<ComponentHeartbeatResponse> listComponentHeartbeat(HeartbeatPageRequest request);
+
+    /**
+     * List group heartbeat by page
+     *
+     * @param request paging query request
+     * @return list of group heartbeat
+     */
+    PageResult<GroupHeartbeatResponse> listGroupHeartbeat(HeartbeatPageRequest request);
+
+    /**
+     * List stream heartbeat by page
+     *
+     * @param request paging query request
+     * @return list of stream heartbeat
+     */
+    PageResult<StreamHeartbeatResponse> listStreamHeartbeat(HeartbeatPageRequest request);
+}
diff --git a/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/impl/HeartbeatImpl.java b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/impl/HeartbeatImpl.java
new file mode 100644
index 000000000..9d2f7079c
--- /dev/null
+++ b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/impl/HeartbeatImpl.java
@@ -0,0 +1,100 @@
+/*
+ * 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.inlong.manager.client.api.impl;
+
+import org.apache.inlong.manager.client.api.ClientConfiguration;
+import org.apache.inlong.manager.client.api.Heartbeat;
+import org.apache.inlong.manager.client.api.inner.client.ClientFactory;
+import org.apache.inlong.manager.client.api.inner.client.HeartbeatClient;
+import org.apache.inlong.manager.client.api.util.ClientUtils;
+import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
+import org.apache.inlong.manager.common.util.Preconditions;
+import org.apache.inlong.manager.pojo.common.PageResult;
+import org.apache.inlong.manager.pojo.heartbeat.ComponentHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.GroupHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatPageRequest;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatQueryRequest;
+import org.apache.inlong.manager.pojo.heartbeat.StreamHeartbeatResponse;
+
+/**
+ * Heartbeat interface implementation
+ */
+public class HeartbeatImpl implements Heartbeat {
+
+    private final HeartbeatClient heartbeatClient;
+
+    public HeartbeatImpl(ClientConfiguration configuration) {
+        ClientFactory clientFactory = ClientUtils.getClientFactory(configuration);
+        this.heartbeatClient = clientFactory.getHeartbeatClient();
+    }
+
+    @Override
+    public ComponentHeartbeatResponse getComponentHeartbeat(HeartbeatQueryRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInstance(), ErrorCodeEnum.REQUEST_INSTANCE_EMPTY.getMessage());
+
+        return heartbeatClient.getComponentHeartbeat(request);
+    }
+
+    @Override
+    public GroupHeartbeatResponse getGroupHeartbeat(HeartbeatQueryRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInstance(), ErrorCodeEnum.REQUEST_INSTANCE_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInlongGroupId(), ErrorCodeEnum.GROUP_ID_IS_EMPTY.getMessage());
+
+        return heartbeatClient.getGroupHeartbeat(request);
+    }
+
+    @Override
+    public StreamHeartbeatResponse getStreamHeartbeat(HeartbeatQueryRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInstance(), ErrorCodeEnum.REQUEST_INSTANCE_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInlongGroupId(), ErrorCodeEnum.GROUP_ID_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInlongStreamId(), ErrorCodeEnum.STREAM_ID_IS_EMPTY.getMessage());
+
+        return heartbeatClient.getStreamHeartbeat(request);
+    }
+
+    @Override
+    public PageResult<ComponentHeartbeatResponse> listComponentHeartbeat(HeartbeatPageRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+
+        return heartbeatClient.listComponentHeartbeat(request);
+    }
+
+    @Override
+    public PageResult<GroupHeartbeatResponse> listGroupHeartbeat(HeartbeatPageRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+
+        return heartbeatClient.listGroupHeartbeat(request);
+    }
+
+    @Override
+    public PageResult<StreamHeartbeatResponse> listStreamHeartbeat(HeartbeatPageRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInlongGroupId(), ErrorCodeEnum.GROUP_ID_IS_EMPTY.getMessage());
+
+        return heartbeatClient.listStreamHeartbeat(request);
+    }
+}
diff --git a/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/inner/client/ClientFactory.java b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/inner/client/ClientFactory.java
index c82e3618b..a6c8cdc64 100644
--- a/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/inner/client/ClientFactory.java
+++ b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/inner/client/ClientFactory.java
@@ -46,6 +46,8 @@ public class ClientFactory {
 
     private final NoAuthClient noAuthClient;
 
+    private final HeartbeatClient heartbeatClient;
+
     private final WorkflowApproverClient workflowApproverClient;
 
     public ClientFactory(ClientConfiguration configuration) {
@@ -59,6 +61,7 @@ public class ClientFactory {
         dataNodeClient = new DataNodeClient(configuration);
         userClient = new UserClient(configuration);
         noAuthClient = new NoAuthClient(configuration);
+        heartbeatClient = new HeartbeatClient(configuration);
         workflowApproverClient = new WorkflowApproverClient(configuration);
     }
 }
diff --git a/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/inner/client/HeartbeatClient.java b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/inner/client/HeartbeatClient.java
new file mode 100644
index 000000000..d8af81a2f
--- /dev/null
+++ b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/inner/client/HeartbeatClient.java
@@ -0,0 +1,146 @@
+/*
+ * 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.inlong.manager.client.api.inner.client;
+
+import org.apache.inlong.manager.client.api.ClientConfiguration;
+import org.apache.inlong.manager.client.api.service.HeartbeatApi;
+import org.apache.inlong.manager.client.api.util.ClientUtils;
+import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
+import org.apache.inlong.manager.common.util.Preconditions;
+import org.apache.inlong.manager.pojo.common.PageResult;
+import org.apache.inlong.manager.pojo.common.Response;
+import org.apache.inlong.manager.pojo.heartbeat.ComponentHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.GroupHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatPageRequest;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatQueryRequest;
+import org.apache.inlong.manager.pojo.heartbeat.StreamHeartbeatResponse;
+
+/**
+ * Client for {@link HeartbeatApi}.
+ */
+public class HeartbeatClient {
+
+    private final HeartbeatApi heartbeatApi;
+
+    public HeartbeatClient(ClientConfiguration configuration) {
+        heartbeatApi = ClientUtils.createRetrofit(configuration).create(HeartbeatApi.class);
+    }
+
+    /**
+     * Get component heartbeat
+     *
+     * @param request query request of heartbeat
+     * @return component heartbeat
+     */
+    public ComponentHeartbeatResponse getComponentHeartbeat(HeartbeatQueryRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInstance(), ErrorCodeEnum.REQUEST_INSTANCE_EMPTY.getMessage());
+
+        Response<ComponentHeartbeatResponse> response = ClientUtils.executeHttpCall(
+                heartbeatApi.getComponentHeartbeat(request));
+        ClientUtils.assertRespSuccess(response);
+        return response.getData();
+    }
+
+    /**
+     * Get inlong group heartbeat
+     *
+     * @param request query request of heartbeat
+     * @return group heartbeat
+     */
+    public GroupHeartbeatResponse getGroupHeartbeat(HeartbeatQueryRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInstance(), ErrorCodeEnum.REQUEST_INSTANCE_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInlongGroupId(), ErrorCodeEnum.GROUP_ID_IS_EMPTY.getMessage());
+
+        Response<GroupHeartbeatResponse> response = ClientUtils.executeHttpCall(
+                heartbeatApi.getGroupHeartbeat(request));
+        ClientUtils.assertRespSuccess(response);
+        return response.getData();
+    }
+
+    /**
+     * Get inlong stream heartbeat
+     *
+     * @param request query request of heartbeat
+     * @return stream heartbeat
+     */
+    public StreamHeartbeatResponse getStreamHeartbeat(HeartbeatQueryRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInstance(), ErrorCodeEnum.REQUEST_INSTANCE_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInlongGroupId(), ErrorCodeEnum.GROUP_ID_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInlongStreamId(), ErrorCodeEnum.STREAM_ID_IS_EMPTY.getMessage());
+
+        Response<StreamHeartbeatResponse> response = ClientUtils.executeHttpCall(
+                heartbeatApi.getStreamHeartbeat(request));
+        ClientUtils.assertRespSuccess(response);
+        return response.getData();
+    }
+
+    /**
+     * List component heartbeat by page
+     *
+     * @param request paging query request
+     * @return list of component heartbeat
+     */
+    public PageResult<ComponentHeartbeatResponse> listComponentHeartbeat(HeartbeatPageRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+
+        Response<PageResult<ComponentHeartbeatResponse>> response = ClientUtils.executeHttpCall(
+                heartbeatApi.listComponentHeartbeat(request));
+        ClientUtils.assertRespSuccess(response);
+        return response.getData();
+    }
+
+    /**
+     * List group heartbeat by page
+     *
+     * @param request paging query request
+     * @return list of group heartbeat
+     */
+    public PageResult<GroupHeartbeatResponse> listGroupHeartbeat(HeartbeatPageRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+
+        Response<PageResult<GroupHeartbeatResponse>> response = ClientUtils.executeHttpCall(
+                heartbeatApi.listGroupHeartbeat(request));
+        ClientUtils.assertRespSuccess(response);
+        return response.getData();
+    }
+
+    /**
+     * List stream heartbeat by page
+     *
+     * @param request paging query request
+     * @return list of stream heartbeat
+     */
+    public PageResult<StreamHeartbeatResponse> listStreamHeartbeat(HeartbeatPageRequest request) {
+        Preconditions.checkNotNull(request, ErrorCodeEnum.REQUEST_IS_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getComponent(), ErrorCodeEnum.REQUEST_COMPONENT_EMPTY.getMessage());
+        Preconditions.checkNotEmpty(request.getInlongGroupId(), ErrorCodeEnum.GROUP_ID_IS_EMPTY.getMessage());
+
+        Response<PageResult<StreamHeartbeatResponse>> response = ClientUtils.executeHttpCall(
+                heartbeatApi.listStreamHeartbeat(request));
+        ClientUtils.assertRespSuccess(response);
+        return response.getData();
+    }
+}
diff --git a/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/service/HeartbeatApi.java b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/service/HeartbeatApi.java
new file mode 100644
index 000000000..c2c23a1d6
--- /dev/null
+++ b/inlong-manager/manager-client/src/main/java/org/apache/inlong/manager/client/api/service/HeartbeatApi.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.inlong.manager.client.api.service;
+
+import org.apache.inlong.manager.pojo.common.PageResult;
+import org.apache.inlong.manager.pojo.common.Response;
+import org.apache.inlong.manager.pojo.heartbeat.ComponentHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.GroupHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatPageRequest;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatQueryRequest;
+import org.apache.inlong.manager.pojo.heartbeat.StreamHeartbeatResponse;
+import retrofit2.Call;
+import retrofit2.http.Body;
+import retrofit2.http.POST;
+
+/**
+ * API for HeartbeatController in manager-web
+ */
+public interface HeartbeatApi {
+
+    @POST(value = "heartbeat/component/get")
+    Call<Response<ComponentHeartbeatResponse>> getComponentHeartbeat(@Body HeartbeatQueryRequest request);
+
+    @POST(value = "heartbeat/group/get")
+    Call<Response<GroupHeartbeatResponse>> getGroupHeartbeat(@Body HeartbeatQueryRequest request);
+
+    @POST(value = "heartbeat/stream/get")
+    Call<Response<StreamHeartbeatResponse>> getStreamHeartbeat(@Body HeartbeatQueryRequest request);
+
+    @POST(value = "heartbeat/component/list")
+    Call<Response<PageResult<ComponentHeartbeatResponse>>> listComponentHeartbeat(@Body HeartbeatPageRequest request);
+
+    @POST(value = "heartbeat/group/list")
+    Call<Response<PageResult<GroupHeartbeatResponse>>> listGroupHeartbeat(@Body HeartbeatPageRequest request);
+
+    @POST(value = "heartbeat/stream/list")
+    Call<Response<PageResult<StreamHeartbeatResponse>>> listStreamHeartbeat(@Body HeartbeatPageRequest request);
+}
diff --git a/inlong-manager/manager-client/src/test/java/org/apache/inlong/manager/client/api/inner/HeartbeatClientTest.java b/inlong-manager/manager-client/src/test/java/org/apache/inlong/manager/client/api/inner/HeartbeatClientTest.java
new file mode 100644
index 000000000..f9a42bd0e
--- /dev/null
+++ b/inlong-manager/manager-client/src/test/java/org/apache/inlong/manager/client/api/inner/HeartbeatClientTest.java
@@ -0,0 +1,204 @@
+/*
+ * 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.inlong.manager.client.api.inner;
+
+import com.google.common.collect.Lists;
+import org.apache.inlong.common.enums.ComponentTypeEnum;
+import org.apache.inlong.manager.client.api.inner.client.HeartbeatClient;
+import org.apache.inlong.manager.common.util.JsonUtils;
+import org.apache.inlong.manager.pojo.common.PageResult;
+import org.apache.inlong.manager.pojo.common.Response;
+import org.apache.inlong.manager.pojo.heartbeat.ComponentHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.GroupHeartbeatResponse;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatPageRequest;
+import org.apache.inlong.manager.pojo.heartbeat.HeartbeatQueryRequest;
+import org.apache.inlong.manager.pojo.heartbeat.StreamHeartbeatResponse;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.okJson;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
+
+/**
+ * Tests for {@link HeartbeatClient}
+ */
+public class HeartbeatClientTest extends ClientFactoryTest {
+
+    private static final HeartbeatClient heartbeatClient = clientFactory.getHeartbeatClient();
+
+    @Test
+    void testGetComponent() {
+        ComponentHeartbeatResponse response = ComponentHeartbeatResponse.builder()
+                .component(ComponentTypeEnum.Agent.getName())
+                .instance("127.0.0.1")
+                .build();
+
+        stubFor(
+                post(urlMatching("/inlong/manager/api/heartbeat/component/get.*"))
+                        .willReturn(
+                                okJson(JsonUtils.toJsonString(
+                                        Response.success(response))
+                                )
+                        )
+        );
+
+        HeartbeatQueryRequest request = new HeartbeatQueryRequest();
+        request.setComponent(ComponentTypeEnum.Agent.getName());
+        request.setInstance("127.0.0.1");
+        ComponentHeartbeatResponse result = heartbeatClient.getComponentHeartbeat(request);
+        Assertions.assertEquals(request.getComponent(), result.getComponent());
+        Assertions.assertEquals(request.getInstance(), result.getInstance());
+    }
+
+    @Test
+    void testGetGroup() {
+        GroupHeartbeatResponse response = new GroupHeartbeatResponse();
+        response.setComponent(ComponentTypeEnum.Agent.getName());
+        response.setInstance("127.0.0.1");
+        response.setInlongGroupId("test_group");
+
+        stubFor(
+                post(urlMatching("/inlong/manager/api/heartbeat/group/get.*"))
+                        .willReturn(
+                                okJson(JsonUtils.toJsonString(
+                                        Response.success(response))
+                                )
+                        )
+        );
+
+        HeartbeatQueryRequest request = new HeartbeatQueryRequest();
+        request.setComponent(ComponentTypeEnum.Agent.getName());
+        request.setInstance("127.0.0.1");
+        request.setInlongGroupId("test_group");
+        GroupHeartbeatResponse result = heartbeatClient.getGroupHeartbeat(request);
+        Assertions.assertEquals(request.getComponent(), result.getComponent());
+        Assertions.assertEquals(request.getInstance(), result.getInstance());
+        Assertions.assertEquals(request.getInlongGroupId(), result.getInlongGroupId());
+    }
+
+    @Test
+    void testGetStream() {
+        StreamHeartbeatResponse response = new StreamHeartbeatResponse();
+        response.setComponent(ComponentTypeEnum.Agent.getName());
+        response.setInstance("127.0.0.1");
+        response.setInlongGroupId("test_group");
+        response.setInlongStreamId("test_stream");
+
+        stubFor(
+                post(urlMatching("/inlong/manager/api/heartbeat/stream/get.*"))
+                        .willReturn(
+                                okJson(JsonUtils.toJsonString(
+                                        Response.success(response))
+                                )
+                        )
+        );
+
+        HeartbeatQueryRequest request = new HeartbeatQueryRequest();
+        request.setComponent(ComponentTypeEnum.Agent.getName());
+        request.setInstance("127.0.0.1");
+        request.setInlongGroupId("test_group");
+        request.setInlongStreamId("test_stream");
+        StreamHeartbeatResponse result = heartbeatClient.getStreamHeartbeat(request);
+        Assertions.assertEquals(request.getComponent(), result.getComponent());
+        Assertions.assertEquals(request.getInstance(), result.getInstance());
+        Assertions.assertEquals(request.getInlongGroupId(), result.getInlongGroupId());
+        Assertions.assertEquals(request.getInlongStreamId(), result.getInlongStreamId());
+    }
+
+    @Test
+    void testListComponent() {
+        List<ComponentHeartbeatResponse> responses = Lists.newArrayList(
+                ComponentHeartbeatResponse.builder()
+                        .component(ComponentTypeEnum.Agent.getName())
+                        .instance("127.0.0.1")
+                        .build()
+        );
+
+        stubFor(
+                post(urlMatching("/inlong/manager/api/heartbeat/component/list.*"))
+                        .willReturn(
+                                okJson(JsonUtils.toJsonString(
+                                                Response.success(new PageResult<>(responses))
+                                        )
+                                )
+                        )
+        );
+
+        HeartbeatPageRequest request = new HeartbeatPageRequest();
+        request.setComponent(ComponentTypeEnum.Agent.getName());
+        PageResult<ComponentHeartbeatResponse> pageResult = heartbeatClient.listComponentHeartbeat(request);
+        Assertions.assertEquals(JsonUtils.toJsonString(responses),JsonUtils.toJsonString(pageResult.getList()));
+    }
+
+    @Test
+    void testListGroup() {
+        List<GroupHeartbeatResponse> responses = Lists.newArrayList(
+                GroupHeartbeatResponse.builder()
+                        .component(ComponentTypeEnum.Agent.getName())
+                        .instance("127.0.0.1")
+                        .build()
+        );
+
+        stubFor(
+                post(urlMatching("/inlong/manager/api/heartbeat/group/list.*"))
+                        .willReturn(
+                                okJson(JsonUtils.toJsonString(
+                                                Response.success(new PageResult<>(responses))
+                                        )
+                                )
+                        )
+        );
+
+        HeartbeatPageRequest request = new HeartbeatPageRequest();
+        request.setComponent(ComponentTypeEnum.Agent.getName());
+        PageResult<GroupHeartbeatResponse> pageResult = heartbeatClient.listGroupHeartbeat(request);
+        Assertions.assertEquals(JsonUtils.toJsonString(responses),JsonUtils.toJsonString(pageResult.getList()));
+    }
+
+    @Test
+    void testListStream() {
+        List<StreamHeartbeatResponse> responses = Lists.newArrayList(
+                StreamHeartbeatResponse.builder()
+                        .component(ComponentTypeEnum.Agent.getName())
+                        .inlongGroupId("test_group")
+                        .inlongStreamId("test_stream")
+                        .instance("127.0.0.1")
+                        .build()
+        );
+
+        stubFor(
+                post(urlMatching("/inlong/manager/api/heartbeat/stream/list.*"))
+                        .willReturn(
+                                okJson(JsonUtils.toJsonString(
+                                                Response.success(new PageResult<>(responses))
+                                        )
+                                )
+                        )
+        );
+
+        HeartbeatPageRequest request = new HeartbeatPageRequest();
+        request.setComponent(ComponentTypeEnum.Agent.getName());
+        request.setInlongGroupId("test_group");
+        PageResult<StreamHeartbeatResponse> pageResult = heartbeatClient.listStreamHeartbeat(request);
+        Assertions.assertEquals(JsonUtils.toJsonString(responses),JsonUtils.toJsonString(pageResult.getList()));
+    }
+}
diff --git a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/ComponentHeartbeatResponse.java b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/ComponentHeartbeatResponse.java
index a5efc6475..faa703ccc 100644
--- a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/ComponentHeartbeatResponse.java
+++ b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/ComponentHeartbeatResponse.java
@@ -20,7 +20,10 @@ package org.apache.inlong.manager.pojo.heartbeat;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.util.Date;
 
@@ -28,6 +31,9 @@ import java.util.Date;
  * Component heartbeat response
  */
 @Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
 @ApiModel("Component heartbeat response")
 public class ComponentHeartbeatResponse {
 
diff --git a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/GroupHeartbeatResponse.java b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/GroupHeartbeatResponse.java
index ac0b8116a..150cff140 100644
--- a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/GroupHeartbeatResponse.java
+++ b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/GroupHeartbeatResponse.java
@@ -20,7 +20,10 @@ package org.apache.inlong.manager.pojo.heartbeat;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.util.Date;
 
@@ -28,6 +31,9 @@ import java.util.Date;
  * Inlong group heartbeat response
  */
 @Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
 @ApiModel("Inlong group heartbeat response")
 public class GroupHeartbeatResponse {
 
diff --git a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/StreamHeartbeatResponse.java b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/StreamHeartbeatResponse.java
index 554378364..40f262091 100644
--- a/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/StreamHeartbeatResponse.java
+++ b/inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/heartbeat/StreamHeartbeatResponse.java
@@ -20,7 +20,10 @@ package org.apache.inlong.manager.pojo.heartbeat;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.util.Date;
 
@@ -28,6 +31,9 @@ import java.util.Date;
  * Inlong stream heartbeat response
  */
 @Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
 @ApiModel("Inlong stream heartbeat response")
 public class StreamHeartbeatResponse {