aboutsummaryrefslogblamecommitdiff
path: root/kamon-annotation/src/test/scala/kamon/annotation/StaticAnnotationInstrumentationSpec.scala
blob: aea83409a7be53c8fa42b70e6e1c42f1c75b0d48 (plain) (tree)































































































































































































                                                                                                                                      
/*
 * =========================================================================================
 * Copyright © 2013-2015 the kamon project <http://kamon.io/>
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language governing permissions
 * and limitations under the License.
 * =========================================================================================
 */

package kamon.annotation

import com.typesafe.config.ConfigFactory
import kamon.metric.{ HistogramKey, MinMaxCounterKey, CounterKey }
import kamon.testkit.BaseKamonSpec

class StaticAnnotationInstrumentationSpec extends BaseKamonSpec("static-annotation-instrumentation-spec") {
  import kamon.metric.TraceMetricsSpec.SegmentSyntax

  override lazy val config =
    ConfigFactory.parseString(
      """
        |kamon.metric {
        |  tick-interval = 1 hour
        |  default-collection-context-buffer-size = 100
        |}
      """.stripMargin)

  "the Kamon Annotation module" should {
    "create a new trace when is invoked a method annotated with @Trace in a Scala Object" in {
      for (id  1 to 10) AnnotatedObject.trace()

      val snapshot = takeSnapshotOf("trace", "trace")
      snapshot.histogram("elapsed-time").get.numberOfMeasurements should be(10)
      snapshot.segments.size should be(0)
    }
    "create a segment when is invoked a method annotated with @Trace and @Segment in a Scala Object" in {
      for (id  1 to 10) AnnotatedObject.segment()

      val snapshot = takeSnapshotOf("trace-with-segment", "trace")
      snapshot.histogram("elapsed-time").get.numberOfMeasurements should be(10)

      snapshot.segments.size should be(2)
      snapshot.segment("segment", "segments", "segment") should not be empty
      snapshot.segment("inner-segment", "inner", "segment") should not be empty
    }

    "create a segment when is invoked a method annotated with @Trace and @Segment and evaluate EL expressions in a Scala Object" in {
      for (id  1 to 10) AnnotatedObject.segmentWithEL()

      val snapshot = takeSnapshotOf("trace-with-segment-el", "trace")
      snapshot.histogram("elapsed-time").get.numberOfMeasurements should be(10)

      snapshot.segments.size should be(2)
      snapshot.segment("segment:10", "segments", "segment") should not be empty
      snapshot.segment("inner-segment", "inner", "segment") should not be empty
    }

    "count the invocations of a method annotated with @Count in a Scala Object" in {
      for (id  1 to 10) AnnotatedObject.count()

      val snapshot = takeSnapshotOf("simple-metric", "simple-metric")
      snapshot.counter("count").get.count should be(10)
    }

    "count the invocations of a method annotated with @Count and evaluate EL expressions in a Scala Object" in {
      for (id  1 to 2) AnnotatedObject.countWithEL()

      val snapshot = takeSnapshotOf("simple-metric", "simple-metric")
      snapshot.counter("count:10").get.count should be(2)

      val counterKey = (name: String)  (key: CounterKey)  key.name == name

      snapshot.counters.keys.find(counterKey("count:10")).get.metadata should be(Map("counter" -> "1", "env" -> "prod"))
    }

    "count the current invocations of a method annotated with @MinMaxCount in a Scala Object" in {
      for (id  1 to 10) {
        AnnotatedObject.countMinMax()
      }

      val snapshot = takeSnapshotOf("simple-metric", "simple-metric")
      snapshot.minMaxCounter("minMax").get.max should be(1)
    }

    "count the current invocations of a method annotated with @MinMaxCount and evaluate EL expressions in a Scala Object" in {
      for (id  1 to 10) AnnotatedObject.countMinMaxWithEL()

      val snapshot = takeSnapshotOf("simple-metric", "simple-metric")
      snapshot.minMaxCounter("minMax:10").get.max should be(1)

      val minMaxKey = (name: String)  (key: MinMaxCounterKey)  key.name == name

      snapshot.minMaxCounters.keys.find(minMaxKey("minMax:10")).get.metadata should be(Map("minMax" -> "1", "env" -> "dev"))
    }

    "measure the time spent in the execution of a method annotated with @Time in a Scala Object" in {
      for (id  1 to 1) AnnotatedObject.time()

      val snapshot = takeSnapshotOf("simple-metric", "simple-metric")
      snapshot.histogram("time").get.numberOfMeasurements should be(1)
    }

    "measure the time spent in the execution of a method annotated with @Time and evaluate EL expressions in a Scala Object" in {
      for (id  1 to 1) AnnotatedObject.timeWithEL()

      val snapshot = takeSnapshotOf("simple-metric", "simple-metric")
      snapshot.histogram("time:10").get.numberOfMeasurements should be(1)

      val histogramKey = (name: String)  (key: HistogramKey)  key.name == name

      snapshot.histograms.keys.find(histogramKey("time:10")).get.metadata should be(Map("slow-service" -> "service", "env" -> "prod"))
    }

    "record the value returned by a method annotated with @Histogram in a Scala Object" in {
      for (value  1 to 5) AnnotatedObject.histogram(value)

      val snapshot = takeSnapshotOf("simple-metric", "simple-metric")
      snapshot.histogram("histogram").get.numberOfMeasurements should be(5)
      snapshot.histogram("histogram").get.min should be(1)
      snapshot.histogram("histogram").get.max should be(5)
      snapshot.histogram("histogram").get.sum should be(15)
    }

    "record the value returned by a method annotated with @Histogram and evaluate EL expressions in a Scala Object" in {
      for (value  1 to 2) AnnotatedObject.histogramWithEL(value)

      val snapshot = takeSnapshotOf("simple-metric", "simple-metric")
      snapshot.histogram("histogram:10").get.numberOfMeasurements should be(2)
      snapshot.histogram("histogram:10").get.min should be(1)
      snapshot.histogram("histogram:10").get.max should be(2)

      val histogramKey = (name: String)  (key: HistogramKey)  key.name == name

      snapshot.histograms.keys.find(histogramKey("histogram:10")).get.metadata should be(Map("histogram" -> "hdr", "env" -> "prod"))
    }
  }
}

@EnableKamon
object AnnotatedObject {

  val Id = "10"

  @Trace("trace")
  def trace(): Unit = {}

  @Trace("trace-with-segment")
  @Segment(name = "segment", category = "segments", library = "segment")
  def segment(): Unit = {
    inner() // method annotated with @Segment
  }

  @Trace("trace-with-segment-el")
  @Segment(name = "#{'segment:' += AnnotatedObject$.MODULE$.Id}", category = "segments", library = "segment")
  def segmentWithEL(): Unit = {
    inner() // method annotated with @Segment
  }

  @Count(name = "count")
  def count(): Unit = {}

  @Count(name = "${'count:' += AnnotatedObject$.MODULE$.Id}", tags = "${'counter':'1', 'env':'prod'}")
  def countWithEL(): Unit = {}

  @MinMaxCount(name = "minMax")
  def countMinMax(): Unit = {}

  @MinMaxCount(name = "#{'minMax:' += AnnotatedObject$.MODULE$.Id}", tags = "#{'minMax':'1', 'env':'dev'}")
  def countMinMaxWithEL(): Unit = {}

  @Time(name = "time")
  def time(): Unit = {}

  @Time(name = "${'time:' += AnnotatedObject$.MODULE$.Id}", tags = "${'slow-service':'service', 'env':'prod'}")
  def timeWithEL(): Unit = {}

  @Histogram(name = "histogram")
  def histogram(value: Long): Long = value

  @Histogram(name = "#{'histogram:' += AnnotatedObject$.MODULE$.Id}", tags = "${'histogram':'hdr', 'env':'prod'}")
  def histogramWithEL(value: Long): Long = value

  @Segment(name = "inner-segment", category = "inner", library = "segment")
  private def inner(): Unit = {}
}