diff --git a/docs/references/http_api_reference.mdx b/docs/references/http_api_reference.mdx
index 003ebb31eb..a93c8ee260 100644
--- a/docs/references/http_api_reference.mdx
+++ b/docs/references/http_api_reference.mdx
@@ -2370,4 +2370,168 @@ A `500` HTTP status code indicates an error condition. The response includes a J
----
\ No newline at end of file
+---
+
+## Show buffer
+
+**GET** `/instance/buffer`
+
+List the cached buffer objects in database.
+
+### Request
+
+- Method: GET
+- URL: `/instance/buffer`
+- Headers: `accept: application/json`
+
+#### Request example
+
+```shell
+curl --request GET \
+ --url http://localhost:23820/instance/buffer \
+ --header 'accept: application/json'
+```
+
+### Response
+
+
+
+
+The response includes a JSON object like the following:
+
+```shell
+{
+ "buffer": [
+ {
+ "buffered_type": "Persistent",
+ "path": "/var/infinity/data/nlAn5spku9_db_default_db/sNzUhKy3er_table_table1/seg_0/blk_0/0.col",
+ "size": "32768",
+ "status": "Freed",
+ "type": "data"
+ },
+ {
+ "buffered_type": "Persistent",
+ "path": "/var/infinity/data/nlAn5spku9_db_default_db/sNzUhKy3er_table_table1/seg_0/blk_0/2.col",
+ "size": "131072",
+ "status": "Freed",
+ "type": "data"
+ },
+ {
+ "buffered_type": "Persistent",
+ "path": "/var/infinity/data/nlAn5spku9_db_default_db/sNzUhKy3er_table_table1/seg_0/blk_0/version",
+ "size": "65536",
+ "status": "Freed",
+ "type": "version data"
+ }
+ ],
+ "error_code": 0
+}
+```
+
+- `"error_code"`: `integer`
+ `0`: The operation succeeds.
+
+
+
+
+A `500` HTTP status code indicates an error condition. The response includes a JSON object like the following:
+
+```shell
+{
+ "error_code": 2005,
+ "error_message": "Not support in maintenance mode"
+}
+```
+
+- `"error_code"`: `integer`
+ A non-zero value indicates a specific error condition.
+- `"error_message"`: `string`
+ When `error_code` is non-zero, `"error_message"` provides additional details about the error.
+
+
+
+
+---
+
+## Show profiles
+
+**GET** `/instance/profiles`
+
+When set session variable 'enable_profiling', Infinity will record query profile information. This command is to list recorded queries profile.
+
+### Request
+
+- Method: GET
+- URL: `/instance/profiles`
+- Headers: `accept: application/json`
+
+#### Request example
+
+```shell
+curl --request GET \
+ --url http://localhost:23820/instance/profiles \
+ --header 'accept: application/json'
+```
+
+### Response
+
+
+
+
+The response includes a JSON object like the following:
+
+```shell
+{
+ "error_code": 0,
+ "profiles": [
+ {
+ "command parsing": "250us",
+ "commit": "0ns",
+ "execution": "380us",
+ "logical plan building": "133us",
+ "physical plan building": "44us",
+ "pipeline building": "38us",
+ "plan optimizing": "1000ns",
+ "record_no": "0",
+ "rollback": "35us",
+ "task building": "70us",
+ "total_cost": "951us"
+ }
+ ]
+}
+```
+
+- `"error_code"`: `integer`
+ `0`: The operation succeeds.
+
+
+
+
+A `500` HTTP status code indicates an error condition. The response includes a JSON object like the following:
+
+```shell
+{
+ "error_code": 2005,
+ "error_message": "Not support in maintenance mode"
+}
+```
+
+- `"error_code"`: `integer`
+ A non-zero value indicates a specific error condition.
+- `"error_message"`: `string`
+ When `error_code` is non-zero, `"error_message"` provides additional details about the error.
+
+
+
+
+---
diff --git a/example/http/show_metrics.sh b/example/http/show_metrics.sh
new file mode 100755
index 0000000000..57fdb47f9b
--- /dev/null
+++ b/example/http/show_metrics.sh
@@ -0,0 +1,38 @@
+# Copyright(C) 2024 InfiniFlow, Inc. All rights reserved.
+#
+# Licensed 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
+#
+# https://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.
+
+# show buffer
+echo -e '\n-- show buffer'
+curl --request GET \
+ --url http://localhost:23820/instance/buffer \
+ --header 'accept: application/json'
+
+# show profiles
+echo -e '\n\n-- show profiles'
+curl --request GET \
+ --url http://localhost:23820/instance/profiles \
+ --header 'accept: application/json'
+
+# show memindex
+echo -e '\n\n-- show memindex'
+curl --request GET \
+ --url http://localhost:23820/instance/memindex \
+ --header 'accept: application/json'
+
+# show queries
+echo -e '\n\n-- show queries'
+curl --request GET \
+ --url http://localhost:23820/instance/queries \
+ --header 'accept: application/json'
+
diff --git a/src/network/http_server.cpp b/src/network/http_server.cpp
index f4adcc4283..bca7899be8 100644
--- a/src/network/http_server.cpp
+++ b/src/network/http_server.cpp
@@ -3313,6 +3313,162 @@ class SetConfigHandler final : public HttpRequestHandler {
}
};
+class ShowBufferHandler final : public HttpRequestHandler {
+public:
+ SharedPtr handle(const SharedPtr &request) final {
+ auto infinity = Infinity::RemoteConnect();
+ DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });
+
+ nlohmann::json json_response;
+ HTTPStatus http_status;
+ QueryResult result = infinity->Query("show buffer");
+
+ if (result.IsOk()) {
+ SizeT block_rows = result.result_table_->DataBlockCount();
+ for (SizeT block_id = 0; block_id < block_rows; ++block_id) {
+ DataBlock *data_block = result.result_table_->GetDataBlockById(block_id).get();
+ auto row_count = data_block->row_count();
+ auto column_cnt = result.result_table_->ColumnCount();
+ for (int row = 0; row < row_count; ++row) {
+ nlohmann::json json_table;
+ for (SizeT col = 0; col < column_cnt; ++col) {
+ const String &column_name = result.result_table_->GetColumnNameById(col);
+ Value value = data_block->GetValue(col, row);
+ const String &column_value = value.ToString();
+ json_table[column_name] = column_value;
+ }
+ json_response["buffer"].push_back(json_table);
+ }
+ }
+ json_response["error_code"] = 0;
+ http_status = HTTPStatus::CODE_200;
+ } else {
+ json_response["error_code"] = result.ErrorCode();
+ json_response["error_message"] = result.ErrorMsg();
+ http_status = HTTPStatus::CODE_500;
+ }
+
+ return ResponseFactory::createResponse(http_status, json_response.dump());
+ }
+};
+
+class ShowProfilesHandler final : public HttpRequestHandler {
+public:
+ SharedPtr handle(const SharedPtr &request) final {
+ auto infinity = Infinity::RemoteConnect();
+ DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });
+
+ nlohmann::json json_response;
+ HTTPStatus http_status;
+ QueryResult result = infinity->Query("show profiles");
+
+ if (result.IsOk()) {
+ SizeT block_rows = result.result_table_->DataBlockCount();
+ for (SizeT block_id = 0; block_id < block_rows; ++block_id) {
+ DataBlock *data_block = result.result_table_->GetDataBlockById(block_id).get();
+ auto row_count = data_block->row_count();
+ auto column_cnt = result.result_table_->ColumnCount();
+ for (int row = 0; row < row_count; ++row) {
+ nlohmann::json json_table;
+ for (SizeT col = 0; col < column_cnt; ++col) {
+ const String &column_name = result.result_table_->GetColumnNameById(col);
+ Value value = data_block->GetValue(col, row);
+ const String &column_value = value.ToString();
+ json_table[column_name] = column_value;
+ }
+ json_response["profiles"].push_back(json_table);
+ }
+ }
+ json_response["error_code"] = 0;
+ http_status = HTTPStatus::CODE_200;
+ } else {
+ json_response["error_code"] = result.ErrorCode();
+ json_response["error_message"] = result.ErrorMsg();
+ http_status = HTTPStatus::CODE_500;
+ }
+
+ return ResponseFactory::createResponse(http_status, json_response.dump());
+ }
+};
+
+class ShowMemIndexHandler final : public HttpRequestHandler {
+public:
+ SharedPtr handle(const SharedPtr &request) final {
+ auto infinity = Infinity::RemoteConnect();
+ DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });
+
+ nlohmann::json json_response;
+ HTTPStatus http_status;
+ QueryResult result = infinity->Query("show memindex");
+
+ if (result.IsOk()) {
+ SizeT block_rows = result.result_table_->DataBlockCount();
+ for (SizeT block_id = 0; block_id < block_rows; ++block_id) {
+ DataBlock *data_block = result.result_table_->GetDataBlockById(block_id).get();
+ auto row_count = data_block->row_count();
+ auto column_cnt = result.result_table_->ColumnCount();
+ for (int row = 0; row < row_count; ++row) {
+ nlohmann::json json_table;
+ for (SizeT col = 0; col < column_cnt; ++col) {
+ const String &column_name = result.result_table_->GetColumnNameById(col);
+ Value value = data_block->GetValue(col, row);
+ const String &column_value = value.ToString();
+ json_table[column_name] = column_value;
+ }
+ json_response["index"].push_back(json_table);
+ }
+ }
+ json_response["error_code"] = 0;
+ http_status = HTTPStatus::CODE_200;
+ } else {
+ json_response["error_code"] = result.ErrorCode();
+ json_response["error_message"] = result.ErrorMsg();
+ http_status = HTTPStatus::CODE_500;
+ }
+
+ return ResponseFactory::createResponse(http_status, json_response.dump());
+ }
+};
+
+class ShowQueriesHandler final : public HttpRequestHandler {
+public:
+ SharedPtr handle(const SharedPtr &request) final {
+ auto infinity = Infinity::RemoteConnect();
+ DeferFn defer_fn([&]() { infinity->RemoteDisconnect(); });
+
+ nlohmann::json json_response;
+ HTTPStatus http_status;
+ QueryResult result = infinity->Query("show queries");
+
+ if (result.IsOk()) {
+ SizeT block_rows = result.result_table_->DataBlockCount();
+ for (SizeT block_id = 0; block_id < block_rows; ++block_id) {
+ DataBlock *data_block = result.result_table_->GetDataBlockById(block_id).get();
+ auto row_count = data_block->row_count();
+ auto column_cnt = result.result_table_->ColumnCount();
+ for (int row = 0; row < row_count; ++row) {
+ nlohmann::json json_table;
+ for (SizeT col = 0; col < column_cnt; ++col) {
+ const String &column_name = result.result_table_->GetColumnNameById(col);
+ Value value = data_block->GetValue(col, row);
+ const String &column_value = value.ToString();
+ json_table[column_name] = column_value;
+ }
+ json_response["queries"].push_back(json_table);
+ }
+ }
+ json_response["error_code"] = 0;
+ http_status = HTTPStatus::CODE_200;
+ } else {
+ json_response["error_code"] = result.ErrorCode();
+ json_response["error_message"] = result.ErrorMsg();
+ http_status = HTTPStatus::CODE_500;
+ }
+
+ return ResponseFactory::createResponse(http_status, json_response.dump());
+ }
+};
+
class ShowCurrentNodeHandler final : public HttpRequestHandler {
public:
SharedPtr handle(const SharedPtr &request) final {
@@ -3449,6 +3605,12 @@ void HTTPServer::Start(const String& ip_address, u16 port) {
router->route("POST", "/configs", MakeShared());
+ // metrics
+ router->route("GET", "/instance/buffer", MakeShared());
+ router->route("GET", "/instance/profiles", MakeShared());
+ router->route("GET", "/instance/memindex", MakeShared());
+ router->route("GET", "/instance/queries", MakeShared());
+
// variable
router->route("GET", "/variables/global", MakeShared());
router->route("GET", "/variables/global/{variable_name}", MakeShared());