summaryrefslogtreecommitdiffstats
path: root/container-core
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorn.christian@seime.no>2017-07-11 16:08:49 +0200
committerGitHub <noreply@github.com>2017-07-11 16:08:49 +0200
commit730fd6edd9569cd328ccabf3655394bb9ad081f1 (patch)
tree0dc8b15d25af7aebfbfa49da99ffd79faad4ba27 /container-core
parent2ceac3d88f57d218ced860eec76d60dd9d05fb99 (diff)
Revert "Bjorncs/scala stuff"
Diffstat (limited to 'container-core')
-rw-r--r--container-core/src/main/java/com/yahoo/container/core/config/HandlersConfigurerDi.java16
-rw-r--r--container-core/src/main/scala/com/yahoo/container/handler/observability/Graphviz.scala33
-rw-r--r--container-core/src/main/scala/com/yahoo/container/handler/observability/HtmlUtil.scala42
-rw-r--r--container-core/src/main/scala/com/yahoo/container/handler/observability/OverviewHandler.scala118
4 files changed, 209 insertions, 0 deletions
diff --git a/container-core/src/main/java/com/yahoo/container/core/config/HandlersConfigurerDi.java b/container-core/src/main/java/com/yahoo/container/core/config/HandlersConfigurerDi.java
index 66fb4c73560..01ff6918f7b 100644
--- a/container-core/src/main/java/com/yahoo/container/core/config/HandlersConfigurerDi.java
+++ b/container-core/src/main/java/com/yahoo/container/core/config/HandlersConfigurerDi.java
@@ -13,9 +13,12 @@ import com.yahoo.container.core.DiagnosticsConfig;
import com.yahoo.container.di.ComponentDeconstructor;
import com.yahoo.container.di.Container;
import com.yahoo.container.di.componentgraph.core.ComponentGraph;
+import com.yahoo.container.di.componentgraph.core.DotGraph;
import com.yahoo.container.di.config.SubscriberFactory;
import com.yahoo.container.di.osgi.OsgiUtil;
+import com.yahoo.container.handler.observability.OverviewHandler;
import com.yahoo.container.logging.AccessLog;
+import com.yahoo.container.logging.AccessLogInterface;
import com.yahoo.jdisc.application.OsgiFramework;
import com.yahoo.jdisc.handler.RequestHandler;
import com.yahoo.jdisc.service.ClientProvider;
@@ -25,12 +28,14 @@ import com.yahoo.language.simple.SimpleLinguistics;
import com.yahoo.log.LogLevel;
import com.yahoo.osgi.OsgiImpl;
import com.yahoo.statistics.Statistics;
+
import org.osgi.framework.Bundle;
import org.osgi.framework.wiring.BundleWiring;
import scala.collection.immutable.Set;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
@@ -148,6 +153,7 @@ public class HandlersConfigurerDi {
RegistriesHack registriesHack = currentGraph.getInstance(RegistriesHack.class);
assert (registriesHack != null);
+ injectDotGraph();
}
@SuppressWarnings("deprecation")
@@ -170,6 +176,16 @@ public class HandlersConfigurerDi {
});
}
+ private void injectDotGraph() {
+ try {
+ OverviewHandler overviewHandler = currentGraph.getInstance(OverviewHandler.class);
+ overviewHandler.setDotGraph(DotGraph.generate(currentGraph));
+ } catch (Exception e) {
+ log.fine("No overview handler");
+ }
+
+ }
+
public void reloadConfig(long generation) {
container.reloadConfig(generation);
}
diff --git a/container-core/src/main/scala/com/yahoo/container/handler/observability/Graphviz.scala b/container-core/src/main/scala/com/yahoo/container/handler/observability/Graphviz.scala
new file mode 100644
index 00000000000..845f0857323
--- /dev/null
+++ b/container-core/src/main/scala/com/yahoo/container/handler/observability/Graphviz.scala
@@ -0,0 +1,33 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.container.handler.observability
+
+import com.yahoo.text.Utf8
+import com.yahoo.io.IOUtils
+import java.io.{IOException, InputStreamReader, InputStream}
+import com.google.common.io.ByteStreams
+
+/**
+ * @author tonytv
+ */
+
+object Graphviz {
+
+ @throws(classOf[IOException])
+ def runDot(outputType: String, graph: String) = {
+ val process = Runtime.getRuntime.exec(Array("/bin/sh", "-c", "unflatten -l7 | dot -T" + outputType))
+ process.getOutputStream.write(Utf8.toBytes(graph))
+ process.getOutputStream.close()
+
+ val result = ByteStreams.toByteArray(process.getInputStream)
+ process.waitFor() match {
+ case 0 => result
+ case 127 => throw new RuntimeException("Couldn't find dot, please ensure that Graphviz is installed.")
+ case _ => throw new RuntimeException("Failed running dot: " + readString(process.getErrorStream))
+ }
+ }
+
+ private def readString(inputStream: InputStream): String = {
+ IOUtils.readAll(new InputStreamReader(inputStream, "UTF-8"))
+ }
+
+}
diff --git a/container-core/src/main/scala/com/yahoo/container/handler/observability/HtmlUtil.scala b/container-core/src/main/scala/com/yahoo/container/handler/observability/HtmlUtil.scala
new file mode 100644
index 00000000000..6469d4604d2
--- /dev/null
+++ b/container-core/src/main/scala/com/yahoo/container/handler/observability/HtmlUtil.scala
@@ -0,0 +1,42 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.container.handler.observability
+
+import xml.{PrettyPrinter, Elem}
+
+
+/**
+ * @author gjoranv
+ * @author tonytv
+ */
+object HtmlUtil {
+ def link(target: String, anchor: String): Elem =
+ <a href={target}>{anchor}</a>
+
+ def link(targetAndAnchor: String): Elem = link(targetAndAnchor, targetAndAnchor)
+
+ def unorderedList(items: Elem*) =
+ <ul>
+ {items}
+ </ul>
+
+ def li[T](children: T*) =
+ <li>{children}</li>
+
+ def h1(name: String) =
+ <h1>{name}</h1>
+
+ def html(title: String, body: Elem*) =
+ <html>
+ <head>
+ <title>{title}</title>
+ </head>
+ <body>
+ {body}
+ </body>
+ </html>
+
+ def prettyPrintXhtml(elem: Elem): String = {
+ """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">""" +
+ "\n" + new PrettyPrinter(120, 2).format(elem)
+ }
+}
diff --git a/container-core/src/main/scala/com/yahoo/container/handler/observability/OverviewHandler.scala b/container-core/src/main/scala/com/yahoo/container/handler/observability/OverviewHandler.scala
new file mode 100644
index 00000000000..fcb00bb72ef
--- /dev/null
+++ b/container-core/src/main/scala/com/yahoo/container/handler/observability/OverviewHandler.scala
@@ -0,0 +1,118 @@
+// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.container.handler.observability
+
+import java.util.concurrent.Executor
+
+import HtmlUtil._
+import OverviewHandler._
+import com.yahoo.container.jdisc.{HttpResponse, HttpRequest, ThreadedHttpRequestHandler}
+import com.yahoo.text.Utf8
+import java.io.{PrintWriter, OutputStream}
+
+
+/**
+ * @author gjoranv
+ * @author tonytv
+ */
+class OverviewHandler(executor: Executor) extends ThreadedHttpRequestHandler(executor) {
+
+ @volatile
+ private var dotGraph: String = _
+
+ def handle(request: HttpRequest): HttpResponse = {
+ val path = request.getUri.getPath
+
+ try {
+ if (path.endsWith("/ComponentGraph"))
+ handleComponentGraph(request)
+ else if (path.endsWith("/Overview"))
+ handleOverview(request)
+ else
+ null
+ } catch {
+ case e: Exception => errorResponse(e.getMessage)
+ }
+
+ }
+
+ def handleOverview(request: HttpRequest): HttpResponse = {
+ new HttpResponse(com.yahoo.jdisc.Response.Status.OK) {
+ def render(stream: OutputStream) {
+ stream.write(Utf8.toBytes(overviewPageText))
+ }
+
+ override def getContentType: String = {
+ "text/html"
+ }
+ }
+ }
+
+ def errorResponse(message: String): HttpResponse = {
+ new HttpResponse(com.yahoo.jdisc.Response.Status.BAD_REQUEST) {
+ def render(stream: OutputStream) {
+ new PrintWriter(stream).println(message)
+ }
+ }
+ }
+
+ def handleComponentGraph(request: HttpRequest): HttpResponse = {
+ var graphType = request.getProperty("type");
+ if (graphType == null)
+ graphType = "text"
+
+ graphType match {
+ case "text" => textualComponentGraph(dotGraph)
+ case t if componentGraphTypes.contains(t) => graphicalComponentGraph(t, Graphviz.runDot(graphType,dotGraph))
+ case t => errorResponse(t)
+ }
+ }
+
+ def textualComponentGraph(dotGraph: String) =
+ new HttpResponse(com.yahoo.jdisc.Response.Status.OK) {
+ def render(stream: OutputStream) {
+ stream.write(Utf8.toBytes(dotGraph))
+ }
+
+ override def getContentType: String = {
+ "text/plain"
+ }
+ }
+
+ def graphicalComponentGraph(graphType: String, image: Array[Byte] ): HttpResponse =
+ new HttpResponse(com.yahoo.jdisc.Response.Status.OK) {
+ def render(output: OutputStream) {
+ output.write(image)
+ }
+
+ override def getContentType: String = {
+ componentGraphTypes(graphType)
+ }
+ }
+
+ def setDotGraph(dotGraph: String) {
+ this.dotGraph = dotGraph
+ }
+}
+
+object OverviewHandler {
+ val componentGraphTypes = Map(
+ "svg" -> "image/svg+xml",
+ "png" -> "image/png",
+ "text" -> "text/plain")
+
+ val overviewPageText = prettyPrintXhtml(overviewPage)
+
+ private def overviewPage = {
+ def componentGraphLink(graphType: String) = link("Overview/ComponentGraph?type=" + graphType, graphType)
+
+
+ html(
+ title = "Container Overview",
+ body =
+ h1("Container Overview"),
+ unorderedList(
+ li(link("ApplicationStatus")),
+ li("ComponentGraph" +: (componentGraphTypes.keys map {componentGraphLink}).toSeq :_*)))
+ }
+
+}