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

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


The following commit(s) were added to refs/heads/master by this push:
     new 51e02d053 [#960][part-3] feat(dashboard): Provides a start-stop script 
for the dashboard. (#1056)
51e02d053 is described below

commit 51e02d0539786b3888832c16a4248bc2ded44513
Author: yl09099 <[email protected]>
AuthorDate: Thu Nov 23 09:51:27 2023 +0800

    [#960][part-3] feat(dashboard): Provides a start-stop script for the 
dashboard. (#1056)
    
    ### What changes were proposed in this pull request?
    Provides a start-stop script for the dashboard.
    
    ### Why are the changes needed?
    
    Fix: https://github.com/apache/incubator-uniffle/issues/960
    
    ### Does this PR introduce any user-facing change?
    Start and close the dashboard module using shell scripts.
    
    ### How was this patch tested?
    UT.
---
 bin/start-dashboard.sh                             | 86 ++++++++++++++++++++++
 bin/stop-dashboard.sh                              | 28 +++++++
 build_distribution.sh                              |  7 ++
 common/pom.xml                                     |  4 +
 .../uniffle/dashboard/web/JettyServerFront.java    | 28 ++++++-
 .../dashboard/web/config/DashboardConf.java        |  6 ++
 .../dashboard/web/proxy/WebProxyServlet.java       | 79 ++++++++++++++++++++
 dashboard/src/main/webapp/src/api/api.js           |  4 +-
 .../main/webapp/src/components/ApplicationPage.vue |  1 -
 .../src/components/CoordinatorServerPage.vue       |  6 +-
 dashboard/src/main/webapp/vue.config.js            |  8 --
 docs/dashboard_guide.md                            | 42 +++++++++++
 pom.xml                                            |  5 ++
 13 files changed, 286 insertions(+), 18 deletions(-)

diff --git a/bin/start-dashboard.sh b/bin/start-dashboard.sh
new file mode 100644
index 000000000..9a5251500
--- /dev/null
+++ b/bin/start-dashboard.sh
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+set -o pipefail
+set -o nounset   # exit the script if you try to use an uninitialised variable
+set -o errexit   # exit the script if any statement returns a non-true return 
value
+
+source "$(dirname "$0")/utils.sh"
+load_rss_env
+
+cd "$RSS_HOME"
+
+COORDINATOR_CONF_FILE="${RSS_CONF_DIR}/coordinator.conf"
+JAR_DIR="${RSS_HOME}/jars"
+LOG_CONF_FILE="${RSS_CONF_DIR}/log4j.properties"
+LOG_PATH="${RSS_LOG_DIR}/dashboard.log"
+OUT_PATH="${RSS_LOG_DIR}/dashboard.out"
+
+MAIN_CLASS="org.apache.uniffle.dashboard.web.JettyServerFront"
+
+HADOOP_DEPENDENCY="$("$HADOOP_HOME/bin/hadoop" classpath --glob)"
+
+echo "Check process existence"
+is_jvm_process_running "$JPS" $MAIN_CLASS
+
+CLASSPATH=""
+
+for file in $(ls ${JAR_DIR}/dashboard/*.jar 2>/dev/null); do
+  CLASSPATH=$CLASSPATH:$file
+done
+
+mkdir -p "${RSS_LOG_DIR}"
+mkdir -p "${RSS_PID_DIR}"
+
+CLASSPATH=$CLASSPATH:$HADOOP_CONF_DIR:$HADOOP_DEPENDENCY
+JAVA_LIB_PATH="-Djava.library.path=$HADOOP_HOME/lib/native"
+
+echo "class path is $CLASSPATH"
+
+JVM_ARGS=" -server \
+          -Xmx${XMX_SIZE:-8g} \
+          -Xms${XMX_SIZE:-8g} \
+          -XX:+UseG1GC \
+          -XX:MaxGCPauseMillis=200 \
+          -XX:ParallelGCThreads=20 \
+          -XX:ConcGCThreads=5 \
+          -XX:InitiatingHeapOccupancyPercent=45 \
+          -XX:+PrintGC \
+          -XX:+PrintAdaptiveSizePolicy \
+          -XX:+PrintGCDateStamps \
+          -XX:+PrintGCTimeStamps \
+          -XX:+PrintGCDetails \
+          -Xloggc:${RSS_LOG_DIR}/gc-%t.log"
+
+JAVA11_EXTRA_ARGS=" -XX:+IgnoreUnrecognizedVMOptions \
+          -Xlog:gc:tags,time,uptime,level"
+
+ARGS=""
+
+if [ -f ${LOG_CONF_FILE} ]; then
+  ARGS="$ARGS -Dlog4j.configuration=file:${LOG_CONF_FILE} 
-Dlog.path=${LOG_PATH}"
+else
+  echo "Exit with error: ${LOG_CONF_FILE} file doesn't exist."
+  exit 1
+fi
+
+$RUNNER $ARGS $JVM_ARGS $JAVA11_EXTRA_ARGS -cp $CLASSPATH $MAIN_CLASS --conf 
"$COORDINATOR_CONF_FILE" $@ &> $OUT_PATH &
+
+get_pid_file_name uniffle-dashboard
+echo $! >${RSS_PID_DIR}/${pid_file}
diff --git a/bin/stop-dashboard.sh b/bin/stop-dashboard.sh
new file mode 100644
index 000000000..289aebae2
--- /dev/null
+++ b/bin/stop-dashboard.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+#
+
+set -o pipefail
+set -o nounset   # exit the script if you try to use an uninitialised variable
+set -o errexit   # exit the script if any statement returns a non-true return 
value
+
+source "$(dirname "$0")/utils.sh"
+load_rss_env
+
+common_shutdown "uniffle-dashboard" "${RSS_PID_DIR}"
diff --git a/build_distribution.sh b/build_distribution.sh
index f3c413e78..62ecc83aa 100755
--- a/build_distribution.sh
+++ b/build_distribution.sh
@@ -169,6 +169,13 @@ echo "copy $COORDINATOR_JAR to ${COORDINATOR_JAR_DIR}"
 cp $COORDINATOR_JAR ${COORDINATOR_JAR_DIR}
 cp "${RSS_HOME}"/coordinator/target/jars/* ${COORDINATOR_JAR_DIR}
 
+DASHBOARD_JAR_DIR="${DISTDIR}/jars/dashboard"
+mkdir -p $DASHBOARD_JAR_DIR
+DASHBOARD_JAR="${RSS_HOME}/dashboard/target/dashboard-${VERSION}.jar"
+echo "copy $DASHBOARD_JAR to ${DASHBOARD_JAR_DIR}"
+cp $DASHBOARD_JAR $DASHBOARD_JAR_DIR
+cp "${RSS_HOME}"/dashboard/target/jars/* ${DASHBOARD_JAR_DIR}
+
 CLI_JAR_DIR="${DISTDIR}/jars/cli"
 mkdir -p $CLI_JAR_DIR
 CLI_JAR="${RSS_HOME}/cli/target/cli-${VERSION}.jar"
diff --git a/common/pom.xml b/common/pom.xml
index 2ad3bfc4d..9f9d11d12 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -145,6 +145,10 @@
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-util</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.eclipse.jetty</groupId>
+      <artifactId>jetty-proxy</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.apache.hbase.thirdparty</groupId>
       <artifactId>hbase-shaded-jersey</artifactId>
diff --git 
a/dashboard/src/main/java/org/apache/uniffle/dashboard/web/JettyServerFront.java
 
b/dashboard/src/main/java/org/apache/uniffle/dashboard/web/JettyServerFront.java
index 7518f9591..65e1fd46d 100644
--- 
a/dashboard/src/main/java/org/apache/uniffle/dashboard/web/JettyServerFront.java
+++ 
b/dashboard/src/main/java/org/apache/uniffle/dashboard/web/JettyServerFront.java
@@ -22,12 +22,16 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import org.eclipse.jetty.proxy.ProxyServlet;
+import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.HttpConfiguration;
 import org.eclipse.jetty.server.HttpConnectionFactory;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.HandlerList;
 import org.eclipse.jetty.server.handler.ResourceHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
 import org.eclipse.jetty.util.resource.Resource;
 import org.eclipse.jetty.util.thread.ExecutorThreadPool;
 import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
@@ -40,6 +44,7 @@ import org.apache.uniffle.common.config.ReconfigurableBase;
 import org.apache.uniffle.common.util.ExitUtils;
 import org.apache.uniffle.common.util.ThreadUtils;
 import org.apache.uniffle.dashboard.web.config.DashboardConf;
+import org.apache.uniffle.dashboard.web.proxy.WebProxyServlet;
 
 public class JettyServerFront {
 
@@ -83,14 +88,29 @@ public class JettyServerFront {
   }
 
   private void setRootServletHandler() {
-    final ContextHandler contextHandler = new ContextHandler("/");
+    HandlerList handlers = new HandlerList();
+    ResourceHandler resourceHandler = addResourceHandler();
+    String coordinatorWebAddress = 
conf.getString(DashboardConf.COORDINATOR_WEB_ADDRESS);
+    ServletContextHandler servletContextHandler = 
addProxyHandler(coordinatorWebAddress);
+    handlers.setHandlers(new Handler[] {resourceHandler, 
servletContextHandler});
+    server.setHandler(handlers);
+  }
+
+  private static ResourceHandler addResourceHandler() {
     ResourceHandler resourceHandler = new ResourceHandler();
     resourceHandler.setDirectoriesListed(true);
     resourceHandler.setBaseResource(
         
Resource.newResource(JettyServerFront.class.getClassLoader().getResource("static")));
     resourceHandler.setWelcomeFiles(new String[] {"index.html"});
-    contextHandler.setHandler(resourceHandler);
-    server.setHandler(contextHandler);
+    return resourceHandler;
+  }
+
+  private static ServletContextHandler addProxyHandler(String 
coordinatorWebAddress) {
+    ProxyServlet proxyServlet = new WebProxyServlet(coordinatorWebAddress);
+    ServletHolder holder = new ServletHolder(proxyServlet);
+    ServletContextHandler contextHandler = new ServletContextHandler();
+    contextHandler.addServlet(holder, "/api/*");
+    return contextHandler;
   }
 
   private void addHttpConnector(int port, HttpConfiguration httpConfig, long 
idleTimeout) {
diff --git 
a/dashboard/src/main/java/org/apache/uniffle/dashboard/web/config/DashboardConf.java
 
b/dashboard/src/main/java/org/apache/uniffle/dashboard/web/config/DashboardConf.java
index f2a6cccf0..8d1fbbb32 100644
--- 
a/dashboard/src/main/java/org/apache/uniffle/dashboard/web/config/DashboardConf.java
+++ 
b/dashboard/src/main/java/org/apache/uniffle/dashboard/web/config/DashboardConf.java
@@ -30,6 +30,12 @@ public class DashboardConf extends RssBaseConf {
           .defaultValue(19988)
           .withDescription("http server http port");
 
+  public static final ConfigOption<String> COORDINATOR_WEB_ADDRESS =
+      ConfigOptions.key("coordinator.web.address")
+          .stringType()
+          .noDefaultValue()
+          .withDescription("Coordinator jetty port request address");
+
   public static final ConfigOption<Long> DASHBOARD_STOP_TIMEOUT =
       ConfigOptions.key("rss.dashboard.stop.timeout")
           .longType()
diff --git 
a/dashboard/src/main/java/org/apache/uniffle/dashboard/web/proxy/WebProxyServlet.java
 
b/dashboard/src/main/java/org/apache/uniffle/dashboard/web/proxy/WebProxyServlet.java
new file mode 100644
index 000000000..2877cc6ef
--- /dev/null
+++ 
b/dashboard/src/main/java/org/apache/uniffle/dashboard/web/proxy/WebProxyServlet.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.uniffle.dashboard.web.proxy;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.api.Response;
+import org.eclipse.jetty.proxy.ProxyServlet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WebProxyServlet extends ProxyServlet {
+
+  private String targetAddress;
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(WebProxyServlet.class);
+
+  public WebProxyServlet(String targetAddress) {
+    this.targetAddress = targetAddress;
+  }
+
+  @Override
+  protected String rewriteTarget(HttpServletRequest clientRequest) {
+    if (!validateDestination(clientRequest.getServerName(), 
clientRequest.getServerPort())) {
+      return null;
+    }
+    StringBuilder target = new StringBuilder();
+
+    if (targetAddress.endsWith("/")) {
+      targetAddress = targetAddress.substring(0, targetAddress.length() - 1);
+    }
+    
target.append(targetAddress).append("/api").append(clientRequest.getPathInfo());
+    String query = clientRequest.getQueryString();
+    if (query != null) {
+      target.append("?").append(query);
+    }
+    return target.toString();
+  }
+
+  @Override
+  protected void onProxyRewriteFailed(
+      HttpServletRequest clientRequest, HttpServletResponse clientResponse) {}
+
+  @Override
+  protected void onProxyResponseFailure(
+      HttpServletRequest clientRequest,
+      HttpServletResponse proxyResponse,
+      Response serverResponse,
+      Throwable failure) {}
+
+  @Override
+  protected String filterServerResponseHeader(
+      HttpServletRequest clientRequest,
+      Response serverResponse,
+      String headerName,
+      String headerValue) {
+    return null;
+  }
+
+  @Override
+  protected void addXForwardedHeaders(HttpServletRequest clientRequest, 
Request proxyRequest) {}
+}
diff --git a/dashboard/src/main/webapp/src/api/api.js 
b/dashboard/src/main/webapp/src/api/api.js
index c346d1d2e..d70e24b2b 100644
--- a/dashboard/src/main/webapp/src/api/api.js
+++ b/dashboard/src/main/webapp/src/api/api.js
@@ -69,10 +69,10 @@ export function getAppTotal(params){
 
 // Create an interface for the app basic information list
 export function getApplicationInfoList(params){
-    return http.get('/app/appinfos', params,{})
+    return http.get('/app/appInfos', params,{})
 }
 
 // Create an interface for the number of apps for a user
 export function getTotalForUser(params){
-    return http.get('/app/usertotal', params,{})
+    return http.get('/app/userTotal', params,{})
 }
diff --git a/dashboard/src/main/webapp/src/components/ApplicationPage.vue 
b/dashboard/src/main/webapp/src/components/ApplicationPage.vue
index 90f176218..8d96f6254 100644
--- a/dashboard/src/main/webapp/src/components/ApplicationPage.vue
+++ b/dashboard/src/main/webapp/src/components/ApplicationPage.vue
@@ -73,7 +73,6 @@ export default {
 
     async function getTotalForUserPage() {
       const res = await getTotalForUser();
-      console.log(res)
       pageData.userAppCount = res.data.data
     }
 
diff --git a/dashboard/src/main/webapp/src/components/CoordinatorServerPage.vue 
b/dashboard/src/main/webapp/src/components/CoordinatorServerPage.vue
index 76d9e657a..ca30d47bb 100644
--- a/dashboard/src/main/webapp/src/components/CoordinatorServerPage.vue
+++ b/dashboard/src/main/webapp/src/components/CoordinatorServerPage.vue
@@ -73,7 +73,7 @@
         </div>
       </el-collapse-item>
       <el-collapse-item title="Coordinator Properties" name="2">
-        <el-table :data="pageData.tableData" style="width: 100%">
+        <el-table :data="pageData.tableData" stripe style="width: 100%">
           <el-table-column prop="argumentKey" label="Name" min-width="380"/>
           <el-table-column prop="argumentValue" label="Value" min-width="380"/>
         </el-table>
@@ -96,11 +96,11 @@ export default {
     );
     async function getCoordinatorServerConfPage() {
       const res = await getCoordinatorConf();
-      pageData.serverInfo = res.data.data
+      pageData.tableData = res.data.data
     }
     async function getCoorServerInfo() {
       const res = await getCoordinatorServerInfo();
-      pageData.tableData = res.data.data
+      pageData.serverInfo = res.data.data
     }
     onMounted(() => {
       getCoordinatorServerConfPage();
diff --git a/dashboard/src/main/webapp/vue.config.js 
b/dashboard/src/main/webapp/vue.config.js
index 64ab67d57..a007fc8ba 100644
--- a/dashboard/src/main/webapp/vue.config.js
+++ b/dashboard/src/main/webapp/vue.config.js
@@ -16,12 +16,4 @@
  */
 
 module.exports ={
-  devServer:{
-    proxy:{
-      '/api':{
-        target:'http://localhost:9528',
-        changeOrigin:true
-      }
-    }
-  }
 }
diff --git a/docs/dashboard_guide.md b/docs/dashboard_guide.md
new file mode 100644
index 000000000..34d48e7df
--- /dev/null
+++ b/docs/dashboard_guide.md
@@ -0,0 +1,42 @@
+---
+layout: page
+displayTitle: Dashboard Guide
+title: Dashboard Guide
+description: Dashboard Guide
+license: |
+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.
+---
+# Dashboard Guide
+
+## Summary
+This document explains how to install and start Uniffle's dashboard.
+
+### Configure related parameters
+In $RSS_HOME/conf directory, configure the dashboard data request port and 
front-end access port in the coordinator
+``` shell
+## Front-end access port
+rss.dashboard.http.port 19997
+## The dashboard request data port, which is the Coordinator's HTTP port
+## coordinator.hostname is the hostname or IP address of a Coordinator
+coordinator.web.address http://coordinator.hostname:19998/
+```
+
+### Start the dashboard process
+In the $RSS_HOME/bin directory, start with a script.
+``` shell
+## Start dashboard
+sh start-dashboard.sh
+
+## Close dashboard
+sh stop-dashboard.sh
diff --git a/pom.xml b/pom.xml
index 944fc575e..87806e565 100644
--- a/pom.xml
+++ b/pom.xml
@@ -711,6 +711,11 @@
         <artifactId>jetty-servlet</artifactId>
         <version>${jetty.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-proxy</artifactId>
+        <version>${jetty.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-server</artifactId>

Reply via email to