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

lichaoyong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 6c4d7c6  [Feature] Add QueryDetail to store query statistics. (#3744)
6c4d7c6 is described below

commit 6c4d7c60dd03386c4186c7a4a1eb1d609ded8278
Author: lichaoyong <lichaoyong...@gmail.com>
AuthorDate: Mon Jun 15 18:16:54 2020 +0800

    [Feature] Add QueryDetail to store query statistics. (#3744)
    
    1. Store the query statistics in memory.
    2. Supporting RESTFUL interface to get the statistics.
---
 be/src/http/action/stream_load.cpp                 |   4 +-
 be/src/runtime/client_cache.cpp                    |   4 +-
 be/src/runtime/memory/chunk_allocator.cpp          |   8 +-
 be/src/runtime/mysql_result_writer.cpp             |   9 +-
 be/src/runtime/tmp_file_mgr.cc                     |   2 +-
 be/src/util/doris_metrics.cpp                      |   5 +-
 be/src/util/doris_metrics.h                        | 170 ++++++++++-----------
 be/src/util/metrics.cpp                            |  12 +-
 be/src/util/metrics.h                              |   7 +-
 be/src/util/system_metrics.cpp                     |  12 +-
 be/src/util/thrift_server.cpp                      |   4 +-
 be/test/http/metrics_action_test.cpp               |   2 +-
 be/test/util/doris_metrics_test.cpp                |  12 --
 be/test/util/new_metrics_test.cpp                  |  18 +--
 docs/.vuepress/sidebar/en.js                       |   4 +
 docs/.vuepress/sidebar/zh-CN.js                    |   4 +
 .../http-actions/connection-action.md              |  42 +++++
 .../http-actions/profile-action.md                 | 120 +++++++++++++++
 .../http-actions/query-detail-action.md            |  61 ++++++++
 .../http-actions/show-data-action.md               |  35 +++++
 .../http-actions/connection-action.md              |  42 +++++
 .../http-actions/profile-action.md                 | 120 +++++++++++++++
 .../http-actions/query-detail-action.md            |  59 +++++++
 .../http-actions/show-data-action.md               |  35 +++++
 fe/src/main/java/org/apache/doris/PaloFe.java      |   1 -
 .../org/apache/doris/common/ThreadPoolManager.java |   2 +-
 .../apache/doris/common/util/RuntimeProfile.java   |   2 +-
 .../java/org/apache/doris/http/HttpServer.java     |   8 +
 .../apache/doris/http/rest/ConnectionAction.java   |  61 ++++++++
 .../org/apache/doris/http/rest/ProfileAction.java  |  60 ++++++++
 .../apache/doris/http/rest/QueryDetailAction.java  |  56 +++++++
 .../org/apache/doris/http/rest/ShowDataAction.java |  88 +++++++++++
 .../org/apache/doris/master/ReportHandler.java     |   2 +-
 .../main/java/org/apache/doris/metric/Metric.java  |   7 +-
 .../java/org/apache/doris/metric/MetricRepo.java   |  48 +++---
 .../java/org/apache/doris/qe/ConnectContext.java   |  12 ++
 .../java/org/apache/doris/qe/ConnectProcessor.java |  10 +-
 .../main/java/org/apache/doris/qe/QueryDetail.java | 129 ++++++++++++++++
 .../java/org/apache/doris/qe/QueryDetailQueue.java |  69 +++++++++
 .../java/org/apache/doris/qe/StmtExecutor.java     |  18 ++-
 .../doris/common/util/RuntimeProfileTest.java      |   2 +-
 .../org/apache/doris/qe/QueryDetailQueueTest.java  |  73 +++++++++
 42 files changed, 1266 insertions(+), 173 deletions(-)

diff --git a/be/src/http/action/stream_load.cpp 
b/be/src/http/action/stream_load.cpp
index 1322e85..798e702 100644
--- a/be/src/http/action/stream_load.cpp
+++ b/be/src/http/action/stream_load.cpp
@@ -59,10 +59,10 @@
 
 namespace doris {
 
-METRIC_DEFINE_INT_COUNTER(streaming_load_requests_total, MetricUnit::NUMBER);
+METRIC_DEFINE_INT_COUNTER(streaming_load_requests_total, MetricUnit::REQUESTS);
 METRIC_DEFINE_INT_COUNTER(streaming_load_bytes, MetricUnit::BYTES);
 METRIC_DEFINE_INT_COUNTER(streaming_load_duration_ms, 
MetricUnit::MILLISECONDS);
-METRIC_DEFINE_INT_GAUGE(streaming_load_current_processing, MetricUnit::NUMBER);
+METRIC_DEFINE_INT_GAUGE(streaming_load_current_processing, 
MetricUnit::REQUESTS);
 
 #ifdef BE_TEST
 TStreamLoadPutResult k_stream_load_put_result;
diff --git a/be/src/runtime/client_cache.cpp b/be/src/runtime/client_cache.cpp
index 7144684..832678d 100644
--- a/be/src/runtime/client_cache.cpp
+++ b/be/src/runtime/client_cache.cpp
@@ -216,12 +216,12 @@ void ClientCacheHelper::init_metrics(MetricRegistry* 
metrics, const std::string&
     // usage, but ensures that _metrics_enabled is published.
     boost::lock_guard<boost::mutex> lock(_lock);
 
-    _used_clients.reset(new IntGauge(MetricUnit::NUMBER));
+    _used_clients.reset(new IntGauge(MetricUnit::NOUNIT));
     metrics->register_metric("thrift_used_clients",
                              MetricLabels().add("name", key_prefix),
                              _used_clients.get());
 
-    _opened_clients.reset(new IntGauge(MetricUnit::NUMBER));
+    _opened_clients.reset(new IntGauge(MetricUnit::NOUNIT));
     metrics->register_metric("thrift_opened_clients",
                              MetricLabels().add("name", key_prefix),
                              _opened_clients.get());
diff --git a/be/src/runtime/memory/chunk_allocator.cpp 
b/be/src/runtime/memory/chunk_allocator.cpp
index c5e68f2..1ccbc5c 100644
--- a/be/src/runtime/memory/chunk_allocator.cpp
+++ b/be/src/runtime/memory/chunk_allocator.cpp
@@ -34,10 +34,10 @@ namespace doris {
 
 ChunkAllocator* ChunkAllocator::_s_instance = nullptr;
 
-static IntCounter local_core_alloc_count(MetricUnit::NUMBER);
-static IntCounter other_core_alloc_count(MetricUnit::NUMBER);
-static IntCounter system_alloc_count(MetricUnit::NUMBER);
-static IntCounter system_free_count(MetricUnit::NUMBER);
+static IntCounter local_core_alloc_count(MetricUnit::NOUNIT);
+static IntCounter other_core_alloc_count(MetricUnit::NOUNIT);
+static IntCounter system_alloc_count(MetricUnit::NOUNIT);
+static IntCounter system_free_count(MetricUnit::NOUNIT);
 static IntCounter system_alloc_cost_ns(MetricUnit::NANOSECONDS);
 static IntCounter system_free_cost_ns(MetricUnit::NANOSECONDS);
 
diff --git a/be/src/runtime/mysql_result_writer.cpp 
b/be/src/runtime/mysql_result_writer.cpp
index 036ec4a..0c8cc43 100644
--- a/be/src/runtime/mysql_result_writer.cpp
+++ b/be/src/runtime/mysql_result_writer.cpp
@@ -61,11 +61,10 @@ Status MysqlResultWriter::init(RuntimeState* state) {
 }
 
 void MysqlResultWriter::_init_profile() {
-    RuntimeProfile* profile = 
_parent_profile->create_child("MySQLResultWriter", true, true);
-    _append_row_batch_timer = ADD_TIMER(profile, "AppendBatchTime");
-    _convert_tuple_timer = ADD_CHILD_TIMER(profile, "TupleConvertTime", 
"AppendBatchTime");
-    _result_send_timer = ADD_CHILD_TIMER(profile, "ResultRendTime", 
"AppendBatchTime");
-    _sent_rows_counter = ADD_COUNTER(profile, "NumSentRows", TUnit::UNIT);
+    _append_row_batch_timer = ADD_TIMER(_parent_profile, "AppendBatchTime");
+    _convert_tuple_timer = ADD_CHILD_TIMER(_parent_profile, 
"TupleConvertTime", "AppendBatchTime");
+    _result_send_timer = ADD_CHILD_TIMER(_parent_profile, "ResultRendTime", 
"AppendBatchTime");
+    _sent_rows_counter = ADD_COUNTER(_parent_profile, "NumSentRows", 
TUnit::UNIT);
 }
 
 Status MysqlResultWriter::_add_one_row(TupleRow* row) {
diff --git a/be/src/runtime/tmp_file_mgr.cc b/be/src/runtime/tmp_file_mgr.cc
index badc903..d286cea 100644
--- a/be/src/runtime/tmp_file_mgr.cc
+++ b/be/src/runtime/tmp_file_mgr.cc
@@ -119,7 +119,7 @@ Status TmpFileMgr::init_custom(
     }
 
     DCHECK(metrics != NULL);
-    _num_active_scratch_dirs_metric.reset(new IntGauge(MetricUnit::NUMBER));
+    _num_active_scratch_dirs_metric.reset(new IntGauge(MetricUnit::NOUNIT));
     metrics->register_metric("active_scratch_dirs", 
_num_active_scratch_dirs_metric.get());
     //_active_scratch_dirs_metric = metrics->register_metric(new 
SetMetric<std::string>(
     //        TMP_FILE_MGR_ACTIVE_SCRATCH_DIRS_LIST,
diff --git a/be/src/util/doris_metrics.cpp b/be/src/util/doris_metrics.cpp
index 0853bd4..a90b0d0 100644
--- a/be/src/util/doris_metrics.cpp
+++ b/be/src/util/doris_metrics.cpp
@@ -34,11 +34,9 @@ DorisMetrics::DorisMetrics() : _name("doris_be"), 
_hook_name("doris_metrics"), _
     REGISTER_DORIS_METRIC(fragment_requests_total);
     REGISTER_DORIS_METRIC(fragment_request_duration_us);
     REGISTER_DORIS_METRIC(http_requests_total);
-    REGISTER_DORIS_METRIC(http_request_duration_us);
     REGISTER_DORIS_METRIC(http_request_send_bytes);
     REGISTER_DORIS_METRIC(query_scan_bytes);
     REGISTER_DORIS_METRIC(query_scan_rows);
-    REGISTER_DORIS_METRIC(ranges_processed_total);
 
     REGISTER_DORIS_METRIC(memtable_flush_total);
     REGISTER_DORIS_METRIC(memtable_flush_duration_us);
@@ -180,7 +178,6 @@ DorisMetrics::DorisMetrics() : _name("doris_be"), 
_hook_name("doris_metrics"), _
     REGISTER_DORIS_METRIC(disk_sync_total);
     REGISTER_DORIS_METRIC(blocks_open_reading);
     REGISTER_DORIS_METRIC(blocks_open_writing);
-    REGISTER_DORIS_METRIC(blocks_push_remote_duration_us);
 }
 
 void DorisMetrics::initialize(
@@ -196,7 +193,7 @@ void DorisMetrics::initialize(
         _metrics.register_metric("disks_avail_capacity", 
MetricLabels().add("path", path), gauge);
         gauge = disks_data_used_capacity.set_key(path, MetricUnit::BYTES);
         _metrics.register_metric("disks_data_used_capacity", 
MetricLabels().add("path", path), gauge);
-        gauge = disks_state.set_key(path, MetricUnit::BYTES);
+        gauge = disks_state.set_key(path, MetricUnit::NOUNIT);
         _metrics.register_metric("disks_state", MetricLabels().add("path", 
path), gauge);
     }
 
diff --git a/be/src/util/doris_metrics.h b/be/src/util/doris_metrics.h
index e6775b5..1e802e2 100644
--- a/be/src/util/doris_metrics.h
+++ b/be/src/util/doris_metrics.h
@@ -55,67 +55,65 @@ private:
 class DorisMetrics {
 public:
        // counters
-       METRIC_DEFINE_INT_COUNTER(fragment_requests_total, MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_COUNTER(fragment_requests_total, 
MetricUnit::REQUESTS);
        METRIC_DEFINE_INT_COUNTER(fragment_request_duration_us, 
MetricUnit::MICROSECONDS);
-       METRIC_DEFINE_INT_COUNTER(http_requests_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(http_request_duration_us, 
MetricUnit::MICROSECONDS);
+       METRIC_DEFINE_INT_COUNTER(http_requests_total, MetricUnit::REQUESTS);
        METRIC_DEFINE_INT_COUNTER(http_request_send_bytes, MetricUnit::BYTES);
        METRIC_DEFINE_INT_COUNTER(query_scan_bytes, MetricUnit::BYTES);
-       METRIC_DEFINE_INT_COUNTER(query_scan_rows, MetricUnit::BYTES);
-       METRIC_DEFINE_INT_COUNTER(ranges_processed_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(push_requests_success_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(push_requests_fail_total, MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_COUNTER(query_scan_rows, MetricUnit::ROWS);
+       METRIC_DEFINE_INT_COUNTER(push_requests_success_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(push_requests_fail_total, 
MetricUnit::REQUESTS);
        METRIC_DEFINE_INT_COUNTER(push_request_duration_us, 
MetricUnit::MICROSECONDS);
        METRIC_DEFINE_INT_COUNTER(push_request_write_bytes, MetricUnit::BYTES);
        METRIC_DEFINE_INT_COUNTER(push_request_write_rows, MetricUnit::ROWS);
-       METRIC_DEFINE_INT_COUNTER(create_tablet_requests_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(create_tablet_requests_failed, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(drop_tablet_requests_total, 
MetricUnit::NUMBER);
-       
-       METRIC_DEFINE_INT_COUNTER(report_all_tablets_requests_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(report_all_tablets_requests_failed, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(report_tablet_requests_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(report_tablet_requests_failed, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(report_disk_requests_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(report_disk_requests_failed, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(report_task_requests_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(report_task_requests_failed, 
MetricUnit::NUMBER);
-       
-       METRIC_DEFINE_INT_COUNTER(schema_change_requests_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(schema_change_requests_failed, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(create_rollup_requests_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(create_rollup_requests_failed, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(storage_migrate_requests_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(delete_requests_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(delete_requests_failed, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(clone_requests_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(clone_requests_failed, MetricUnit::NUMBER);
-       
-       METRIC_DEFINE_INT_COUNTER(finish_task_requests_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(finish_task_requests_failed, 
MetricUnit::NUMBER);
-       
-       METRIC_DEFINE_INT_COUNTER(base_compaction_request_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(base_compaction_request_failed, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(cumulative_compaction_request_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(cumulative_compaction_request_failed, 
MetricUnit::NUMBER);
-       
-       METRIC_DEFINE_INT_COUNTER(base_compaction_deltas_total, 
MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_COUNTER(create_tablet_requests_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(create_tablet_requests_failed, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(drop_tablet_requests_total, 
MetricUnit::REQUESTS);
+       
+       METRIC_DEFINE_INT_COUNTER(report_all_tablets_requests_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(report_all_tablets_requests_failed, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(report_tablet_requests_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(report_tablet_requests_failed, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(report_disk_requests_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(report_disk_requests_failed, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(report_task_requests_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(report_task_requests_failed, 
MetricUnit::REQUESTS);
+       
+       METRIC_DEFINE_INT_COUNTER(schema_change_requests_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(schema_change_requests_failed, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(create_rollup_requests_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(create_rollup_requests_failed, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(storage_migrate_requests_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(delete_requests_total, MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(delete_requests_failed, MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(clone_requests_total, MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(clone_requests_failed, MetricUnit::REQUESTS);
+       
+       METRIC_DEFINE_INT_COUNTER(finish_task_requests_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(finish_task_requests_failed, 
MetricUnit::REQUESTS);
+       
+       METRIC_DEFINE_INT_COUNTER(base_compaction_request_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(base_compaction_request_failed, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(cumulative_compaction_request_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(cumulative_compaction_request_failed, 
MetricUnit::REQUESTS);
+       
+       METRIC_DEFINE_INT_COUNTER(base_compaction_deltas_total, 
MetricUnit::ROWSETS);
        METRIC_DEFINE_INT_COUNTER(base_compaction_bytes_total, 
MetricUnit::BYTES);
-       METRIC_DEFINE_INT_COUNTER(cumulative_compaction_deltas_total, 
MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_COUNTER(cumulative_compaction_deltas_total, 
MetricUnit::ROWSETS);
        METRIC_DEFINE_INT_COUNTER(cumulative_compaction_bytes_total, 
MetricUnit::BYTES);
        
-       METRIC_DEFINE_INT_COUNTER(publish_task_request_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(publish_task_failed_total, 
MetricUnit::NUMBER);
-       
-       METRIC_DEFINE_INT_COUNTER(meta_write_request_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(meta_write_request_duration_us, 
MetricUnit::MICROSECONDS);
-       METRIC_DEFINE_INT_COUNTER(meta_read_request_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(meta_read_request_duration_us, 
MetricUnit::MICROSECONDS);
+       METRIC_DEFINE_INT_COUNTER(publish_task_request_total, 
MetricUnit::REQUESTS);
+       METRIC_DEFINE_INT_COUNTER(publish_task_failed_total, 
MetricUnit::REQUESTS);
        
+    METRIC_DEFINE_INT_COUNTER(meta_write_request_total, MetricUnit::REQUESTS);
+    METRIC_DEFINE_INT_COUNTER(meta_write_request_duration_us, 
MetricUnit::MICROSECONDS);
+    METRIC_DEFINE_INT_COUNTER(meta_read_request_total, MetricUnit::REQUESTS);
+    METRIC_DEFINE_INT_COUNTER(meta_read_request_duration_us, 
MetricUnit::MICROSECONDS);
+
        // Counters for segment_v2
        // -----------------------
        // total number of segments read
-       METRIC_DEFINE_INT_COUNTER(segment_read_total, MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_COUNTER(segment_read_total, MetricUnit::OPERATIONS);
        // total number of rows in queried segments (before index pruning)
        METRIC_DEFINE_INT_COUNTER(segment_row_total, MetricUnit::ROWS);
        // total number of rows selected by short key index
@@ -123,24 +121,24 @@ public:
        // total number of rows selected by zone map index
        METRIC_DEFINE_INT_COUNTER(segment_rows_read_by_zone_map, 
MetricUnit::ROWS);
        
-       METRIC_DEFINE_INT_COUNTER(txn_begin_request_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(txn_commit_request_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(txn_rollback_request_total, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(txn_exec_plan_total, MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_COUNTER(txn_begin_request_total, 
MetricUnit::OPERATIONS);
+       METRIC_DEFINE_INT_COUNTER(txn_commit_request_total, 
MetricUnit::OPERATIONS);
+       METRIC_DEFINE_INT_COUNTER(txn_rollback_request_total, 
MetricUnit::OPERATIONS);
+       METRIC_DEFINE_INT_COUNTER(txn_exec_plan_total, MetricUnit::OPERATIONS);
        METRIC_DEFINE_INT_COUNTER(stream_receive_bytes_total, 
MetricUnit::BYTES);
        METRIC_DEFINE_INT_COUNTER(stream_load_rows_total, MetricUnit::ROWS);
        METRIC_DEFINE_INT_COUNTER(load_rows_total, MetricUnit::ROWS);
        METRIC_DEFINE_INT_COUNTER(load_bytes_total, MetricUnit::BYTES);
        
-       METRIC_DEFINE_INT_COUNTER(memtable_flush_total, MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_COUNTER(memtable_flush_total, MetricUnit::OPERATIONS);
        METRIC_DEFINE_INT_COUNTER(memtable_flush_duration_us, 
MetricUnit::MICROSECONDS);
        
        // Gauges
        METRIC_DEFINE_INT_GAUGE(memory_pool_bytes_total, MetricUnit::BYTES);
-       METRIC_DEFINE_INT_GAUGE(process_thread_num, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_GAUGE(process_fd_num_used, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_GAUGE(process_fd_num_limit_soft, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_GAUGE(process_fd_num_limit_hard, MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_GAUGE(process_thread_num, MetricUnit::NOUNIT);
+       METRIC_DEFINE_INT_GAUGE(process_fd_num_used, MetricUnit::NOUNIT);
+       METRIC_DEFINE_INT_GAUGE(process_fd_num_limit_soft, MetricUnit::NOUNIT);
+       METRIC_DEFINE_INT_GAUGE(process_fd_num_limit_hard, MetricUnit::NOUNIT);
     IntGaugeMetricsMap disks_total_capacity;
     IntGaugeMetricsMap disks_avail_capacity;
     IntGaugeMetricsMap disks_data_used_capacity;
@@ -149,46 +147,44 @@ public:
        // the max compaction score of all tablets.
        // Record base and cumulative scores separately, because
        // we need to get the larger of the two.
-       METRIC_DEFINE_INT_GAUGE(tablet_cumulative_max_compaction_score, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_GAUGE(tablet_base_max_compaction_score, 
MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_GAUGE(tablet_cumulative_max_compaction_score, 
MetricUnit::NOUNIT);
+       METRIC_DEFINE_INT_GAUGE(tablet_base_max_compaction_score, 
MetricUnit::NOUNIT);
        
        // The following metrics will be calculated
        // by metric calculator
-       METRIC_DEFINE_INT_GAUGE(push_request_write_bytes_per_second, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_GAUGE(query_scan_bytes_per_second, 
MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_GAUGE(push_request_write_bytes_per_second, 
MetricUnit::BYTES);
+       METRIC_DEFINE_INT_GAUGE(query_scan_bytes_per_second, MetricUnit::BYTES);
        METRIC_DEFINE_INT_GAUGE(max_disk_io_util_percent, MetricUnit::PERCENT);
-       METRIC_DEFINE_INT_GAUGE(max_network_send_bytes_rate, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_GAUGE(max_network_receive_bytes_rate, 
MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_GAUGE(max_network_send_bytes_rate, MetricUnit::BYTES);
+       METRIC_DEFINE_INT_GAUGE(max_network_receive_bytes_rate, 
MetricUnit::BYTES);
        
        // Metrics related with BlockManager
-       METRIC_DEFINE_INT_COUNTER(readable_blocks_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(writable_blocks_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(blocks_created_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_COUNTER(blocks_deleted_total, MetricUnit::NUMBER);
+       METRIC_DEFINE_INT_COUNTER(readable_blocks_total, MetricUnit::BLOCKS);
+       METRIC_DEFINE_INT_COUNTER(writable_blocks_total, MetricUnit::BLOCKS);
+       METRIC_DEFINE_INT_COUNTER(blocks_created_total, MetricUnit::OPERATIONS);
+       METRIC_DEFINE_INT_COUNTER(blocks_deleted_total, MetricUnit::OPERATIONS);
        METRIC_DEFINE_INT_COUNTER(bytes_read_total, MetricUnit::BYTES);
        METRIC_DEFINE_INT_COUNTER(bytes_written_total, MetricUnit::BYTES);
-       METRIC_DEFINE_INT_COUNTER(disk_sync_total, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_GAUGE(blocks_open_reading, MetricUnit::NUMBER);
-       METRIC_DEFINE_INT_GAUGE(blocks_open_writing, MetricUnit::NUMBER);
-       
-       METRIC_DEFINE_INT_COUNTER(blocks_push_remote_duration_us, 
MetricUnit::MICROSECONDS);
+       METRIC_DEFINE_INT_COUNTER(disk_sync_total, MetricUnit::OPERATIONS);
+       METRIC_DEFINE_INT_GAUGE(blocks_open_reading, MetricUnit::BLOCKS);
+       METRIC_DEFINE_INT_GAUGE(blocks_open_writing, MetricUnit::BLOCKS);
        
        // Size of some global containers
-       METRIC_DEFINE_UINT_GAUGE(rowset_count_generated_and_in_use, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(unused_rowsets_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(broker_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(data_stream_receiver_count, 
MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(fragment_endpoint_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(active_scan_context_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(plan_fragment_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(load_channel_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(result_buffer_block_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(result_block_queue_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(routine_load_task_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(small_file_cache_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(stream_load_pipe_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(brpc_endpoint_stub_count, MetricUnit::NUMBER);
-       METRIC_DEFINE_UINT_GAUGE(tablet_writer_count, MetricUnit::NUMBER);
+       METRIC_DEFINE_UINT_GAUGE(rowset_count_generated_and_in_use, 
MetricUnit::ROWSETS);
+       METRIC_DEFINE_UINT_GAUGE(unused_rowsets_count, MetricUnit::ROWSETS);
+       METRIC_DEFINE_UINT_GAUGE(broker_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(data_stream_receiver_count, 
MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(fragment_endpoint_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(active_scan_context_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(plan_fragment_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(load_channel_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(result_buffer_block_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(result_block_queue_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(routine_load_task_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(small_file_cache_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(stream_load_pipe_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(brpc_endpoint_stub_count, MetricUnit::NOUNIT);
+       METRIC_DEFINE_UINT_GAUGE(tablet_writer_count, MetricUnit::NOUNIT);
 
     static DorisMetrics* instance() {
         static DorisMetrics instance;
diff --git a/be/src/util/metrics.cpp b/be/src/util/metrics.cpp
index b702489..7ad9433 100644
--- a/be/src/util/metrics.cpp
+++ b/be/src/util/metrics.cpp
@@ -59,10 +59,18 @@ const char* unit_name(MetricUnit unit) {
         return "bytes";
     case MetricUnit::ROWS:
         return "rows";
-    case MetricUnit::NUMBER:
-        return "number";
     case MetricUnit::PERCENT:
         return "percent";
+    case MetricUnit::REQUESTS:
+        return "requests";
+    case MetricUnit::OPERATIONS:
+        return "operations";
+    case MetricUnit::BLOCKS:
+        return "blocks";
+    case MetricUnit::ROWSETS:
+        return "rowsets";
+    case MetricUnit::CONNECTIONS:
+        return "rowsets";
     default:
         return "nounit";
     }
diff --git a/be/src/util/metrics.h b/be/src/util/metrics.h
index 4a22f2a..f6e9bdd 100644
--- a/be/src/util/metrics.h
+++ b/be/src/util/metrics.h
@@ -54,8 +54,13 @@ enum class MetricUnit {
     SECONDS,
     BYTES,
     ROWS,
-    NUMBER,
     PERCENT,
+    REQUESTS,
+    OPERATIONS,
+    BLOCKS,
+    ROWSETS,
+    CONNECTIONS,
+    PACKETS,
     NOUNIT
 };
 
diff --git a/be/src/util/system_metrics.cpp b/be/src/util/system_metrics.cpp
index ba9e91a..79d8c6b 100644
--- a/be/src/util/system_metrics.cpp
+++ b/be/src/util/system_metrics.cpp
@@ -49,10 +49,10 @@ struct MemoryMetrics {
 };
 
 struct DiskMetrics {
-    METRIC_DEFINE_INT_LOCK_COUNTER(reads_completed, MetricUnit::NUMBER);
+    METRIC_DEFINE_INT_LOCK_COUNTER(reads_completed, MetricUnit::OPERATIONS);
     METRIC_DEFINE_INT_LOCK_COUNTER(bytes_read, MetricUnit::BYTES);
     METRIC_DEFINE_INT_LOCK_COUNTER(read_time_ms, MetricUnit::MILLISECONDS);
-    METRIC_DEFINE_INT_LOCK_COUNTER(writes_completed, MetricUnit::NUMBER);
+    METRIC_DEFINE_INT_LOCK_COUNTER(writes_completed, MetricUnit::OPERATIONS);
     METRIC_DEFINE_INT_LOCK_COUNTER(bytes_written, MetricUnit::BYTES);
     METRIC_DEFINE_INT_LOCK_COUNTER(write_time_ms, MetricUnit::MILLISECONDS);
     METRIC_DEFINE_INT_LOCK_COUNTER(io_time_ms, MetricUnit::MILLISECONDS);
@@ -61,9 +61,9 @@ struct DiskMetrics {
 
 struct NetMetrics {
     METRIC_DEFINE_INT_LOCK_COUNTER(receive_bytes, MetricUnit::BYTES);
-    METRIC_DEFINE_INT_LOCK_COUNTER(receive_packets, MetricUnit::NUMBER);
+    METRIC_DEFINE_INT_LOCK_COUNTER(receive_packets, MetricUnit::PACKETS);
     METRIC_DEFINE_INT_LOCK_COUNTER(send_bytes, MetricUnit::BYTES);
-    METRIC_DEFINE_INT_LOCK_COUNTER(send_packets, MetricUnit::NUMBER);
+    METRIC_DEFINE_INT_LOCK_COUNTER(send_packets, MetricUnit::PACKETS);
 };
 
 // metrics read from /proc/net/snmp
@@ -75,8 +75,8 @@ struct SnmpMetrics {
 };
 
 struct FileDescriptorMetrics {
-    METRIC_DEFINE_INT_GAUGE(fd_num_limit, MetricUnit::NUMBER);
-    METRIC_DEFINE_INT_GAUGE(fd_num_used, MetricUnit::NUMBER);
+    METRIC_DEFINE_INT_GAUGE(fd_num_limit, MetricUnit::NOUNIT);
+    METRIC_DEFINE_INT_GAUGE(fd_num_used, MetricUnit::NOUNIT);
 };
 
 SystemMetrics::SystemMetrics() {
diff --git a/be/src/util/thrift_server.cpp b/be/src/util/thrift_server.cpp
index 9985732..2931c76 100644
--- a/be/src/util/thrift_server.cpp
+++ b/be/src/util/thrift_server.cpp
@@ -276,12 +276,12 @@ ThriftServer::ThriftServer(
             _session_handler(NULL) {
     if (metrics != NULL) {
         _metrics_enabled = true;
-        _current_connections.reset(new IntGauge(MetricUnit::NUMBER));
+        _current_connections.reset(new IntGauge(MetricUnit::CONNECTIONS));
         metrics->register_metric("thrift_current_connections", 
                                  MetricLabels().add("name", name),
                                  _current_connections.get());
 
-        _connections_total.reset(new IntCounter(MetricUnit::NUMBER));
+        _connections_total.reset(new IntCounter(MetricUnit::CONNECTIONS));
         metrics->register_metric("thrift_connections_total",
                                  MetricLabels().add("name", name),
                                  _connections_total.get());
diff --git a/be/test/http/metrics_action_test.cpp 
b/be/test/http/metrics_action_test.cpp
index 6bbab74..417696e 100644
--- a/be/test/http/metrics_action_test.cpp
+++ b/be/test/http/metrics_action_test.cpp
@@ -56,7 +56,7 @@ TEST_F(MetricsActionTest, prometheus_output) {
     IntGauge cpu_idle(MetricUnit::PERCENT);
     cpu_idle.set_value(50);
     registry.register_metric("cpu_idle", &cpu_idle);
-    IntCounter put_requests_total(MetricUnit::NUMBER);
+    IntCounter put_requests_total(MetricUnit::NOUNIT);
     put_requests_total.increment(2345);
     registry.register_metric("requests_total",
                              MetricLabels().add("type", "put").add("path", 
"/sports"),
diff --git a/be/test/util/doris_metrics_test.cpp 
b/be/test/util/doris_metrics_test.cpp
index 76a6a2e..cf728b4 100644
--- a/be/test/util/doris_metrics_test.cpp
+++ b/be/test/util/doris_metrics_test.cpp
@@ -100,12 +100,6 @@ TEST_F(DorisMetricsTest, Normal) {
         ASSERT_STREQ("102", metric->to_string().c_str());
     }
     {
-        DorisMetrics::instance()->http_request_duration_us.increment(103);
-        auto metric = metrics->get_metric("http_request_duration_us");
-        ASSERT_TRUE(metric != nullptr);
-        ASSERT_STREQ("103", metric->to_string().c_str());
-    }
-    {
         DorisMetrics::instance()->http_request_send_bytes.increment(104);
         auto metric = metrics->get_metric("http_request_send_bytes");
         ASSERT_TRUE(metric != nullptr);
@@ -124,12 +118,6 @@ TEST_F(DorisMetricsTest, Normal) {
         ASSERT_STREQ("105", metric->to_string().c_str());
     }
     {
-        DorisMetrics::instance()->ranges_processed_total.increment(13);
-        auto metric = metrics->get_metric("ranges_processed_total");
-        ASSERT_TRUE(metric != nullptr);
-        ASSERT_STREQ("13", metric->to_string().c_str());
-    }
-    {
         DorisMetrics::instance()->push_requests_success_total.increment(106);
         auto metric = metrics->get_metric("push_requests_total",
                                           MetricLabels().add("status", 
"SUCCESS"));
diff --git a/be/test/util/new_metrics_test.cpp 
b/be/test/util/new_metrics_test.cpp
index 649593b..d8a7860 100644
--- a/be/test/util/new_metrics_test.cpp
+++ b/be/test/util/new_metrics_test.cpp
@@ -36,7 +36,7 @@ public:
 
 TEST_F(MetricsTest, Counter) {
     {
-        IntCounter counter(MetricUnit::NUMBER);
+        IntCounter counter(MetricUnit::NOUNIT);
         ASSERT_EQ(0, counter.value());
         counter.increment(100);
         ASSERT_EQ(100, counter.value());
@@ -44,7 +44,7 @@ TEST_F(MetricsTest, Counter) {
         ASSERT_STREQ("100", counter.to_string().c_str());
     }
     {
-        DoubleCounter counter(MetricUnit::NUMBER);
+        DoubleCounter counter(MetricUnit::NOUNIT);
         ASSERT_EQ(0.0, counter.value());
         counter.increment(1.23);
         ASSERT_EQ(1.23, counter.value());
@@ -65,7 +65,7 @@ void mt_updater(IntCounter* counter, std::atomic<uint64_t>* 
used_time) {
 }
 
 TEST_F(MetricsTest, CounterPerf) {
-    IntCounter counter(MetricUnit::NUMBER);
+    IntCounter counter(MetricUnit::NOUNIT);
     volatile int64_t sum = 0;
 
     {
@@ -91,7 +91,7 @@ TEST_F(MetricsTest, CounterPerf) {
     ASSERT_EQ(100000000, counter.value());
     ASSERT_EQ(100000000, sum);
     {
-        IntCounter mt_counter(MetricUnit::NUMBER);
+        IntCounter mt_counter(MetricUnit::NOUNIT);
         std::vector<std::thread> updaters;
         std::atomic<uint64_t> used_time(0);
         for (int i = 0; i < 8; ++i) {
@@ -108,7 +108,7 @@ TEST_F(MetricsTest, CounterPerf) {
 
 TEST_F(MetricsTest, Gauge) {
     {
-        IntGauge gauge(MetricUnit::NUMBER);
+        IntGauge gauge(MetricUnit::NOUNIT);
         ASSERT_EQ(0, gauge.value());
         gauge.set_value(100);
         ASSERT_EQ(100, gauge.value());
@@ -116,7 +116,7 @@ TEST_F(MetricsTest, Gauge) {
         ASSERT_STREQ("100", gauge.to_string().c_str());
     }
     {
-        DoubleGauge gauge(MetricUnit::NUMBER);
+        DoubleGauge gauge(MetricUnit::NOUNIT);
         ASSERT_EQ(0.0, gauge.value());
         gauge.set_value(1.23);
         ASSERT_EQ(1.23, gauge.value());
@@ -205,9 +205,9 @@ private:
 };
 
 TEST_F(MetricsTest, MetricCollector) {
-    IntCounter puts(MetricUnit::NUMBER);
+    IntCounter puts(MetricUnit::NOUNIT);
     puts.increment(101);
-    IntCounter gets(MetricUnit::NUMBER);
+    IntCounter gets(MetricUnit::NOUNIT);
     gets.increment(201);
     MetricCollector collector;
     ASSERT_TRUE(collector.add_metic(MetricLabels().add("type", "put"), &puts));
@@ -216,7 +216,7 @@ TEST_F(MetricsTest, MetricCollector) {
 
     {
         // Can't add different type to one collector
-        IntGauge post(MetricUnit::NUMBER);
+        IntGauge post(MetricUnit::NOUNIT);
         ASSERT_FALSE(collector.add_metic(MetricLabels().add("type", "post"), 
&post));
     }
 
diff --git a/docs/.vuepress/sidebar/en.js b/docs/.vuepress/sidebar/en.js
index a1607be..9f5d0c1 100644
--- a/docs/.vuepress/sidebar/en.js
+++ b/docs/.vuepress/sidebar/en.js
@@ -77,6 +77,10 @@ module.exports = [
           "fe-get-log-file",
           "get-label-state",
           "restore-tablet",
+          "profile-action",
+          "connection-action",
+          "query-detail-action",
+          "show-data-action",
         ],
         sidebarDepth: 1,
       },
diff --git a/docs/.vuepress/sidebar/zh-CN.js b/docs/.vuepress/sidebar/zh-CN.js
index 6c5e77f..7e33c48 100644
--- a/docs/.vuepress/sidebar/zh-CN.js
+++ b/docs/.vuepress/sidebar/zh-CN.js
@@ -84,6 +84,10 @@ module.exports = [
           "fe-get-log-file",
           "get-label-state",
           "restore-tablet",
+          "profile-action",
+          "connection-action",
+          "query-detail-action",
+          "show-data-action",
         ],
         sidebarDepth: 1,
       },
diff --git a/docs/en/administrator-guide/http-actions/connection-action.md 
b/docs/en/administrator-guide/http-actions/connection-action.md
new file mode 100644
index 0000000..d7d81e0
--- /dev/null
+++ b/docs/en/administrator-guide/http-actions/connection-action.md
@@ -0,0 +1,42 @@
+---
+{
+    "title": "CONNECTION",
+    "language": "en"
+}
+---
+
+<!-- 
+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.
+-->
+
+# CONNECTION
+
+To get current query_id from connection
+
+```
+curl -X GET http://fe_host:fe_http_port/api/connection?connection_id=123
+```
+
+If connection_id does not exist, return 404 NOT FOUND ERROR
+
+If connection_id exists, return last query_id belongs to connection_id
+```
+{
+    "query_id" : 9133b7efa92a44c8-8ed4b44772ec2a0c
+}
+```
diff --git a/docs/en/administrator-guide/http-actions/profile-action.md 
b/docs/en/administrator-guide/http-actions/profile-action.md
new file mode 100644
index 0000000..7851fa6
--- /dev/null
+++ b/docs/en/administrator-guide/http-actions/profile-action.md
@@ -0,0 +1,120 @@
+---
+{
+    "title": "RPOFILE",
+    "language": "en"
+}
+---
+
+<!-- 
+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.
+-->
+
+# PROFILE 
+   
+To get query profile using query_id
+
+```
+curl -X GET http://fe_host:fe_http_port/api/profile?query_id=123
+```
+
+If query_id is not exists, return 404 NOT FOUND ERROR
+
+If query_id exists, return query profile like this
+```
+Query:
+  Summary:
+     - Query ID: a0a9259df9844029-845331577440a3bd
+     - Start Time: 2020-06-15 14:10:05
+     - End Time: 2020-06-15 14:10:05
+     - Total: 8ms
+     - Query Type: Query
+     - Query State: EOF
+     - Doris Version: trunk
+     - User: root
+     - Default Db: default_cluster:test
+     - Sql Statement: select * from table1
+  Execution Profile a0a9259df9844029-845331577440a3bd:(Active: 7.315ms, % 
non-child: 100.00%)
+    Fragment 0:
+      Instance a0a9259df9844029-845331577440a3be 
(host=TNetworkAddress(hostname:172.26.108.176, port:9560)):(Active: 1.523ms, % 
non-child: 0.24%)
+         - MemoryLimit: 2.00 GB
+         - PeakUsedReservation: 0.00
+         - PeakMemoryUsage: 72.00 KB
+         - RowsProduced: 5
+         - AverageThreadTokens: 0.00
+         - PeakReservation: 0.00
+        BlockMgr:
+           - BlocksCreated: 0
+           - BlockWritesOutstanding: 0
+           - BytesWritten: 0.00
+           - TotalEncryptionTime: 0ns
+           - BufferedPins: 0
+           - TotalReadBlockTime: 0ns
+           - TotalBufferWaitTime: 0ns
+           - BlocksRecycled: 0
+           - TotalIntegrityCheckTime: 0ns
+           - MaxBlockSize: 8.00 MB
+        DataBufferSender 
(dst_fragment_instance_id=a0a9259df9844029-845331577440a3be):
+           - AppendBatchTime: 9.23us
+             - ResultRendTime: 956ns
+             - TupleConvertTime: 5.735us
+           - NumSentRows: 5
+        OLAP_SCAN_NODE (id=0):(Active: 1.506ms, % non-child: 20.59%)
+           - TotalRawReadTime: 0ns
+           - CompressedBytesRead: 6.47 KB
+           - PeakMemoryUsage: 0.00
+           - RowsPushedCondFiltered: 0
+           - ScanRangesComplete: 0
+           - ScanTime: 25.195us
+           - BitmapIndexFilterTimer: 0ns
+           - BitmapIndexFilterCount: 0
+           - NumScanners: 65
+           - RowsStatsFiltered: 0
+           - VectorPredEvalTime: 0ns
+           - BlockSeekTime: 1.299ms
+           - RawRowsRead: 1.91K (1910)
+           - ScannerThreadsVoluntaryContextSwitches: 0
+           - RowsDelFiltered: 0
+           - IndexLoadTime: 911.104us
+           - NumDiskAccess: 1
+           - ScannerThreadsTotalWallClockTime: 0ns
+             - MaterializeTupleTime: 0ns
+             - ScannerThreadsUserTime: 0ns
+             - ScannerThreadsSysTime: 0ns
+           - TotalPagesNum: 0
+           - RowsReturnedRate: 3.319K /sec
+           - BlockLoadTime: 539.289us
+           - CachedPagesNum: 0
+           - BlocksLoad: 384
+           - UncompressedBytesRead: 0.00
+           - RowsBloomFilterFiltered: 0
+           - TabletCount : 1
+           - RowsReturned: 5
+           - ScannerThreadsInvoluntaryContextSwitches: 0
+           - DecompressorTimer: 0ns
+           - RowsVectorPredFiltered: 0
+           - ReaderInitTime: 6.498ms
+           - RowsRead: 5
+           - PerReadThreadRawHdfsThroughput: 0.0 /sec
+           - BlockFetchTime: 4.318ms
+           - ShowHintsTime: 0ns
+           - TotalReadThroughput: 0.0 /sec
+           - IOTimer: 1.154ms
+           - BytesRead: 48.49 KB
+           - BlockConvertTime: 97.539us
+           - BlockSeekCount: 0
+```
diff --git a/docs/en/administrator-guide/http-actions/query-detail-action.md 
b/docs/en/administrator-guide/http-actions/query-detail-action.md
new file mode 100644
index 0000000..b4b5f0e
--- /dev/null
+++ b/docs/en/administrator-guide/http-actions/query-detail-action.md
@@ -0,0 +1,61 @@
+---
+{
+    "title": "QUERY DETAIL",
+    "language": "en"
+}
+---
+
+<!-- 
+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.
+-->
+
+# QUERY DETAIL
+   
+Collect the query details from FE. You should set the event_time.
+FE will return the query detail after the event_time.
+The unit of event_time is milliseconds.
+
+```
+curl -X GET 
http://fe_host:fe_http_port/api/query_detail?event_time=1592054515284
+```
+
+The query details will be be returned as JSON
+```
+[
+  {
+    "eventTime": 1592201405063,
+    "queryId": "a0a9259df9844029-845331577440a3bd",
+    "startTime": 1592201405055,
+    "endTime": 1592201405063,
+    "latency": 8,
+    "state": "FINISHED",
+    "database": "test",
+    "sql": "select * from table1"
+  }, 
+  {
+    "eventTime": 1592201420842,
+    "queryId": "21cd79c3e1634e8a-bdac090c7e7bcc36",
+    "startTime": 1592201420834,
+    "endTime": 1592201420842,
+    "latency": 8,
+    "state": "FINISHED",
+    "database": "test",
+    "sql": "select * from table1"
+  }
+]
+```
diff --git a/docs/en/administrator-guide/http-actions/show-data-action.md 
b/docs/en/administrator-guide/http-actions/show-data-action.md
new file mode 100644
index 0000000..5e767ff
--- /dev/null
+++ b/docs/en/administrator-guide/http-actions/show-data-action.md
@@ -0,0 +1,35 @@
+---
+{
+    "title": "SHOW DATA",
+    "language": "en"
+}
+---
+
+<!-- 
+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.
+-->
+
+# SHOW DATA
+   
+To all size occupied by cluster
+
+```
+curl -X GET http://fe_host:fe_http_port/api/show_data
+```
+
+The return value is the total size of the cluster
diff --git a/docs/zh-CN/administrator-guide/http-actions/connection-action.md 
b/docs/zh-CN/administrator-guide/http-actions/connection-action.md
new file mode 100644
index 0000000..3852575
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/http-actions/connection-action.md
@@ -0,0 +1,42 @@
+---
+{
+    "title": "CONNECTION",
+    "language": "zh-CN"
+}
+---
+
+<!-- 
+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.
+-->
+
+# CONNECTION
+   
+通过connection_id, 获取当前连接的query_id
+
+```
+curl -X GET http://fe_host:fe_http_port/api/connection?connection_id=123
+```
+
+如果connection_id不存在,直接返回404 NOT FOUND错误
+
+如果connection_id存在,会返回当前connectiond_id上一个进行的query_id
+```
+{
+    "query_id" : 9133b7efa92a44c8-8ed4b44772ec2a0c
+}
+```
diff --git a/docs/zh-CN/administrator-guide/http-actions/profile-action.md 
b/docs/zh-CN/administrator-guide/http-actions/profile-action.md
new file mode 100644
index 0000000..84bde4c
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/http-actions/profile-action.md
@@ -0,0 +1,120 @@
+---
+{
+    "title": "RPOFILE",
+    "language": "zh-CN"
+}
+---
+
+<!-- 
+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.
+-->
+
+# PROFILE 
+
+通过query_id获取query profile
+
+```
+curl -X GET http://fe_host:fe_http_port/api/profile?query_id=123
+```
+
+如果query_id不存在, 直接返回404 NOT FOUND错误
+
+如果query_id存在,返回下列文本的profile
+```
+Query:
+  Summary:
+     - Query ID: a0a9259df9844029-845331577440a3bd
+     - Start Time: 2020-06-15 14:10:05
+     - End Time: 2020-06-15 14:10:05
+     - Total: 8ms
+     - Query Type: Query
+     - Query State: EOF
+     - Doris Version: trunk
+     - User: root
+     - Default Db: default_cluster:test
+     - Sql Statement: select * from table1
+  Execution Profile a0a9259df9844029-845331577440a3bd:(Active: 7.315ms, % 
non-child: 100.00%)
+    Fragment 0:
+      Instance a0a9259df9844029-845331577440a3be 
(host=TNetworkAddress(hostname:172.26.108.176, port:9560)):(Active: 1.523ms, % 
non-child: 0.24%)
+         - MemoryLimit: 2.00 GB
+         - PeakUsedReservation: 0.00
+         - PeakMemoryUsage: 72.00 KB
+         - RowsProduced: 5
+         - AverageThreadTokens: 0.00
+         - PeakReservation: 0.00
+        BlockMgr:
+           - BlocksCreated: 0
+           - BlockWritesOutstanding: 0
+           - BytesWritten: 0.00
+           - TotalEncryptionTime: 0ns
+           - BufferedPins: 0
+           - TotalReadBlockTime: 0ns
+           - TotalBufferWaitTime: 0ns
+           - BlocksRecycled: 0
+           - TotalIntegrityCheckTime: 0ns
+           - MaxBlockSize: 8.00 MB
+        DataBufferSender 
(dst_fragment_instance_id=a0a9259df9844029-845331577440a3be):
+           - AppendBatchTime: 9.23us
+             - ResultRendTime: 956ns
+             - TupleConvertTime: 5.735us
+           - NumSentRows: 5
+        OLAP_SCAN_NODE (id=0):(Active: 1.506ms, % non-child: 20.59%)
+           - TotalRawReadTime: 0ns
+           - CompressedBytesRead: 6.47 KB
+           - PeakMemoryUsage: 0.00
+           - RowsPushedCondFiltered: 0
+           - ScanRangesComplete: 0
+           - ScanTime: 25.195us
+           - BitmapIndexFilterTimer: 0ns
+           - BitmapIndexFilterCount: 0
+           - NumScanners: 65
+           - RowsStatsFiltered: 0
+           - VectorPredEvalTime: 0ns
+           - BlockSeekTime: 1.299ms
+           - RawRowsRead: 1.91K (1910)
+           - ScannerThreadsVoluntaryContextSwitches: 0
+           - RowsDelFiltered: 0
+           - IndexLoadTime: 911.104us
+           - NumDiskAccess: 1
+           - ScannerThreadsTotalWallClockTime: 0ns
+             - MaterializeTupleTime: 0ns
+             - ScannerThreadsUserTime: 0ns
+             - ScannerThreadsSysTime: 0ns
+           - TotalPagesNum: 0
+           - RowsReturnedRate: 3.319K /sec
+           - BlockLoadTime: 539.289us
+           - CachedPagesNum: 0
+           - BlocksLoad: 384
+           - UncompressedBytesRead: 0.00
+           - RowsBloomFilterFiltered: 0
+           - TabletCount : 1
+           - RowsReturned: 5
+           - ScannerThreadsInvoluntaryContextSwitches: 0
+           - DecompressorTimer: 0ns
+           - RowsVectorPredFiltered: 0
+           - ReaderInitTime: 6.498ms
+           - RowsRead: 5
+           - PerReadThreadRawHdfsThroughput: 0.0 /sec
+           - BlockFetchTime: 4.318ms
+           - ShowHintsTime: 0ns
+           - TotalReadThroughput: 0.0 /sec
+           - IOTimer: 1.154ms
+           - BytesRead: 48.49 KB
+           - BlockConvertTime: 97.539us
+           - BlockSeekCount: 0
+```
diff --git a/docs/zh-CN/administrator-guide/http-actions/query-detail-action.md 
b/docs/zh-CN/administrator-guide/http-actions/query-detail-action.md
new file mode 100644
index 0000000..da07e3f
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/http-actions/query-detail-action.md
@@ -0,0 +1,59 @@
+---
+{
+    "title": "QUERY DETAIL",
+    "language": "zh-CN"
+}
+---
+
+<!-- 
+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.
+-->
+
+# QUERY DETAIL
+   
+从FE获取所有的查询细节,获取关于查询执行的相关信息。
+FE会返回在event_time之后的查询细节,其中event_time单位会精确到毫秒。
+
+```
+curl -X GET 
http://fe_host:fe_http_port/api/query_detail?event_time=1592054515284
+```
+
+查询信息会以JSON格式返回。
+```
+[
+  {
+    "eventTime": 1592201405063,
+    "queryId": "a0a9259df9844029-845331577440a3bd",
+    "startTime": 1592201405055,
+    "endTime": 1592201405063,
+    "latency": 8,
+    "state": "FINISHED",
+    "database": "test",
+    "sql": "select * from table1"
+  },
+  {
+    "eventTime": 1592201420842,
+    "queryId": "21cd79c3e1634e8a-bdac090c7e7bcc36",
+    "startTime": 1592201420834,
+    "endTime": 1592201420842,
+    "latency": 8,
+    "state": "FINISHED",
+    "database": "test",
+    "sql": "select * from table1"
+  }
+]
diff --git a/docs/zh-CN/administrator-guide/http-actions/show-data-action.md 
b/docs/zh-CN/administrator-guide/http-actions/show-data-action.md
new file mode 100644
index 0000000..178bfcc
--- /dev/null
+++ b/docs/zh-CN/administrator-guide/http-actions/show-data-action.md
@@ -0,0 +1,35 @@
+---
+{
+    "title": "SHOW DATA",
+    "language": "zh-CN"
+}
+---
+
+<!-- 
+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.
+-->
+
+# SHOW DATA
+   
+获取当前集群占用的总空间大小
+
+```
+curl -X GET http://fe_host:fe_http_port/api/show_data
+```
+
+返回值就是集群的总数据大小
diff --git a/fe/src/main/java/org/apache/doris/PaloFe.java 
b/fe/src/main/java/org/apache/doris/PaloFe.java
index 2f01788..2fbae1f 100644
--- a/fe/src/main/java/org/apache/doris/PaloFe.java
+++ b/fe/src/main/java/org/apache/doris/PaloFe.java
@@ -73,7 +73,6 @@ public class PaloFe {
         }
 
         CommandLineOptions cmdLineOpts = parseArgs(args);
-        System.out.println(cmdLineOpts.toString());
 
         try {
             // pid file
diff --git a/fe/src/main/java/org/apache/doris/common/ThreadPoolManager.java 
b/fe/src/main/java/org/apache/doris/common/ThreadPoolManager.java
index ef9b088..c7dafeb 100644
--- a/fe/src/main/java/org/apache/doris/common/ThreadPoolManager.java
+++ b/fe/src/main/java/org/apache/doris/common/ThreadPoolManager.java
@@ -69,7 +69,7 @@ public class ThreadPoolManager {
 
     public static void registerThreadPoolMetric(String poolName, 
ThreadPoolExecutor threadPool) {
         for (String poolMetricType : poolMerticTypes) {
-            GaugeMetric<Integer> gauge = new 
GaugeMetric<Integer>("thread_pool", MetricUnit.NUMBER, "thread_pool 
statistics") {
+            GaugeMetric<Integer> gauge = new 
GaugeMetric<Integer>("thread_pool", MetricUnit.NOUNIT, "thread_pool 
statistics") {
                 @Override
                 public Integer getValue() {
                     String metricType = this.getLabels().get(1).getValue();
diff --git a/fe/src/main/java/org/apache/doris/common/util/RuntimeProfile.java 
b/fe/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
index a6ee648..d462c08 100644
--- a/fe/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
+++ b/fe/src/main/java/org/apache/doris/common/util/RuntimeProfile.java
@@ -204,7 +204,7 @@ public class RuntimeProfile {
         
         // 2. info String
         for (String key : this.infoStringsDisplayOrder) {
-            builder.append(prefix).append("  ").append(key).append(": ")
+            builder.append(prefix).append("   - ").append(key).append(": ")
                 .append(this.infoStrings.get(key)).append("\n");
         }
         
diff --git a/fe/src/main/java/org/apache/doris/http/HttpServer.java 
b/fe/src/main/java/org/apache/doris/http/HttpServer.java
index 37d7c5e..1d4dcc4 100644
--- a/fe/src/main/java/org/apache/doris/http/HttpServer.java
+++ b/fe/src/main/java/org/apache/doris/http/HttpServer.java
@@ -42,6 +42,7 @@ import org.apache.doris.http.meta.MetaService.VersionAction;
 import org.apache.doris.http.rest.BootstrapFinishAction;
 import org.apache.doris.http.rest.CancelStreamLoad;
 import org.apache.doris.http.rest.CheckDecommissionAction;
+import org.apache.doris.http.rest.ConnectionAction;
 import org.apache.doris.http.rest.GetDdlStmtAction;
 import org.apache.doris.http.rest.GetLoadInfoAction;
 import org.apache.doris.http.rest.GetLogFileAction;
@@ -58,8 +59,11 @@ import org.apache.doris.http.rest.MultiDesc;
 import org.apache.doris.http.rest.MultiList;
 import org.apache.doris.http.rest.MultiStart;
 import org.apache.doris.http.rest.MultiUnload;
+import org.apache.doris.http.rest.ProfileAction;
+import org.apache.doris.http.rest.QueryDetailAction;
 import org.apache.doris.http.rest.RowCountAction;
 import org.apache.doris.http.rest.SetConfigAction;
+import org.apache.doris.http.rest.ShowDataAction;
 import org.apache.doris.http.rest.ShowMetaInfoAction;
 import org.apache.doris.http.rest.ShowProcAction;
 import org.apache.doris.http.rest.ShowRuntimeInfoAction;
@@ -152,6 +156,10 @@ public class HttpServer {
         ColocateMetaService.BucketSeqAction.registerAction(controller);
         ColocateMetaService.ColocateMetaAction.registerAction(controller);
         ColocateMetaService.MarkGroupStableAction.registerAction(controller);
+        ProfileAction.registerAction(controller);
+        QueryDetailAction.registerAction(controller);
+        ConnectionAction.registerAction(controller);
+        ShowDataAction.registerAction(controller);
 
         // meta service action
         File imageDir = MetaHelper.getMasterImageDir();
diff --git a/fe/src/main/java/org/apache/doris/http/rest/ConnectionAction.java 
b/fe/src/main/java/org/apache/doris/http/rest/ConnectionAction.java
new file mode 100644
index 0000000..2d486be
--- /dev/null
+++ b/fe/src/main/java/org/apache/doris/http/rest/ConnectionAction.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.doris.http.rest;
+
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import org.apache.doris.common.util.DebugUtil;
+import org.apache.doris.http.ActionController;
+import org.apache.doris.http.BaseRequest;
+import org.apache.doris.http.BaseResponse;
+import org.apache.doris.http.IllegalArgException;
+import org.apache.doris.qe.ConnectContext;
+import org.apache.doris.service.ExecuteEnv;
+
+// This class is used to get current query_id of connection_id.
+// Every connection holds at most one query at every point.
+// Some we can get query_id firstly, and get query by query_id.
+public class ConnectionAction extends RestBaseAction {
+    public ConnectionAction(ActionController controller) {
+        super(controller);
+    }
+
+    public static void registerAction (ActionController controller) throws 
IllegalArgException {
+        controller.registerHandler(HttpMethod.GET, "/api/connection", new 
ConnectionAction(controller));
+    }
+
+    @Override
+    public void execute(BaseRequest request, BaseResponse response) {
+        String connStr = request.getSingleParameter("connection_id");
+        if (connStr == null) {
+            response.getContent().append("not valid parameter");
+            sendResult(request, response, HttpResponseStatus.BAD_REQUEST);
+            return;
+        }
+        long connectionId = Long.valueOf(connStr.trim());
+        ConnectContext context = 
ExecuteEnv.getInstance().getScheduler().getContext(connectionId);
+        if (context == null || context.queryId() == null) {
+            response.getContent().append("connection id " + connectionId + " 
not found.");
+            sendResult(request, response, HttpResponseStatus.NOT_FOUND);
+            return;
+        }
+        String queryId = DebugUtil.printId(context.queryId());
+        response.getContent().append("{\"query_id\" : " + queryId + "}");
+        sendResult(request, response);
+    }
+}
diff --git a/fe/src/main/java/org/apache/doris/http/rest/ProfileAction.java 
b/fe/src/main/java/org/apache/doris/http/rest/ProfileAction.java
new file mode 100644
index 0000000..0bb35ed
--- /dev/null
+++ b/fe/src/main/java/org/apache/doris/http/rest/ProfileAction.java
@@ -0,0 +1,60 @@
+// 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.doris.http.rest;
+
+import org.apache.doris.common.util.ProfileManager;
+import org.apache.doris.http.ActionController;
+import org.apache.doris.http.BaseRequest;
+import org.apache.doris.http.BaseResponse;
+import org.apache.doris.http.IllegalArgException;
+
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpResponseStatus;
+
+// This class is a RESTFUL interface to get query profile.
+// It will be used in query monitor to collect profiles.   
+// Usage:
+//      wget http://fe_host:fe_http_port/api/profile?query_id=123456
+public class ProfileAction extends RestBaseAction {
+
+    public ProfileAction(ActionController controller) {
+        super(controller);
+    }
+
+    public static void registerAction (ActionController controller) throws 
IllegalArgException {
+        controller.registerHandler(HttpMethod.GET, "/api/profile", new 
ProfileAction(controller));
+    }
+
+    @Override
+    public void execute(BaseRequest request, BaseResponse response) {
+        String queryId = request.getSingleParameter("query_id");
+        if (queryId == null) {
+            response.getContent().append("not valid parameter");
+            sendResult(request, response, HttpResponseStatus.BAD_REQUEST);
+            return;
+        }
+        String queryProfileStr = 
ProfileManager.getInstance().getProfile(queryId);
+        if (queryProfileStr != null) {
+            response.getContent().append(queryProfileStr);
+            sendResult(request, response);
+        } else {
+            response.getContent().append("query id " + queryId + " not 
found.");
+            sendResult(request, response, HttpResponseStatus.NOT_FOUND);
+        }
+    }
+}
diff --git a/fe/src/main/java/org/apache/doris/http/rest/QueryDetailAction.java 
b/fe/src/main/java/org/apache/doris/http/rest/QueryDetailAction.java
new file mode 100644
index 0000000..c12a640
--- /dev/null
+++ b/fe/src/main/java/org/apache/doris/http/rest/QueryDetailAction.java
@@ -0,0 +1,56 @@
+// 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.doris.http.rest;
+
+import com.google.gson.Gson;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import java.util.List;
+import org.apache.doris.http.ActionController;
+import org.apache.doris.http.BaseRequest;
+import org.apache.doris.http.BaseResponse;
+import org.apache.doris.http.IllegalArgException;
+import org.apache.doris.qe.QueryDetail;
+import org.apache.doris.qe.QueryDetailQueue;
+
+public class QueryDetailAction extends RestBaseAction {
+
+    public QueryDetailAction(ActionController controller) {
+        super(controller);
+    }
+
+    public static void registerAction (ActionController controller) throws 
IllegalArgException {
+        controller.registerHandler(HttpMethod.GET, "/api/query_detail", new 
QueryDetailAction(controller));
+    }
+
+    @Override
+    public void execute(BaseRequest request, BaseResponse response) {
+        String eventTimeStr = request.getSingleParameter("event_time");
+        if (eventTimeStr == null) {
+            response.getContent().append("not valid parameter");
+            sendResult(request, response, HttpResponseStatus.BAD_REQUEST);
+            return;
+        }
+        long eventTime = Long.valueOf(eventTimeStr.trim());
+        List<QueryDetail> queryDetails = 
QueryDetailQueue.getQueryDetails(eventTime);
+        Gson gson = new Gson();
+        String json_string = gson.toJson(queryDetails);
+        response.getContent().append(json_string);
+        sendResult(request, response);
+    }
+}
diff --git a/fe/src/main/java/org/apache/doris/http/rest/ShowDataAction.java 
b/fe/src/main/java/org/apache/doris/http/rest/ShowDataAction.java
new file mode 100644
index 0000000..2f4e77a
--- /dev/null
+++ b/fe/src/main/java/org/apache/doris/http/rest/ShowDataAction.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.doris.http.rest;
+
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import org.apache.doris.catalog.Catalog;
+import org.apache.doris.catalog.Database;
+import org.apache.doris.catalog.OlapTable;
+import org.apache.doris.catalog.Table;
+import org.apache.doris.catalog.Table.TableType;
+import org.apache.doris.http.ActionController;
+import org.apache.doris.http.BaseRequest;
+import org.apache.doris.http.BaseResponse;
+import org.apache.doris.http.IllegalArgException;
+
+import io.netty.handler.codec.http.HttpMethod;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.List;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class ShowDataAction extends RestBaseAction {
+    private static final Logger LOG = 
LogManager.getLogger(ShowDataAction.class);
+
+    public ShowDataAction(ActionController controller) {
+        super(controller);
+    }
+
+    public static void registerAction (ActionController controller) throws 
IllegalArgException {
+        controller.registerHandler(HttpMethod.GET, "/api/show_data", new 
ShowDataAction(controller));
+    }
+
+    public long getDataSizeOfDatabase(Database db) {
+        long totalSize = 0;
+        db.readLock();
+        // sort by table name
+        List<Table> tables = db.getTables();
+        for (Table table : tables) {
+            if (table.getType() != TableType.OLAP) {
+                continue;
+            }
+
+            long tableSize = ((OlapTable)table).getDataSize();
+            totalSize += tableSize;
+        } // end for tables
+        db.readUnlock();
+        return totalSize;
+    }
+
+    @Override
+    public void execute(BaseRequest request, BaseResponse response) {
+        String dbName = request.getSingleParameter("db");
+        ConcurrentHashMap<String, Database> fullNameToDb = 
Catalog.getCurrentCatalog().getFullNameToDb();
+        long totalSize = 0;
+        if (dbName != null) {
+            Database db = fullNameToDb.get("default_cluster:"+dbName);
+            if (db == null) {
+                response.getContent().append("database " + dbName + " not 
found.");
+                sendResult(request, response, HttpResponseStatus.NOT_FOUND);
+                return;
+            }
+            totalSize = getDataSizeOfDatabase(db);    
+        } else {
+            for (Database db : fullNameToDb.values()) {
+                LOG.info("database name: {}", db.getFullName());
+                totalSize += getDataSizeOfDatabase(db);
+            }
+        }
+        response.getContent().append(String.valueOf(totalSize));
+        sendResult(request, response);
+    }
+}
diff --git a/fe/src/main/java/org/apache/doris/master/ReportHandler.java 
b/fe/src/main/java/org/apache/doris/master/ReportHandler.java
index 18550af..ca7b8d5 100644
--- a/fe/src/main/java/org/apache/doris/master/ReportHandler.java
+++ b/fe/src/main/java/org/apache/doris/master/ReportHandler.java
@@ -100,7 +100,7 @@ public class ReportHandler extends Daemon {
 
     public ReportHandler() {
         GaugeMetric<Long> gaugeQueueSize = new GaugeMetric<Long>(
-                "report_queue_size", MetricUnit.NUMBER, "report queue size") {
+                "report_queue_size", MetricUnit.NOUNIT, "report queue size") {
             @Override
             public Long getValue() {
                 return (long) reportQueue.size();
diff --git a/fe/src/main/java/org/apache/doris/metric/Metric.java 
b/fe/src/main/java/org/apache/doris/metric/Metric.java
index e5e029c..b6e2a0e 100644
--- a/fe/src/main/java/org/apache/doris/metric/Metric.java
+++ b/fe/src/main/java/org/apache/doris/metric/Metric.java
@@ -33,8 +33,13 @@ public abstract class Metric<T> {
         SECONDS,
         BYTES,
         ROWS,
-        NUMBER,
         PERCENT,
+        REQUESTS,
+        OPERATIONS,
+        BLOCKS,
+        ROWSETS,
+        CONNECTIONS,
+        PACKETS,
         NOUNIT
     };
 
diff --git a/fe/src/main/java/org/apache/doris/metric/MetricRepo.java 
b/fe/src/main/java/org/apache/doris/metric/MetricRepo.java
index 82407bf..2bc8434 100644
--- a/fe/src/main/java/org/apache/doris/metric/MetricRepo.java
+++ b/fe/src/main/java/org/apache/doris/metric/MetricRepo.java
@@ -98,7 +98,7 @@ public final class MetricRepo {
         for (EtlJobType jobType : EtlJobType.values()) {
             for (JobState state : JobState.values()) {
                 GaugeMetric<Long> gauge = (GaugeMetric<Long>) new 
GaugeMetric<Long>("job",
-                        MetricUnit.NUMBER, "job statistics") {
+                        MetricUnit.NOUNIT, "job statistics") {
                     @Override
                     public Long getValue() {
                         if (!Catalog.getCurrentCatalog().isMaster()) {
@@ -122,7 +122,7 @@ public final class MetricRepo {
             }
             
             GaugeMetric<Long> gauge = (GaugeMetric<Long>) new 
GaugeMetric<Long>("job",
-                    MetricUnit.NUMBER, "job statistics") {
+                    MetricUnit.NOUNIT, "job statistics") {
                 @Override
                 public Long getValue() {
                     if (!Catalog.getCurrentCatalog().isMaster()) {
@@ -146,7 +146,7 @@ public final class MetricRepo {
 
         // connections
         GaugeMetric<Integer> conections = (GaugeMetric<Integer>) new 
GaugeMetric<Integer>(
-                "connection_total", MetricUnit.NUMBER, "total connections") {
+                "connection_total", MetricUnit.CONNECTIONS, "total 
connections") {
             @Override
             public Integer getValue() {
                 return 
ExecuteEnv.getInstance().getScheduler().getConnectionNum();
@@ -156,7 +156,7 @@ public final class MetricRepo {
 
         // journal id
         GaugeMetric<Long> maxJournalId = (GaugeMetric<Long>) new 
GaugeMetric<Long>(
-                "max_journal_id", MetricUnit.NUMBER, "max journal id of this 
frontends") {
+                "max_journal_id", MetricUnit.NOUNIT, "max journal id of this 
frontends") {
             @Override
             public Long getValue() {
                 EditLog editLog = Catalog.getCurrentCatalog().getEditLog();
@@ -170,7 +170,7 @@ public final class MetricRepo {
 
         // scheduled tablet num
         GaugeMetric<Long> scheduledTabletNum = (GaugeMetric<Long>) new 
GaugeMetric<Long>(
-                "scheduled_tablet_num", MetricUnit.NUMBER, "number of tablets 
being scheduled") {
+                "scheduled_tablet_num", MetricUnit.NOUNIT, "number of tablets 
being scheduled") {
             @Override
             public Long getValue() {
                 if (!Catalog.getCurrentCatalog().isMaster()) {
@@ -183,50 +183,50 @@ public final class MetricRepo {
 
         // qps, rps and error rate
         // these metrics should be set an init value, in case that metric 
calculator is not running
-        GAUGE_QUERY_PER_SECOND = new GaugeMetricImpl<>("qps", 
MetricUnit.NUMBER, "query per second");
+        GAUGE_QUERY_PER_SECOND = new GaugeMetricImpl<>("qps", 
MetricUnit.NOUNIT, "query per second");
         GAUGE_QUERY_PER_SECOND.setValue(0.0);
         PALO_METRIC_REGISTER.addPaloMetrics(GAUGE_QUERY_PER_SECOND);
-        GAUGE_REQUEST_PER_SECOND = new GaugeMetricImpl<>("rps", 
MetricUnit.NUMBER, "request per second");
+        GAUGE_REQUEST_PER_SECOND = new GaugeMetricImpl<>("rps", 
MetricUnit.NOUNIT, "request per second");
         GAUGE_REQUEST_PER_SECOND.setValue(0.0);
         PALO_METRIC_REGISTER.addPaloMetrics(GAUGE_REQUEST_PER_SECOND);
-        GAUGE_QUERY_ERR_RATE = new GaugeMetricImpl<>("query_err_rate", 
MetricUnit.NUMBER, "query error rate");
+        GAUGE_QUERY_ERR_RATE = new GaugeMetricImpl<>("query_err_rate", 
MetricUnit.NOUNIT, "query error rate");
         PALO_METRIC_REGISTER.addPaloMetrics(GAUGE_QUERY_ERR_RATE);
         GAUGE_QUERY_ERR_RATE.setValue(0.0);
         GAUGE_MAX_TABLET_COMPACTION_SCORE = new 
GaugeMetricImpl<>("max_tablet_compaction_score",
-                MetricUnit.NUMBER, "max tablet compaction score of all 
backends");
+                MetricUnit.NOUNIT, "max tablet compaction score of all 
backends");
         PALO_METRIC_REGISTER.addPaloMetrics(GAUGE_MAX_TABLET_COMPACTION_SCORE);
         GAUGE_MAX_TABLET_COMPACTION_SCORE.setValue(0L);
 
         // 2. counter
-        COUNTER_REQUEST_ALL = new LongCounterMetric("request_total", 
MetricUnit.NUMBER, "total request");
+        COUNTER_REQUEST_ALL = new LongCounterMetric("request_total", 
MetricUnit.REQUESTS, "total request");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_REQUEST_ALL);
-        COUNTER_QUERY_ALL = new LongCounterMetric("query_total", 
MetricUnit.NUMBER, "total query");
+        COUNTER_QUERY_ALL = new LongCounterMetric("query_total", 
MetricUnit.REQUESTS, "total query");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_QUERY_ALL);
-        COUNTER_QUERY_ERR = new LongCounterMetric("query_err", 
MetricUnit.NUMBER, "total error query");
+        COUNTER_QUERY_ERR = new LongCounterMetric("query_err", 
MetricUnit.REQUESTS, "total error query");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_QUERY_ERR);
-        COUNTER_LOAD_ADD = new LongCounterMetric("load_add", 
MetricUnit.NUMBER, "total load submit");
+        COUNTER_LOAD_ADD = new LongCounterMetric("load_add", 
MetricUnit.REQUESTS, "total load submit");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_LOAD_ADD);
-        COUNTER_LOAD_FINISHED = new LongCounterMetric("load_finished", 
MetricUnit.NUMBER, "total load finished");
+        COUNTER_LOAD_FINISHED = new LongCounterMetric("load_finished", 
MetricUnit.REQUESTS, "total load finished");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_LOAD_FINISHED);
-        COUNTER_EDIT_LOG_WRITE = new LongCounterMetric("edit_log_write", 
MetricUnit.NUMBER, "counter of edit log write into bdbje");
+        COUNTER_EDIT_LOG_WRITE = new LongCounterMetric("edit_log_write", 
MetricUnit.OPERATIONS, "counter of edit log write into bdbje");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_EDIT_LOG_WRITE);
-        COUNTER_EDIT_LOG_READ = new LongCounterMetric("edit_log_read", 
MetricUnit.NUMBER, "counter of edit log read from bdbje");
+        COUNTER_EDIT_LOG_READ = new LongCounterMetric("edit_log_read", 
MetricUnit.OPERATIONS, "counter of edit log read from bdbje");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_EDIT_LOG_READ);
         COUNTER_EDIT_LOG_SIZE_BYTES = new 
LongCounterMetric("edit_log_size_bytes", MetricUnit.BYTES, "size of edit log");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_EDIT_LOG_SIZE_BYTES);
-        COUNTER_IMAGE_WRITE = new LongCounterMetric("image_write", 
MetricUnit.NUMBER, "counter of image generated");
+        COUNTER_IMAGE_WRITE = new LongCounterMetric("image_write", 
MetricUnit.OPERATIONS, "counter of image generated");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_IMAGE_WRITE);
-        COUNTER_IMAGE_PUSH = new LongCounterMetric("image_push", 
MetricUnit.NUMBER,
+        COUNTER_IMAGE_PUSH = new LongCounterMetric("image_push", 
MetricUnit.OPERATIONS,
                 "counter of image succeeded in pushing to other frontends");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_IMAGE_PUSH);
 
-        COUNTER_TXN_REJECT = new LongCounterMetric("txn_reject", 
MetricUnit.NUMBER, "counter of rejected transactions");
+        COUNTER_TXN_REJECT = new LongCounterMetric("txn_reject", 
MetricUnit.REQUESTS, "counter of rejected transactions");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_TXN_REJECT);
-        COUNTER_TXN_BEGIN = new LongCounterMetric("txn_begin", 
MetricUnit.NUMBER, "counter of begining transactions");
+        COUNTER_TXN_BEGIN = new LongCounterMetric("txn_begin", 
MetricUnit.REQUESTS, "counter of begining transactions");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_TXN_BEGIN);
-        COUNTER_TXN_SUCCESS = new LongCounterMetric("txn_success", 
MetricUnit.NUMBER, "counter of success transactions");
+        COUNTER_TXN_SUCCESS = new LongCounterMetric("txn_success", 
MetricUnit.REQUESTS, "counter of success transactions");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_TXN_SUCCESS);
-        COUNTER_TXN_FAILED = new LongCounterMetric("txn_failed", 
MetricUnit.NUMBER, "counter of failed transactions");
+        COUNTER_TXN_FAILED = new LongCounterMetric("txn_failed", 
MetricUnit.REQUESTS, "counter of failed transactions");
         PALO_METRIC_REGISTER.addPaloMetrics(COUNTER_TXN_FAILED);
 
         COUNTER_ROUTINE_LOAD_ROWS = new LongCounterMetric("routine_load_rows", 
MetricUnit.ROWS, "total rows of routine load");
@@ -296,7 +296,7 @@ public final class MetricRepo {
 
             // tablet number of each backends
             GaugeMetric<Long> tabletNum = (GaugeMetric<Long>) new 
GaugeMetric<Long>(TABLET_NUM,
-                    MetricUnit.NUMBER, "tablet number") {
+                    MetricUnit.NOUNIT, "tablet number") {
                 @Override
                 public Long getValue() {
                     if (!Catalog.getCurrentCatalog().isMaster()) {
@@ -310,7 +310,7 @@ public final class MetricRepo {
 
             // max compaction score of tablets on each backends
             GaugeMetric<Long> tabletMaxCompactionScore = (GaugeMetric<Long>) 
new GaugeMetric<Long>(
-                    TABLET_MAX_COMPACTION_SCORE, MetricUnit.NUMBER,
+                    TABLET_MAX_COMPACTION_SCORE, MetricUnit.NOUNIT,
                     "tablet max compaction score") {
                 @Override
                 public Long getValue() {
diff --git a/fe/src/main/java/org/apache/doris/qe/ConnectContext.java 
b/fe/src/main/java/org/apache/doris/qe/ConnectContext.java
index 6094818..8627087 100644
--- a/fe/src/main/java/org/apache/doris/qe/ConnectContext.java
+++ b/fe/src/main/java/org/apache/doris/qe/ConnectContext.java
@@ -25,6 +25,7 @@ import org.apache.doris.mysql.MysqlChannel;
 import org.apache.doris.mysql.MysqlCommand;
 import org.apache.doris.mysql.MysqlSerializer;
 import org.apache.doris.plugin.AuditEvent.AuditEventBuilder;
+import org.apache.doris.qe.QueryDetail;
 import org.apache.doris.thrift.TResourceInfo;
 import org.apache.doris.thrift.TUniqueId;
 
@@ -97,6 +98,8 @@ public class ConnectContext {
 
     protected String remoteIP;
 
+    protected QueryDetail queryDetail;
+
     public static ConnectContext get() {
         return threadLocalInfo.get();
     }
@@ -135,6 +138,7 @@ public class ConnectContext {
         if (channel != null) {
             remoteIP = mysqlChannel.getRemoteIp();
         }
+        queryDetail = null;
     }
 
     public long getStmtId() {
@@ -161,6 +165,14 @@ public class ConnectContext {
         this.remoteIP = remoteIP;
     }
 
+    public void setQueryDetail(QueryDetail queryDetail) {
+        this.queryDetail = queryDetail;
+    }
+
+    public QueryDetail getQueryDetail() {
+        return queryDetail;
+    }
+
     public AuditEventBuilder getAuditEventBuilder() {
         return auditEventBuilder;
     }
diff --git a/fe/src/main/java/org/apache/doris/qe/ConnectProcessor.java 
b/fe/src/main/java/org/apache/doris/qe/ConnectProcessor.java
index 74833ab..100f2b1 100644
--- a/fe/src/main/java/org/apache/doris/qe/ConnectProcessor.java
+++ b/fe/src/main/java/org/apache/doris/qe/ConnectProcessor.java
@@ -43,6 +43,8 @@ import org.apache.doris.mysql.MysqlSerializer;
 import org.apache.doris.mysql.MysqlServerStatusFlag;
 import org.apache.doris.plugin.AuditEvent.EventType;
 import org.apache.doris.proto.PQueryStatistics;
+import org.apache.doris.qe.QueryDetail;
+import org.apache.doris.qe.QueryDetailQueue;
 import org.apache.doris.service.FrontendOptions;
 import org.apache.doris.thrift.TMasterOpRequest;
 import org.apache.doris.thrift.TMasterOpResult;
@@ -106,7 +108,8 @@ public class ConnectProcessor {
 
     private void auditAfterExec(String origStmt, StatementBase parsedStmt, 
PQueryStatistics statistics) {
         // slow query
-        long elapseMs = System.currentTimeMillis() - ctx.getStartTime();
+        long endTime = System.currentTimeMillis();
+        long elapseMs = endTime - ctx.getStartTime();
         
         ctx.getAuditEventBuilder().setEventType(EventType.AFTER_QUERY)
             .setState(ctx.getState().toString()).setQueryTime(elapseMs)
@@ -127,6 +130,11 @@ public class ConnectProcessor {
                 MetricRepo.HISTO_QUERY_LATENCY.update(elapseMs);
             }
             ctx.getAuditEventBuilder().setIsQuery(true);
+            ctx.getQueryDetail().setEventTime(endTime);
+            ctx.getQueryDetail().setEndTime(endTime);
+            ctx.getQueryDetail().setLatency(elapseMs);
+            ctx.getQueryDetail().setState(QueryDetail.QueryMemState.FINISHED);
+            QueryDetailQueue.addOrUpdateQueryDetail(ctx.getQueryDetail());
         } else {
             ctx.getAuditEventBuilder().setIsQuery(false);
         }
diff --git a/fe/src/main/java/org/apache/doris/qe/QueryDetail.java 
b/fe/src/main/java/org/apache/doris/qe/QueryDetail.java
new file mode 100644
index 0000000..e87c464
--- /dev/null
+++ b/fe/src/main/java/org/apache/doris/qe/QueryDetail.java
@@ -0,0 +1,129 @@
+// 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.doris.qe;
+
+public class QueryDetail {
+    public enum QueryMemState {
+        RUNNING,
+        FINISHED,
+        FAILED,
+        CANCELLED 
+    };
+
+    // When query received, FE will construct a QueryDetail
+    // object. This object will set queryId, startTime, sql
+    // fields. As well state is be set as RUNNING. 
+    // After query finished, endTime and latency will
+    // be set and state will be updated to be FINISHED/FAILED/CANCELLED
+    // according to the query execution results.
+    // So, one query will be inserted into as a item and 
+    // be udpated upon finished. To indicate the two event,
+    // a extra field named eventTime is added.
+    private long eventTime;
+    private String queryId;
+    private long startTime;
+    // endTime and latency are update upon query finished.
+    // default value will set to be minus one(-1).
+    private long endTime;
+    private long latency;
+    private QueryMemState state;
+    private String database;
+    private String sql;
+
+    public QueryDetail(long eventTime, String queryId, long startTime,
+                       long endTime, long latency, QueryMemState state,
+                       String database, String sql) {
+        this.eventTime = eventTime;
+        this.queryId = queryId;
+        this.startTime = startTime;
+        this.endTime = endTime;
+        this.latency = latency;
+        this.state = state;
+        if (database.equals("")) {
+            this.database = "";
+        } else {
+            String[] stringPieces = database.split(":", -1);
+            this.database = stringPieces[1]; // eliminate cluster name
+        }
+        this.sql = sql;
+    }
+
+    public void setEventTime(long eventTime) {
+        this.eventTime = eventTime;
+    }
+
+    public long getEventTime() {
+        return eventTime;
+    }
+
+    public void setQueryId(String queryId) {
+        this.queryId = queryId;
+    }
+
+    public String getQueryId() {
+        return queryId;
+    }
+
+    public void setStartTime(long startTime) {
+        this.startTime = startTime;
+    }
+
+    public long getStartTime() {
+        return startTime;
+    }
+
+    public void setEndTime(long endTime) {
+        this.endTime = endTime;
+    }
+
+    public long getEndTime() {
+        return endTime;
+    }
+     
+    public void setLatency(long latency) {
+        this.latency = latency;
+    }
+
+    public long getLatency() {
+        return latency;
+    }
+
+    public void setState(QueryMemState state) {
+        this.state = state;
+    }
+
+    public QueryMemState getState() {
+        return state;
+    }
+
+    public void setDatabase(String database) {
+        this.database = database;
+    }
+
+    public String getDatabase() {
+        return database;
+    }
+
+    public void setSql(String sql) {
+        this.sql = sql;
+    }
+
+    public String getSql() {
+        return sql;
+    }
+}
diff --git a/fe/src/main/java/org/apache/doris/qe/QueryDetailQueue.java 
b/fe/src/main/java/org/apache/doris/qe/QueryDetailQueue.java
new file mode 100644
index 0000000..97f26d5
--- /dev/null
+++ b/fe/src/main/java/org/apache/doris/qe/QueryDetailQueue.java
@@ -0,0 +1,69 @@
+// 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.doris.qe;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import org.apache.doris.qe.QueryDetail;
+
+// Queue of QueryDetail.
+// It's used to collect queries for monitor.
+// The default copacity is 10000.
+public class QueryDetailQueue {
+    private static Map<String, QueryDetail> runningQueries = Maps.newHashMap();
+    private static LinkedList<QueryDetail> totalQueries = new 
LinkedList<QueryDetail>();
+    private static int queryCapacity = 10000;
+
+    public static synchronized void addOrUpdateQueryDetail(QueryDetail 
queryDetail) {
+        if (runningQueries.get(queryDetail.getQueryId()) == null) {
+            if (queryDetail.getState() == QueryDetail.QueryMemState.RUNNING) {
+                runningQueries.put(queryDetail.getQueryId(), queryDetail);
+                totalQueries.add(queryDetail);
+            } else {
+                totalQueries.add(queryDetail);
+            }
+        } else {
+            if (queryDetail.getState() != QueryDetail.QueryMemState.RUNNING) {
+                QueryDetail qDetail = 
runningQueries.remove(queryDetail.getQueryId());
+                qDetail.setLatency(queryDetail.getLatency());
+                qDetail.setState(queryDetail.getState());
+            }
+        }
+        if (totalQueries.size() > queryCapacity) {
+            QueryDetail qDetail = totalQueries.remove();
+            runningQueries.remove(qDetail.getQueryId());
+        }
+    }
+
+    public static synchronized List<QueryDetail> getQueryDetails(long 
eventTime) {
+        List<QueryDetail> results = Lists.newArrayList();
+        Iterator<QueryDetail> it = totalQueries.iterator();
+        while(it.hasNext()) {
+            QueryDetail queryDetail = it.next();
+            if (queryDetail.getEventTime() > eventTime) {
+                results.add(queryDetail);
+            }
+        }
+        return results; 
+    }
+
+};
diff --git a/fe/src/main/java/org/apache/doris/qe/StmtExecutor.java 
b/fe/src/main/java/org/apache/doris/qe/StmtExecutor.java
index ec4d529..876f2f6 100644
--- a/fe/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -64,6 +64,8 @@ import org.apache.doris.mysql.MysqlSerializer;
 import org.apache.doris.mysql.privilege.PrivPredicate;
 import org.apache.doris.planner.Planner;
 import org.apache.doris.proto.PQueryStatistics;
+import org.apache.doris.qe.QueryDetail;
+import org.apache.doris.qe.QueryDetailQueue;
 import org.apache.doris.qe.QueryState.MysqlStateType;
 import org.apache.doris.rewrite.ExprRewriter;
 import org.apache.doris.rpc.RpcException;
@@ -223,6 +225,10 @@ public class StmtExecutor {
 
         long beginTimeInNanoSecond = TimeUtils.getStartTime();
         context.setStmtId(STMT_ID_GENERATOR.incrementAndGet());
+
+        // set query id
+        UUID uuid = UUID.randomUUID();
+        context.setQueryId(new TUniqueId(uuid.getMostSignificantBits(), 
uuid.getLeastSignificantBits()));
         try {
             // analyze this query
             analyze(context.getSessionVariable().toThrift());
@@ -340,7 +346,6 @@ public class StmtExecutor {
         profile.computeTimeInChildProfile();
         StringBuilder builder = new StringBuilder();
         profile.prettyPrint(builder, "");
-        System.out.println(builder.toString());
         ProfileManager.getInstance().pushProfile(profile);
     }
 
@@ -559,9 +564,14 @@ public class StmtExecutor {
         context.getMysqlChannel().reset();
         QueryStmt queryStmt = (QueryStmt) parsedStmt;
 
-        // assign query id before explain query return
-        UUID uuid = UUID.randomUUID();
-        context.setQueryId(new TUniqueId(uuid.getMostSignificantBits(), 
uuid.getLeastSignificantBits()));
+        QueryDetail queryDetail = new QueryDetail(context.getStartTime(),
+                                                  
DebugUtil.printId(context.queryId()),
+                                                  context.getStartTime(), -1, 
-1,
+                                                  
QueryDetail.QueryMemState.RUNNING,
+                                                  context.getDatabase(),
+                                                  originStmt.originStmt);
+        context.setQueryDetail(queryDetail);
+        QueryDetailQueue.addOrUpdateQueryDetail(queryDetail);
 
         if (queryStmt.isExplain()) {
             String explainString = 
planner.getExplainString(planner.getFragments(), TExplainLevel.VERBOSE);
diff --git 
a/fe/src/test/java/org/apache/doris/common/util/RuntimeProfileTest.java 
b/fe/src/test/java/org/apache/doris/common/util/RuntimeProfileTest.java
index b1c10ef..6ca409c 100644
--- a/fe/src/test/java/org/apache/doris/common/util/RuntimeProfileTest.java
+++ b/fe/src/test/java/org/apache/doris/common/util/RuntimeProfileTest.java
@@ -95,7 +95,7 @@ public class RuntimeProfileTest {
         StringBuilder builder = new StringBuilder();
         profile.prettyPrint(builder, "");
         Assert.assertEquals(builder.toString(), 
-                "profileName:\n  key: value4\n  key3: value3\n");
+                "profileName:\n   - key: value4\n   - key3: value3\n");
     }
     
     @Test
diff --git a/fe/src/test/java/org/apache/doris/qe/QueryDetailQueueTest.java 
b/fe/src/test/java/org/apache/doris/qe/QueryDetailQueueTest.java
new file mode 100644
index 0000000..cd7b707
--- /dev/null
+++ b/fe/src/test/java/org/apache/doris/qe/QueryDetailQueueTest.java
@@ -0,0 +1,73 @@
+// 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.doris.qe;
+
+import com.google.common.collect.Lists;
+import com.google.gson.Gson;
+
+import org.apache.doris.qe.QueryDetail;
+import org.apache.doris.qe.QueryDetailQueue;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.List;
+
+public class QueryDetailQueueTest {
+    @Test
+    public void testQueryDetailQueue() {
+        long eventTime = 1592208814796L;
+        QueryDetail queryDetail = new QueryDetail(eventTime, 
"219a2d5443c542d4-8fc938db37c892e3",
+                                                  eventTime, -1, -1, 
QueryDetail.QueryMemState.RUNNING,
+                                                  "default_cluster:testDb", 
"select * from table1 limit 1");
+        QueryDetailQueue.addOrUpdateQueryDetail(queryDetail);
+
+        List<QueryDetail> queryDetails = 
QueryDetailQueue.getQueryDetails(eventTime);
+        Assert.assertTrue(queryDetails.size() == 0); 
+
+        queryDetails = QueryDetailQueue.getQueryDetails(eventTime - 1);
+        Assert.assertTrue(queryDetails.size() == 1); 
+
+        Gson gson = new Gson();
+        String json_string = gson.toJson(queryDetails);
+        String query_detail_string = "[{\"eventTime\":1592208814796," 
+                                     + 
"\"queryId\":\"219a2d5443c542d4-8fc938db37c892e3\","
+                                     + 
"\"startTime\":1592208814796,\"endTime\":-1,\"latency\":-1,"
+                                     + 
"\"state\":\"RUNNING\",\"database\":\"testDb\","
+                                     + "\"sql\":\"select * from table1 limit 
1\"}]";
+        Assert.assertEquals(json_string, query_detail_string);
+
+        queryDetail.setEventTime(eventTime + 1);
+        queryDetail.setEndTime(eventTime + 1);
+        queryDetail.setLatency(1);
+        queryDetail.setState(QueryDetail.QueryMemState.FINISHED);
+        QueryDetailQueue.addOrUpdateQueryDetail(queryDetail);
+
+        queryDetails = QueryDetailQueue.getQueryDetails(eventTime);
+        Assert.assertTrue(queryDetails.size() == 1); 
+
+        json_string = gson.toJson(queryDetails);
+        query_detail_string = "[{\"eventTime\":1592208814797," 
+                              + 
"\"queryId\":\"219a2d5443c542d4-8fc938db37c892e3\","
+                              + 
"\"startTime\":1592208814796,\"endTime\":1592208814797,"
+                              + 
"\"latency\":1,\"state\":\"FINISHED\",\"database\":\"testDb\","
+                              + "\"sql\":\"select * from table1 limit 1\"}]";
+        Assert.assertEquals(json_string, query_detail_string);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to