Skip to content

Commit

Permalink
Implement stats collection for builds (mit-cml#2397)
Browse files Browse the repository at this point in the history
* Implement stats collection for builds

Change-Id: If2ef82e55747522633fe2a3c458445f99332d7ac
  • Loading branch information
ewpatton authored Apr 16, 2021
1 parent 017b0bf commit bd3680f
Show file tree
Hide file tree
Showing 8 changed files with 641 additions and 224 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
// Copyright 2011-2021 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

package com.google.appinventor.buildserver;

import com.google.appinventor.buildserver.stats.SimpleStatReporter;
import com.google.appinventor.buildserver.stats.StatCalculator;
import com.google.appinventor.buildserver.stats.StatCalculator.Stats;
import com.google.appinventor.buildserver.stats.StatReporter;
import com.google.appinventor.common.version.GitBuildId;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteStreams;
Expand Down Expand Up @@ -67,7 +72,7 @@
// The Java class will be hosted at the URI path "/buildserver"
@Path("/buildserver")
public class BuildServer {
private ProjectBuilder projectBuilder = new ProjectBuilder();
private ProjectBuilder projectBuilder = new ProjectBuilder(statReporter);

static class ProgressReporter {
// We create a ProgressReporter instance which is handed off to the
Expand Down Expand Up @@ -152,6 +157,10 @@ static class CommandLineOptions {
usage = "the directory to cache the pre-dexed libraries")
String dexCacheDir = null;

@Option(name = "--statreporter",
usage = "the reporter to use for collecting stats")
String statReporter = "com.google.appinventor.buildserver.stats.SimpleStatReporter";

}

private static final CommandLineOptions commandLineOptions = new CommandLineOptions();
Expand Down Expand Up @@ -180,6 +189,9 @@ static class CommandLineOptions {
//The number of failed build requests for this server run
private static final AtomicInteger failedBuildRequests = new AtomicInteger(0);

// The reporter for gathering build stats.
private static StatReporter statReporter;

//The number of failed build requests for this server run
private static int maximumActiveBuildTasks = 0;

Expand Down Expand Up @@ -313,16 +325,55 @@ public Response var() throws IOException {
variables.put("maximum-simultaneous-build-tasks-occurred", maximumActiveBuildTasks + "");
variables.put("active-build-tasks", buildExecutor.getActiveTaskCount() + "");

return mapToHtml(variables);
}

private Response mapToHtml(Map<String, String> variables) {
StringBuilder html = new StringBuilder();
html.append("<html><body><tt>");
for (Map.Entry<String, String> variable : variables.entrySet()) {
html.append("<b>").append(variable.getKey()).append("</b> ")
.append(variable.getValue()).append("<br>");
.append(variable.getValue()).append("<br>");
}
html.append("</tt></body></html>");
return Response.ok(html.toString(), MediaType.TEXT_HTML_TYPE).build();
}

@GET
@Path("stats")
@Produces(MediaType.TEXT_HTML)
public Response stats() throws IOException {
Map<String, String> variables = new LinkedHashMap<String, String>();

variables.put("hostname", InetAddress.getLocalHost().getHostName());

// Build Stats
if (statReporter instanceof SimpleStatReporter) {
StatCalculator calculator = new StatCalculator();
processStats("last1000.",
calculator.computeStats(((SimpleStatReporter) statReporter).getOrderedStats()),
variables);
processStats("successes.",
calculator.computeStats(((SimpleStatReporter) statReporter).getSuccessStats()),
variables);
processStats("failures.",
calculator.computeStats(((SimpleStatReporter) statReporter).getFailureStats()),
variables);
}

return mapToHtml(variables);
}

private void processStats(String prefix, Stats stats, Map<String, String> variables) {
variables.put(prefix + "min", stats.getMinTime() + " ms");
variables.put(prefix + "avg", stats.getAvgTime() + " ms");
variables.put(prefix + "max", stats.getMaxTime() + " ms");
variables.put(prefix + "std", stats.getStdev() + " ms");
for (String stage : stats.getStageNames()) {
processStats(prefix + stage + ".", stats.getStageStats(stage), variables);
}
}

/**
* Indicate that the server is shutting down.
*
Expand Down Expand Up @@ -731,7 +782,9 @@ public static void main(String[] args) throws IOException {
CmdLineParser cmdLineParser = new CmdLineParser(commandLineOptions);
try {
cmdLineParser.parseArgument(args);
} catch (CmdLineException e) {
Class<?> clazz = Class.forName(commandLineOptions.statReporter);
BuildServer.statReporter = clazz.asSubclass(StatReporter.class).newInstance();
} catch (CmdLineException | ReflectiveOperationException e) {
LOG.severe(e.getMessage());
cmdLineParser.printUsage(System.err);
System.exit(1);
Expand Down Expand Up @@ -773,7 +826,6 @@ public void run() {
}
});


// Now that the command line options have been processed, we can create the buildExecutor.
buildExecutor = new NonQueuingExecutor(commandLineOptions.maxSimultaneousBuilds);

Expand Down
Loading

0 comments on commit bd3680f

Please sign in to comment.