akka.http.scaladsl.model.HttpCharsets Scala Examples

The following examples show how to use akka.http.scaladsl.model.HttpCharsets. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: SprayJsonSupport.scala    From mist   with Apache License 2.0 5 votes vote down vote up
package io.hydrosphere.mist.master.interfaces

import scala.language.implicitConversions
import akka.http.scaladsl.marshalling.{ ToEntityMarshaller, Marshaller }
import akka.http.scaladsl.unmarshalling.{ FromEntityUnmarshaller, Unmarshaller }
import akka.http.scaladsl.model.{ MediaTypes, HttpCharsets }

import spray.json._


trait SprayJsonSupport {
  implicit def sprayJsonUnmarshallerConverter[T](reader: RootJsonReader[T]): FromEntityUnmarshaller[T] =
    sprayJsonUnmarshaller(reader)
  implicit def sprayJsonUnmarshaller[T](implicit reader: RootJsonReader[T]): FromEntityUnmarshaller[T] =
    sprayJsValueUnmarshaller.map(jsonReader[T].read)
  implicit def sprayJsValueUnmarshaller: FromEntityUnmarshaller[JsValue] =
    Unmarshaller.byteStringUnmarshaller.mapWithCharset { (data, charset) ⇒
      val input =
        if (charset == HttpCharsets.`UTF-8`) ParserInput(data.toArray)
        else ParserInput(data.decodeString(charset.nioCharset.name)) // FIXME: identify charset by instance, not by name!
      JsonParser(input)
    }

  implicit def sprayJsonMarshallerConverter[T](writer: RootJsonWriter[T])(implicit printer: JsonPrinter = PrettyPrinter): ToEntityMarshaller[T] =
    sprayJsonMarshaller[T](writer, printer)
  implicit def sprayJsonMarshaller[T](implicit writer: RootJsonWriter[T], printer: JsonPrinter = PrettyPrinter): ToEntityMarshaller[T] =
    sprayJsValueMarshaller compose writer.write
  implicit def sprayJsValueMarshaller(implicit printer: JsonPrinter = PrettyPrinter): ToEntityMarshaller[JsValue] =
    Marshaller.StringMarshaller.wrap(MediaTypes.`application/json`)(printer)
}
object SprayJsonSupport extends SprayJsonSupport 
Example 2
Source File: PlayJsonSupport.scala    From akka-cluster-manager   with MIT License 5 votes vote down vote up
package io.orkestra.cluster.management

import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
import akka.http.scaladsl.model.HttpCharsets
import akka.http.scaladsl.model.MediaTypes.`application/json`
import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller}
import akka.stream.Materializer
import play.api.libs.json._

import scala.concurrent.ExecutionContext
import scala.language.implicitConversions


trait PlayJsonSupport {

  type Printer = (JsValue ⇒ String)

  def read[T](jsValue: JsValue)(implicit reads: Reads[T]): T = {
    reads.reads(jsValue) match {
      case s: JsSuccess[T] ⇒ s.get
      case e: JsError ⇒ throw JsResultException(e.errors)
    }
  }

  implicit def playJsonUnmarshallerConverter[T](reads: Reads[T])(implicit ec: ExecutionContext, mat: Materializer): FromEntityUnmarshaller[T] =
    playJsonUnmarshaller(reads, ec, mat)

  implicit def playJsonUnmarshaller[T](implicit reads: Reads[T], ec: ExecutionContext, mat: Materializer): FromEntityUnmarshaller[T] =
    playJsValueUnmarshaller.map(read[T])

  implicit def playJsValueUnmarshaller(implicit ec: ExecutionContext, mat: Materializer): FromEntityUnmarshaller[JsValue] =
    Unmarshaller.byteStringUnmarshaller.forContentTypes(`application/json`).mapWithCharset { (data, charset) ⇒
      if (charset == HttpCharsets.`UTF-8`) Json.parse(data.toArray)
      else Json.parse(data.decodeString(charset.nioCharset.name)) // FIXME: identify charset by instance, not by name!
    }

  implicit def playJsonMarshallerConverter[T](writes: Writes[T])(implicit printer: Printer = Json.prettyPrint, ec: ExecutionContext): ToEntityMarshaller[T] =
    playJsonMarshaller[T](writes, printer, ec)

  implicit def playJsonMarshaller[T](implicit writes: Writes[T], printer: Printer = Json.prettyPrint, ec: ExecutionContext): ToEntityMarshaller[T] =
    playJsValueMarshaller[T].compose(writes.writes)

  implicit def playJsValueMarshaller[T](implicit writes: Writes[T], printer: Printer = Json.prettyPrint, ec: ExecutionContext): ToEntityMarshaller[JsValue] =
    Marshaller.StringMarshaller.wrap(`application/json`)(printer)
}

object PlayJsonSupport extends PlayJsonSupport 
Example 3
Source File: StaticResourceTest.scala    From sumobot   with Apache License 2.0 5 votes vote down vote up
package com.sumologic.sumobot.http_frontend

import akka.http.scaladsl.model.{ContentType, ContentTypes, HttpCharsets, MediaTypes}
import com.sumologic.sumobot.test.annotated.SumoBotSpec

class StaticResourceTest extends SumoBotSpec {
  "StaticResource" should {
    "return correct content type" when {
      "passing .html file" in {
        StaticResource("test.html").contentType should
          be(ContentTypes.`text/html(UTF-8)`)
      }

      "passing .css file" in {
        StaticResource("test.css").contentType should
          be(ContentType(MediaTypes.`text/css`, HttpCharsets.`UTF-8`))
      }

      "passing unknown extension" in {
        StaticResource("test.unknown").contentType should
          be(ContentTypes.`text/html(UTF-8)`)
      }
    }
  }
} 
Example 4
Source File: StaticResource.scala    From sumobot   with Apache License 2.0 5 votes vote down vote up
package com.sumologic.sumobot.http_frontend

import akka.http.scaladsl.model.{ContentType, ContentTypes, HttpCharsets, MediaTypes}
import org.apache.commons.io.IOUtils

object StaticResource {
  private[http_frontend] val DefaultContentType = ContentTypes.`text/html(UTF-8)`

  case class ContentTypePair(extension: String, contentType: ContentType)

  private[http_frontend] val KnownContentTypes = Array(
    ContentTypePair(".html", ContentTypes.`text/html(UTF-8)`),
    ContentTypePair(".css", ContentType(MediaTypes.`text/css`, HttpCharsets.`UTF-8`)),
    ContentTypePair(".js", ContentType(MediaTypes.`application/javascript`, HttpCharsets.`UTF-8`))
  )
}

case class StaticResource(filename: String) {
  def contents: Array[Byte] = {
    val stream = getClass.getResourceAsStream(filename)
    val result = IOUtils.toByteArray(stream)

    stream.close()
    result
  }

  def contentType: ContentType = {
    val contentType = StaticResource.KnownContentTypes.find(contentType => filename.endsWith(contentType.extension))
      .map(contentTypePair => contentTypePair.contentType)
    contentType.getOrElse(StaticResource.DefaultContentType)
  }
} 
Example 5
Source File: application.scala    From phobos   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.phobos.akka_http.marshalling

import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
import akka.http.scaladsl.model.{HttpCharsets, HttpEntity, MediaTypes}
import akka.http.scaladsl.unmarshalling.{FromResponseUnmarshaller, Unmarshaller}
import ru.tinkoff.phobos.decoding.XmlDecoder
import ru.tinkoff.phobos.encoding.XmlEncoder

object application {
  implicit def soapApplicationXmlMarshaller[T](implicit encoder: XmlEncoder[T]): ToEntityMarshaller[T] =
    Marshaller.withFixedContentType(MediaTypes.`application/xml` withCharset HttpCharsets.`UTF-8`) { body =>
      HttpEntity(MediaTypes.`application/xml` withCharset HttpCharsets.`UTF-8`, encoder.encode(body))
    }

  implicit def soapApplicationXmlUnmarshaller[T](implicit decoder: XmlDecoder[T]): FromResponseUnmarshaller[T] =
    Unmarshaller.messageUnmarshallerFromEntityUnmarshaller(Unmarshaller.stringUnmarshaller.map { str =>
      decoder.decode(str).fold(err => throw err, identity)
    })
} 
Example 6
Source File: RedocAkkaHttp.scala    From tapir   with Apache License 2.0 5 votes vote down vote up
package sttp.tapir.redoc.akkahttp

import akka.http.scaladsl.model.{ContentTypes, HttpCharsets, HttpEntity, MediaType, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route

class RedocAkkaHttp(title: String, yaml: String, yamlName: String = "docs.yaml", redocVersion: String = "2.0.0-rc.23") {
  lazy val html: String =
    s"""
       |<!DOCTYPE html>
       |<html>
       |<head>
       |  <title>${title}</title>
       |  <!-- needed for adaptive design -->
       |  <meta charset="utf-8"/>
       |  <meta name="viewport" content="width=device-width, initial-scale=1">
       |  <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
       |
       |  <!--
       |  ReDoc doesn't change outer page styles
       |  -->
       |  <style>
       |    body {
       |      margin: 0;
       |      padding: 0;
       |    }
       |  </style>
       |</head>
       |<body>
       |<redoc spec-url='${yamlName}' expand-responses="200,201"></redoc>
       |<script src="https://cdn.jsdelivr.net/npm/redoc@${redocVersion}/bundles/redoc.standalone.js"></script>
       |</body>
       |</html>
       |""".stripMargin

  def routes: Route = {
    get {
      pathEnd {
        redirectToTrailingSlashIfMissing(StatusCodes.MovedPermanently) {
          complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, html))
        }
      } ~ pathSingleSlash {
        complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, html))
      } ~ path(yamlName) {
        complete(HttpEntity(MediaType.textWithFixedCharset("yaml", HttpCharsets.`UTF-8`), yaml))
      }
    }
  }

} 
Example 7
Source File: PropertiesApi.scala    From iep-apps   with Apache License 2.0 5 votes vote down vote up
package com.netflix.iep.archaius

import java.io.StringWriter
import java.util.Properties

import akka.actor.ActorRefFactory
import akka.http.scaladsl.model.HttpCharsets
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.HttpEntity
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import com.netflix.atlas.akka.CustomDirectives._
import com.netflix.atlas.akka.WebApi
import com.netflix.atlas.json.Json
import com.netflix.frigga.Names

class PropertiesApi(
  val propContext: PropertiesContext,
  implicit val actorRefFactory: ActorRefFactory
) extends WebApi {

  def routes: Route = {
    endpointPath("api" / "v1" / "property") {
      get {
        parameter("asg") { asg =>
          extractRequest { request =>
            val cluster = Names.parseName(asg).getCluster
            if (propContext.initialized) {
              val props = propContext.getClusterProps(cluster)
              complete(encode(request, props))
            } else {
              complete(HttpResponse(StatusCodes.ServiceUnavailable))
            }
          }
        }
      }
    }
  }

  private def encode(request: HttpRequest, props: List[PropertiesApi.Property]): HttpResponse = {
    val useJson = request.headers.exists(h => h.is("accept") && h.value == "application/json")
    if (useJson) {
      HttpResponse(
        StatusCodes.OK,
        entity = HttpEntity(MediaTypes.`application/json`, Json.encode(props))
      )
    } else {
      val ps = new Properties
      props.foreach { p =>
        ps.setProperty(p.key, p.value)
      }
      val writer = new StringWriter()
      ps.store(writer, s"count: ${ps.size}")
      writer.close()
      val entity =
        HttpEntity(MediaTypes.`text/plain`.toContentType(HttpCharsets.`UTF-8`), writer.toString)
      HttpResponse(StatusCodes.OK, entity = entity)
    }
  }
}

object PropertiesApi {
  case class Property(id: String, cluster: String, key: String, value: String, timestamp: Long)
} 
Example 8
Source File: patch.scala    From skuber   with Apache License 2.0 5 votes vote down vote up
package skuber.api

import akka.http.scaladsl.model.{HttpCharsets, MediaType}
import play.api.libs.json.Writes

package object patch {

  object CustomMediaTypes {
    val `application/merge-patch+json` = MediaType.applicationWithFixedCharset("merge-patch+json", HttpCharsets.`UTF-8`)
    val `application/strategic-merge-patch+json` = MediaType.applicationWithFixedCharset("strategic-merge-patch+json", HttpCharsets.`UTF-8`)
  }

  object JsonPatchOperation {
    sealed trait Operation {
      def op: String
    }

    trait ValueOperation[T] extends Operation {
      type ValueType = T
      def path: String
      def value: ValueType
      def fmt: Writes[T]
    }

    trait UnaryOperation extends Operation {
      def path: String
    }

    trait DirectionalOperation extends Operation {
      def from: String
      def path: String
    }

    case class Add[T](path: String, value: T)(implicit val fmt: Writes[T]) extends ValueOperation[T] {
      val op = "add"
    }

    case class Remove(path: String) extends UnaryOperation {
      val op = "remove"
    }

    case class Replace[T](path: String, value: T)(implicit val fmt: Writes[T]) extends ValueOperation[T] {
      val op = "replace"
    }

    case class Move(from: String, path: String) extends DirectionalOperation {
      val op = "move"
    }

    case class Copy(from: String, path: String) extends DirectionalOperation {
      val op = "copy"
    }
  }

  trait Patch {
    val strategy: PatchStrategy
  }

  sealed trait PatchStrategy

  sealed trait MergePatchStrategy extends PatchStrategy

  case object StrategicMergePatchStrategy extends MergePatchStrategy

  case object JsonMergePatchStrategy extends MergePatchStrategy

  case object JsonPatchStrategy extends PatchStrategy

  case class JsonPatch(operations: List[JsonPatchOperation.Operation]) extends Patch {
    override val strategy = JsonPatchStrategy
  }

  trait JsonMergePatch extends Patch {
    override val strategy = JsonMergePatchStrategy
  }

  trait StrategicMergePatch extends Patch {
    override val strategy = StrategicMergePatchStrategy
  }

  case class MetadataPatch(labels: Option[Map[String, String]] = Some(Map()),
                           annotations: Option[Map[String, String]] = Some(Map()),
                           override val strategy: MergePatchStrategy = StrategicMergePatchStrategy) extends Patch

} 
Example 9
Source File: MetricsEndpointSpec.scala    From prometheus-akka-http   with MIT License 5 votes vote down vote up
package com.lonelyplanet.prometheus.api

import java.io.StringWriter

import akka.http.scaladsl.model.HttpCharsets
import akka.http.scaladsl.testkit.ScalatestRouteTest
import com.lonelyplanet.prometheus.Utils._
import io.prometheus.client.exporter.common.TextFormat
import io.prometheus.client.{CollectorRegistry, Histogram}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import scala.util.Random

class MetricsEndpointSpec extends AnyFlatSpec with Matchers with ScalatestRouteTest {

  "Metrics endpoint" should "return the correct media type and charset" in {
    val api = createEndpoint(CollectorRegistry.defaultRegistry)
    Get("/metrics") ~> api.routes ~> check {
      mediaType.subType shouldBe "plain"
      mediaType.isText shouldBe true
      mediaType.params shouldBe Map("version" -> "0.0.4")
      charset shouldBe HttpCharsets.`UTF-8`
    }
  }

  it should "return serialized metrics in the prometheus text format" in {
    val registry = new CollectorRegistry()
    val api = createEndpoint(registry)
    val hist = Histogram.build().name(RandomTestName).help(RandomTestHelp).linearBuckets(0, 1, 10).register(registry)

    hist.observe(Math.abs(Random.nextDouble()))

    Get("/metrics") ~> api.routes ~> check {
      val resp = responseAs[String]
      val writer = new StringWriter()
      TextFormat.write004(writer, registry.metricFamilySamples())

      resp shouldBe writer.toString
    }
  }

  private val RandomTestName = generateRandomStringOfLength(16)
  private val RandomTestHelp = generateRandomStringOfLength(16)

  private def createEndpoint(collectorRegistry: CollectorRegistry) = {
    new MetricsEndpoint(collectorRegistry)
  }

} 
Example 10
Source File: RefreshTokenStrategy.scala    From akka-http-oauth2-client   with Apache License 2.0 5 votes vote down vote up
package com.github.dakatsuka.akka.http.oauth2.client.strategy

import akka.NotUsed
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{ FormData, HttpCharsets, HttpRequest, Uri }
import akka.stream.scaladsl.Source
import com.github.dakatsuka.akka.http.oauth2.client.{ ConfigLike, GrantType }

class RefreshTokenStrategy extends Strategy(GrantType.RefreshToken) {
  override def getAuthorizeUrl(config: ConfigLike, params: Map[String, String] = Map.empty): Option[Uri] = None

  override def getAccessTokenSource(config: ConfigLike, params: Map[String, String] = Map.empty): Source[HttpRequest, NotUsed] = {
    require(params.contains("refresh_token"))

    val uri = Uri
      .apply(config.site.toASCIIString)
      .withPath(Uri.Path(config.tokenUrl))

    val request = HttpRequest(
      method = config.tokenMethod,
      uri = uri,
      headers = List(
        RawHeader("Accept", "*/*")
      ),
      FormData(
        params ++ Map(
          "grant_type"    -> grant.value,
          "client_id"     -> config.clientId,
          "client_secret" -> config.clientSecret
        )
      ).toEntity(HttpCharsets.`UTF-8`)
    )

    Source.single(request)
  }
} 
Example 11
Source File: AkkaBodyUnmarshaller.scala    From chronicler   with Apache License 2.0 5 votes vote down vote up
package com.github.fsanaulla.chronicler.akka.shared.handlers

import akka.http.scaladsl.coding.Gzip
import akka.http.scaladsl.model.{HttpCharsets, HttpEntity}
import akka.http.scaladsl.unmarshalling.Unmarshaller
import akka.stream.Materializer
import akka.util.ByteString
import com.github.fsanaulla.chronicler.core.alias.ErrorOr
import com.github.fsanaulla.chronicler.core.jawn.RichJParser
import org.typelevel.jawn.ast.{JParser, JValue}

import scala.concurrent.{ExecutionContext, Future}

final class AkkaBodyUnmarshaller(compressed: Boolean)
  extends Unmarshaller[HttpEntity, ErrorOr[JValue]] {

  override def apply(
      value: HttpEntity
    )(implicit ec: ExecutionContext,
      mat: Materializer
    ): Future[ErrorOr[JValue]] = {

    // get encoding from response content type, otherwise use UTF-8 as default
    val encoding = value.contentType.charsetOption
      .getOrElse(HttpCharsets.`UTF-8`)
      .nioCharset()

    val srcBody = if (compressed) value.dataBytes.via(Gzip.decoderFlow) else value.dataBytes

    srcBody
      .runFold(ByteString.empty)(_ ++ _)
      .map(_.decodeString(encoding))
      .map(JParser.parseFromStringEither)
  }
} 
Example 12
Source File: HttpClientTransformers.scala    From wix-http-testkit   with MIT License 5 votes vote down vote up
package com.wix.e2e.http.client.transformers

import java.io.File

import akka.http.scaladsl.model.{ContentType, ContentTypes, HttpCharsets, MediaTypes}
import com.wix.e2e.http.client.transformers.internals._

trait HttpClientTransformers extends HttpClientRequestUrlTransformers
                                with HttpClientRequestHeadersTransformers
                                with HttpClientRequestBodyTransformers
                                with HttpClientRequestTransformersOps

object HttpClientTransformers extends HttpClientTransformers

trait HttpClientContentTypes {
  val TextPlain = ContentTypes.`text/plain(UTF-8)`
  val JsonContent = ContentTypes.`application/json`
  val XmlContent = ContentType(MediaTypes.`application/xml`, HttpCharsets.`UTF-8`)
  val BinaryStream = ContentTypes.`application/octet-stream`
  val FormUrlEncoded = ContentTypes.`application/x-www-form-urlencoded`
}

object HttpClientContentTypes extends HttpClientContentTypes

sealed trait RequestPart
case class PlainRequestPart(body: String, contentType: ContentType = TextPlain) extends RequestPart
case class BinaryRequestPart(body: Array[Byte], contentType: ContentType = BinaryStream, filename: Option[String] = None) extends RequestPart
case class FileRequestPart(file: File, contentType: ContentType = BinaryStream, filename: Option[String] = None) extends RequestPart
case class FileNameRequestPart(filepath: String, contentType: ContentType = BinaryStream, filename: Option[String] = None) extends RequestPart 
Example 13
Source File: ApiTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.monitoring.metrics

import akka.http.scaladsl.model.headers.HttpEncodings._
import akka.http.scaladsl.model.headers.{`Accept-Encoding`, `Content-Encoding`, HttpEncoding, HttpEncodings}
import akka.http.scaladsl.model.{HttpCharsets, HttpEntity, HttpResponse}
import akka.http.scaladsl.testkit.ScalatestRouteTest
import kamon.prometheus.PrometheusReporter
import org.apache.openwhisk.core.monitoring.metrics.OpenWhiskEvents.MetricConfig
import org.junit.runner.RunWith
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.junit.JUnitRunner
import org.scalatest.matchers.Matcher
import org.scalatest.{BeforeAndAfterAll, FlatSpec, Matchers}
import pureconfig.loadConfigOrThrow
import io.prometheus.client.CollectorRegistry
import pureconfig.generic.auto._

import scala.concurrent.duration.DurationInt

@RunWith(classOf[JUnitRunner])
class ApiTests
    extends FlatSpec
    with Matchers
    with ScalatestRouteTest
    with EventsTestHelper
    with ScalaFutures
    with BeforeAndAfterAll {
  implicit val timeoutConfig = PatienceConfig(1.minute)

  private var api: PrometheusEventsApi = _
  private var consumer: EventConsumer = _

  override protected def beforeAll(): Unit = {
    super.beforeAll()
    CollectorRegistry.defaultRegistry.clear()
    val metricConfig = loadConfigOrThrow[MetricConfig](system.settings.config, "user-events")
    val mericRecorder = PrometheusRecorder(new PrometheusReporter, metricConfig)
    consumer = createConsumer(56754, system.settings.config, mericRecorder)
    api = new PrometheusEventsApi(consumer, createExporter())
  }

  protected override def afterAll(): Unit = {
    consumer.shutdown().futureValue
    super.afterAll()
  }

  behavior of "EventsApi"

  it should "respond ping request" in {
    Get("/ping") ~> api.routes ~> check {
      //Due to retries using a random port does not immediately result in failure
      handled shouldBe true
    }
  }

  it should "respond metrics request" in {
    Get("/metrics") ~> `Accept-Encoding`(gzip) ~> api.routes ~> check {
      contentType.charsetOption shouldBe Some(HttpCharsets.`UTF-8`)
      contentType.mediaType.params("version") shouldBe "0.0.4"
      response should haveContentEncoding(gzip)
    }
  }

  private def haveContentEncoding(encoding: HttpEncoding): Matcher[HttpResponse] =
    be(encoding) compose {
      (_: HttpResponse).header[`Content-Encoding`].map(_.encodings.head).getOrElse(HttpEncodings.identity)
    }

  private def createExporter(): PrometheusExporter = () => HttpEntity(PrometheusExporter.textV4, "foo".getBytes)
} 
Example 14
Source File: PrometheusEventsApi.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.monitoring.metrics

import akka.http.scaladsl.model.StatusCodes.ServiceUnavailable
import akka.http.scaladsl.model.{ContentType, HttpCharsets, MediaType, MessageEntity}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import org.apache.openwhisk.connector.kafka.KafkaMetricRoute

import scala.concurrent.ExecutionContext

trait PrometheusExporter {
  def getReport(): MessageEntity
}

object PrometheusExporter {
  val textV4: ContentType = ContentType.apply(
    MediaType.textWithFixedCharset("plain", HttpCharsets.`UTF-8`).withParams(Map("version" -> "0.0.4")))
}

class PrometheusEventsApi(consumer: EventConsumer, prometheus: PrometheusExporter)(implicit ec: ExecutionContext) {
  val routes: Route = {
    get {
      path("ping") {
        if (consumer.isRunning) {
          complete("pong")
        } else {
          complete(ServiceUnavailable -> "Consumer not running")
        }
      } ~ path("metrics") {
        encodeResponse {
          complete(prometheus.getReport())
        }
      } ~ KafkaMetricRoute(consumer)
    }
  }
} 
Example 15
Source File: Prometheus.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.common
import java.nio.charset.StandardCharsets.UTF_8

import akka.http.scaladsl.model.{ContentType, HttpCharsets, HttpEntity, MediaType}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import kamon.Kamon
import kamon.prometheus.PrometheusReporter

class KamonPrometheus extends AutoCloseable {
  private val reporter = new PrometheusReporter
  private val v4: ContentType = ContentType.apply(
    MediaType.textWithFixedCharset("plain", HttpCharsets.`UTF-8`).withParams(Map("version" -> "0.0.4")))
  Kamon.registerModule("prometheus", reporter)

  def route: Route = path("metrics") {
    get {
      encodeResponse {
        complete(getReport())
      }
    }
  }

  private def getReport() = HttpEntity(v4, reporter.scrapeData().getBytes(UTF_8))

  override def close(): Unit = reporter.stop()
}

object MetricsRoute {
  private val impl =
    if (TransactionId.metricsKamon && TransactionId.metricConfig.prometheusEnabled) Some(new KamonPrometheus)
    else None

  def apply(): Route = impl.map(_.route).getOrElse(reject)
} 
Example 16
Source File: PrometheusTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.common
import akka.http.scaladsl.coding.Gzip
import akka.http.scaladsl.model.{HttpCharsets, HttpResponse}
import akka.http.scaladsl.model.headers.HttpEncodings.gzip
import akka.http.scaladsl.model.headers.{`Accept-Encoding`, `Content-Encoding`, HttpEncoding, HttpEncodings}
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.http.scaladsl.unmarshalling.Unmarshal
import com.typesafe.config.ConfigFactory
import kamon.Kamon
import org.junit.runner.RunWith
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.junit.JUnitRunner
import org.scalatest.matchers.Matcher
import org.scalatest.{BeforeAndAfterAll, FlatSpec, Matchers}

import scala.concurrent.duration._

@RunWith(classOf[JUnitRunner])
class PrometheusTests extends FlatSpec with Matchers with ScalatestRouteTest with BeforeAndAfterAll with ScalaFutures {
  behavior of "Prometheus"

  override protected def beforeAll(): Unit = {
    super.beforeAll()
    //Modify Kamon to have a very small tick interval
    val newConfig = ConfigFactory.parseString("""kamon {
      |  metric {
      |    tick-interval = 50 ms
      |    optimistic-tick-alignment = no
      |  }
      |}""".stripMargin).withFallback(ConfigFactory.load())
    Kamon.reconfigure(newConfig)
  }

  override protected def afterAll(): Unit = {
    super.afterAll()
    Kamon.reconfigure(ConfigFactory.load())
  }

  it should "respond to /metrics" in {
    val api = new KamonPrometheus
    Kamon.counter("foo_bar").withoutTags().increment(42)

    //Sleep to ensure that Kamon metrics are pushed to reporters
    Thread.sleep(2.seconds.toMillis)
    Get("/metrics") ~> `Accept-Encoding`(gzip) ~> api.route ~> check {
      // Check that response confirms to what Prometheus scrapper accepts
      contentType.charsetOption shouldBe Some(HttpCharsets.`UTF-8`)
      contentType.mediaType.params("version") shouldBe "0.0.4"
      response should haveContentEncoding(gzip)

      val responseText = Unmarshal(Gzip.decodeMessage(response)).to[String].futureValue
      withClue(responseText) {
        responseText should include("foo_bar")
      }
    }
    api.close()
  }

  it should "not be enabled by default" in {
    Get("/metrics") ~> MetricsRoute() ~> check {
      handled shouldBe false
    }
  }

  private def haveContentEncoding(encoding: HttpEncoding): Matcher[HttpResponse] =
    be(encoding) compose {
      (_: HttpResponse).header[`Content-Encoding`].map(_.encodings.head).getOrElse(HttpEncodings.identity)
    }
} 
Example 17
Source File: PrometheusMarshallers.scala    From akka-http-metrics   with Apache License 2.0 5 votes vote down vote up
package fr.davit.akka.http.metrics.prometheus.marshalling

import java.io.StringWriter

import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
import akka.http.scaladsl.model.{ContentType, HttpCharsets, HttpEntity, MediaTypes}
import fr.davit.akka.http.metrics.prometheus.PrometheusRegistry
import io.prometheus.client.exporter.common.TextFormat

trait PrometheusMarshallers {

  val PrometheusContentType: ContentType = {
    MediaTypes.`text/plain` withParams Map("version" -> "0.0.4") withCharset HttpCharsets.`UTF-8`
  }

  implicit val marshaller: ToEntityMarshaller[PrometheusRegistry] = {
    Marshaller.opaque { registry =>
      val output = new StringWriter()
      try {
        TextFormat.write004(output, registry.underlying.metricFamilySamples)
        HttpEntity(output.toString).withContentType(PrometheusContentType)
      } finally {
        output.close()
      }
    }
  }
}

object PrometheusMarshallers extends PrometheusMarshallers