io.prometheus.client.CollectorRegistry Scala Examples
The following examples show how to use io.prometheus.client.CollectorRegistry.
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: PrometheusController.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters.controllers import akka.util.ByteString import com.github.stijndehaes.playprometheusfilters.utils.WriterAdapter import javax.inject._ import play.api.mvc._ import io.prometheus.client.CollectorRegistry import io.prometheus.client.exporter.common.TextFormat import org.slf4j.LoggerFactory import play.api.http.HttpEntity class PrometheusController @Inject()(registry: CollectorRegistry, cc: ControllerComponents) extends AbstractController(cc) { private val logger = LoggerFactory.getLogger(classOf[PrometheusController]) def getMetrics = Action { logger.trace("Metrics call received") val samples = new StringBuilder() val writer = new WriterAdapter(samples) TextFormat.write004(writer, registry.metricFamilySamples()) writer.close() Result( header = ResponseHeader(200, Map.empty), body = HttpEntity.Strict(ByteString(samples.toString), Some(TextFormat.CONTENT_TYPE_004)) ) } }
Example 2
Source File: PrometheusMetricsReporterApiSpec.scala From kafka4s with Apache License 2.0 | 5 votes |
package com.banno.kafka.metrics.prometheus import scala.collection.compat._ import cats.implicits._ import cats.effect.IO import com.banno.kafka._ import com.banno.kafka.producer._ import com.banno.kafka.consumer._ import org.apache.kafka.clients.producer.ProducerRecord import org.apache.kafka.common.TopicPartition import io.prometheus.client.CollectorRegistry import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import scala.jdk.CollectionConverters._ import scala.concurrent.ExecutionContext import scala.concurrent.duration._ class PrometheusMetricsReporterApiSpec extends AnyFlatSpec with Matchers with InMemoryKafka { implicit val defaultContextShift = IO.contextShift(ExecutionContext.global) implicit val defaultConcurrent = IO.ioConcurrentEffect(defaultContextShift) implicit val defaultTimer = IO.timer(ExecutionContext.global) //when kafka clients change their metrics, this test will help identify the changes we need to make "Prometheus reporter" should "register Prometheus collectors for all known Kafka metrics" in { val topic = createTopic(2) val records = List(new ProducerRecord(topic, 0, "a", "a"), new ProducerRecord(topic, 1, "b", "b")) ProducerApi .resource[IO, String, String]( BootstrapServers(bootstrapServer), MetricReporters[ProducerPrometheusReporter] ) .use( p => ConsumerApi .resource[IO, String, String]( BootstrapServers(bootstrapServer), ClientId("c1"), MetricReporters[ConsumerPrometheusReporter] ) .use( c1 => ConsumerApi .resource[IO, String, String]( BootstrapServers(bootstrapServer), ClientId("c2"), MetricReporters[ConsumerPrometheusReporter] ) .use( c2 => for { _ <- p.sendSyncBatch(records) _ <- c1.assign(topic, Map.empty[TopicPartition, Long]) _ <- c1.poll(1 second) _ <- c1.poll(1 second) _ <- c2.assign(topic, Map.empty[TopicPartition, Long]) _ <- c2.poll(1 second) _ <- c2.poll(1 second) _ <- IO.sleep(PrometheusMetricsReporterApi.defaultUpdatePeriod + (1 second)) _ <- p.close _ <- c1.close _ <- c2.close } yield { val registry = CollectorRegistry.defaultRegistry registry.metricFamilySamples.asScala .count(_.name.startsWith("kafka_producer")) should ===(56) registry.metricFamilySamples.asScala .find(_.name == "kafka_producer_record_send_total") .map(_.samples.asScala.map(_.value)) should ===(Some(List(2))) registry.metricFamilySamples.asScala .count(_.name.startsWith("kafka_consumer")) should ===(50) registry.metricFamilySamples.asScala .find(_.name == "kafka_consumer_records_consumed_total") .map(_.samples.asScala.map(_.value)) should ===(Some(List(2, 2))) registry.metricFamilySamples.asScala .find(_.name == "kafka_consumer_topic_records_consumed_total") .map(_.samples.asScala.map(_.value)) should ===(Some(List(2, 2))) } ) ) ) .unsafeRunSync() } }
Example 3
Source File: MetricFamilySamplesEntity.scala From prometheus-akka-http with MIT License | 5 votes |
package com.lonelyplanet.prometheus.api import java.io.{StringWriter, Writer} import java.util import akka.http.scaladsl.marshalling.{ToEntityMarshaller, Marshaller} import akka.http.scaladsl.model._ import io.prometheus.client.Collector.MetricFamilySamples import io.prometheus.client.CollectorRegistry import io.prometheus.client.exporter.common.TextFormat case class MetricFamilySamplesEntity(samples: util.Enumeration[MetricFamilySamples]) object MetricFamilySamplesEntity { private val mediaTypeParams = Map("version" -> "0.0.4") private val mediaType = MediaType.customWithFixedCharset("text", "plain", HttpCharsets.`UTF-8`, params = mediaTypeParams) def fromRegistry(collectorRegistry: CollectorRegistry): MetricFamilySamplesEntity = { MetricFamilySamplesEntity(collectorRegistry.metricFamilySamples()) } def toPrometheusTextFormat(e: MetricFamilySamplesEntity): String = { val writer: Writer = new StringWriter() TextFormat.write004(writer, e.samples) writer.toString } implicit val metricsFamilySamplesMarshaller: ToEntityMarshaller[MetricFamilySamplesEntity] = { Marshaller.withFixedContentType(mediaType) { s => HttpEntity(mediaType, toPrometheusTextFormat(s)) } } }
Example 4
Source File: MetricsEndpoint.scala From prometheus-akka-http with MIT License | 5 votes |
package com.lonelyplanet.prometheus.api import akka.http.scaladsl.server.Directives._ import io.prometheus.client.CollectorRegistry class MetricsEndpoint(registry: CollectorRegistry) { val routes = { get { path("metrics") { complete { MetricFamilySamplesEntity.fromRegistry(registry) } } } } }
Example 5
Source File: ResponseTimeRecorder.scala From prometheus-akka-http with MIT License | 5 votes |
package com.lonelyplanet.prometheus import io.prometheus.client.{CollectorRegistry, Histogram} import scala.concurrent.duration import scala.concurrent.duration.{FiniteDuration, TimeUnit} trait ResponseTimeRecorder { def recordResponseTime(endpoint: String, responseTime: FiniteDuration): Unit } class PrometheusResponseTimeRecorder( metricName: String, metricHelp: String, buckets: List[Double], endpointLabelName: String, registry: CollectorRegistry, timeUnit: TimeUnit) extends ResponseTimeRecorder { private val responseTimes = buildHistogram.register(registry) override def recordResponseTime(endpoint: String, responseTime: FiniteDuration): Unit = { responseTimes.labels(endpoint).observe(responseTime.toUnit(timeUnit)) } private def buildHistogram = Histogram .build() .name(metricName) .help(metricHelp) .labelNames(endpointLabelName) .buckets(buckets: _*) } object PrometheusResponseTimeRecorder { val DefaultBuckets = List(.01, .025, .05, .075, .10, .125, .15, .175, .20, .225, .25, .275, .30, .325, .35, .40, .45, .50, .60, .70, 1.0, 2.0, 3.0, 5.0, 10.0) val DefaultMetricName = "request_processing_seconds" val DefaultMetricHelp = "Time spent processing request" val DefaultEndpointLabel = "endpoint" val DefaultTimeUnit = duration.SECONDS lazy val DefaultRegistry = CollectorRegistry.defaultRegistry lazy val Default = { new PrometheusResponseTimeRecorder( DefaultMetricName, DefaultMetricHelp, DefaultBuckets, DefaultEndpointLabel, DefaultRegistry, DefaultTimeUnit) } } class NoOpResponseTimeRecorder extends ResponseTimeRecorder { def recordResponseTime(endpoint: String, responseTime: FiniteDuration): Unit = () }
Example 6
Source File: EventObserver.scala From prometheus-akka-http with MIT License | 5 votes |
package com.lonelyplanet.prometheus import io.prometheus.client.{Counter, CollectorRegistry} trait EventObserver { def observe(eventName: String, eventDetails: String): Unit } class PrometheusEventObserver( metricName: String, metricHelp: String, eventLabelName: String, eventDetailsLabelName: String, registry: CollectorRegistry) extends EventObserver { val counter = buildCounter.register(registry) private def buildCounter = Counter .build() .name(metricName) .help(metricHelp) .labelNames(eventLabelName, eventDetailsLabelName) override def observe(eventName: String, eventDetails: String): Unit = { counter.labels(eventName, eventDetails).inc() } } object PrometheusEventObserver { private val SuccessfulOperationMetricName = "operation_success" private val SuccessfulOperationMetricHelp = "The number of observed successful operations" private val FailedOperationMetricName = "operation_failure" private val FailedOperationMetricHelp = "The number of observed failed operations" private val DefaultEventLabelName = "event" private val DefaultEventDetailsLabelName = "details" private val DefaultRegistry = CollectorRegistry.defaultRegistry // Common event observers used in scala projects in Open Planet micro-services lazy val SuccessfulOperations = withDefaultsFromMetricNameAndHelp(SuccessfulOperationMetricName, SuccessfulOperationMetricHelp) lazy val FailedOperations = withDefaultsFromMetricNameAndHelp(FailedOperationMetricName, FailedOperationMetricHelp) private def withDefaultsFromMetricNameAndHelp(metricName: String, metricHelp: String) = { new PrometheusEventObserver( metricName, metricHelp, DefaultEventLabelName, DefaultEventDetailsLabelName, DefaultRegistry) } } class NoOpEventObserver extends EventObserver { def observe(eventName: String, eventDetails: String): Unit = () }
Example 7
Source File: MetricsEndpointSpec.scala From prometheus-akka-http with MIT License | 5 votes |
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 8
Source File: PrometheusEventObserverSpec.scala From prometheus-akka-http with MIT License | 5 votes |
package com.lonelyplanet.prometheus import com.lonelyplanet.prometheus.Utils._ import io.prometheus.client.CollectorRegistry import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers class PrometheusEventObserverSpec extends AnyFlatSpec with Matchers { "PrometheusEventObserver" should "record observed events in a counter" in { val registry = new CollectorRegistry() val randomMetricName = generateRandomString val randomMetricHelp = generateRandomString val randomEventLabelName = generateRandomString val randomEventDetailsLabelName = generateRandomString val randomEventName = generateRandomString val randomEventDetails = generateRandomString val eventObserver = new PrometheusEventObserver( randomMetricName, randomMetricHelp, randomEventLabelName, randomEventDetailsLabelName, registry) def getCounterValue = { registry.getSampleValue( randomMetricName, Array(randomEventLabelName, randomEventDetailsLabelName), Array(randomEventName, randomEventDetails)) } getCounterValue shouldBe null eventObserver.observe(randomEventName, randomEventDetails) getCounterValue should not be null getCounterValue.intValue() shouldBe 1 } }
Example 9
Source File: PrometheusResponseTimeRecorderSpec.scala From prometheus-akka-http with MIT License | 5 votes |
package com.lonelyplanet.prometheus import io.prometheus.client.{Collector, CollectorRegistry} import org.scalamock.scalatest.MockFactory import com.lonelyplanet.prometheus.Utils._ import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import scala.concurrent.duration import scala.concurrent.duration.FiniteDuration import scala.util.Random class PrometheusResponseTimeRecorderSpec extends AnyFlatSpec with Matchers with MockFactory { "PrometheusLatencyRecorder" should "register a histogram and record request latencies" in { val registry = new CollectorRegistry() val randomMetricName = generateRandomString val randomMetricHelp = generateRandomString val randomLabelName = generateRandomString val randomEndpointName = generateRandomString val randomLatency = Math.abs(Random.nextInt(10000)) // our random value will end up in the second bucket val buckets = List((randomLatency - 1).toDouble, (randomLatency + 1).toDouble) val recorder = new PrometheusResponseTimeRecorder( randomMetricName, randomMetricHelp, buckets, randomLabelName, registry, duration.MILLISECONDS) recorder.recordResponseTime(randomEndpointName, FiniteDuration(randomLatency, duration.MILLISECONDS)) val first = getBucketValue(registry, randomMetricName, List(randomLabelName), List(randomEndpointName), buckets.head) val second = getBucketValue(registry, randomMetricName, List(randomLabelName), List(randomEndpointName), buckets.last) val positiveInf = getBucketValue(registry, randomMetricName, List(randomLabelName), List(randomEndpointName), Double.PositiveInfinity) first shouldBe 0 second shouldBe 1 positiveInf shouldBe 1 } private def getBucketValue(registry: CollectorRegistry, metricName: String, labelNames: List[String], labelValues: List[String], bucket: Double) = { val name = metricName + "_bucket" // 'le' should be the first label in the list val allLabelNames = (Array("le") ++ labelNames).reverse val allLabelValues = (Array(Collector.doubleToGoString(bucket)) ++ labelValues).reverse registry.getSampleValue(name, allLabelNames, allLabelValues).intValue() } }
Example 10
Source File: PrometheusModule.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters import io.prometheus.client.CollectorRegistry import io.prometheus.client.hotspot._ import org.slf4j.LoggerFactory import play.api.inject.{Binding, Module} import play.api.{Configuration, Environment} object PrometheusModule { val defaultExportsKey = "play-prometheus-filters.register-default-hotspot-collectors" } class PrometheusModule extends Module { import PrometheusModule._ private val logger = LoggerFactory.getLogger(classOf[PrometheusModule]) override def bindings(environment: Environment, configuration: Configuration): Seq[Binding[_]] = { CollectorRegistry.defaultRegistry.clear() configuration.getOptional[Boolean](defaultExportsKey).foreach { enabled => if (enabled) { logger.info("Default exports are enabled") DefaultExports.initialize() logger.info("Default exports registered") } else { logger.info("Default exports are disabled") } } Seq( bind[CollectorRegistry].to(CollectorRegistry.defaultRegistry) ) } }
Example 11
Source File: PrometheusRoutingSpec.scala From vinyldns with Apache License 2.0 | 5 votes |
package vinyldns.api.route import akka.http.scaladsl.model.{HttpProtocol, HttpResponse, StatusCodes} import akka.http.scaladsl.testkit.ScalatestRouteTest import io.prometheus.client.CollectorRegistry import io.prometheus.client.dropwizard.DropwizardExports import org.scalatestplus.mockito.MockitoSugar import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec import org.scalatest.BeforeAndAfterEach import vinyldns.core.VinylDNSMetrics class PrometheusRoutingSpec extends AnyWordSpec with ScalatestRouteTest with PrometheusRoute with BeforeAndAfterEach with MockitoSugar with Matchers { val metricRegistry = VinylDNSMetrics.metricsRegistry val collectorRegistry = CollectorRegistry.defaultRegistry collectorRegistry.register(new DropwizardExports(metricRegistry)) "GET /metrics/prometheus" should { "return metrics logged in prometheus" in { Get("/metrics/prometheus") ~> prometheusRoute ~> check { response.status shouldBe StatusCodes.OK val resultStatus = responseAs[HttpResponse] resultStatus.protocol shouldBe HttpProtocol("HTTP/1.1") } } } }
Example 12
Source File: PrometheusModuleSpec.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters import io.prometheus.client.{Collector, CollectorRegistry} import org.scalatest.{BeforeAndAfter, MustMatchers, PrivateMethodTester, WordSpec} import org.scalatestplus.play.guice.GuiceOneAppPerTest import play.api.inject.guice.GuiceApplicationBuilder class PrometheusModuleSpec extends WordSpec with MustMatchers with BeforeAndAfter with PrivateMethodTester with GuiceOneAppPerTest { before { // clearing registry before each test CollectorRegistry.defaultRegistry.clear() } "PrometheusModule" should { "register default exporters when enabled" in { // default enabled val app = new GuiceApplicationBuilder() .configure(PrometheusModule.defaultExportsKey -> true) .build() val collector = app.injector.instanceOf[CollectorRegistry] val collectors = PrivateMethod[java.util.HashSet[Collector]]('collectors) (collector invokePrivate collectors()).size must be > 0 } "not register default exporters when disabled" in { // disable default exporters val app = new GuiceApplicationBuilder() .configure(PrometheusModule.defaultExportsKey -> false) .build() val collector = app.injector.instanceOf[CollectorRegistry] val collectors = PrivateMethod[java.util.HashSet[Collector]]('collectors) (collector invokePrivate collectors()).size must be (0) } } def getExporterNames: Seq[String] = { val exportNames = collection.mutable.Buffer.empty[String] val mfs = registry.metricFamilySamples() while(mfs.hasMoreElements) { exportNames += mfs.nextElement().name } exportNames } } }
Example 13
Source File: PrometheusControllerSpec.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters.controllers import java.util.Collections import io.prometheus.client.Collector.MetricFamilySamples import io.prometheus.client.{Collector, CollectorRegistry} import org.mockito.Mockito._ import org.scalatest.mockito.MockitoSugar import org.scalatestplus.play.PlaySpec import play.api.mvc.Results import play.api.test.FakeRequest import play.api.test.Helpers._ class PrometheusControllerSpec extends PlaySpec with Results with MockitoSugar { "Get metrics method" should { "Return the prometheus metrics" in { val collectorRegistry = mock[CollectorRegistry] val metricsFamilySample = new MetricFamilySamples("test", Collector.Type.COUNTER, "help", Collections.emptyList()) when(collectorRegistry.metricFamilySamples()).thenReturn(new java.util.Vector(Collections.singleton(metricsFamilySample)).elements) val client = new PrometheusController(collectorRegistry, stubControllerComponents()) val request = FakeRequest(GET, "/metrics") val result = client.getMetrics.apply(request) status(result) mustBe OK contentAsString(result) mustBe "# HELP test help\n# TYPE test counter\n" } } }
Example 14
Source File: RouteLatencyFilterSpec.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters.filters import com.github.stijndehaes.playprometheusfilters.metrics.DefaultPlayUnmatchedDefaults import com.github.stijndehaes.playprometheusfilters.mocks.MockController import io.prometheus.client.CollectorRegistry import org.mockito.ArgumentMatchers.any import org.mockito.Mockito.verify import org.scalatest.mockito.MockitoSugar import org.scalatest.{MustMatchers, WordSpec} import org.scalatestplus.play.guice.GuiceOneAppPerSuite import play.api.Configuration import play.api.libs.typedmap.TypedMap import play.api.mvc._ import play.api.routing.{HandlerDef, Router} import play.api.test.Helpers.stubControllerComponents import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits} import scala.concurrent.ExecutionContext.Implicits.global class RouteLatencyFilterSpec extends WordSpec with MustMatchers with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite { private implicit val mat = app.materializer private val configuration = mock[Configuration] "Filter constructor" should { "Add a histogram to the prometheus registry" in { val collectorRegistry = mock[CollectorRegistry] new RouteLatencyFilter(collectorRegistry, configuration) verify(collectorRegistry).register(any()) } } "Apply method" should { "Measure the latency" in { val filter = new RouteLatencyFilter(mock[CollectorRegistry], configuration) val rh = FakeRequest().withAttrs( TypedMap( Router.Attrs.HandlerDef -> HandlerDef(null, null, null, "test", null, null ,null ,null ,null) )) val action = new MockController(stubControllerComponents()).ok await(filter(action)(rh).run()) val metrics = filter.metrics(0).metric.collect() metrics must have size 1 val samples = metrics.get(0).samples //this is the count sample val countSample = samples.get(samples.size() - 2) countSample.value mustBe 1.0 countSample.labelValues must have size 1 countSample.labelValues.get(0) mustBe "test" } "Measure the latency for an unmatched route" in { val filter = new RouteLatencyFilter(mock[CollectorRegistry], configuration) val rh = FakeRequest() val action = new MockController(stubControllerComponents()).error await(filter(action)(rh).run()) val metrics = filter.metrics(0).metric.collect() metrics must have size 1 val samples = metrics.get(0).samples //this is the count sample val countSample = samples.get(samples.size() - 2) countSample.value mustBe 1.0 countSample.labelValues must have size 1 countSample.labelValues.get(0) mustBe DefaultPlayUnmatchedDefaults.UnmatchedRouteString } } }
Example 15
Source File: MetricFilterSpec.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters.filters import com.github.stijndehaes.playprometheusfilters.metrics.CounterRequestMetrics.CounterRequestMetricBuilder import com.github.stijndehaes.playprometheusfilters.metrics.{DefaultPlayUnmatchedDefaults, RequestMetric} import com.github.stijndehaes.playprometheusfilters.mocks.MockController import com.typesafe.config.ConfigFactory import io.prometheus.client.CollectorRegistry import org.scalatest.mockito.MockitoSugar import org.scalatestplus.play.PlaySpec import org.scalatestplus.play.guice.GuiceOneAppPerSuite import play.api.Configuration import play.api.mvc._ import play.api.test.Helpers._ import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits} import scala.concurrent.ExecutionContext.Implicits.global class MetricFilterSpec extends PlaySpec with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite { val configuration = Configuration(ConfigFactory.parseString( """play-prometheus-filters.exclude.paths = ["/test"]""" )) "Filter constructor" should { "Get exclude paths from configuration" in { implicit val mat = app.materializer val filter = new MetricsFilter(configuration) { override val metrics = List.empty[RequestMetric[_, RequestHeader, Result]] } filter.excludePaths must have size 1 // only check size since cannot compare Regex's } } "Apply method" should { "skip metrics for excluded paths" in { implicit val mat = app.materializer val collectorRegistry = mock[CollectorRegistry] val filter = new MetricsFilter(configuration) { override val metrics = List( CounterRequestMetricBuilder.build(collectorRegistry, DefaultPlayUnmatchedDefaults) ) } val rh = FakeRequest("GET", "/test") val action = new MockController(stubControllerComponents()).ok await(filter(action)(rh).run()) val metrics = filter.metrics(0).metric.collect() metrics must have size 1 val samples = metrics.get(0).samples samples.size() mustBe 0 // expect no metrics } } }
Example 16
Source File: StatusCounterFilterSpec.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters.filters import com.github.stijndehaes.playprometheusfilters.mocks.MockController import io.prometheus.client.CollectorRegistry import org.mockito.ArgumentMatchers.any import org.mockito.Mockito.verify import org.scalatest.mockito.MockitoSugar import org.scalatest.{MustMatchers, WordSpec} import org.scalatestplus.play.guice.GuiceOneAppPerSuite import play.api.Configuration import play.api.mvc.Results import play.api.test.Helpers.stubControllerComponents import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits} import scala.concurrent.ExecutionContext.Implicits.global class StatusCounterFilterSpec extends WordSpec with MustMatchers with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite { private implicit val mat = app.materializer private val configuration = mock[Configuration] "Filter constructor" should { "Add a counter to the prometheus registry" in { val collectorRegistry = mock[CollectorRegistry] new StatusCounterFilter(collectorRegistry, configuration) verify(collectorRegistry).register(any()) } } "Apply method" should { "Count the requests with status" in { val filter = new StatusCounterFilter(mock[CollectorRegistry], configuration) val rh = FakeRequest() val action = new MockController(stubControllerComponents()).ok await(filter(action)(rh).run()) val metrics = filter.metrics(0).metric.collect() metrics must have size 1 val samples = metrics.get(0).samples samples.get(0).value mustBe 1.0 samples.get(0).labelValues must have size 1 samples.get(0).labelValues.get(0) mustBe "200" } } }
Example 17
Source File: StatusAndRouteLatencyFilterSpec.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters.filters import com.github.stijndehaes.playprometheusfilters.metrics.DefaultPlayUnmatchedDefaults import com.github.stijndehaes.playprometheusfilters.mocks.MockController import io.prometheus.client.CollectorRegistry import org.mockito.ArgumentMatchers.any import org.mockito.Mockito.verify import org.scalatest.mockito.MockitoSugar import org.scalatest.{MustMatchers, WordSpec} import org.scalatestplus.play.guice.GuiceOneAppPerSuite import play.api.Configuration import play.api.libs.typedmap.TypedMap import play.api.mvc.Results import play.api.routing.{HandlerDef, Router} import play.api.test.Helpers.stubControllerComponents import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits} import scala.concurrent.ExecutionContext.Implicits.global class StatusAndRouteLatencyFilterSpec extends WordSpec with MustMatchers with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite { private implicit val mat = app.materializer private val configuration = mock[Configuration] "Filter constructor" should { "Add a histogram to the prometheus registry" in { val collectorRegistry = mock[CollectorRegistry] new StatusAndRouteLatencyFilter(collectorRegistry, configuration) verify(collectorRegistry).register(any()) } } "Apply method" should { "Measure the latency" in { val filter = new StatusAndRouteLatencyFilter(mock[CollectorRegistry], configuration) val rh = FakeRequest().withAttrs( TypedMap( Router.Attrs.HandlerDef -> HandlerDef(null, null, "testController", "test", null, "GET", "/path", null ,null) )) val action = new MockController(stubControllerComponents()).ok await(filter(action)(rh).run()) val metrics = filter.metrics(0).metric.collect() metrics must have size 1 val samples = metrics.get(0).samples //this is the count sample val countSample = samples.get(samples.size() - 2) countSample.value mustBe 1.0 countSample.labelValues must have size 5 countSample.labelValues.get(0) mustBe "test" countSample.labelValues.get(1) mustBe "200" countSample.labelValues.get(2) mustBe "testController" countSample.labelValues.get(3) mustBe "/path" countSample.labelValues.get(4) mustBe "GET" } "Measure the latency for an unmatched route" in { val filter = new StatusAndRouteLatencyFilter(mock[CollectorRegistry], configuration) val rh = FakeRequest() val action = new MockController(stubControllerComponents()).error await(filter(action)(rh).run()) val metrics = filter.metrics(0).metric.collect() metrics must have size 1 val samples = metrics.get(0).samples //this is the count sample val countSample = samples.get(samples.size() - 2) countSample.value mustBe 1.0 countSample.labelValues must have size 5 countSample.labelValues.get(0) mustBe DefaultPlayUnmatchedDefaults.UnmatchedRouteString countSample.labelValues.get(1) mustBe "404" countSample.labelValues.get(2) mustBe DefaultPlayUnmatchedDefaults.UnmatchedControllerString countSample.labelValues.get(3) mustBe DefaultPlayUnmatchedDefaults.UnmatchedPathString countSample.labelValues.get(4) mustBe DefaultPlayUnmatchedDefaults.UnmatchedVerbString } } }
Example 18
Source File: LatencyFilterSpec.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters.filters import com.github.stijndehaes.playprometheusfilters.mocks.MockController import io.prometheus.client.CollectorRegistry import org.mockito.ArgumentMatchers._ import org.mockito.Mockito._ import org.scalatest.mockito.MockitoSugar import org.scalatestplus.play.PlaySpec import org.scalatestplus.play.guice.GuiceOneAppPerSuite import play.api.Configuration import play.api.mvc._ import play.api.test.Helpers._ import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits} import scala.concurrent.ExecutionContext.Implicits.global class LatencyFilterSpec extends PlaySpec with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite { val configuration = mock[Configuration] "Filter constructor" should { "Add a histogram to the prometheus registry" in { implicit val mat = app.materializer val collectorRegistry = mock[CollectorRegistry] new LatencyFilter(collectorRegistry, configuration) verify(collectorRegistry).register(any()) } } "Apply method" should { "Measure the latency" in { implicit val mat = app.materializer val filter = new LatencyFilter(mock[CollectorRegistry], configuration) val rh = FakeRequest() val action = new MockController(stubControllerComponents()).ok await(filter(action)(rh).run()) val metrics = filter.metrics(0).metric.collect() metrics must have size 1 val samples = metrics.get(0).samples //this is the count sample val countSample = samples.get(samples.size() - 2) countSample.value mustBe 1.0 countSample.labelValues must have size 0 } } }
Example 19
Source File: StatusAndRouteCounterFilterSpec.scala From play-prometheus-filters with MIT License | 5 votes |
package com.github.stijndehaes.playprometheusfilters.filters import com.github.stijndehaes.playprometheusfilters.metrics.DefaultPlayUnmatchedDefaults import com.github.stijndehaes.playprometheusfilters.mocks.MockController import io.prometheus.client.CollectorRegistry import org.mockito.ArgumentMatchers.any import org.mockito.Mockito.verify import org.scalatest.mockito.MockitoSugar import org.scalatest.{MustMatchers, WordSpec} import org.scalatestplus.play.guice.GuiceOneAppPerSuite import play.api.Configuration import play.api.libs.typedmap.TypedMap import play.api.mvc.Results import play.api.routing.{HandlerDef, Router} import play.api.test.Helpers.stubControllerComponents import play.api.test.{DefaultAwaitTimeout, FakeRequest, FutureAwaits} import scala.concurrent.ExecutionContext.Implicits.global class StatusAndRouteCounterFilterSpec extends WordSpec with MustMatchers with MockitoSugar with Results with DefaultAwaitTimeout with FutureAwaits with GuiceOneAppPerSuite { private implicit val mat = app.materializer private val configuration = mock[Configuration] "Filter constructor" should { "Add a histogram to the prometheus registry" in { val collectorRegistry = mock[CollectorRegistry] new StatusAndRouteLatencyFilter(collectorRegistry, configuration) verify(collectorRegistry).register(any()) } } "Apply method" should { "Measure the count" in { val filter = new StatusAndRouteCounterFilter(mock[CollectorRegistry], configuration) val rh = FakeRequest().withAttrs( TypedMap( Router.Attrs.HandlerDef -> HandlerDef(null, null, "testController", "test", null, "GET", "/path", null ,null) )) val action = new MockController(stubControllerComponents()).ok await(filter(action)(rh).run()) val metrics = filter.metrics(0).metric.collect() metrics must have size 1 val samples = metrics.get(0).samples //this is the count sample val countSample = samples.get(0) countSample.value mustBe 1.0 countSample.labelValues must have size 5 countSample.labelValues.get(0) mustBe "test" countSample.labelValues.get(1) mustBe "200" countSample.labelValues.get(2) mustBe "testController" countSample.labelValues.get(3) mustBe "/path" countSample.labelValues.get(4) mustBe "GET" } "Measure the count for an unmatched route" in { val filter = new StatusAndRouteCounterFilter(mock[CollectorRegistry], configuration) val rh = FakeRequest() val action = new MockController(stubControllerComponents()).error await(filter(action)(rh).run()) val metrics = filter.metrics(0).metric.collect() metrics must have size 1 val samples = metrics.get(0).samples //this is the count sample val countSample = samples.get(0) countSample.value mustBe 1.0 countSample.labelValues must have size 5 countSample.labelValues.get(0) mustBe DefaultPlayUnmatchedDefaults.UnmatchedRouteString countSample.labelValues.get(1) mustBe "404" countSample.labelValues.get(2) mustBe DefaultPlayUnmatchedDefaults.UnmatchedControllerString countSample.labelValues.get(3) mustBe DefaultPlayUnmatchedDefaults.UnmatchedPathString countSample.labelValues.get(4) mustBe DefaultPlayUnmatchedDefaults.UnmatchedVerbString } } }
Example 20
Source File: PrometheusStatsReceiverTest.scala From finagle-prometheus with MIT License | 5 votes |
package com.samstarling.prometheusfinagle import com.twitter.app.LoadService import com.twitter.finagle.stats.{StatsReceiver, Verbosity} import com.twitter.finagle.util.DefaultTimer import com.twitter.util.Duration import io.prometheus.client.CollectorRegistry class PrometheusStatsReceiverTest extends UnitTest { "PrometheusStatsReceiverTest" should { "have a zero-argument constructor" in { new PrometheusStatsReceiver() must not(throwA[RuntimeException]) } // This depends on content in test/resources/META-INF/services "be loaded as a StatsReceiver by LoadService" in { val classes: Seq[Class[_]] = LoadService[StatsReceiver]().map(_.getClass) classes.contains(classOf[PrometheusStatsReceiver]) ==== true } "be able to be instantiated by newInstance" in { classOf[PrometheusStatsReceiver].newInstance() must not( throwA[NoSuchMethodException]) } "allow a registry to be passed" in { val registry = CollectorRegistry.defaultRegistry new PrometheusStatsReceiver(registry) must not(throwA[RuntimeException]) } "allow a registry, namespace, and a Timer to be passed" in { val registry = CollectorRegistry.defaultRegistry val namespace = "testnamespace" new PrometheusStatsReceiver(registry, namespace, DefaultTimer.twitter, Duration.fromSeconds(1)) must not( throwA[RuntimeException]) } "allow metrics and labels with unsafe characters" in { val registry = CollectorRegistry.defaultRegistry val namespace = "test_metric_names_and_labels" val statsReceiver = new PrometheusStatsReceiver(registry, namespace, DefaultTimer.twitter, Duration.fromSeconds(1)) val metrics = Seq( Seq("finagle", "build/revision"), Seq("foo/bar", "baz"), Seq("foo/bar", "build/revision"), Seq("foo-bar", "baz"), Seq("finagle", "build-revsion"), ) metrics foreach { name => statsReceiver.stat(Verbosity.Default, name: _*) } must not(throwA[IllegalArgumentException]) } } }
Example 21
Source File: package.scala From zio-metrics with Apache License 2.0 | 5 votes |
package zio.metrics import zio.{ Has, ZLayer } import zio.{ Ref, Task, UIO } package object prometheus { import io.prometheus.client.{ Counter => PCounter } import io.prometheus.client.{ Gauge => PGauge } import io.prometheus.client.{ Histogram => PHistogram } import io.prometheus.client.CollectorRegistry import io.prometheus.client.{ Summary => PSummary } type Registry = Has[Registry.Service] object Registry { trait Service { def getCurrent(): UIO[CollectorRegistry] def registerCounter[L: Show](label: Label[L]): Task[PCounter] def registerGauge[L: Show](label: Label[L]): Task[PGauge] def registerHistogram[L: Show](label: Label[L], buckets: Buckets): Task[PHistogram] def registerSummary[L: Show](label: Label[L], quantiles: List[(Double, Double)]): Task[PSummary] } type PTimer = PSummary.Timer type Percentile = Double type Tolerance = Double val explicit: ZLayer[Has[Option[CollectorRegistry]], Nothing, Registry] = ZLayer.fromFunction[Has[Option[CollectorRegistry]], Registry.Service]( optionalRegistry => new Service { private val registryRef: UIO[Ref[CollectorRegistry]] = { val registry = optionalRegistry.get Ref.make(registry.getOrElse(CollectorRegistry.defaultRegistry)) } def getCurrent(): UIO[CollectorRegistry] = registryRef >>= (_.get) def registerCounter[A: Show](label: Label[A]): Task[PCounter] = registryRef >>= (_.modify(r => { val name = Show[A].show(label.name) val c = PCounter .build() .name(name) .labelNames(label.labels: _*) .help(s"$name counter") .register(r) (c, r) })) def registerGauge[L: Show](label: Label[L]): Task[PGauge] = registryRef >>= (_.modify(r => { val name = Show[L].show(label.name) val g = PGauge .build() .name(name) .labelNames(label.labels: _*) .help(s"$name gauge") .register(r) (g, r) })) def registerHistogram[L: Show](label: Label[L], buckets: Buckets): Task[PHistogram] = registryRef >>= (_.modify(r => { val name = Show[L].show(label.name) val hb = PHistogram .build() .name(name) .labelNames(label.labels: _*) .help(s"$name histogram") val h = buckets match { case DefaultBuckets(bs) => if (bs.isEmpty) hb else hb.buckets(bs: _*) case LinearBuckets(s, w, c) => hb.linearBuckets(s, w, c) case ExponentialBuckets(s, f, c) => hb.exponentialBuckets(s, f, c) } (h.register(r), r) })) def registerSummary[L: Show](label: Label[L], quantiles: List[(Percentile, Tolerance)]): Task[PSummary] = registryRef >>= (_.modify(r => { val name = Show[L].show(label.name) val sb = PSummary .build() .name(name) .labelNames(label.labels: _*) .help(s"$name timer") val s = quantiles.foldLeft(sb)((acc, c) => acc.quantile(c._1, c._2)).register(r) (s, r) })) } ) val live: ZLayer[Any, Nothing, Has[Registry.Service]] = ZLayer.succeed[Option[CollectorRegistry]](None) >>> explicit } }
Example 22
Source File: PrometheusMarshallersSpec.scala From akka-http-metrics with Apache License 2.0 | 5 votes |
package fr.davit.akka.http.metrics.prometheus.marshalling import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.testkit.ScalatestRouteTest import fr.davit.akka.http.metrics.core.HttpMetricsRegistry.StatusGroupDimension import fr.davit.akka.http.metrics.core.scaladsl.server.HttpMetricsDirectives.metrics import fr.davit.akka.http.metrics.prometheus.{PrometheusRegistry, PrometheusSettings} import io.prometheus.client.CollectorRegistry import org.scalatest.BeforeAndAfterAll import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import scala.concurrent.duration._ class PrometheusMarshallersSpec extends AnyFlatSpec with Matchers with ScalatestRouteTest with BeforeAndAfterAll { trait Fixture extends PrometheusMarshallers { val registry = PrometheusRegistry( new CollectorRegistry(), PrometheusSettings.default.withIncludeStatusDimension(true) ) io.prometheus.client.Counter .build("other_metric", "An other metric") .register(registry.underlying) } override def afterAll(): Unit = { cleanUp() super.afterAll() } "PrometheusMarshallers" should "expose metrics as prometheus format" in new Fixture { // register labeled metrics so they appear at least once // use metrics so they appear in the report val dimensions = Seq(StatusGroupDimension(StatusCodes.OK)) registry.requests.inc() registry.receivedBytes.update(10) registry.active.inc() registry.responses.inc(dimensions) registry.errors.inc(dimensions) registry.duration.observe(1.second, dimensions) registry.sentBytes.update(10, dimensions) Get() ~> metrics(registry) ~> check { response.entity.contentType shouldBe PrometheusMarshallers.PrometheusContentType val text = responseAs[String] // println(text) val metrics = text .split('\n') .filterNot(_.startsWith("#")) .map(_.takeWhile(c => c != ' ' && c != '{')) .distinct metrics should contain theSameElementsAs Seq( "akka_http_requests_active", "akka_http_requests_total", "akka_http_requests_size_bytes_bucket", "akka_http_requests_size_bytes_count", "akka_http_requests_size_bytes_sum", "akka_http_responses_total", "akka_http_responses_errors_total", "akka_http_responses_duration_seconds_bucket", "akka_http_responses_duration_seconds_count", "akka_http_responses_duration_seconds_sum", "akka_http_responses_size_bytes_bucket", "akka_http_responses_size_bytes_count", "akka_http_responses_size_bytes_sum", "akka_http_connections_active", "akka_http_connections_total", "other_metric" ) } } }
Example 23
Source File: ApiTests.scala From openwhisk with Apache License 2.0 | 5 votes |
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 24
Source File: OpenWhiskEventsTests.scala From openwhisk with Apache License 2.0 | 5 votes |
package org.apache.openwhisk.core.monitoring.metrics import akka.http.scaladsl.Http import akka.http.scaladsl.model.{HttpRequest, StatusCodes} import akka.http.scaladsl.unmarshalling.Unmarshal import com.typesafe.config.ConfigFactory import io.prometheus.client.CollectorRegistry import kamon.Kamon import org.junit.runner.RunWith import org.scalatest.junit.JUnitRunner import scala.concurrent.duration._ import scala.util.Try @RunWith(classOf[JUnitRunner]) class OpenWhiskEventsTests extends KafkaSpecBase { behavior of "Server" it should "start working http server" in { val httpPort = freePort() val globalConfig = system.settings.config val config = ConfigFactory.parseString(s""" | akka.kafka.consumer.kafka-clients { | bootstrap.servers = "localhost:$kafkaPort" | } | kamon { | metric { | tick-interval = 50 ms | optimistic-tick-alignment = no | } | } | whisk { | user-events { | port = $httpPort | rename-tags { | namespace = "ow_namespace" | } | } | } """.stripMargin).withFallback(globalConfig) CollectorRegistry.defaultRegistry.clear() val binding = OpenWhiskEvents.start(config).futureValue val res = get("localhost", httpPort, "/ping") res shouldBe Some(StatusCodes.OK, "pong") //Check if metrics using Kamon API gets included in consolidated Prometheus Kamon.counter("fooTest").withoutTags().increment(42) sleep(1.second) val metricRes = get("localhost", httpPort, "/metrics") metricRes.get._2 should include("fooTest") binding.unbind().futureValue } def get(host: String, port: Int, path: String = "/") = { val response = Try { Http() .singleRequest(HttpRequest(uri = s"http://$host:$port$path")) .futureValue }.toOption response.map { res => (res.status, Unmarshal(res).to[String].futureValue) } } }
Example 25
Source File: TestServer.scala From finagle-prometheus with MIT License | 5 votes |
package com.samstarling.prometheusfinagle.examples import java.net.InetSocketAddress import com.samstarling.prometheusfinagle.PrometheusStatsReceiver import com.samstarling.prometheusfinagle.metrics.{MetricsService, Telemetry} import com.twitter.finagle.builder.ServerBuilder import com.twitter.finagle.http._ import com.twitter.finagle.http.path._ import com.twitter.finagle.http.service.{NotFoundService, RoutingService} import com.twitter.finagle.loadbalancer.perHostStats import com.twitter.finagle.{Http, Service} import io.prometheus.client.CollectorRegistry object TestServer extends App { perHostStats.parse("true") val registry = CollectorRegistry.defaultRegistry val statsReceiver = new PrometheusStatsReceiver(registry) val telemetry = new Telemetry(registry, "namespace") val emojiService = new EmojiService(statsReceiver) val metricsService = new MetricsService(registry) val echoService = new EchoService val customTelemetryService = new CustomTelemetryService(telemetry) val router: Service[Request, Response] = RoutingService.byMethodAndPathObject { case (Method.Get, Root / "emoji") => emojiService case (Method.Get, Root / "metrics") => metricsService case (Method.Get, Root / "echo") => echoService case (Method.Get, Root / "custom") => customTelemetryService case _ => new NotFoundService } ServerBuilder() .stack(Http.server) .name("testserver") .bindTo(new InetSocketAddress(8080)) .build(router) }
Example 26
Source File: MetricsService.scala From finagle-prometheus with MIT License | 5 votes |
package com.samstarling.prometheusfinagle.metrics import java.io.StringWriter import com.twitter.finagle.Service import com.twitter.finagle.http.{Request, Response, Status} import com.twitter.util.Future import io.prometheus.client.CollectorRegistry import io.prometheus.client.exporter.common.TextFormat class MetricsService(registry: CollectorRegistry) extends Service[Request, Response] { override def apply(request: Request): Future[Response] = { val writer = new StringWriter TextFormat.write004(writer, registry.metricFamilySamples()) val response = Response(request.version, Status.Ok) response.setContentString(writer.toString) Future(response) } }
Example 27
Source File: CollectorRegistryHelper.scala From finagle-prometheus with MIT License | 5 votes |
package com.samstarling.prometheusfinagle.helper import io.prometheus.client.Collector.MetricFamilySamples.{Sample => PrometheusSample} import io.prometheus.client.{Collector, CollectorRegistry} import scala.collection.JavaConverters._ case class CollectorRegistryHelper(registry: CollectorRegistry) { // TODO: Messy def samples: Map[String, List[Sample]] = { def metricFamilies = registry.metricFamilySamples.asScala.toList def allSamples: List[List[Sample]] = metricFamilies.map(_.samples.asScala.toList.map(Sample(_))) def flatSamples: List[Sample] = allSamples.flatten flatSamples .map({ s => s.name -> s }) .groupBy(_._1) .mapValues(_.map(_._2)).toMap } } case class Metric(metric: Collector.MetricFamilySamples) { def samples: Map[String, Sample] = { metric.samples.asScala.toList .map(sample => sample.name -> Sample(sample)) .toMap } } case class Sample(sample: PrometheusSample) { def name: String = sample.name def value: Double = sample.value def dimensions: Map[String, String] = { sample.labelNames.asScala.zip(sample.labelValues.asScala).toMap } }
Example 28
Source File: MetricsServiceSpec.scala From finagle-prometheus with MIT License | 5 votes |
package com.samstarling.prometheusfinagle.metrics import com.samstarling.prometheusfinagle.UnitTest import com.twitter.finagle.http.{Method, Request} import com.twitter.util.Await import io.prometheus.client.CollectorRegistry import org.specs2.specification.Scope class MetricsServiceSpec extends UnitTest { trait Context extends Scope { val registry = new CollectorRegistry(true) val telemetry = new Telemetry(registry, "unit_test") val service = new MetricsService(registry) } "it renders metrics correctly" in new Context { telemetry.counter("foo").inc() val request = Request(Method.Get, "/") val response = Await.result(service.apply(request)) response.getContentString.trim ==== "# HELP unit_test_foo No help provided\n" + "# TYPE unit_test_foo counter\n" + "unit_test_foo 1.0" } }
Example 29
Source File: package.scala From zio-metrics with Apache License 2.0 | 5 votes |
package zio.metrics.prometheus import zio.{ Has, Layer, Task, ZLayer } import io.prometheus.client.CollectorRegistry import io.prometheus.client.exporter.{ HTTPServer, PushGateway } import io.prometheus.client.bridge.Graphite import io.prometheus.client.exporter.common.TextFormat import io.prometheus.client.exporter.HttpConnectionFactory import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory import io.prometheus.client.hotspot.DefaultExports import java.net.InetSocketAddress import java.io.StringWriter package object exporters { type Exporters = Has[Exporters.Service] object Exporters { trait Service { def http(r: CollectorRegistry, port: Int): Task[HTTPServer] def graphite(r: CollectorRegistry, host: String, port: Int, intervalSeconds: Int): Task[Thread] def pushGateway( r: CollectorRegistry, hots: String, port: Int, jobName: String, user: Option[String], password: Option[String], httpConnectionFactory: Option[HttpConnectionFactory] ): Task[Unit] def write004(r: CollectorRegistry): Task[String] def initializeDefaultExports(r: CollectorRegistry): Task[Unit] } val live: Layer[Nothing, Exporters] = ZLayer.succeed(new Service { def http(r: CollectorRegistry, port: Int): zio.Task[HTTPServer] = Task { new HTTPServer(new InetSocketAddress(port), r) } def graphite(r: CollectorRegistry, host: String, port: Int, intervalSeconds: Int): Task[Thread] = Task { val g = new Graphite(host, port) g.start(r, intervalSeconds) } def pushGateway( r: CollectorRegistry, host: String, port: Int, jobName: String, user: Option[String], password: Option[String], httpConnectionFactory: Option[HttpConnectionFactory] ): Task[Unit] = Task { val pg = new PushGateway(s"$host:$port") if (user.isDefined) for { u <- user p <- password } yield pg.setConnectionFactory(new BasicAuthHttpConnectionFactory(u, p)) else if (httpConnectionFactory.isDefined) for { conn <- httpConnectionFactory } yield pg.setConnectionFactory(conn) pg.pushAdd(r, jobName) } def write004(r: CollectorRegistry): Task[String] = Task { val writer = new StringWriter TextFormat.write004(writer, r.metricFamilySamples) writer.toString } def initializeDefaultExports(r: CollectorRegistry): Task[Unit] = Task(DefaultExports.initialize()) }) def stopHttp(server: HTTPServer): Task[Unit] = Task(server.stop()) } }
Example 30
Source File: HttpLatencyMonitoringFilterSpec.scala From finagle-prometheus with MIT License | 5 votes |
package com.samstarling.prometheusfinagle.filter import com.samstarling.prometheusfinagle.UnitTest import com.samstarling.prometheusfinagle.helper.{CollectorHelper, CollectorRegistryHelper} import com.samstarling.prometheusfinagle.metrics.Telemetry import com.twitter.finagle.Service import com.twitter.finagle.http.{Method, Request, Response, Status} import com.twitter.finagle.util.DefaultTimer import com.twitter.util.{Await, Duration, Future, Timer} import io.prometheus.client.CollectorRegistry import org.specs2.specification.Scope class HttpLatencyMonitoringFilterSpec extends UnitTest { class SlowService extends Service[Request, Response] { implicit val timer = DefaultTimer.twitter override def apply(request: Request): Future[Response] = { Future .value(Response(request.version, Status.Ok)) .delayed(Duration.fromMilliseconds(1500)) } } trait Context extends Scope { val registry = new CollectorRegistry(true) val registryHelper = CollectorRegistryHelper(registry) val telemetry = new Telemetry(registry, "test") val buckets = Seq(1.0, 2.0) val labeller = new TestLabeller val filter = new HttpLatencyMonitoringFilter(telemetry, buckets, labeller) val service = mock[Service[Request, Response]] val slowService = new SlowService val request = Request(Method.Get, "/foo/bar") val serviceResponse = Response(Status.Created) val histogram = telemetry.histogram(name = "incoming_http_request_latency_seconds") service.apply(request) returns Future.value(serviceResponse) } "HttpLatencyMonitoringFilter" >> { "passes requests on to the next service" in new Context { Await.result(filter.apply(request, service)) there was one(service).apply(request) } "returns the Response from the next service" in new Context { val actualResponse = Await.result(filter.apply(request, service)) actualResponse ==== serviceResponse } "counts the request" in new Context { Await.result(filter.apply(request, slowService)) registryHelper.samples .get("test_incoming_http_request_latency_seconds_count") .map(_.map(_.value).sum) must beSome(1.0).eventually } "increments the counter with the labels from the labeller" in new Context { Await.result(filter.apply(request, service)) registryHelper.samples .get("test_incoming_http_request_latency_seconds_count") .map(_.head.dimensions.get("foo").get) must beSome("bar").eventually } "categorises requests into the correct bucket" in new Context { Await.result(filter.apply(request, slowService)) // Our request takes ~1500ms, so it should NOT fall into the "less than or equal to 1 second" bucket (le=0.5) registryHelper.samples .get("test_incoming_http_request_latency_seconds_bucket") .flatMap(_.find(_.dimensions.get("le").contains("1.0"))) .map(_.value) must beSome(0.0).eventually // However, it should fall into the "less than or equal to 2 seconds" bucket (le=0.5) registryHelper.samples .get("test_incoming_http_request_latency_seconds_bucket") .flatMap(_.find(_.dimensions.get("le").contains("2.0"))) .map(_.value) must beSome(1.0).eventually // It should also fall into the "+Inf" bucket registryHelper.samples .get("test_incoming_http_request_latency_seconds_bucket") .flatMap(_.find(_.dimensions.get("le").contains("+Inf"))) .map(_.value) must beSome(1.0).eventually } } }
Example 31
Source File: HttpMonitoringFilterSpec.scala From finagle-prometheus with MIT License | 5 votes |
package com.samstarling.prometheusfinagle.filter import com.samstarling.prometheusfinagle.UnitTest import com.samstarling.prometheusfinagle.helper.CollectorHelper import com.samstarling.prometheusfinagle.metrics.Telemetry import com.twitter.finagle.Service import com.twitter.finagle.http.{Method, Request, Response, Status} import com.twitter.util.{Await, Future} import io.prometheus.client.CollectorRegistry import org.specs2.specification.Scope import scala.collection.JavaConverters._ class HttpMonitoringFilterSpec extends UnitTest { trait Context extends Scope { val registry = new CollectorRegistry(true) val telemetry = new Telemetry(registry, "test") val labeller = new TestLabeller val filter = new HttpMonitoringFilter(telemetry, labeller) val service = mock[Service[Request, Response]] val request = Request(Method.Get, "/foo/bar") val serviceResponse = Response(Status.Created) val counter = telemetry.counter(name = "incoming_http_requests_total") service.apply(request) returns Future.value(serviceResponse) } "HttpMonitoringFilter" >> { "passes requests on to the next service" in new Context { Await.result(filter.apply(request, service)) there was one(service).apply(request) } "returns the Response from the next service" in new Context { val actualResponse = Await.result(filter.apply(request, service)) actualResponse ==== serviceResponse } "increments the incoming_http_requests_total counter" in new Context { Await.result(filter.apply(request, service)) Await.result(filter.apply(request, service)) CollectorHelper.firstSampleFor(counter).map { sample => sample.value ==== 2.0 } } "adds the correct help label" in new Context { Await.result(filter.apply(request, service)) CollectorHelper.firstMetricFor(counter).map { metric => metric.help ==== "The number of incoming HTTP requests" } } "increments the counter with the labels from the labeller" in new Context { Await.result(filter.apply(request, service)) CollectorHelper.firstSampleFor(counter).map { sample => sample.labelNames.asScala(0) ==== "foo" sample.labelValues.asScala(0) ==== "bar" } } } }
Example 32
Source File: DeduplicatedCollectorRegistry.scala From spark-metrics with Apache License 2.0 | 5 votes |
package com.banzaicloud.spark.metrics import java.{lang, util} import java.util.Collections import io.prometheus.client.{Collector, CollectorRegistry} import scala.collection.JavaConverters._ import org.apache.spark.internal.Logging import scala.util.{Failure, Try} class DeduplicatedCollectorRegistry(parent: CollectorRegistry = CollectorRegistry.defaultRegistry) extends CollectorRegistry with Logging { private type MetricsEnum = util.Enumeration[Collector.MetricFamilySamples] override def register(m: Collector): Unit = { // in case collectors with the same name are registered multiple times keep the first one Try(parent.register(m)) match { case Failure(ex) if ex.getMessage.startsWith("Collector already registered that provides name:") => // TODO: find a more robust solution for checking if there is already a collector registered for a specific metric case Failure(ex) => throw ex case _ => } } override def unregister(m: Collector): Unit = parent.unregister(m) override def clear(): Unit = parent.clear() override def getSampleValue(name: String, labelNames: Array[String], labelValues: Array[String]): lang.Double = { parent.getSampleValue(name, labelNames, labelValues) } override def getSampleValue(name: String): lang.Double = parent.getSampleValue(name) override def metricFamilySamples(): MetricsEnum = { deduplicate(parent.metricFamilySamples()) } override def filteredMetricFamilySamples(includedNames: util.Set[String]): MetricsEnum = { deduplicate(parent.filteredMetricFamilySamples(includedNames)) } private def deduplicate(source: MetricsEnum): MetricsEnum = { val metrics = source.asScala.toSeq val deduplicated = metrics .groupBy(f => (f.name, f.`type`)) .flatMap { case (_, single) if single.lengthCompare(2) < 0 => single case ((name, metricType), duplicates) => logDebug(s"Found ${duplicates.length} metrics with the same name '${name}' and type ${metricType}") duplicates.lastOption } .toList .asJava Collections.enumeration(deduplicated) } }
Example 33
Source File: DeduplicatedCollectorRegistrySuite.scala From spark-metrics with Apache License 2.0 | 5 votes |
package com.banzaicloud.spark.metrics import com.codahale.metrics.MetricRegistry import io.prometheus.client.{Collector, CollectorRegistry} import io.prometheus.client.dropwizard.DropwizardExports import org.junit.{Assert, Test} import scala.collection.JavaConverters._ class DeduplicatedCollectorRegistrySuite { @Test def testDeduplication(): Unit = { // given val baseRegistry = new MetricRegistry val registryA = new MetricRegistry val counterA = registryA.counter("counter") counterA.inc(20) counterA.inc(30) val registryB = new MetricRegistry val counterB = registryB.counter("counter") counterB.inc(40) counterB.inc(50) baseRegistry.register("hive_", registryA) baseRegistry.register("hive.", registryB) val metricsExports = new DropwizardExports(baseRegistry) val deduplicatedCollectorRegistry = new DeduplicatedCollectorRegistry(new CollectorRegistry(true)) // when metricsExports.register(deduplicatedCollectorRegistry) val samples = deduplicatedCollectorRegistry.metricFamilySamples() // then val actual = samples .asScala .filter(mfs => mfs.`type`== Collector.Type.GAUGE && mfs.name == "hive__counter") Assert.assertEquals(1, actual.size) } }
Example 34
Source File: AkkaHttpPrometheusExporter.scala From cloudstate with Apache License 2.0 | 5 votes |
package io.cloudstate.proxy import java.io.OutputStreamWriter import java.util import akka.actor.ActorSystem import akka.http.scaladsl.Http import io.prometheus.client.CollectorRegistry import akka.http.scaladsl.model._ import akka.http.scaladsl.server.Directives._ import akka.stream.Materializer import akka.util.ByteString import io.prometheus.client.exporter.common.TextFormat import scala.concurrent.Future class AkkaHttpPrometheusExporter(metricsPort: Int, registry: CollectorRegistry = CollectorRegistry.defaultRegistry)( implicit system: ActorSystem, mat: Materializer ) { private[this] final val PrometheusContentType = ContentType.parse(TextFormat.CONTENT_TYPE_004).right.get private def routes = get { (path("metrics") | pathSingleSlash) { encodeResponse { parameter(Symbol("name[]").*) { names => complete { val namesSet = new util.HashSet[String]() names.foreach(namesSet.add) val builder = ByteString.newBuilder val writer = new OutputStreamWriter(builder.asOutputStream) TextFormat.write004(writer, registry.filteredMetricFamilySamples(namesSet)) // Very important to flush the writer before we build the byte string! writer.flush() HttpEntity(PrometheusContentType, builder.result()) } } } } } def start(): Future[Http.ServerBinding] = Http().bindAndHandle(routes, "0.0.0.0", metricsPort) }
Example 35
Source File: PrometheusEndpointSink.scala From kafka-lag-exporter with Apache License 2.0 | 5 votes |
package com.lightbend.kafkalagexporter import com.lightbend.kafkalagexporter.MetricsSink._ import com.lightbend.kafkalagexporter.EndpointSink.ClusterGlobalLabels import com.lightbend.kafkalagexporter.PrometheusEndpointSink.Metrics import io.prometheus.client.exporter.HTTPServer import io.prometheus.client.hotspot.DefaultExports import io.prometheus.client.{CollectorRegistry, Gauge} import scala.util.Try object PrometheusEndpointSink { type Metrics = Map[GaugeDefinition, Gauge] def apply(definitions: MetricDefinitions, metricWhitelist: List[String], clusterGlobalLabels: ClusterGlobalLabels, server: HTTPServer, registry: CollectorRegistry): MetricsSink = { Try(new PrometheusEndpointSink(definitions, metricWhitelist, clusterGlobalLabels, server, registry)) .fold(t => throw new Exception("Could not create Prometheus Endpoint", t), sink => sink) } } class PrometheusEndpointSink private(definitions: MetricDefinitions, metricWhitelist: List[String], clusterGlobalLabels: ClusterGlobalLabels, server: HTTPServer, registry: CollectorRegistry) extends EndpointSink(clusterGlobalLabels) { DefaultExports.initialize() private val metrics: Metrics = { definitions.filter(d => metricWhitelist.exists(d.name.matches)).map { d => d -> Gauge.build() .name(d.name) .help(d.help) .labelNames(globalLabelNames ++ d.labels: _*) .register(registry) }.toMap } override def report(m: MetricValue): Unit = { if (metricWhitelist.exists(m.definition.name.matches)) { val metric = metrics.getOrElse(m.definition, throw new IllegalArgumentException(s"No metric with definition ${m.definition.name} registered")) metric.labels(getGlobalLabelValuesOrDefault(m.clusterName) ++ m.labels: _*).set(m.value) } } override def remove(m: RemoveMetric): Unit = { if (metricWhitelist.exists(m.definition.name.matches)) { for { gauge <- metrics.get(m.definition) } { val metricLabels = getGlobalLabelValuesOrDefault(m.clusterName) ++ m.labels gauge.remove(metricLabels: _*) } } } override def stop(): Unit = { registry.clear() server.stop() } }
Example 36
Source File: MainApp.scala From kafka-lag-exporter with Apache License 2.0 | 5 votes |
package com.lightbend.kafkalagexporter import java.util.concurrent.Executors import akka.actor.typed.ActorSystem import com.typesafe.config.{Config, ConfigFactory} import io.prometheus.client.CollectorRegistry import io.prometheus.client.exporter.HTTPServer import scala.concurrent.duration._ import scala.concurrent.{Await, ExecutionContext} object MainApp extends App { val system = start() // Add shutdown hook to respond to SIGTERM and gracefully shutdown the actor system sys.ShutdownHookThread { system ! KafkaClusterManager.Stop Await.result(system.whenTerminated, 10 seconds) } def start(config: Config = ConfigFactory.load()): ActorSystem[KafkaClusterManager.Message] = { // Cached thread pool for various Kafka calls for non-blocking I/O val kafkaClientEc = ExecutionContext.fromExecutor(Executors.newCachedThreadPool()) val appConfig = AppConfig(config) val clientCreator = (cluster: KafkaCluster) => KafkaClient(cluster, appConfig.clientGroupId, appConfig.clientTimeout)(kafkaClientEc) var endpointCreators : List[KafkaClusterManager.NamedCreator] = List() appConfig.prometheusConfig.foreach { prometheus => val prometheusCreator = KafkaClusterManager.NamedCreator( "prometheus-lag-reporter", (() => PrometheusEndpointSink( Metrics.definitions, appConfig.metricWhitelist, appConfig.clustersGlobalLabels(), new HTTPServer(prometheus.port), CollectorRegistry.defaultRegistry )) ) endpointCreators = prometheusCreator :: endpointCreators } appConfig.graphiteConfig.foreach { _ => val graphiteCreator = KafkaClusterManager.NamedCreator( "graphite-lag-reporter", (() => GraphiteEndpointSink(appConfig.metricWhitelist, appConfig.clustersGlobalLabels(), appConfig.graphiteConfig))) endpointCreators = graphiteCreator :: endpointCreators } ActorSystem( KafkaClusterManager.init(appConfig, endpointCreators, clientCreator), "kafka-lag-exporter") } }
Example 37
Source File: PrometheusRouting.scala From vinyldns with Apache License 2.0 | 5 votes |
package vinyldns.api.route import java.io.StringWriter import akka.http.scaladsl.model._ import akka.http.scaladsl.server.Directives import io.prometheus.client.CollectorRegistry import io.prometheus.client.exporter.common.TextFormat import scala.collection.JavaConverters._ trait PrometheusRoute extends Directives { def collectorRegistry: CollectorRegistry private val `text/plain; version=0.0.4; charset=utf-8` = ContentType { MediaType.customWithFixedCharset( "text", "plain", HttpCharsets.`UTF-8`, params = Map("version" -> "0.0.4") ) } def renderMetrics(registry: CollectorRegistry, names: Set[String]): String = { val writer = new StringWriter() TextFormat.write004(writer, registry.filteredMetricFamilySamples(names.toSet.asJava)) writer.toString } val prometheusRoute = (get & path("metrics" / "prometheus") & parameter('name.*)) { names => val content = renderMetrics(collectorRegistry, names.toSet) complete { HttpResponse(entity = HttpEntity(`text/plain; version=0.0.4; charset=utf-8`, content)) } } }