
com.twitter.server.handler.ServerRegistryHandler.scala Maven / Gradle / Ivy
package com.twitter.server.handler
import com.twitter.finagle.Service
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finagle.server.ServerRegistry
import com.twitter.finagle.util.StackRegistry
import com.twitter.io.Buf
import com.twitter.server.util.HttpUtils.{new404, newResponse, parse}
import com.twitter.server.util.MetricSource
import com.twitter.server.view.StackRegistryView
import com.twitter.util.Future
private object ServerRegistryHandler {
def render(servers: Seq[(String, StackRegistry.Entry)]): String =
s"""
"""
}
/**
* Renders information about servers registered to Finagle's ServerRegistry
* in an html fragment. Servers can be queried by passing in the server name
* as part of the uri (ex. "/admin/servers/myserver").
*/
class ServerRegistryHandler(
uriPrefix: String,
source: MetricSource = new MetricSource,
registry: StackRegistry = ServerRegistry)
extends Service[Request, Response] {
// Search the metrics source for the stat scope that includes `serverName`.
// The search namespace includes both "$serverName/" and "srv/$serverName"
// to take into account finagle's ServerStatsReceiver. Note, unnamed servers are
// ignored as we can't dissambiguate their stats.
private[this] def findScope(serverName: String): Option[String] = {
val k0 = s"$serverName"
val k1 = s"srv/$serverName"
if (source.contains(s"$k0/load")) Some(k0)
else if (source.contains(s"$k1/load")) Some(k1)
else None
}
def apply(req: Request): Future[Response] = {
val (path, _) = parse(req.uri)
path.stripPrefix(uriPrefix) match {
case idx@("index.html" | "index.htm" | "index.txt" | "servers") =>
val servers = (registry.registrants flatMap {
case e: StackRegistry.Entry if e.name.nonEmpty =>
for (scope <- findScope(e.name)) yield (scope, e)
case _ => Nil
}).toSeq
val html = ServerRegistryHandler.render(servers)
// This is useful to avoid the returned fragment being wrapped
// with an index in the context of an ajax call.
val typ = if (idx.endsWith(".txt")) "text/plain" else "text/html"
newResponse(
contentType = s"$typ;charset=UTF-8",
content = Buf.Utf8(html)
)
case name =>
val entries = registry.registrants filter { _.name == name }
if (entries.isEmpty) new404(s"$name could not be found.") else {
val server = entries.head
val scope = findScope(server.name)
val html = StackRegistryView.render(server, scope)
newResponse(
contentType = "text/html;charset=UTF-8",
content = Buf.Utf8(html)
)
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy