You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by bo...@apache.org on 2019/05/28 10:26:14 UTC

[impala] 05/08: IMPALA-6903: Download profile from WebUI in text format

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

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

commit b00d031fb37b83924d4dfa020360f35540717501
Author: Yongzhi Chen <yc...@cloudera.com>
AuthorDate: Mon May 13 20:33:44 2019 -0400

    IMPALA-6903: Download profile from WebUI in text format
    
    Add a link called "Download Text Profile" to profile tab.
    The link allows users to download runtime profiles as UTF-8
    encoded file.
    Get text profile from backend by making http request.
    
    Tests:
    Manually tested to check downloaded files.
    Ran all core tests.
    Add test_download_text_profile to test_web_pages.py.
    
    Change-Id: Ie030c2bb330211f51840417b9f7880f19174af7b
    Reviewed-on: http://gerrit.cloudera.org:8080/13333
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 be/src/service/impala-http-handler.cc | 19 ++++++++++++++++---
 be/src/service/impala-http-handler.h  |  9 +++++++++
 tests/webserver/test_web_pages.py     | 22 ++++++++++++++++++++++
 www/query_profile.tmpl                | 10 +++++++++-
 4 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/be/src/service/impala-http-handler.cc b/be/src/service/impala-http-handler.cc
index aef22b0..3cfd65a 100644
--- a/be/src/service/impala-http-handler.cc
+++ b/be/src/service/impala-http-handler.cc
@@ -124,6 +124,9 @@ void ImpalaHttpHandler::RegisterHandlers(Webserver* webserver) {
   webserver->RegisterUrlCallback("/query_profile_encoded", "raw_text.tmpl",
       MakeCallback(this, &ImpalaHttpHandler::QueryProfileEncodedHandler), false);
 
+  webserver->RegisterUrlCallback("/query_profile_plain_text", "raw_text.tmpl",
+        MakeCallback(this, &ImpalaHttpHandler::QueryProfileTextHandler), false);
+
   webserver->RegisterUrlCallback("/inflight_query_ids", "raw_text.tmpl",
       MakeCallback(this, &ImpalaHttpHandler::InflightQueryIdsHandler), false);
 
@@ -239,8 +242,8 @@ void ImpalaHttpHandler::QueryProfileHandler(const Webserver::WebRequest& req,
   document->AddMember("query_id", query_id, document->GetAllocator());
 }
 
-void ImpalaHttpHandler::QueryProfileEncodedHandler(const Webserver::WebRequest& req,
-    Document* document) {
+void ImpalaHttpHandler::QueryProfileHelper(const Webserver::WebRequest& req,
+    Document* document, TRuntimeProfileFormat::type format) {
   TUniqueId unique_id;
   stringstream ss;
   Status status = ParseIdFromRequest(req, &unique_id, "query_id");
@@ -248,7 +251,7 @@ void ImpalaHttpHandler::QueryProfileEncodedHandler(const Webserver::WebRequest&
     ss << status.GetDetail();
   } else {
     Status status = server_->GetRuntimeProfileOutput(
-        unique_id, "", TRuntimeProfileFormat::BASE64, &ss, nullptr);
+      unique_id, "", format, &ss, nullptr);
     if (!status.ok()) {
       ss.str(Substitute("Could not obtain runtime profile: $0", status.GetDetail()));
     }
@@ -259,6 +262,16 @@ void ImpalaHttpHandler::QueryProfileEncodedHandler(const Webserver::WebRequest&
   document->AddMember("contents", profile, document->GetAllocator());
 }
 
+void ImpalaHttpHandler::QueryProfileEncodedHandler(const Webserver::WebRequest& req,
+    Document* document) {
+  QueryProfileHelper(req, document, TRuntimeProfileFormat::BASE64);
+}
+
+void ImpalaHttpHandler::QueryProfileTextHandler(const Webserver::WebRequest& req,
+    Document* document) {
+  QueryProfileHelper(req, document, TRuntimeProfileFormat::STRING);
+}
+
 void ImpalaHttpHandler::InflightQueryIdsHandler(const Webserver::WebRequest& req,
     Document* document) {
   stringstream ss;
diff --git a/be/src/service/impala-http-handler.h b/be/src/service/impala-http-handler.h
index 07530cb..ce742a4 100644
--- a/be/src/service/impala-http-handler.h
+++ b/be/src/service/impala-http-handler.h
@@ -109,11 +109,20 @@ class ImpalaHttpHandler {
   void CloseSessionHandler(const Webserver::WebRequest& req,
       rapidjson::Document* document);
 
+  /// Helper method to put query profile in 'document' with required format.
+  void QueryProfileHelper(const Webserver::WebRequest& req,
+      rapidjson::Document* document, TRuntimeProfileFormat::type format);
+
   /// Upon return, 'document' will contain the query profile as a base64 encoded object in
   /// 'contents'.
   void QueryProfileEncodedHandler(const Webserver::WebRequest& req,
       rapidjson::Document* document);
 
+  /// Upon return, 'document' will contain the query profile as a utf8 string in
+  /// 'contents'.
+  void QueryProfileTextHandler(const Webserver::WebRequest& req,
+      rapidjson::Document* document);
+
   /// Produces a list of inflight query IDs printed as text in 'contents'.
   void InflightQueryIdsHandler(const Webserver::WebRequest& req,
       rapidjson::Document* document);
diff --git a/tests/webserver/test_web_pages.py b/tests/webserver/test_web_pages.py
index 2960599..581df17 100644
--- a/tests/webserver/test_web_pages.py
+++ b/tests/webserver/test_web_pages.py
@@ -542,3 +542,25 @@ class TestWebPage(ImpalaTestSuite):
     assert backend_row['is_executor']
     assert not backend_row['is_quiescing']
     assert len(backend_row['admit_mem_limit']) > 0
+
+  def test_download_text_profile(self):
+    """Test download text profile for a query"""
+    query = "select count(*) from functional.alltypes"
+    query_id = self.client.execute(query).query_id
+    profile_page_url = "{0}query_profile?query_id={1}".format(
+        self.ROOT_URL, query_id)
+    # Check the text download tag is there.
+    responses = self.get_and_check_status(
+        profile_page_url, "Download Text Profile",
+        ports_to_test=self.IMPALAD_TEST_PORT)
+    assert len(responses) == 1
+    download_link = "query_profile_plain_text?query_id={0}".format(
+        query_id)
+    assert download_link in responses[0].text
+    # Get the response from download link and validate it by checking
+    # the query is in the file.
+    responses = self.get_and_check_status(
+        self.ROOT_URL + download_link, query, self.IMPALAD_TEST_PORT)
+    # Check the query id is in the content of the reponse.
+    assert len(responses) == 1
+    assert query_id in responses[0].text
diff --git a/www/query_profile.tmpl b/www/query_profile.tmpl
index 4103227..4f93fdb 100644
--- a/www/query_profile.tmpl
+++ b/www/query_profile.tmpl
@@ -25,11 +25,19 @@ under the License.
 {{> www/query_detail_tabs.tmpl }}
 
 <h4>
-  <a href="/query_profile_encoded?query_id={{query_id}}" download="profile_{{query_id}}">
+  <a href="/query_profile_encoded?query_id={{query_id}}"
+      download="thrift_profile_{{query_id}}">
     Download Thrift Profile
   </a>
 </h4>
 
+<h4>
+  <a href="/query_profile_plain_text?query_id={{query_id}}"
+      download="profile_{{query_id}}">
+   Download Text Profile
+  </a>
+</h4>
+
 <pre>{{profile}}</pre>
 
 <script>