From cd300053cfec39dc75c1ea47b08ab5c78fe3f4bb Mon Sep 17 00:00:00 2001 From: Ivan Topolnjak Date: Sun, 15 Feb 2015 11:16:21 +0100 Subject: ! core: move the TraceContext manipulation API to the Tracer companion object. --- .../akka/instrumentation/RemotingInstrumentation.scala | 6 +++--- .../instrumentation/RemotingInstrumentationSpec.scala | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'kamon-akka-remote/src') diff --git a/kamon-akka-remote/src/main/scala/kamon/akka/instrumentation/RemotingInstrumentation.scala b/kamon-akka-remote/src/main/scala/kamon/akka/instrumentation/RemotingInstrumentation.scala index 32a3bcc9..50fbc815 100644 --- a/kamon-akka-remote/src/main/scala/kamon/akka/instrumentation/RemotingInstrumentation.scala +++ b/kamon-akka-remote/src/main/scala/kamon/akka/instrumentation/RemotingInstrumentation.scala @@ -6,7 +6,7 @@ import akka.remote.{ RemoteActorRefProvider, Ack, SeqNo } import akka.remote.WireFormats._ import akka.util.ByteString import kamon.Kamon -import kamon.trace.TraceContext +import kamon.trace.{ Tracer, TraceContext } import kamon.util.MilliTimestamp import org.aspectj.lang.ProceedingJoinPoint import org.aspectj.lang.annotation._ @@ -33,7 +33,7 @@ class RemotingInstrumentation { envelopeBuilder.setMessage(serializedMessage) // Attach the TraceContext info, if available. - TraceContext.map { context ⇒ + Tracer.currentContext.collect { context ⇒ envelopeBuilder.setTraceContext(RemoteTraceContext.newBuilder() .setTraceName(context.name) @@ -93,7 +93,7 @@ class RemotingInstrumentation { remoteTraceContext.getIsOpen, isLocal = false) - TraceContext.setCurrentContext(ctx) + Tracer.setCurrentContext(ctx) } pjp.proceed() diff --git a/kamon-akka-remote/src/test/scala/kamon/akka/instrumentation/RemotingInstrumentationSpec.scala b/kamon-akka-remote/src/test/scala/kamon/akka/instrumentation/RemotingInstrumentationSpec.scala index ccfde35a..d8535ff8 100644 --- a/kamon-akka-remote/src/test/scala/kamon/akka/instrumentation/RemotingInstrumentationSpec.scala +++ b/kamon-akka-remote/src/test/scala/kamon/akka/instrumentation/RemotingInstrumentationSpec.scala @@ -9,7 +9,7 @@ import akka.testkit.{ ImplicitSender, TestKitBase } import akka.util.Timeout import com.typesafe.config.ConfigFactory import kamon.Kamon -import kamon.trace.TraceContext +import kamon.trace.Tracer import org.scalatest.{ Matchers, WordSpecLike } import scala.concurrent.duration._ @@ -61,7 +61,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat "The Remoting instrumentation" should { "propagate the TraceContext when creating a new remote actor" in { - TraceContext.withContext(tracer.newContext("deploy-remote-actor", "deploy-remote-actor-1")) { + Tracer.withContext(tracer.newContext("deploy-remote-actor", "deploy-remote-actor-1")) { system.actorOf(TraceTokenReplier.remoteProps(Some(testActor), RemoteSystemAddress), "remote-deploy-fixture") } @@ -71,7 +71,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat "propagate the TraceContext when sending a message to a remotely deployed actor" in { val remoteRef = system.actorOf(TraceTokenReplier.remoteProps(None, RemoteSystemAddress), "remote-message-fixture") - TraceContext.withContext(tracer.newContext("message-remote-actor", "message-remote-actor-1")) { + Tracer.withContext(tracer.newContext("message-remote-actor", "message-remote-actor-1")) { remoteRef ! "reply-trace-token" } @@ -83,7 +83,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat implicit val askTimeout = Timeout(10 seconds) val remoteRef = system.actorOf(TraceTokenReplier.remoteProps(None, RemoteSystemAddress), "remote-ask-and-pipe-fixture") - TraceContext.withContext(tracer.newContext("ask-and-pipe-remote-actor", "ask-and-pipe-remote-actor-1")) { + Tracer.withContext(tracer.newContext("ask-and-pipe-remote-actor", "ask-and-pipe-remote-actor-1")) { (remoteRef ? "reply-trace-token") pipeTo (testActor) } @@ -95,7 +95,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat remoteSystem.actorOf(TraceTokenReplier.props(None), "actor-selection-target-b") val selection = system.actorSelection(RemoteSystemAddress + "/user/actor-selection-target-*") - TraceContext.withContext(tracer.newContext("message-remote-actor-selection", "message-remote-actor-selection-1")) { + Tracer.withContext(tracer.newContext("message-remote-actor-selection", "message-remote-actor-selection-1")) { selection ! "reply-trace-token" } @@ -107,7 +107,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat "propagate the TraceContext a remotely supervised child fails" in { val supervisor = system.actorOf(Props(new SupervisorOfRemote(testActor, RemoteSystemAddress))) - TraceContext.withContext(tracer.newContext("remote-supervision", "remote-supervision-1")) { + Tracer.withContext(tracer.newContext("remote-supervision", "remote-supervision-1")) { supervisor ! "fail" } @@ -118,7 +118,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat remoteSystem.actorOf(TraceTokenReplier.props(None), "remote-routee") val router = system.actorOf(RoundRobinGroup(List(RemoteSystemAddress + "/user/actor-selection-target-*")).props(), "router") - TraceContext.withContext(tracer.newContext("remote-routee", "remote-routee-1")) { + Tracer.withContext(tracer.newContext("remote-routee", "remote-routee-1")) { router ! "reply-trace-token" } @@ -141,7 +141,7 @@ class TraceTokenReplier(creationTraceContextListener: Option[ActorRef]) extends } def currentTraceContextInfo: String = { - val ctx = TraceContext.currentContext + val ctx = Tracer.currentContext s"name=${ctx.name}|token=${ctx.token}|isOpen=${ctx.isOpen}" } } @@ -170,7 +170,7 @@ class SupervisorOfRemote(traceContextListener: ActorRef, remoteAddress: Address) } def currentTraceContextInfo: String = { - val ctx = TraceContext.currentContext + val ctx = Tracer.currentContext s"name=${ctx.name}|token=${ctx.token}|isOpen=${ctx.isOpen}" } } -- cgit v1.2.3 From eb07f2f0b583c759e9cfaba27e3bcddeaf05a4cf Mon Sep 17 00:00:00 2001 From: Ivan Topolnjak Date: Fri, 17 Apr 2015 19:11:41 +0200 Subject: = core: add commodity trace context manipulation methods to the Tracer. --- .../instrumentation/RemotingInstrumentation.scala | 2 +- .../RemotingInstrumentationSpec.scala | 12 +- kamon-core/src/main/scala/kamon/Kamon.scala | 13 +- .../src/main/scala/kamon/metric/Metrics.scala | 364 --------------------- .../main/scala/kamon/metric/MetricsModule.scala | 364 +++++++++++++++++++++ .../kamon/metric/SubscriptionsDispatcher.scala | 4 +- .../scala/kamon/trace/MetricsOnlyContext.scala | 2 +- kamon-core/src/main/scala/kamon/trace/Tracer.scala | 132 -------- .../src/main/scala/kamon/trace/TracerModule.scala | 172 ++++++++++ .../main/scala/kamon/trace/TracingContext.scala | 2 +- .../test/scala/kamon/testkit/BaseKamonSpec.scala | 6 +- .../instrumentation/RequestInstrumentation.scala | 2 +- .../ServerRequestInstrumentation.scala | 2 +- .../system/jmx/GarbageCollectionMetrics.scala | 4 +- .../jmx/JmxSystemMetricRecorderCompanion.scala | 4 +- .../kamon/system/sigar/SigarMetricsUpdater.scala | 4 +- 16 files changed, 563 insertions(+), 526 deletions(-) delete mode 100644 kamon-core/src/main/scala/kamon/metric/Metrics.scala create mode 100644 kamon-core/src/main/scala/kamon/metric/MetricsModule.scala delete mode 100644 kamon-core/src/main/scala/kamon/trace/Tracer.scala create mode 100644 kamon-core/src/main/scala/kamon/trace/TracerModule.scala (limited to 'kamon-akka-remote/src') diff --git a/kamon-akka-remote/src/main/scala/kamon/akka/instrumentation/RemotingInstrumentation.scala b/kamon-akka-remote/src/main/scala/kamon/akka/instrumentation/RemotingInstrumentation.scala index 50fbc815..7564cfd0 100644 --- a/kamon-akka-remote/src/main/scala/kamon/akka/instrumentation/RemotingInstrumentation.scala +++ b/kamon-akka-remote/src/main/scala/kamon/akka/instrumentation/RemotingInstrumentation.scala @@ -88,7 +88,7 @@ class RemotingInstrumentation { val ctx = tracer.newContext( remoteTraceContext.getTraceName, - remoteTraceContext.getTraceToken, + Option(remoteTraceContext.getTraceToken), new MilliTimestamp(remoteTraceContext.getStartMilliTime()).toRelativeNanoTimestamp, remoteTraceContext.getIsOpen, isLocal = false) diff --git a/kamon-akka-remote/src/test/scala/kamon/akka/instrumentation/RemotingInstrumentationSpec.scala b/kamon-akka-remote/src/test/scala/kamon/akka/instrumentation/RemotingInstrumentationSpec.scala index d8535ff8..e63e06ef 100644 --- a/kamon-akka-remote/src/test/scala/kamon/akka/instrumentation/RemotingInstrumentationSpec.scala +++ b/kamon-akka-remote/src/test/scala/kamon/akka/instrumentation/RemotingInstrumentationSpec.scala @@ -61,7 +61,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat "The Remoting instrumentation" should { "propagate the TraceContext when creating a new remote actor" in { - Tracer.withContext(tracer.newContext("deploy-remote-actor", "deploy-remote-actor-1")) { + Tracer.withContext(tracer.newContext("deploy-remote-actor", Some("deploy-remote-actor-1"))) { system.actorOf(TraceTokenReplier.remoteProps(Some(testActor), RemoteSystemAddress), "remote-deploy-fixture") } @@ -71,7 +71,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat "propagate the TraceContext when sending a message to a remotely deployed actor" in { val remoteRef = system.actorOf(TraceTokenReplier.remoteProps(None, RemoteSystemAddress), "remote-message-fixture") - Tracer.withContext(tracer.newContext("message-remote-actor", "message-remote-actor-1")) { + Tracer.withContext(tracer.newContext("message-remote-actor", Some("message-remote-actor-1"))) { remoteRef ! "reply-trace-token" } @@ -83,7 +83,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat implicit val askTimeout = Timeout(10 seconds) val remoteRef = system.actorOf(TraceTokenReplier.remoteProps(None, RemoteSystemAddress), "remote-ask-and-pipe-fixture") - Tracer.withContext(tracer.newContext("ask-and-pipe-remote-actor", "ask-and-pipe-remote-actor-1")) { + Tracer.withContext(tracer.newContext("ask-and-pipe-remote-actor", Some("ask-and-pipe-remote-actor-1"))) { (remoteRef ? "reply-trace-token") pipeTo (testActor) } @@ -95,7 +95,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat remoteSystem.actorOf(TraceTokenReplier.props(None), "actor-selection-target-b") val selection = system.actorSelection(RemoteSystemAddress + "/user/actor-selection-target-*") - Tracer.withContext(tracer.newContext("message-remote-actor-selection", "message-remote-actor-selection-1")) { + Tracer.withContext(tracer.newContext("message-remote-actor-selection", Some("message-remote-actor-selection-1"))) { selection ! "reply-trace-token" } @@ -107,7 +107,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat "propagate the TraceContext a remotely supervised child fails" in { val supervisor = system.actorOf(Props(new SupervisorOfRemote(testActor, RemoteSystemAddress))) - Tracer.withContext(tracer.newContext("remote-supervision", "remote-supervision-1")) { + Tracer.withContext(tracer.newContext("remote-supervision", Some("remote-supervision-1"))) { supervisor ! "fail" } @@ -118,7 +118,7 @@ class RemotingInstrumentationSpec extends TestKitBase with WordSpecLike with Mat remoteSystem.actorOf(TraceTokenReplier.props(None), "remote-routee") val router = system.actorOf(RoundRobinGroup(List(RemoteSystemAddress + "/user/actor-selection-target-*")).props(), "router") - Tracer.withContext(tracer.newContext("remote-routee", "remote-routee-1")) { + Tracer.withContext(tracer.newContext("remote-routee", Some("remote-routee-1"))) { router ! "reply-trace-token" } diff --git a/kamon-core/src/main/scala/kamon/Kamon.scala b/kamon-core/src/main/scala/kamon/Kamon.scala index f8253875..d819588c 100644 --- a/kamon-core/src/main/scala/kamon/Kamon.scala +++ b/kamon-core/src/main/scala/kamon/Kamon.scala @@ -18,13 +18,12 @@ import _root_.akka.actor import _root_.akka.actor._ import com.typesafe.config.{ ConfigFactory, Config } import kamon.metric._ -import kamon.metric.instrument.Gauge -import kamon.trace.{ TracerImpl, Tracer } +import kamon.trace.{ TracerModuleImpl, TracerModule } object Kamon { trait Extension extends actor.Extension - private case class KamonCoreComponents(metrics: Metrics, tracer: Tracer) + private case class KamonCoreComponents(metrics: MetricsModule, tracer: TracerModule) @volatile private var _system: ActorSystem = _ @volatile private var _coreComponents: Option[KamonCoreComponents] = None @@ -40,8 +39,8 @@ object Kamon { } if (_coreComponents.isEmpty) { - val metrics = MetricsImpl(config) - val tracer = TracerImpl(metrics, config) + val metrics = MetricsModuleImpl(config) + val tracer = TracerModuleImpl(metrics, config) _coreComponents = Some(KamonCoreComponents(metrics, tracer)) _system = ActorSystem("kamon", resolveInternalConfig) @@ -62,10 +61,10 @@ object Kamon { _system = null } - def metrics: Metrics = + def metrics: MetricsModule = ifStarted(_.metrics) - def tracer: Tracer = + def tracer: TracerModule = ifStarted(_.tracer) def apply[T <: Kamon.Extension](key: ExtensionId[T]): T = diff --git a/kamon-core/src/main/scala/kamon/metric/Metrics.scala b/kamon-core/src/main/scala/kamon/metric/Metrics.scala deleted file mode 100644 index 9fd9e771..00000000 --- a/kamon-core/src/main/scala/kamon/metric/Metrics.scala +++ /dev/null @@ -1,364 +0,0 @@ -/* - * ========================================================================================= - * Copyright © 2013 the kamon project - * - * 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.metric - -import akka.actor._ -import com.typesafe.config.Config -import kamon.metric.SubscriptionsDispatcher.{ Subscribe, Unsubscribe } -import kamon.metric.instrument.Gauge.CurrentValueCollector -import kamon.metric.instrument.Histogram.DynamicRange -import kamon.metric.instrument._ -import kamon.util.LazyActorRef - -import scala.collection.concurrent.TrieMap -import scala.concurrent.duration.FiniteDuration - -case class EntityRegistration[T <: EntityRecorder](entity: Entity, recorder: T) - -trait Metrics { - def settings: MetricsSettings - - def shouldTrack(entity: Entity): Boolean - - def shouldTrack(entityName: String, category: String): Boolean = - shouldTrack(Entity(entityName, category)) - - // - // Histograms registration and removal - // - - def histogram(name: String): Histogram = - registerHistogram(name) - - def histogram(name: String, unitOfMeasurement: UnitOfMeasurement): Histogram = - registerHistogram(name, unitOfMeasurement = Some(unitOfMeasurement)) - - def histogram(name: String, dynamicRange: DynamicRange): Histogram = - registerHistogram(name, dynamicRange = Some(dynamicRange)) - - def histogram(name: String, unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange): Histogram = - registerHistogram(name, unitOfMeasurement = Some(unitOfMeasurement), dynamicRange = Some(dynamicRange)) - - def histogram(name: String, tags: Map[String, String]): Histogram = - registerHistogram(name, tags) - - def histogram(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement): Histogram = - registerHistogram(name, tags, Some(unitOfMeasurement)) - - def histogram(name: String, tags: Map[String, String], dynamicRange: DynamicRange): Histogram = - registerHistogram(name, tags, dynamicRange = Some(dynamicRange)) - - def histogram(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange): Histogram = - registerHistogram(name, tags, Some(unitOfMeasurement), Some(dynamicRange)) - - def removeHistogram(name: String): Boolean = - removeHistogram(name, Map.empty) - - def registerHistogram(name: String, tags: Map[String, String] = Map.empty, unitOfMeasurement: Option[UnitOfMeasurement] = None, - dynamicRange: Option[DynamicRange] = None): Histogram - - def removeHistogram(name: String, tags: Map[String, String]): Boolean - - // - // MinMaxCounter registration and removal - // - - def minMaxCounter(name: String): MinMaxCounter = - registerMinMaxCounter(name) - - def minMaxCounter(name: String, unitOfMeasurement: UnitOfMeasurement): MinMaxCounter = - registerMinMaxCounter(name, unitOfMeasurement = Some(unitOfMeasurement)) - - def minMaxCounter(name: String, dynamicRange: DynamicRange): MinMaxCounter = - registerMinMaxCounter(name, dynamicRange = Some(dynamicRange)) - - def minMaxCounter(name: String, refreshInterval: FiniteDuration): MinMaxCounter = - registerMinMaxCounter(name, refreshInterval = Some(refreshInterval)) - - def minMaxCounter(name: String, dynamicRange: DynamicRange, refreshInterval: FiniteDuration): MinMaxCounter = - registerMinMaxCounter(name, dynamicRange = Some(dynamicRange), refreshInterval = Some(refreshInterval)) - - def minMaxCounter(name: String, unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange): MinMaxCounter = - registerMinMaxCounter(name, unitOfMeasurement = Some(unitOfMeasurement), dynamicRange = Some(dynamicRange)) - - def minMaxCounter(name: String, tags: Map[String, String]): MinMaxCounter = - registerMinMaxCounter(name, tags) - - def minMaxCounter(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement): MinMaxCounter = - registerMinMaxCounter(name, tags, Some(unitOfMeasurement)) - - def minMaxCounter(name: String, tags: Map[String, String], dynamicRange: DynamicRange): MinMaxCounter = - registerMinMaxCounter(name, tags, dynamicRange = Some(dynamicRange)) - - def minMaxCounter(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange): MinMaxCounter = - registerMinMaxCounter(name, tags, Some(unitOfMeasurement), Some(dynamicRange)) - - def removeMinMaxCounter(name: String): Boolean = - removeMinMaxCounter(name, Map.empty) - - def removeMinMaxCounter(name: String, tags: Map[String, String]): Boolean - - def registerMinMaxCounter(name: String, tags: Map[String, String] = Map.empty, unitOfMeasurement: Option[UnitOfMeasurement] = None, - dynamicRange: Option[DynamicRange] = None, refreshInterval: Option[FiniteDuration] = None): MinMaxCounter - - // - // Gauge registration and removal - // - - def gauge(name: String)(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector) - - def gauge(name: String, unitOfMeasurement: UnitOfMeasurement)(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector, unitOfMeasurement = Some(unitOfMeasurement)) - - def gauge(name: String, dynamicRange: DynamicRange)(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector, dynamicRange = Some(dynamicRange)) - - def gauge(name: String, refreshInterval: FiniteDuration)(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector, refreshInterval = Some(refreshInterval)) - - def gauge(name: String, dynamicRange: DynamicRange, refreshInterval: FiniteDuration)(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector, dynamicRange = Some(dynamicRange), refreshInterval = Some(refreshInterval)) - - def gauge(name: String, unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange)(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector, unitOfMeasurement = Some(unitOfMeasurement), dynamicRange = Some(dynamicRange)) - - def gauge(name: String, tags: Map[String, String])(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector, tags) - - def gauge(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement)(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector, tags, Some(unitOfMeasurement)) - - def gauge(name: String, tags: Map[String, String], dynamicRange: DynamicRange)(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector, tags, dynamicRange = Some(dynamicRange)) - - def gauge(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange)(valueCollector: CurrentValueCollector): Gauge = - registerGauge(name, valueCollector, tags, Some(unitOfMeasurement), Some(dynamicRange)) - - def removeGauge(name: String): Boolean = - removeGauge(name, Map.empty) - - def removeGauge(name: String, tags: Map[String, String]): Boolean - - def registerGauge(name: String, valueCollector: CurrentValueCollector, tags: Map[String, String] = Map.empty, - unitOfMeasurement: Option[UnitOfMeasurement] = None, dynamicRange: Option[DynamicRange] = None, - refreshInterval: Option[FiniteDuration] = None): Gauge - - // - // Counters registration and removal - // - - def counter(name: String): Counter = - registerCounter(name) - - def counter(name: String, unitOfMeasurement: UnitOfMeasurement): Counter = - registerCounter(name, unitOfMeasurement = Some(unitOfMeasurement)) - - def counter(name: String, tags: Map[String, String]): Counter = - registerCounter(name, tags) - - def counter(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement): Counter = - registerCounter(name, tags, Some(unitOfMeasurement)) - - def removeCounter(name: String): Boolean = - removeCounter(name, Map.empty) - - def removeCounter(name: String, tags: Map[String, String]): Boolean - - def registerCounter(name: String, tags: Map[String, String] = Map.empty, unitOfMeasurement: Option[UnitOfMeasurement] = None, - dynamicRange: Option[DynamicRange] = None): Counter - - // - // Entities registration and removal - // - - def entity[T <: EntityRecorder](recorderFactory: EntityRecorderFactory[T], name: String): T = - entity(recorderFactory, Entity(name, recorderFactory.category)) - - def entity[T <: EntityRecorder](recorderFactory: EntityRecorderFactory[T], name: String, tags: Map[String, String]): T = - entity(recorderFactory, Entity(name, recorderFactory.category, tags)) - - def removeEntity(name: String, category: String): Boolean = - removeEntity(Entity(name, category, Map.empty)) - - def removeEntity(name: String, category: String, tags: Map[String, String]): Boolean = - removeEntity(Entity(name, category, tags)) - - def removeEntity(entity: Entity): Boolean - - def entity[T <: EntityRecorder](recorderFactory: EntityRecorderFactory[T], entity: Entity): T - - def find(name: String, category: String): Option[EntityRecorder] = - find(Entity(name, category)) - - def find(name: String, category: String, tags: Map[String, String]): Option[EntityRecorder] = - find(Entity(name, category, tags)) - - def find(entity: Entity): Option[EntityRecorder] - - def subscribe(filter: SubscriptionFilter, subscriber: ActorRef): Unit = - subscribe(filter, subscriber, permanently = true) - - def subscribe(category: String, selection: String, subscriber: ActorRef, permanently: Boolean): Unit = - subscribe(SubscriptionFilter(category, selection), subscriber, permanently) - - def subscribe(category: String, selection: String, subscriber: ActorRef): Unit = - subscribe(SubscriptionFilter(category, selection), subscriber, permanently = true) - - def subscribe(filter: SubscriptionFilter, subscriber: ActorRef, permanently: Boolean): Unit - - def unsubscribe(subscriber: ActorRef): Unit - - def buildDefaultCollectionContext: CollectionContext - - def instrumentFactory(category: String): InstrumentFactory -} - -private[kamon] class MetricsImpl(config: Config) extends Metrics { - import kamon.util.TriemapAtomicGetOrElseUpdate.Syntax - - private val _trackedEntities = TrieMap.empty[Entity, EntityRecorder] - private val _subscriptions = new LazyActorRef - - val settings = MetricsSettings(config) - - def shouldTrack(entity: Entity): Boolean = - settings.entityFilters.get(entity.category).map { - filter ⇒ filter.accept(entity.name) - - } getOrElse (settings.trackUnmatchedEntities) - - def registerHistogram(name: String, tags: Map[String, String], unitOfMeasurement: Option[UnitOfMeasurement], - dynamicRange: Option[DynamicRange]): Histogram = { - - val histogramEntity = Entity(name, SingleInstrumentEntityRecorder.Histogram, tags) - val recorder = _trackedEntities.atomicGetOrElseUpdate(histogramEntity, { - val factory = instrumentFactory(histogramEntity.category) - HistogramRecorder(HistogramKey(histogramEntity.category, unitOfMeasurement.getOrElse(UnitOfMeasurement.Unknown)), - factory.createHistogram(name, dynamicRange)) - }, _.cleanup) - - recorder.asInstanceOf[HistogramRecorder].instrument - } - - def removeHistogram(name: String, tags: Map[String, String]): Boolean = - _trackedEntities.remove(Entity(name, SingleInstrumentEntityRecorder.Histogram, tags)).isDefined - - def registerMinMaxCounter(name: String, tags: Map[String, String], unitOfMeasurement: Option[UnitOfMeasurement], dynamicRange: Option[DynamicRange], - refreshInterval: Option[FiniteDuration]): MinMaxCounter = { - - val minMaxCounterEntity = Entity(name, SingleInstrumentEntityRecorder.MinMaxCounter, tags) - val recorder = _trackedEntities.atomicGetOrElseUpdate(minMaxCounterEntity, { - val factory = instrumentFactory(minMaxCounterEntity.category) - MinMaxCounterRecorder(MinMaxCounterKey(minMaxCounterEntity.category, unitOfMeasurement.getOrElse(UnitOfMeasurement.Unknown)), - factory.createMinMaxCounter(name, dynamicRange, refreshInterval)) - }, _.cleanup) - - recorder.asInstanceOf[MinMaxCounterRecorder].instrument - } - - def removeMinMaxCounter(name: String, tags: Map[String, String]): Boolean = - _trackedEntities.remove(Entity(name, SingleInstrumentEntityRecorder.MinMaxCounter, tags)).isDefined - - def registerGauge(name: String, valueCollector: CurrentValueCollector, tags: Map[String, String] = Map.empty, - unitOfMeasurement: Option[UnitOfMeasurement] = None, dynamicRange: Option[DynamicRange] = None, - refreshInterval: Option[FiniteDuration] = None): Gauge = { - - val gaugeEntity = Entity(name, SingleInstrumentEntityRecorder.Gauge, tags) - val recorder = _trackedEntities.atomicGetOrElseUpdate(gaugeEntity, { - val factory = instrumentFactory(gaugeEntity.category) - GaugeRecorder(MinMaxCounterKey(gaugeEntity.category, unitOfMeasurement.getOrElse(UnitOfMeasurement.Unknown)), - factory.createGauge(name, dynamicRange, refreshInterval, valueCollector)) - }, _.cleanup) - - recorder.asInstanceOf[GaugeRecorder].instrument - } - - def removeGauge(name: String, tags: Map[String, String]): Boolean = - _trackedEntities.remove(Entity(name, SingleInstrumentEntityRecorder.Gauge, tags)).isDefined - - def registerCounter(name: String, tags: Map[String, String] = Map.empty, unitOfMeasurement: Option[UnitOfMeasurement] = None, - dynamicRange: Option[DynamicRange] = None): Counter = { - - val counterEntity = Entity(name, SingleInstrumentEntityRecorder.Counter, tags) - val recorder = _trackedEntities.atomicGetOrElseUpdate(counterEntity, { - val factory = instrumentFactory(counterEntity.category) - CounterRecorder(CounterKey(counterEntity.category, unitOfMeasurement.getOrElse(UnitOfMeasurement.Unknown)), - factory.createCounter()) - }, _.cleanup) - - recorder.asInstanceOf[CounterRecorder].instrument - } - - def removeCounter(name: String, tags: Map[String, String]): Boolean = - _trackedEntities.remove(Entity(name, SingleInstrumentEntityRecorder.Counter, tags)).isDefined - - def entity[T <: EntityRecorder](recorderFactory: EntityRecorderFactory[T], entity: Entity): T = { - _trackedEntities.atomicGetOrElseUpdate(entity, { - recorderFactory.createRecorder(instrumentFactory(recorderFactory.category)) - }, _.cleanup).asInstanceOf[T] - } - - def removeEntity(entity: Entity): Boolean = - _trackedEntities.remove(entity).isDefined - - def find(entity: Entity): Option[EntityRecorder] = - _trackedEntities.get(entity) - - def subscribe(filter: SubscriptionFilter, subscriber: ActorRef, permanent: Boolean): Unit = - _subscriptions.tell(Subscribe(filter, subscriber, permanent)) - - def unsubscribe(subscriber: ActorRef): Unit = - _subscriptions.tell(Unsubscribe(subscriber)) - - def buildDefaultCollectionContext: CollectionContext = - CollectionContext(settings.defaultCollectionContextBufferSize) - - def instrumentFactory(category: String): InstrumentFactory = - settings.instrumentFactories.getOrElse(category, settings.defaultInstrumentFactory) - - private[kamon] def collectSnapshots(collectionContext: CollectionContext): Map[Entity, EntitySnapshot] = { - val builder = Map.newBuilder[Entity, EntitySnapshot] - _trackedEntities.foreach { - case (identity, recorder) ⇒ builder += ((identity, recorder.collect(collectionContext))) - } - - builder.result() - } - - /** - * Metrics Extension initialization. - */ - private var _system: ActorSystem = null - private lazy val _start = { - _subscriptions.point(_system.actorOf(SubscriptionsDispatcher.props(settings.tickInterval, this), "metrics")) - settings.pointScheduler(DefaultRefreshScheduler(_system.scheduler, _system.dispatcher)) - } - - def start(system: ActorSystem): Unit = synchronized { - _system = system - _start - _system = null - } -} - -private[kamon] object MetricsImpl { - - def apply(config: Config) = - new MetricsImpl(config) -} - diff --git a/kamon-core/src/main/scala/kamon/metric/MetricsModule.scala b/kamon-core/src/main/scala/kamon/metric/MetricsModule.scala new file mode 100644 index 00000000..9f2bbbef --- /dev/null +++ b/kamon-core/src/main/scala/kamon/metric/MetricsModule.scala @@ -0,0 +1,364 @@ +/* + * ========================================================================================= + * Copyright © 2013 the kamon project + * + * 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.metric + +import akka.actor._ +import com.typesafe.config.Config +import kamon.metric.SubscriptionsDispatcher.{ Subscribe, Unsubscribe } +import kamon.metric.instrument.Gauge.CurrentValueCollector +import kamon.metric.instrument.Histogram.DynamicRange +import kamon.metric.instrument._ +import kamon.util.LazyActorRef + +import scala.collection.concurrent.TrieMap +import scala.concurrent.duration.FiniteDuration + +case class EntityRegistration[T <: EntityRecorder](entity: Entity, recorder: T) + +trait MetricsModule { + def settings: MetricsSettings + + def shouldTrack(entity: Entity): Boolean + + def shouldTrack(entityName: String, category: String): Boolean = + shouldTrack(Entity(entityName, category)) + + // + // Histograms registration and removal + // + + def histogram(name: String): Histogram = + registerHistogram(name) + + def histogram(name: String, unitOfMeasurement: UnitOfMeasurement): Histogram = + registerHistogram(name, unitOfMeasurement = Some(unitOfMeasurement)) + + def histogram(name: String, dynamicRange: DynamicRange): Histogram = + registerHistogram(name, dynamicRange = Some(dynamicRange)) + + def histogram(name: String, unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange): Histogram = + registerHistogram(name, unitOfMeasurement = Some(unitOfMeasurement), dynamicRange = Some(dynamicRange)) + + def histogram(name: String, tags: Map[String, String]): Histogram = + registerHistogram(name, tags) + + def histogram(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement): Histogram = + registerHistogram(name, tags, Some(unitOfMeasurement)) + + def histogram(name: String, tags: Map[String, String], dynamicRange: DynamicRange): Histogram = + registerHistogram(name, tags, dynamicRange = Some(dynamicRange)) + + def histogram(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange): Histogram = + registerHistogram(name, tags, Some(unitOfMeasurement), Some(dynamicRange)) + + def removeHistogram(name: String): Boolean = + removeHistogram(name, Map.empty) + + def registerHistogram(name: String, tags: Map[String, String] = Map.empty, unitOfMeasurement: Option[UnitOfMeasurement] = None, + dynamicRange: Option[DynamicRange] = None): Histogram + + def removeHistogram(name: String, tags: Map[String, String]): Boolean + + // + // MinMaxCounter registration and removal + // + + def minMaxCounter(name: String): MinMaxCounter = + registerMinMaxCounter(name) + + def minMaxCounter(name: String, unitOfMeasurement: UnitOfMeasurement): MinMaxCounter = + registerMinMaxCounter(name, unitOfMeasurement = Some(unitOfMeasurement)) + + def minMaxCounter(name: String, dynamicRange: DynamicRange): MinMaxCounter = + registerMinMaxCounter(name, dynamicRange = Some(dynamicRange)) + + def minMaxCounter(name: String, refreshInterval: FiniteDuration): MinMaxCounter = + registerMinMaxCounter(name, refreshInterval = Some(refreshInterval)) + + def minMaxCounter(name: String, dynamicRange: DynamicRange, refreshInterval: FiniteDuration): MinMaxCounter = + registerMinMaxCounter(name, dynamicRange = Some(dynamicRange), refreshInterval = Some(refreshInterval)) + + def minMaxCounter(name: String, unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange): MinMaxCounter = + registerMinMaxCounter(name, unitOfMeasurement = Some(unitOfMeasurement), dynamicRange = Some(dynamicRange)) + + def minMaxCounter(name: String, tags: Map[String, String]): MinMaxCounter = + registerMinMaxCounter(name, tags) + + def minMaxCounter(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement): MinMaxCounter = + registerMinMaxCounter(name, tags, Some(unitOfMeasurement)) + + def minMaxCounter(name: String, tags: Map[String, String], dynamicRange: DynamicRange): MinMaxCounter = + registerMinMaxCounter(name, tags, dynamicRange = Some(dynamicRange)) + + def minMaxCounter(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange): MinMaxCounter = + registerMinMaxCounter(name, tags, Some(unitOfMeasurement), Some(dynamicRange)) + + def removeMinMaxCounter(name: String): Boolean = + removeMinMaxCounter(name, Map.empty) + + def removeMinMaxCounter(name: String, tags: Map[String, String]): Boolean + + def registerMinMaxCounter(name: String, tags: Map[String, String] = Map.empty, unitOfMeasurement: Option[UnitOfMeasurement] = None, + dynamicRange: Option[DynamicRange] = None, refreshInterval: Option[FiniteDuration] = None): MinMaxCounter + + // + // Gauge registration and removal + // + + def gauge(name: String)(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector) + + def gauge(name: String, unitOfMeasurement: UnitOfMeasurement)(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector, unitOfMeasurement = Some(unitOfMeasurement)) + + def gauge(name: String, dynamicRange: DynamicRange)(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector, dynamicRange = Some(dynamicRange)) + + def gauge(name: String, refreshInterval: FiniteDuration)(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector, refreshInterval = Some(refreshInterval)) + + def gauge(name: String, dynamicRange: DynamicRange, refreshInterval: FiniteDuration)(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector, dynamicRange = Some(dynamicRange), refreshInterval = Some(refreshInterval)) + + def gauge(name: String, unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange)(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector, unitOfMeasurement = Some(unitOfMeasurement), dynamicRange = Some(dynamicRange)) + + def gauge(name: String, tags: Map[String, String])(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector, tags) + + def gauge(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement)(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector, tags, Some(unitOfMeasurement)) + + def gauge(name: String, tags: Map[String, String], dynamicRange: DynamicRange)(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector, tags, dynamicRange = Some(dynamicRange)) + + def gauge(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement, dynamicRange: DynamicRange)(valueCollector: CurrentValueCollector): Gauge = + registerGauge(name, valueCollector, tags, Some(unitOfMeasurement), Some(dynamicRange)) + + def removeGauge(name: String): Boolean = + removeGauge(name, Map.empty) + + def removeGauge(name: String, tags: Map[String, String]): Boolean + + def registerGauge(name: String, valueCollector: CurrentValueCollector, tags: Map[String, String] = Map.empty, + unitOfMeasurement: Option[UnitOfMeasurement] = None, dynamicRange: Option[DynamicRange] = None, + refreshInterval: Option[FiniteDuration] = None): Gauge + + // + // Counters registration and removal + // + + def counter(name: String): Counter = + registerCounter(name) + + def counter(name: String, unitOfMeasurement: UnitOfMeasurement): Counter = + registerCounter(name, unitOfMeasurement = Some(unitOfMeasurement)) + + def counter(name: String, tags: Map[String, String]): Counter = + registerCounter(name, tags) + + def counter(name: String, tags: Map[String, String], unitOfMeasurement: UnitOfMeasurement): Counter = + registerCounter(name, tags, Some(unitOfMeasurement)) + + def removeCounter(name: String): Boolean = + removeCounter(name, Map.empty) + + def removeCounter(name: String, tags: Map[String, String]): Boolean + + def registerCounter(name: String, tags: Map[String, String] = Map.empty, unitOfMeasurement: Option[UnitOfMeasurement] = None, + dynamicRange: Option[DynamicRange] = None): Counter + + // + // Entities registration and removal + // + + def entity[T <: EntityRecorder](recorderFactory: EntityRecorderFactory[T], name: String): T = + entity(recorderFactory, Entity(name, recorderFactory.category)) + + def entity[T <: EntityRecorder](recorderFactory: EntityRecorderFactory[T], name: String, tags: Map[String, String]): T = + entity(recorderFactory, Entity(name, recorderFactory.category, tags)) + + def removeEntity(name: String, category: String): Boolean = + removeEntity(Entity(name, category, Map.empty)) + + def removeEntity(name: String, category: String, tags: Map[String, String]): Boolean = + removeEntity(Entity(name, category, tags)) + + def removeEntity(entity: Entity): Boolean + + def entity[T <: EntityRecorder](recorderFactory: EntityRecorderFactory[T], entity: Entity): T + + def find(name: String, category: String): Option[EntityRecorder] = + find(Entity(name, category)) + + def find(name: String, category: String, tags: Map[String, String]): Option[EntityRecorder] = + find(Entity(name, category, tags)) + + def find(entity: Entity): Option[EntityRecorder] + + def subscribe(filter: SubscriptionFilter, subscriber: ActorRef): Unit = + subscribe(filter, subscriber, permanently = true) + + def subscribe(category: String, selection: String, subscriber: ActorRef, permanently: Boolean): Unit = + subscribe(SubscriptionFilter(category, selection), subscriber, permanently) + + def subscribe(category: String, selection: String, subscriber: ActorRef): Unit = + subscribe(SubscriptionFilter(category, selection), subscriber, permanently = true) + + def subscribe(filter: SubscriptionFilter, subscriber: ActorRef, permanently: Boolean): Unit + + def unsubscribe(subscriber: ActorRef): Unit + + def buildDefaultCollectionContext: CollectionContext + + def instrumentFactory(category: String): InstrumentFactory +} + +private[kamon] class MetricsModuleImpl(config: Config) extends MetricsModule { + import kamon.util.TriemapAtomicGetOrElseUpdate.Syntax + + private val _trackedEntities = TrieMap.empty[Entity, EntityRecorder] + private val _subscriptions = new LazyActorRef + + val settings = MetricsSettings(config) + + def shouldTrack(entity: Entity): Boolean = + settings.entityFilters.get(entity.category).map { + filter ⇒ filter.accept(entity.name) + + } getOrElse (settings.trackUnmatchedEntities) + + def registerHistogram(name: String, tags: Map[String, String], unitOfMeasurement: Option[UnitOfMeasurement], + dynamicRange: Option[DynamicRange]): Histogram = { + + val histogramEntity = Entity(name, SingleInstrumentEntityRecorder.Histogram, tags) + val recorder = _trackedEntities.atomicGetOrElseUpdate(histogramEntity, { + val factory = instrumentFactory(histogramEntity.category) + HistogramRecorder(HistogramKey(histogramEntity.category, unitOfMeasurement.getOrElse(UnitOfMeasurement.Unknown)), + factory.createHistogram(name, dynamicRange)) + }, _.cleanup) + + recorder.asInstanceOf[HistogramRecorder].instrument + } + + def removeHistogram(name: String, tags: Map[String, String]): Boolean = + _trackedEntities.remove(Entity(name, SingleInstrumentEntityRecorder.Histogram, tags)).isDefined + + def registerMinMaxCounter(name: String, tags: Map[String, String], unitOfMeasurement: Option[UnitOfMeasurement], dynamicRange: Option[DynamicRange], + refreshInterval: Option[FiniteDuration]): MinMaxCounter = { + + val minMaxCounterEntity = Entity(name, SingleInstrumentEntityRecorder.MinMaxCounter, tags) + val recorder = _trackedEntities.atomicGetOrElseUpdate(minMaxCounterEntity, { + val factory = instrumentFactory(minMaxCounterEntity.category) + MinMaxCounterRecorder(MinMaxCounterKey(minMaxCounterEntity.category, unitOfMeasurement.getOrElse(UnitOfMeasurement.Unknown)), + factory.createMinMaxCounter(name, dynamicRange, refreshInterval)) + }, _.cleanup) + + recorder.asInstanceOf[MinMaxCounterRecorder].instrument + } + + def removeMinMaxCounter(name: String, tags: Map[String, String]): Boolean = + _trackedEntities.remove(Entity(name, SingleInstrumentEntityRecorder.MinMaxCounter, tags)).isDefined + + def registerGauge(name: String, valueCollector: CurrentValueCollector, tags: Map[String, String] = Map.empty, + unitOfMeasurement: Option[UnitOfMeasurement] = None, dynamicRange: Option[DynamicRange] = None, + refreshInterval: Option[FiniteDuration] = None): Gauge = { + + val gaugeEntity = Entity(name, SingleInstrumentEntityRecorder.Gauge, tags) + val recorder = _trackedEntities.atomicGetOrElseUpdate(gaugeEntity, { + val factory = instrumentFactory(gaugeEntity.category) + GaugeRecorder(MinMaxCounterKey(gaugeEntity.category, unitOfMeasurement.getOrElse(UnitOfMeasurement.Unknown)), + factory.createGauge(name, dynamicRange, refreshInterval, valueCollector)) + }, _.cleanup) + + recorder.asInstanceOf[GaugeRecorder].instrument + } + + def removeGauge(name: String, tags: Map[String, String]): Boolean = + _trackedEntities.remove(Entity(name, SingleInstrumentEntityRecorder.Gauge, tags)).isDefined + + def registerCounter(name: String, tags: Map[String, String] = Map.empty, unitOfMeasurement: Option[UnitOfMeasurement] = None, + dynamicRange: Option[DynamicRange] = None): Counter = { + + val counterEntity = Entity(name, SingleInstrumentEntityRecorder.Counter, tags) + val recorder = _trackedEntities.atomicGetOrElseUpdate(counterEntity, { + val factory = instrumentFactory(counterEntity.category) + CounterRecorder(CounterKey(counterEntity.category, unitOfMeasurement.getOrElse(UnitOfMeasurement.Unknown)), + factory.createCounter()) + }, _.cleanup) + + recorder.asInstanceOf[CounterRecorder].instrument + } + + def removeCounter(name: String, tags: Map[String, String]): Boolean = + _trackedEntities.remove(Entity(name, SingleInstrumentEntityRecorder.Counter, tags)).isDefined + + def entity[T <: EntityRecorder](recorderFactory: EntityRecorderFactory[T], entity: Entity): T = { + _trackedEntities.atomicGetOrElseUpdate(entity, { + recorderFactory.createRecorder(instrumentFactory(recorderFactory.category)) + }, _.cleanup).asInstanceOf[T] + } + + def removeEntity(entity: Entity): Boolean = + _trackedEntities.remove(entity).isDefined + + def find(entity: Entity): Option[EntityRecorder] = + _trackedEntities.get(entity) + + def subscribe(filter: SubscriptionFilter, subscriber: ActorRef, permanent: Boolean): Unit = + _subscriptions.tell(Subscribe(filter, subscriber, permanent)) + + def unsubscribe(subscriber: ActorRef): Unit = + _subscriptions.tell(Unsubscribe(subscriber)) + + def buildDefaultCollectionContext: CollectionContext = + CollectionContext(settings.defaultCollectionContextBufferSize) + + def instrumentFactory(category: String): InstrumentFactory = + settings.instrumentFactories.getOrElse(category, settings.defaultInstrumentFactory) + + private[kamon] def collectSnapshots(collectionContext: CollectionContext): Map[Entity, EntitySnapshot] = { + val builder = Map.newBuilder[Entity, EntitySnapshot] + _trackedEntities.foreach { + case (identity, recorder) ⇒ builder += ((identity, recorder.collect(collectionContext))) + } + + builder.result() + } + + /** + * Metrics Extension initialization. + */ + private var _system: ActorSystem = null + private lazy val _start = { + _subscriptions.point(_system.actorOf(SubscriptionsDispatcher.props(settings.tickInterval, this), "metrics")) + settings.pointScheduler(DefaultRefreshScheduler(_system.scheduler, _system.dispatcher)) + } + + def start(system: ActorSystem): Unit = synchronized { + _system = system + _start + _system = null + } +} + +private[kamon] object MetricsModuleImpl { + + def apply(config: Config) = + new MetricsModuleImpl(config) +} + diff --git a/kamon-core/src/main/scala/kamon/metric/SubscriptionsDispatcher.scala b/kamon-core/src/main/scala/kamon/metric/SubscriptionsDispatcher.scala index 3b6be70b..9f8c7be3 100644 --- a/kamon-core/src/main/scala/kamon/metric/SubscriptionsDispatcher.scala +++ b/kamon-core/src/main/scala/kamon/metric/SubscriptionsDispatcher.scala @@ -24,7 +24,7 @@ import scala.concurrent.duration.FiniteDuration /** * Manages subscriptions to metrics and dispatch snapshots on every tick to all subscribers. */ -private[kamon] class SubscriptionsDispatcher(interval: FiniteDuration, metricsExtension: MetricsImpl) extends Actor { +private[kamon] class SubscriptionsDispatcher(interval: FiniteDuration, metricsExtension: MetricsModuleImpl) extends Actor { var lastTick = MilliTimestamp.now var oneShotSubscriptions = Map.empty[ActorRef, SubscriptionFilter] var permanentSubscriptions = Map.empty[ActorRef, SubscriptionFilter] @@ -81,7 +81,7 @@ private[kamon] class SubscriptionsDispatcher(interval: FiniteDuration, metricsEx } object SubscriptionsDispatcher { - def props(interval: FiniteDuration, metricsExtension: MetricsImpl): Props = + def props(interval: FiniteDuration, metricsExtension: MetricsModuleImpl): Props = Props(new SubscriptionsDispatcher(interval, metricsExtension)) case object Tick diff --git a/kamon-core/src/main/scala/kamon/trace/MetricsOnlyContext.scala b/kamon-core/src/main/scala/kamon/trace/MetricsOnlyContext.scala index 0f09b4be..17be661b 100644 --- a/kamon-core/src/main/scala/kamon/trace/MetricsOnlyContext.scala +++ b/kamon-core/src/main/scala/kamon/trace/MetricsOnlyContext.scala @@ -20,7 +20,7 @@ import java.util.concurrent.ConcurrentLinkedQueue import akka.event.LoggingAdapter import kamon.Kamon -import kamon.metric.{ SegmentMetrics, Metrics, TraceMetrics } +import kamon.metric.{ SegmentMetrics, MetricsModule, TraceMetrics } import kamon.util.{ NanoInterval, RelativeNanoTimestamp } import scala.annotation.tailrec diff --git a/kamon-core/src/main/scala/kamon/trace/Tracer.scala b/kamon-core/src/main/scala/kamon/trace/Tracer.scala deleted file mode 100644 index 472c1d65..00000000 --- a/kamon-core/src/main/scala/kamon/trace/Tracer.scala +++ /dev/null @@ -1,132 +0,0 @@ -/* - * ========================================================================================= - * Copyright © 2013 the kamon project - * - * 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.trace - -import java.net.InetAddress -import java.util.concurrent.atomic.AtomicLong - -import akka.actor._ -import com.typesafe.config.Config -import kamon.metric.Metrics -import kamon.util._ - -import scala.util.Try - -trait Tracer { - def newContext(name: String): TraceContext - def newContext(name: String, token: String): TraceContext - def newContext(name: String, token: String, timestamp: RelativeNanoTimestamp, isOpen: Boolean, isLocal: Boolean): TraceContext - - def subscribe(subscriber: ActorRef): Unit - def unsubscribe(subscriber: ActorRef): Unit -} - -object Tracer { - private[kamon] val _traceContextStorage = new ThreadLocal[TraceContext] { - override def initialValue(): TraceContext = EmptyTraceContext - } - - def currentContext: TraceContext = - _traceContextStorage.get() - - def setCurrentContext(context: TraceContext): Unit = - _traceContextStorage.set(context) - - def clearCurrentContext: Unit = - _traceContextStorage.remove() - - def withContext[T](context: TraceContext)(code: ⇒ T): T = { - val oldContext = _traceContextStorage.get() - _traceContextStorage.set(context) - - try code finally _traceContextStorage.set(oldContext) - } -} - -private[kamon] class TracerImpl(metricsExtension: Metrics, config: Config) extends Tracer { - private val _settings = TraceSettings(config) - private val _hostnamePrefix = Try(InetAddress.getLocalHost.getHostName).getOrElse("unknown-localhost") - private val _tokenCounter = new AtomicLong - - private val _subscriptions = new LazyActorRef - private val _incubator = new LazyActorRef - - private def newToken: String = - _hostnamePrefix + "-" + String.valueOf(_tokenCounter.incrementAndGet()) - - def newContext(name: String): TraceContext = - createTraceContext(name) - - def newContext(name: String, token: String): TraceContext = - createTraceContext(name, token) - - def newContext(name: String, token: String, timestamp: RelativeNanoTimestamp, isOpen: Boolean, isLocal: Boolean): TraceContext = - createTraceContext(name, token, timestamp, isOpen, isLocal) - - private def createTraceContext(traceName: String, token: String = newToken, startTimestamp: RelativeNanoTimestamp = RelativeNanoTimestamp.now, - isOpen: Boolean = true, isLocal: Boolean = true): TraceContext = { - - def newMetricsOnlyContext = new MetricsOnlyContext(traceName, token, isOpen, _settings.levelOfDetail, startTimestamp, null) - - if (_settings.levelOfDetail == LevelOfDetail.MetricsOnly || !isLocal) - newMetricsOnlyContext - else { - if (!_settings.sampler.shouldTrace) - newMetricsOnlyContext - else - new TracingContext(traceName, token, true, _settings.levelOfDetail, isLocal, startTimestamp, null, dispatchTracingContext) - } - } - - def subscribe(subscriber: ActorRef): Unit = - _subscriptions.tell(TraceSubscriptions.Subscribe(subscriber)) - - def unsubscribe(subscriber: ActorRef): Unit = - _subscriptions.tell(TraceSubscriptions.Unsubscribe(subscriber)) - - private[kamon] def dispatchTracingContext(trace: TracingContext): Unit = - if (_settings.sampler.shouldReport(trace.elapsedTime)) - if (trace.shouldIncubate) - _incubator.tell(trace) - else - _subscriptions.tell(trace.generateTraceInfo) - - /** - * Tracer Extension initialization. - */ - private var _system: ActorSystem = null - private lazy val _start = { - val subscriptions = _system.actorOf(Props[TraceSubscriptions], "trace-subscriptions") - _subscriptions.point(subscriptions) - _incubator.point(_system.actorOf(Incubator.props(subscriptions))) - } - - def start(system: ActorSystem): Unit = synchronized { - _system = system - _start - _system = null - } -} - -private[kamon] object TracerImpl { - - def apply(metricsExtension: Metrics, config: Config) = - new TracerImpl(metricsExtension, config) -} - -case class TraceInfo(name: String, token: String, timestamp: NanoTimestamp, elapsedTime: NanoInterval, metadata: Map[String, String], segments: List[SegmentInfo]) -case class SegmentInfo(name: String, category: String, library: String, timestamp: NanoTimestamp, elapsedTime: NanoInterval, metadata: Map[String, String]) \ No newline at end of file diff --git a/kamon-core/src/main/scala/kamon/trace/TracerModule.scala b/kamon-core/src/main/scala/kamon/trace/TracerModule.scala new file mode 100644 index 00000000..416af20e --- /dev/null +++ b/kamon-core/src/main/scala/kamon/trace/TracerModule.scala @@ -0,0 +1,172 @@ +/* + * ========================================================================================= + * Copyright © 2013 the kamon project + * + * 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.trace + +import java.net.InetAddress +import java.util.concurrent.atomic.AtomicLong + +import akka.actor._ +import com.typesafe.config.Config +import kamon.Kamon +import kamon.metric.MetricsModule +import kamon.util._ + +import scala.util.Try + +trait TracerModule { + def newContext(name: String): TraceContext + def newContext(name: String, token: Option[String]): TraceContext + def newContext(name: String, token: Option[String], timestamp: RelativeNanoTimestamp, isOpen: Boolean, isLocal: Boolean): TraceContext + + def subscribe(subscriber: ActorRef): Unit + def unsubscribe(subscriber: ActorRef): Unit +} + +object Tracer { + private[kamon] val _traceContextStorage = new ThreadLocal[TraceContext] { + override def initialValue(): TraceContext = EmptyTraceContext + } + + def currentContext: TraceContext = + _traceContextStorage.get() + + def setCurrentContext(context: TraceContext): Unit = + _traceContextStorage.set(context) + + def clearCurrentContext: Unit = + _traceContextStorage.remove() + + def withContext[T](context: TraceContext)(code: ⇒ T): T = { + val oldContext = _traceContextStorage.get() + _traceContextStorage.set(context) + + try code finally _traceContextStorage.set(oldContext) + } + + // Java variant. + def withContext[T](context: TraceContext, code: Supplier[T]): T = + withContext(context)(code.get) + + def withNewContext[T](traceName: String, traceToken: Option[String], autoFinish: Boolean)(code: ⇒ T): T = { + withContext(Kamon.tracer.newContext(traceName, traceToken)) { + val codeResult = code + if (autoFinish) + currentContext.finish() + + codeResult + } + } + + def withNewContext[T](traceName: String)(code: ⇒ T): T = + withNewContext(traceName, None, false)(code) + + def withNewContext[T](traceName: String, traceToken: Option[String])(code: ⇒ T): T = + withNewContext(traceName, traceToken, false)(code) + + def withNewContext[T](traceName: String, autoFinish: Boolean)(code: ⇒ T): T = + withNewContext(traceName, None, autoFinish)(code) + + // Java variants. + def withNewContext[T](traceName: String, traceToken: Option[String], autoFinish: Boolean, code: Supplier[T]): T = + withNewContext(traceName, traceToken, autoFinish)(code.get) + + def withNewContext[T](traceName: String, code: Supplier[T]): T = + withNewContext(traceName, None, false)(code.get) + + def withNewContext[T](traceName: String, traceToken: Option[String], code: Supplier[T]): T = + withNewContext(traceName, traceToken, false)(code.get) + + def withNewContext[T](traceName: String, autoFinish: Boolean, code: Supplier[T]): T = + withNewContext(traceName, None, autoFinish)(code.get) +} + +private[kamon] class TracerModuleImpl(metricsExtension: MetricsModule, config: Config) extends TracerModule { + private val _settings = TraceSettings(config) + private val _hostnamePrefix = Try(InetAddress.getLocalHost.getHostName).getOrElse("unknown-localhost") + private val _tokenCounter = new AtomicLong + + private val _subscriptions = new LazyActorRef + private val _incubator = new LazyActorRef + + private def newToken: String = + _hostnamePrefix + "-" + String.valueOf(_tokenCounter.incrementAndGet()) + + def newContext(name: String): TraceContext = + createTraceContext(name, None) + + def newContext(name: String, token: Option[String]): TraceContext = + createTraceContext(name, token) + + def newContext(name: String, token: Option[String], timestamp: RelativeNanoTimestamp, isOpen: Boolean, isLocal: Boolean): TraceContext = + createTraceContext(name, token, timestamp, isOpen, isLocal) + + private def createTraceContext(traceName: String, token: Option[String], startTimestamp: RelativeNanoTimestamp = RelativeNanoTimestamp.now, + isOpen: Boolean = true, isLocal: Boolean = true): TraceContext = { + + def newMetricsOnlyContext(token: String): TraceContext = + new MetricsOnlyContext(traceName, token, isOpen, _settings.levelOfDetail, startTimestamp, null) + + val traceToken = token.getOrElse(newToken) + + if (_settings.levelOfDetail == LevelOfDetail.MetricsOnly || !isLocal) + newMetricsOnlyContext(traceToken) + else { + if (!_settings.sampler.shouldTrace) + newMetricsOnlyContext(traceToken) + else + new TracingContext(traceName, traceToken, true, _settings.levelOfDetail, isLocal, startTimestamp, null, dispatchTracingContext) + } + } + + def subscribe(subscriber: ActorRef): Unit = + _subscriptions.tell(TraceSubscriptions.Subscribe(subscriber)) + + def unsubscribe(subscriber: ActorRef): Unit = + _subscriptions.tell(TraceSubscriptions.Unsubscribe(subscriber)) + + private[kamon] def dispatchTracingContext(trace: TracingContext): Unit = + if (_settings.sampler.shouldReport(trace.elapsedTime)) + if (trace.shouldIncubate) + _incubator.tell(trace) + else + _subscriptions.tell(trace.generateTraceInfo) + + /** + * Tracer Extension initialization. + */ + private var _system: ActorSystem = null + private lazy val _start = { + val subscriptions = _system.actorOf(Props[TraceSubscriptions], "trace-subscriptions") + _subscriptions.point(subscriptions) + _incubator.point(_system.actorOf(Incubator.props(subscriptions))) + } + + def start(system: ActorSystem): Unit = synchronized { + _system = system + _start + _system = null + } +} + +private[kamon] object TracerModuleImpl { + + def apply(metricsExtension: MetricsModule, config: Config) = + new TracerModuleImpl(metricsExtension, config) +} + +case class TraceInfo(name: String, token: String, timestamp: NanoTimestamp, elapsedTime: NanoInterval, metadata: Map[String, String], segments: List[SegmentInfo]) +case class SegmentInfo(name: String, category: String, library: String, timestamp: NanoTimestamp, elapsedTime: NanoInterval, metadata: Map[String, String]) \ No newline at end of file diff --git a/kamon-core/src/main/scala/kamon/trace/TracingContext.scala b/kamon-core/src/main/scala/kamon/trace/TracingContext.scala index 9708d25f..9269a99e 100644 --- a/kamon-core/src/main/scala/kamon/trace/TracingContext.scala +++ b/kamon-core/src/main/scala/kamon/trace/TracingContext.scala @@ -21,7 +21,7 @@ import java.util.concurrent.atomic.AtomicInteger import akka.event.LoggingAdapter import kamon.util.{ NanoInterval, RelativeNanoTimestamp, NanoTimestamp } -import kamon.metric.Metrics +import kamon.metric.MetricsModule import scala.collection.concurrent.TrieMap diff --git a/kamon-core/src/test/scala/kamon/testkit/BaseKamonSpec.scala b/kamon-core/src/test/scala/kamon/testkit/BaseKamonSpec.scala index e7b18770..cb909ad9 100644 --- a/kamon-core/src/test/scala/kamon/testkit/BaseKamonSpec.scala +++ b/kamon-core/src/test/scala/kamon/testkit/BaseKamonSpec.scala @@ -20,13 +20,11 @@ import akka.testkit.{ ImplicitSender, TestKitBase } import akka.actor.ActorSystem import com.typesafe.config.{ Config, ConfigFactory } import kamon.Kamon -import kamon.metric.{ Entity, SubscriptionsDispatcher, EntitySnapshot, MetricsImpl } +import kamon.metric.{ Entity, SubscriptionsDispatcher, EntitySnapshot } import kamon.trace.TraceContext import kamon.util.LazyActorRef import org.scalatest.{ BeforeAndAfterAll, Matchers, WordSpecLike } -import scala.reflect.ClassTag - abstract class BaseKamonSpec(actorSystemName: String) extends TestKitBase with WordSpecLike with Matchers with ImplicitSender with BeforeAndAfterAll { lazy val collectionContext = Kamon.metrics.buildDefaultCollectionContext implicit lazy val system: ActorSystem = { @@ -41,7 +39,7 @@ abstract class BaseKamonSpec(actorSystemName: String) extends TestKitBase with W Kamon.tracer.newContext(name) def newContext(name: String, token: String): TraceContext = - Kamon.tracer.newContext(name, token) + Kamon.tracer.newContext(name, Option(token)) def takeSnapshotOf(name: String, category: String): EntitySnapshot = { val recorder = Kamon.metrics.find(name, category).get diff --git a/kamon-play/src/main/scala/kamon/play/instrumentation/RequestInstrumentation.scala b/kamon-play/src/main/scala/kamon/play/instrumentation/RequestInstrumentation.scala index 5214f420..ac73bff0 100644 --- a/kamon-play/src/main/scala/kamon/play/instrumentation/RequestInstrumentation.scala +++ b/kamon-play/src/main/scala/kamon/play/instrumentation/RequestInstrumentation.scala @@ -43,7 +43,7 @@ class RequestInstrumentation { requestHeader.headers.toSimpleMap.find(_._1 == playExtension.traceTokenHeaderName).map(_._2) } else None - val newContext = token.map(t ⇒ tracer.newContext(defaultTraceName, t)).getOrElse(tracer.newContext(defaultTraceName)) + val newContext = tracer.newContext(defaultTraceName, token) Tracer.setCurrentContext(newContext) } diff --git a/kamon-spray/src/main/scala/kamon/spray/instrumentation/ServerRequestInstrumentation.scala b/kamon-spray/src/main/scala/kamon/spray/instrumentation/ServerRequestInstrumentation.scala index 5be156cd..d76b9f58 100644 --- a/kamon-spray/src/main/scala/kamon/spray/instrumentation/ServerRequestInstrumentation.scala +++ b/kamon-spray/src/main/scala/kamon/spray/instrumentation/ServerRequestInstrumentation.scala @@ -46,7 +46,7 @@ class ServerRequestInstrumentation { request.headers.find(_.name == sprayExtension.settings.traceTokenHeaderName).map(_.value) } else None - val newContext = token.map(customToken ⇒ tracer.newContext(defaultTraceName, customToken)) getOrElse (tracer.newContext(defaultTraceName)) + val newContext = tracer.newContext(defaultTraceName, token) Tracer.setCurrentContext(newContext) // Necessary to force initialization of traceContext when initiating the request. diff --git a/kamon-system-metrics/src/main/scala/kamon/system/jmx/GarbageCollectionMetrics.scala b/kamon-system-metrics/src/main/scala/kamon/system/jmx/GarbageCollectionMetrics.scala index 7a5770d8..2e9ea954 100644 --- a/kamon-system-metrics/src/main/scala/kamon/system/jmx/GarbageCollectionMetrics.scala +++ b/kamon-system-metrics/src/main/scala/kamon/system/jmx/GarbageCollectionMetrics.scala @@ -19,7 +19,7 @@ package kamon.system.jmx import java.lang.management.{ GarbageCollectorMXBean, ManagementFactory } import kamon.Kamon -import kamon.metric.{ EntityRecorderFactory, Entity, Metrics, GenericEntityRecorder } +import kamon.metric._ import kamon.metric.instrument.{ DifferentialValueCollector, Time, InstrumentFactory } import scala.collection.JavaConverters._ @@ -44,7 +44,7 @@ object GarbageCollectionMetrics { def sanitizeCollectorName(name: String): String = name.replaceAll("""[^\w]""", "-").toLowerCase - def register(metricsExtension: Metrics): Unit = { + def register(metricsExtension: MetricsModule): Unit = { ManagementFactory.getGarbageCollectorMXBeans.asScala.filter(_.isValid) map { gc ⇒ val gcName = sanitizeCollectorName(gc.getName) Kamon.metrics.entity(EntityRecorderFactory("system-metric", new GarbageCollectionMetrics(gc, _)), s"$gcName-garbage-collector") diff --git a/kamon-system-metrics/src/main/scala/kamon/system/jmx/JmxSystemMetricRecorderCompanion.scala b/kamon-system-metrics/src/main/scala/kamon/system/jmx/JmxSystemMetricRecorderCompanion.scala index 15bd399e..2a86c13c 100644 --- a/kamon-system-metrics/src/main/scala/kamon/system/jmx/JmxSystemMetricRecorderCompanion.scala +++ b/kamon-system-metrics/src/main/scala/kamon/system/jmx/JmxSystemMetricRecorderCompanion.scala @@ -17,10 +17,10 @@ package kamon.system.jmx import kamon.metric.instrument.InstrumentFactory -import kamon.metric.{ EntityRecorderFactory, EntityRecorder, Metrics } +import kamon.metric.{ MetricsModule, EntityRecorderFactory, EntityRecorder } abstract class JmxSystemMetricRecorderCompanion(metricName: String) { - def register(metricsExtension: Metrics): EntityRecorder = + def register(metricsExtension: MetricsModule): EntityRecorder = metricsExtension.entity(EntityRecorderFactory("system-metric", apply(_)), metricName) def apply(instrumentFactory: InstrumentFactory): EntityRecorder diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarMetricsUpdater.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarMetricsUpdater.scala index a1bd3e01..5e5f7518 100644 --- a/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarMetricsUpdater.scala +++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarMetricsUpdater.scala @@ -19,7 +19,7 @@ package kamon.system.sigar import akka.actor.{ Props, Actor } import kamon.Kamon import kamon.metric.instrument.InstrumentFactory -import kamon.metric.{ EntityRecorderFactory, Entity, EntityRecorder, Metrics } +import kamon.metric._ import kamon.system.sigar.SigarMetricsUpdater.UpdateSigarMetrics import org.hyperic.sigar.Sigar @@ -65,7 +65,7 @@ trait SigarMetric extends EntityRecorder { } abstract class SigarMetricRecorderCompanion(metricName: String) { - def register(sigar: Sigar, metricsExtension: Metrics): SigarMetric = + def register(sigar: Sigar, metricsExtension: MetricsModule): SigarMetric = metricsExtension.entity(EntityRecorderFactory("system-metric", apply(sigar, _)), metricName) def apply(sigar: Sigar, instrumentFactory: InstrumentFactory): SigarMetric -- cgit v1.2.3 From 5cb9de39cdd6ef258732a82e6f0d519712d1c37b Mon Sep 17 00:00:00 2001 From: Ivan Topolnjak Date: Mon, 20 Apr 2015 22:56:33 +0200 Subject: = akka-remote: disable auto-start on akka-remote, there is nothing to start. --- kamon-akka-remote/src/main/resources/reference.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'kamon-akka-remote/src') diff --git a/kamon-akka-remote/src/main/resources/reference.conf b/kamon-akka-remote/src/main/resources/reference.conf index 7c6be896..1d805cad 100644 --- a/kamon-akka-remote/src/main/resources/reference.conf +++ b/kamon-akka-remote/src/main/resources/reference.conf @@ -6,7 +6,8 @@ kamon { modules { kamon-akka-remote { - auto-start = yes + // Nothing to auto-start here. + auto-start = no requires-aspectj = yes extension-id = none } -- cgit v1.2.3