* added an icon

* refactored the http server
* shrunk jar size
This commit is contained in:
Sander Hautvast 2020-12-30 12:18:02 +01:00
parent 35af2b6af3
commit 9dff1a37d3
6 changed files with 108 additions and 73 deletions

View file

@ -6,7 +6,7 @@ __Screenshot__
# Highlights: # Highlights:
* Meant for development time (after process stops, data is gone). * Meant for development time (after process stops, data is gone).
* Minimal memory footprint (agent ~ 900 kb). * Minimal memory footprint (829 kb).
* Easy setup (2 commandline arguments for java process) * Easy setup (2 commandline arguments for java process)
* Minimalistic web interface. * Minimalistic web interface.
* Execution time is measured in nanoseconds * Execution time is measured in nanoseconds

15
pom.xml
View file

@ -9,11 +9,6 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<dependencies> <dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>4.1</version>
</dependency>
<dependency> <dependency>
<groupId>org.javassist</groupId> <groupId>org.javassist</groupId>
<artifactId>javassist</artifactId> <artifactId>javassist</artifactId>
@ -34,13 +29,13 @@
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
<version>1.4.195</version> <version>1.4.200</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>1.5.3.RELEASE</version> <version>2.2.5.RELEASE</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -79,7 +74,7 @@
<plugin> <plugin>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version> <version>3.2.2</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@ -88,10 +83,6 @@
</goals> </goals>
<configuration> <configuration>
<relocations> <relocations>
<relocation>
<pattern>org.objectweb.asm</pattern>
<shadedPattern>agent.org.objectweb.asm</shadedPattern>
</relocation>
<relocation> <relocation>
<pattern>org.javassist</pattern> <pattern>org.javassist</pattern>
<shadedPattern>agent.org.javassist</shadedPattern> <shadedPattern>agent.org.javassist</shadedPattern>

View file

@ -3,7 +3,6 @@ package perfix.server;
import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.HttpServer;
import perfix.Registry;
import perfix.server.json.Serializer; import perfix.server.json.Serializer;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -12,13 +11,16 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.logging.Logger; import java.util.function.Function;
public class HTTPServer implements HttpHandler { public class HTTPServer implements HttpHandler {
private static final Logger log = Logger.getLogger("perfix");
private static final String DEFAULT_ROUTE = "DEFAULT";
private final int port; private final int port;
private final ConcurrentMap<String, Function<HttpExchange, ?>> routes = new ConcurrentHashMap<>();
public HTTPServer(int port) { public HTTPServer(int port) {
this.port = port; this.port = port;
@ -30,51 +32,55 @@ public class HTTPServer implements HttpHandler {
server.createContext("/", this); server.createContext("/", this);
server.setExecutor(Executors.newFixedThreadPool(3)); server.setExecutor(Executors.newFixedThreadPool(3));
server.start(); server.start();
PerfixController perfixController = new PerfixController();
routes.put("/report", perfixController::perfixMetrics);
routes.put("/callstack", perfixController::perfixCallstack);
routes.put("/clear", perfixController::clear);
routes.put(DEFAULT_ROUTE, this::staticContent);
System.out.println(" --- Perfix http server running. Point your browser to http://localhost:" + port + "/"); System.out.println(" --- Perfix http server running. Point your browser to http://localhost:" + port + "/");
} catch (IOException ioe) { } catch (IOException ioe) {
System.err.println(" --- Couldn't start Perfix http server:\n" + ioe); System.err.println(" --- Couldn't start Perfix http server:\n" + ioe);
} }
} }
@Override @Override
public void handle(HttpExchange exchange) throws IOException { public void handle(HttpExchange exchange) throws IOException {
String uri = exchange.getRequestURI().toString(); InputStream response = getResponse(exchange);
InputStream response = null;
switch (uri) {
case "/report":
setContentTypeJson(exchange);
response = toStream(perfixMetrics());
break;
case "/callstack":
setContentTypeJson(exchange);
response = toStream(perfixCallstack());
break;
case "/clear":
setContentTypeJson(exchange);
response = toStream(clear());
break;
default:
response = staticContent(exchange, uri);
}
OutputStream outputStream = exchange.getResponseBody(); OutputStream outputStream = exchange.getResponseBody();
exchange.getResponseHeaders().add("Access-Control-Allow-Origin", "*"); exchange.getResponseHeaders().add("Access-Control-Allow-Origin", "*");
exchange.getResponseHeaders().add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); exchange.getResponseHeaders().add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
int length = response.available(); int length = response.available();
exchange.sendResponseHeaders(200, length); exchange.sendResponseHeaders(200, length);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
outputStream.write(response.read()); outputStream.write(response.read());
} }
outputStream.flush(); outputStream.flush();
outputStream.close(); outputStream.close();
} }
private void setContentTypeJson(HttpExchange exchange) { private InputStream getResponse(HttpExchange exchange) {
String uri = exchange.getRequestURI().toString();
Object response;
if (routes.get(uri) != null) {
response = routes.get(uri).apply(exchange);
} else {
response = routes.get(DEFAULT_ROUTE).apply(exchange);
}
if (response instanceof InputStream) {
return (InputStream) response;
} else {
exchange.getResponseHeaders().add("Content-Type", "application/json"); exchange.getResponseHeaders().add("Content-Type", "application/json");
return toStream(Serializer.toJSONString(response));
}
} }
private InputStream staticContent(HttpExchange exchange, String uri) { private InputStream staticContent(HttpExchange exchange) {
String uri = exchange.getRequestURI().toString();
if (uri.equals("/")) { if (uri.equals("/")) {
uri = "/index.html"; uri = "/index.html";
} }
@ -85,6 +91,8 @@ public class HTTPServer implements HttpHandler {
mimeType = "text/css"; mimeType = "text/css";
} else if (uri.endsWith("js")) { } else if (uri.endsWith("js")) {
mimeType = "application/ecmascript"; mimeType = "application/ecmascript";
} else if (uri.equals("/favicon.ico")) {
mimeType = "image/svg+xml";
} else { } else {
mimeType = "text/html"; mimeType = "text/html";
} }
@ -100,39 +108,7 @@ public class HTTPServer implements HttpHandler {
return "NOT FOUND"; return "NOT FOUND";
} }
private String perfixMetrics() {
try {
return Serializer.toJSONString(new ArrayList<>(Registry.sortedMethodsByDuration().values()));
} catch (Exception e) {
log.severe(e.toString());
return e.toString();
}
}
private InputStream toStream(String text) { private InputStream toStream(String text) {
return new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)); return new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
} }
private String perfixCallstack() {
try {
return Serializer.toJSONString(Registry.getCallStack());
} catch (Exception e) {
log.severe(e.toString());
return e.toString();
}
}
private String clear() {
Registry.clear();
try {
return Serializer.toJSONString(Registry.getCallStack());
} catch (Exception e) {
log.severe(e.toString());
return e.toString();
}
}
} }

View file

@ -0,0 +1,25 @@
package perfix.server;
import com.sun.net.httpserver.HttpExchange;
import perfix.MethodNode;
import perfix.Registry;
import perfix.Report;
import java.util.ArrayList;
import java.util.List;
public class PerfixController {
public List<Report> perfixMetrics(HttpExchange exchange) {
return new ArrayList<>(Registry.sortedMethodsByDuration().values());
}
public List<MethodNode> perfixCallstack(HttpExchange exchange) {
return Registry.getCallStack();
}
public String clear(HttpExchange exchange) {
Registry.clear();
return "clear";
}
}

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 187.496 187.496" style="enable-background:new 0 0 187.496 187.496;" xml:space="preserve">
<g>
<path d="M93.748,0C42.056,0,0,42.055,0,93.748s42.056,93.748,93.748,93.748s93.748-42.055,93.748-93.748S145.44,0,93.748,0z
M93.748,173.496C49.774,173.496,14,137.721,14,93.748S49.774,14,93.748,14s79.748,35.775,79.748,79.748
S137.722,173.496,93.748,173.496z"/>
<path d="M102.028,54.809h-26.53c-3.866,0-7,3.134-7,7v31.939v31.939c0,3.866,3.134,7,7,7s7-3.134,7-7v-24.939h19.53
c12.666,0,22.97-10.304,22.97-22.97C124.998,65.113,114.694,54.809,102.028,54.809z M102.028,86.748h-19.53V68.809h19.53
c4.946,0,8.97,4.024,8.97,8.97S106.975,86.748,102.028,86.748z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long