* added an icon
* refactored the http server * shrunk jar size
This commit is contained in:
parent
35af2b6af3
commit
9dff1a37d3
6 changed files with 108 additions and 73 deletions
|
|
@ -6,7 +6,7 @@ __Screenshot__
|
|||
|
||||
# Highlights:
|
||||
* 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)
|
||||
* Minimalistic web interface.
|
||||
* Execution time is measured in nanoseconds
|
||||
|
|
|
|||
15
pom.xml
15
pom.xml
|
|
@ -9,11 +9,6 @@
|
|||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
|
|
@ -34,13 +29,13 @@
|
|||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.195</version>
|
||||
<version>1.4.200</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>1.5.3.RELEASE</version>
|
||||
<version>2.2.5.RELEASE</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
@ -79,7 +74,7 @@
|
|||
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<version>3.2.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
|
@ -88,10 +83,6 @@
|
|||
</goals>
|
||||
<configuration>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>org.objectweb.asm</pattern>
|
||||
<shadedPattern>agent.org.objectweb.asm</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.javassist</pattern>
|
||||
<shadedPattern>agent.org.javassist</shadedPattern>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package perfix.server;
|
|||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
import perfix.Registry;
|
||||
import perfix.server.json.Serializer;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
|
@ -12,13 +11,16 @@ import java.io.InputStream;
|
|||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
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.logging.Logger;
|
||||
import java.util.function.Function;
|
||||
|
||||
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 ConcurrentMap<String, Function<HttpExchange, ?>> routes = new ConcurrentHashMap<>();
|
||||
|
||||
public HTTPServer(int port) {
|
||||
this.port = port;
|
||||
|
|
@ -30,51 +32,55 @@ public class HTTPServer implements HttpHandler {
|
|||
server.createContext("/", this);
|
||||
server.setExecutor(Executors.newFixedThreadPool(3));
|
||||
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 + "/");
|
||||
} catch (IOException ioe) {
|
||||
System.err.println(" --- Couldn't start Perfix http server:\n" + ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange exchange) throws IOException {
|
||||
String uri = exchange.getRequestURI().toString();
|
||||
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);
|
||||
}
|
||||
InputStream response = getResponse(exchange);
|
||||
|
||||
OutputStream outputStream = exchange.getResponseBody();
|
||||
exchange.getResponseHeaders().add("Access-Control-Allow-Origin", "*");
|
||||
exchange.getResponseHeaders().add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
|
||||
int length = response.available();
|
||||
exchange.sendResponseHeaders(200, length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
outputStream.write(response.read());
|
||||
}
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void setContentTypeJson(HttpExchange exchange) {
|
||||
exchange.getResponseHeaders().add("Content-Type", "application/json");
|
||||
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");
|
||||
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("/")) {
|
||||
uri = "/index.html";
|
||||
}
|
||||
|
|
@ -85,6 +91,8 @@ public class HTTPServer implements HttpHandler {
|
|||
mimeType = "text/css";
|
||||
} else if (uri.endsWith("js")) {
|
||||
mimeType = "application/ecmascript";
|
||||
} else if (uri.equals("/favicon.ico")) {
|
||||
mimeType = "image/svg+xml";
|
||||
} else {
|
||||
mimeType = "text/html";
|
||||
}
|
||||
|
|
@ -100,39 +108,7 @@ public class HTTPServer implements HttpHandler {
|
|||
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) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
25
src/main/java/perfix/server/PerfixController.java
Normal file
25
src/main/java/perfix/server/PerfixController.java
Normal 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";
|
||||
}
|
||||
}
|
||||
44
src/main/resources/favicon.ico
Normal file
44
src/main/resources/favicon.ico
Normal 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
Loading…
Add table
Reference in a new issue