Monitoring einer Scala-Anwendung mit Icinga2

Kannst du das mal kurz checken?

Die Verfügbarkeit einer Scala-Anwendung soll überwacht werden. Für das Monitoring setzen wir Icinga2 ein. Mit Icingas „http_check“ Plugins lassen sich health-Endpoints von Server-Anwendungen sehr einfach überwachen.

Ja, aber …

… die Anwendung ist nicht per HTTP erreichbar und stellt keinen health-Endpoint bereit.

Mhh, da gibt es doch was von Akka?!

Mit Scalas Akka HTTP lässt sich mit wenig aufwand ein leichtgewichtiger HTTP/1.1 Server in die Anwendung integrieren und ein rudimentärer health-Endpoint bereitstellen.

package myPackage

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpMethods._
import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Sink

import scala.concurrent.Future

object myApp extends App {

  implicit val system = ActorSystem()
  implicit val materializer = ActorMaterializer()

  private val http = Http()

  //do something

  val serverSource = http.bind(interface = "0.0.0.0", port = 1234)

  val requestHandler: HttpRequest => HttpResponse = {
    case HttpRequest(GET, Uri.Path("/health"), _, _, _) =>
      HttpResponse(200, entity = "I'm alive!")
    case _: HttpRequest =>
      HttpResponse(404, entity = "Unknown resource")
  }

  val bindingFuture: Future[Http.ServerBinding] =
    serverSource.to(Sink.foreach { connection =>
      println("Accepted new connection from " + connection.remoteAddress)
      connection handleWithSyncHandler requestHandler
  }).run()
}

Im Browser lässt sich nun unter http://localhost:1234/health der health-Endpoint der Anwendung aufrufen und antwortet mit einem „HTTP 200  OK“ und der Nachricht „I’m alive!“. Sehr schön!

Und was sagt Icinga dazu?

Leider wird Icingas „http_check“ auf „localhost:1234/health“ vom Akka HTTP Server immer mit einem „HTTP 400 Bad Request“ quittiert. Der „http_check“ steckt damit dauerhaft im Status „Warning“ fest. Natürlich ist unser Ziel auch in Icinga der Status „OK“, da die Anwendung läuft und im Browser das erwartete Ergebnis ausgegeben wurde.

Ich bin OK. Du bist nicht OK.

Ein Blick in die Logs der Scala Anwendung bringt Licht ins Dunkel:

[WARN] ... Illegal request, responding with status '400 Bad Request': 
  Request is missing required `Host` header: Cannot establish effective 
  URI of request to `/health`, request has a relative URI and is missing 
  a `Host` header; consider setting `akka.http.server.default-host-header`

Oha, Icinga setzt beim „http_check“ keinen host-Header. Akkas HTTP Server erwartet diesen aber in der von uns verwendeten Default-Konfiguration. Wer keine Icinga-Installation zur Hand hat, kann das Verhalten auch ganz einfach über die Shell mittels curl reproduzieren. ( explainshell.com )

curl -0 -H 'Host:' localhost:9494/health

Eine gemeinsame Sprache finden

Wie in der Warnung vorgeschlagen, kann der Wert für akka.http.server.default-host-header auf einen nicht leeren Wert gesetzt werden.

# If this setting is empty the server only accepts requests that carry a
# non-empty `Host` header. Otherwise it responds with `400 Bad Request`.
# Set to a non-empty value to be used in lieu of a missing or empty `Host`
# header to make the server accept such requests.
# Note that the server will never accept HTTP/1.1 request without a `Host`
# header, i.e. this setting only affects HTTP/1.1 requests with an empty
# `Host` header as well as HTTP/1.0 requests.
# Examples: `www.spray.io` or `example.com:8080`
default-host-header = ""

Die Scala-Anwendung lässt sich über eine Config-Datei namens „application.conf“ im Classpath z.B. unter „/src/main/resources“ konfigurieren. Für unsere Zwecke ergänzen wir die Einstellung „akka.http.server.default-host-header“ und setzen sie auf einen nicht leeren String, z.B.

akka.http.server.default-host-header = "non-empty-host-header"

Nach dem Neustart der Anwendung antwortet der Akka HTTP Server auch bei fehlendem Host-Header mit einem „HTTP 200 OK“ auf Anfragen an den health-Endpoint. Damit geht der „http_check“ in Icinga wie erwartet in den Status „OK“ über.

Voilà

2 Gedanken zu “Monitoring einer Scala-Anwendung mit Icinga2

  1. Pingback: Aller Blog-Anfang ist schwer | s6z9 – Notes to myself

  2. Pingback: Dem GitLab-Runner auf der Spur | s6z9 – Notes to myself

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s