aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java b/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java
new file mode 100644
index 0000000000..13d4c8be91
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java
@@ -0,0 +1,159 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 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 com.google.devtools.build.lib.webstatusserver;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.BlazeDirectories;
+import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
+import com.google.devtools.build.lib.runtime.BlazeModule;
+import com.google.devtools.build.lib.runtime.BlazeRuntime;
+import com.google.devtools.build.lib.runtime.BlazeServerStartupOptions;
+import com.google.devtools.build.lib.runtime.Command;
+import com.google.devtools.build.lib.util.AbruptExitException;
+import com.google.devtools.build.lib.util.Clock;
+import com.google.devtools.common.options.OptionsBase;
+import com.google.devtools.common.options.OptionsProvider;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.util.LinkedList;
+import java.util.UUID;
+import java.util.logging.Logger;
+
+/**
+ * Web server for monitoring blaze commands status.
+ */
+public class WebStatusServerModule extends BlazeModule {
+ static final String LAST_TEST_URI = "/tests/last";
+ // 100 is an arbitrary limit; it seems like a reasonable size for history and it's okay to change
+ // it
+ private static final int MAX_TESTS_STORED = 100;
+
+ private HttpServer server;
+ private boolean running = false;
+ private BlazeServerStartupOptions serverOptions;
+ private static final Logger LOG =
+ Logger.getLogger(WebStatusServerModule.class.getCanonicalName());
+ private int port;
+ private LinkedList<TestStatusHandler> testsRan = new LinkedList<>();
+ @SuppressWarnings("unused")
+ private WebStatusEventCollector collector;
+ @SuppressWarnings("unused")
+ private IndexPageHandler indexHandler;
+
+ @Override
+ public Iterable<Class<? extends OptionsBase>> getStartupOptions() {
+ return ImmutableList.<Class<? extends OptionsBase>>of(BlazeServerStartupOptions.class);
+ }
+
+ @Override
+ public void blazeStartup(OptionsProvider startupOptions, BlazeVersionInfo versionInfo,
+ UUID instanceId, BlazeDirectories directories, Clock clock) throws AbruptExitException {
+ serverOptions = startupOptions.getOptions(BlazeServerStartupOptions.class);
+ if (serverOptions.useWebStatusServer <= 0) {
+ LOG.info("web status server disabled");
+ return;
+ }
+ port = serverOptions.useWebStatusServer;
+ try {
+ server = HttpServer.create(new InetSocketAddress(port), 0);
+ serveStaticContent();
+ TextHandler lastCommandHandler = new TextHandler("No commands ran yet.");
+ server.createContext("/last", lastCommandHandler);
+ server.setExecutor(null);
+ server.start();
+ indexHandler = new IndexPageHandler(server, this.testsRan);
+ running = true;
+ LOG.info("Running web status server on port " + port);
+ } catch (IOException e) {
+ // TODO(bazel-team): Display information about why it failed
+ running = false;
+ LOG.warning("Unable to run web status server on port " + port);
+ }
+ }
+
+ @Override
+ public void beforeCommand(BlazeRuntime blazeRuntime, Command command) throws AbruptExitException {
+ if (!running) {
+ return;
+ }
+ collector =
+ new WebStatusEventCollector(blazeRuntime.getEventBus(), blazeRuntime.getReporter(), this);
+ }
+
+ public void commandStarted() {
+ WebStatusBuildLog currentBuild = collector.getBuildLog();
+
+ if (testsRan.size() == MAX_TESTS_STORED) {
+ TestStatusHandler oldestTest = testsRan.removeLast();
+ oldestTest.deregister();
+ }
+
+ TestStatusHandler lastTest = new TestStatusHandler(server, currentBuild);
+ testsRan.add(lastTest);
+
+ lastTest.overrideURI(LAST_TEST_URI);
+ }
+
+ private void serveStaticContent() {
+ StaticResourceHandler testjs =
+ StaticResourceHandler.createFromRelativePath("static/test.js", "application/javascript");
+ StaticResourceHandler indexjs =
+ StaticResourceHandler.createFromRelativePath("static/index.js", "application/javascript");
+ StaticResourceHandler style =
+ StaticResourceHandler.createFromRelativePath("static/style.css", "text/css");
+ StaticResourceHandler d3 = StaticResourceHandler.createFromAbsolutePath(
+ "third_party/javascript/d3/d3-js.js", "application/javascript");
+ StaticResourceHandler jquery = StaticResourceHandler.createFromAbsolutePath(
+ "third_party/javascript/jquery/v2_0_3/jquery_uncompressed.jslib",
+ "application/javascript");
+ StaticResourceHandler testFrontend =
+ StaticResourceHandler.createFromRelativePath("static/test.html", "text/html");
+
+ server.createContext("/css/style.css", style);
+ server.createContext("/js/test.js", testjs);
+ server.createContext("/js/index.js", indexjs);
+ server.createContext("/js/lib/d3.js", d3);
+ server.createContext("/js/lib/jquery.js", jquery);
+ server.createContext(LAST_TEST_URI, testFrontend);
+ }
+
+ private static class TextHandler implements HttpHandler {
+ private String response;
+
+ private TextHandler(String response) {
+ this.response = response;
+ }
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ exchange.getResponseHeaders().put("Content-Type", ImmutableList.of("text/plain"));
+ exchange.sendResponseHeaders(200, response.length());
+ OutputStream os = exchange.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ }
+ }
+
+ public int getPort() {
+ return port;
+ }
+}
+