From 9635fa817b80d51e33833cbeede41bad4d2cac51 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sun, 21 Aug 2022 12:11:25 +0200 Subject: [PATCH] Embedded dashboard --- programs/server/CMakeLists.txt | 2 +- programs/server/dashboard.html | 812 +++++++++++++++++++++++++++++ src/Server/HTTPHandlerFactory.cpp | 15 +- src/Server/WebUIRequestHandler.cpp | 38 +- src/Server/WebUIRequestHandler.h | 6 +- 5 files changed, 861 insertions(+), 12 deletions(-) create mode 100644 programs/server/dashboard.html diff --git a/programs/server/CMakeLists.txt b/programs/server/CMakeLists.txt index 643fd2f0ec4..2cfa748d585 100644 --- a/programs/server/CMakeLists.txt +++ b/programs/server/CMakeLists.txt @@ -34,6 +34,6 @@ install(FILES config.xml users.xml DESTINATION "${CLICKHOUSE_ETC_DIR}/clickhouse clickhouse_embed_binaries( TARGET clickhouse_server_configs - RESOURCES config.xml users.xml embedded.xml play.html + RESOURCES config.xml users.xml embedded.xml play.html dashboard.html js/uplot.js ) add_dependencies(clickhouse-server-lib clickhouse_server_configs) diff --git a/programs/server/dashboard.html b/programs/server/dashboard.html new file mode 100644 index 00000000000..d209f50827d --- /dev/null +++ b/programs/server/dashboard.html @@ -0,0 +1,812 @@ + + + + + ClickHouse Dashboard + + + + + +
+
+
+ + + +
+
+ + 🌚🌞 +
+
+
+
+
+ + + diff --git a/src/Server/HTTPHandlerFactory.cpp b/src/Server/HTTPHandlerFactory.cpp index 526b86a5c28..cbf0a2b40a5 100644 --- a/src/Server/HTTPHandlerFactory.cpp +++ b/src/Server/HTTPHandlerFactory.cpp @@ -169,10 +169,17 @@ void addCommonDefaultHandlersFactory(HTTPRequestHandlerFactoryMain & factory, IS replicas_status_handler->allowGetAndHeadRequest(); factory.addHandler(replicas_status_handler); - auto web_ui_handler = std::make_shared>(server, "play.html"); - web_ui_handler->attachNonStrictPath("/play"); - web_ui_handler->allowGetAndHeadRequest(); - factory.addHandler(web_ui_handler); + auto play_handler = std::make_shared>(server); + play_handler->attachNonStrictPath("/play"); + factory.addHandler(play_handler); + + auto dashboard_handler = std::make_shared>(server); + dashboard_handler->attachNonStrictPath("/dashboard"); + factory.addHandler(dashboard_handler); + + auto js_handler = std::make_shared>(server); + js_handler->attachNonStrictPath("/js/"); + factory.addHandler(js_handler); } void addDefaultHandlersFactory(HTTPRequestHandlerFactoryMain & factory, IServer & server, AsynchronousMetrics & async_metrics) diff --git a/src/Server/WebUIRequestHandler.cpp b/src/Server/WebUIRequestHandler.cpp index 50aa0be4778..c1d4535c22a 100644 --- a/src/Server/WebUIRequestHandler.cpp +++ b/src/Server/WebUIRequestHandler.cpp @@ -12,8 +12,8 @@ namespace DB { -WebUIRequestHandler::WebUIRequestHandler(IServer & server_, std::string resource_name_) - : server(server_), resource_name(std::move(resource_name_)) +WebUIRequestHandler::WebUIRequestHandler(IServer & server_) + : server(server_) { } @@ -28,8 +28,38 @@ void WebUIRequestHandler::handleRequest(HTTPServerRequest & request, HTTPServerR response.setChunkedTransferEncoding(true); setResponseDefaultHeaders(response, keep_alive_timeout); - response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_OK); - *response.send() << getResource(resource_name); + + if (request.getURI().starts_with("/play")) + { + response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_OK); + *response.send() << getResource("play.html"); + } + else if (request.getURI().starts_with("/dashboard")) + { + response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_OK); + + std::string html(getResource("dashboard.html")); + + /// Replace a link to external JavaScript file to embedded file. + /// This allows to open the HTML without running a server and to host it on server. + /// Note: we can embed the JavaScript file inline to the HTML, + /// but we don't do it to keep the "view-source" perfectly readable. + + static re2::RE2 uplot_url = R"(https://[^\s"'`]+u[Pp]lot[^\s"'`]*\.js)"; + RE2::Replace(&html, uplot_url, "/js/uplot.js"); + + *response.send() << html; + } + else if (request.getURI() == "/js/uplot.js") + { + response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_OK); + *response.send() << getResource("js/uplot.js"); + } + else + { + response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_NOT_FOUND); + *response.send() << "Not found.\n"; + } } } diff --git a/src/Server/WebUIRequestHandler.h b/src/Server/WebUIRequestHandler.h index 1c52b626091..e05c84c68c2 100644 --- a/src/Server/WebUIRequestHandler.h +++ b/src/Server/WebUIRequestHandler.h @@ -1,6 +1,7 @@ #pragma once #include +#include namespace DB @@ -13,11 +14,10 @@ class WebUIRequestHandler : public HTTPRequestHandler { private: IServer & server; - std::string resource_name; + public: - WebUIRequestHandler(IServer & server_, std::string resource_name_); + WebUIRequestHandler(IServer & server_); void handleRequest(HTTPServerRequest & request, HTTPServerResponse & response) override; }; } -