All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twitter.server.handler.ServerRegistryHandler.scala Maven / Gradle / Ivy

There is a newer version: 18.9.1
Show newest version
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"""
        
        
        
        
        
${ (for ((scope, entry) <- servers) yield { val scopeDash = scope.replace("/", "-") s"""
Load:
...
Failures:
...
Success:
...
Requests:
...
""" }).mkString("\n") }
""" } /** * 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