aboutsummaryrefslogtreecommitdiff
path: root/kamon-core/src/main/scala/kamon/instrumentation
diff options
context:
space:
mode:
authorIvan Topolnjak <ivantopo@gmail.com>2014-07-03 14:39:10 -0300
committerIvan Topolnjak <ivantopo@gmail.com>2014-07-03 14:39:10 -0300
commitfc2333281acc028c79e1cfe00840666deea5a9d1 (patch)
treee81af37eb7f3edee9cffc9703740f36010c48f4a /kamon-core/src/main/scala/kamon/instrumentation
parent9133663dd5f34bb60cb2d431fa4852f4f339cda0 (diff)
parenta3353d3e3fcb1dfab3e8f401187e236e99df2202 (diff)
downloadKamon-fc2333281acc028c79e1cfe00840666deea5a9d1.tar.gz
Kamon-fc2333281acc028c79e1cfe00840666deea5a9d1.tar.bz2
Kamon-fc2333281acc028c79e1cfe00840666deea5a9d1.zip
Merge branch 'wip/metrics-collection-refactor'
Conflicts: kamon-datadog/src/test/scala/kamon/datadog/DatadogMetricSenderSpec.scala
Diffstat (limited to 'kamon-core/src/main/scala/kamon/instrumentation')
-rw-r--r--kamon-core/src/main/scala/kamon/instrumentation/akka/ActorCellInstrumentation.scala130
-rw-r--r--kamon-core/src/main/scala/kamon/instrumentation/akka/ActorLoggingInstrumentation.scala (renamed from kamon-core/src/main/scala/kamon/instrumentation/ActorLoggingTracing.scala)12
-rw-r--r--kamon-core/src/main/scala/kamon/instrumentation/akka/ActorSystemMessageInstrumentation.scala80
-rw-r--r--kamon-core/src/main/scala/kamon/instrumentation/akka/AskPatternInstrumentation.scala55
-rw-r--r--kamon-core/src/main/scala/kamon/instrumentation/akka/DispatcherInstrumentation.scala163
-rw-r--r--kamon-core/src/main/scala/kamon/instrumentation/hdrhistogram/AtomicHistogramFieldsAccessor.scala35
-rw-r--r--kamon-core/src/main/scala/kamon/instrumentation/scala/FutureInstrumentation.scala (renamed from kamon-core/src/main/scala/kamon/instrumentation/FutureTracing.scala)33
7 files changed, 486 insertions, 22 deletions
diff --git a/kamon-core/src/main/scala/kamon/instrumentation/akka/ActorCellInstrumentation.scala b/kamon-core/src/main/scala/kamon/instrumentation/akka/ActorCellInstrumentation.scala
new file mode 100644
index 00000000..5fce4555
--- /dev/null
+++ b/kamon-core/src/main/scala/kamon/instrumentation/akka/ActorCellInstrumentation.scala
@@ -0,0 +1,130 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 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 akka.instrumentation
+
+import akka.actor._
+import akka.dispatch.{ Envelope, MessageDispatcher }
+import kamon.Kamon
+import kamon.metric.ActorMetrics.ActorMetricsRecorder
+import kamon.metric.{ ActorMetrics, Metrics }
+import kamon.trace._
+import org.aspectj.lang.ProceedingJoinPoint
+import org.aspectj.lang.annotation._
+
+@Aspect
+class ActorCellInstrumentation {
+
+ @Pointcut("execution(akka.actor.ActorCell.new(..)) && this(cell) && args(system, ref, props, dispatcher, parent)")
+ def actorCellCreation(cell: ActorCell, system: ActorSystem, ref: ActorRef, props: Props, dispatcher: MessageDispatcher, parent: ActorRef): Unit = {}
+
+ @After("actorCellCreation(cell, system, ref, props, dispatcher, parent)")
+ def afterCreation(cell: ActorCell, system: ActorSystem, ref: ActorRef, props: Props, dispatcher: MessageDispatcher, parent: ActorRef): Unit = {
+
+ val metricsExtension = Kamon(Metrics)(system)
+ val metricIdentity = ActorMetrics(ref.path.elements.mkString("/"))
+ val cellWithMetrics = cell.asInstanceOf[ActorCellMetrics]
+
+ cellWithMetrics.metricIdentity = metricIdentity
+ cellWithMetrics.actorMetricsRecorder = metricsExtension.register(metricIdentity, ActorMetrics.Factory)
+ }
+
+ @Pointcut("(execution(* akka.actor.ActorCell.invoke(*)) || execution(* akka.routing.RoutedActorCell.sendMessage(*))) && this(cell) && args(envelope)")
+ def invokingActorBehaviourAtActorCell(cell: ActorCell, envelope: Envelope) = {}
+
+ @Around("invokingActorBehaviourAtActorCell(cell, envelope)")
+ def aroundBehaviourInvoke(pjp: ProceedingJoinPoint, cell: ActorCell, envelope: Envelope): Any = {
+ val timestampBeforeProcessing = System.nanoTime()
+ val contextAndTimestamp = envelope.asInstanceOf[TraceContextAware]
+ val cellWithMetrics = cell.asInstanceOf[ActorCellMetrics]
+
+ try {
+ TraceRecorder.withTraceContext(contextAndTimestamp.traceContext) {
+ pjp.proceed()
+ }
+ } finally {
+ cellWithMetrics.actorMetricsRecorder.map {
+ am ⇒
+ am.processingTime.record(System.nanoTime() - timestampBeforeProcessing)
+ am.timeInMailbox.record(timestampBeforeProcessing - contextAndTimestamp.captureNanoTime)
+ am.mailboxSize.decrement()
+ }
+ }
+ }
+
+ @Pointcut("execution(* akka.actor.ActorCell.sendMessage(*)) && this(cell)")
+ def sendingMessageToActorCell(cell: ActorCell): Unit = {}
+
+ @After("sendingMessageToActorCell(cell)")
+ def afterSendMessageToActorCell(cell: ActorCell): Unit = {
+ val cellWithMetrics = cell.asInstanceOf[ActorCellMetrics]
+ cellWithMetrics.actorMetricsRecorder.map(am ⇒ am.mailboxSize.increment())
+ }
+
+ @Pointcut("execution(* akka.actor.ActorCell.stop()) && this(cell)")
+ def actorStop(cell: ActorCell): Unit = {}
+
+ @After("actorStop(cell)")
+ def afterStop(cell: ActorCell): Unit = {
+ val cellWithMetrics = cell.asInstanceOf[ActorCellMetrics]
+
+ cellWithMetrics.actorMetricsRecorder.map { p ⇒
+ cellWithMetrics.mailboxSizeCollectorCancellable.cancel()
+ Kamon(Metrics)(cell.system).unregister(cellWithMetrics.metricIdentity)
+ }
+ }
+
+ @Pointcut("execution(* akka.actor.ActorCell.handleInvokeFailure(..)) && this(cell)")
+ def actorInvokeFailure(cell: ActorCell): Unit = {}
+
+ @Before("actorInvokeFailure(cell)")
+ def beforeInvokeFailure(cell: ActorCell): Unit = {
+ val cellWithMetrics = cell.asInstanceOf[ActorCellMetrics]
+
+ cellWithMetrics.actorMetricsRecorder.map {
+ am ⇒ am.errors.increment()
+ }
+ }
+}
+
+trait ActorCellMetrics {
+ var metricIdentity: ActorMetrics = _
+ var actorMetricsRecorder: Option[ActorMetricsRecorder] = _
+ var mailboxSizeCollectorCancellable: Cancellable = _
+}
+
+@Aspect
+class ActorCellMetricsIntoActorCellMixin {
+
+ @DeclareMixin("akka.actor.ActorCell")
+ def mixinActorCellMetricsToActorCell: ActorCellMetrics = new ActorCellMetrics {}
+}
+
+@Aspect
+class TraceContextIntoEnvelopeMixin {
+
+ @DeclareMixin("akka.dispatch.Envelope")
+ def mixinTraceContextAwareToEnvelope: TraceContextAware = TraceContextAware.default
+
+ @Pointcut("execution(akka.dispatch.Envelope.new(..)) && this(ctx)")
+ def envelopeCreation(ctx: TraceContextAware): Unit = {}
+
+ @After("envelopeCreation(ctx)")
+ def afterEnvelopeCreation(ctx: TraceContextAware): Unit = {
+ // Necessary to force the initialization of ContextAware at the moment of creation.
+ ctx.traceContext
+ }
+} \ No newline at end of file
diff --git a/kamon-core/src/main/scala/kamon/instrumentation/ActorLoggingTracing.scala b/kamon-core/src/main/scala/kamon/instrumentation/akka/ActorLoggingInstrumentation.scala
index 85d39d3e..ee9d442f 100644
--- a/kamon-core/src/main/scala/kamon/instrumentation/ActorLoggingTracing.scala
+++ b/kamon-core/src/main/scala/kamon/instrumentation/akka/ActorLoggingInstrumentation.scala
@@ -1,11 +1,11 @@
/*
* =========================================================================================
- * Copyright © 2013 the kamon project <http://kamon.io/>
+ * Copyright © 2013-2014 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
+ * 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,
@@ -14,14 +14,14 @@
* =========================================================================================
*/
-package kamon.instrumentation
+package akka.instrumentation
-import org.aspectj.lang.annotation._
-import org.aspectj.lang.ProceedingJoinPoint
import kamon.trace.{ TraceContextAware, TraceRecorder }
+import org.aspectj.lang.ProceedingJoinPoint
+import org.aspectj.lang.annotation._
@Aspect
-class ActorLoggingTracing {
+class ActorLoggingInstrumentation {
@DeclareMixin("akka.event.Logging.LogEvent+")
def mixinTraceContextAwareToLogEvent: TraceContextAware = TraceContextAware.default
diff --git a/kamon-core/src/main/scala/kamon/instrumentation/akka/ActorSystemMessageInstrumentation.scala b/kamon-core/src/main/scala/kamon/instrumentation/akka/ActorSystemMessageInstrumentation.scala
new file mode 100644
index 00000000..9b6b6866
--- /dev/null
+++ b/kamon-core/src/main/scala/kamon/instrumentation/akka/ActorSystemMessageInstrumentation.scala
@@ -0,0 +1,80 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 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 akka.instrumentation
+
+import akka.dispatch.sysmsg.EarliestFirstSystemMessageList
+import kamon.trace.{ TraceContextAware, TraceRecorder }
+import org.aspectj.lang.ProceedingJoinPoint
+import org.aspectj.lang.annotation._
+
+@Aspect
+class ActorSystemMessageInstrumentation {
+
+ @Pointcut("execution(* akka.actor.ActorCell.invokeAll$1(..)) && args(messages, *)")
+ def systemMessageProcessing(messages: EarliestFirstSystemMessageList): Unit = {}
+
+ @Around("systemMessageProcessing(messages)")
+ def aroundSystemMessageInvoke(pjp: ProceedingJoinPoint, messages: EarliestFirstSystemMessageList): Any = {
+ if (messages.nonEmpty) {
+ val ctx = messages.head.asInstanceOf[TraceContextAware].traceContext
+ TraceRecorder.withTraceContext(ctx)(pjp.proceed())
+
+ } else pjp.proceed()
+ }
+}
+
+@Aspect
+class TraceContextIntoSystemMessageMixin {
+
+ @DeclareMixin("akka.dispatch.sysmsg.SystemMessage+")
+ def mixinTraceContextAwareToSystemMessage: TraceContextAware = TraceContextAware.default
+
+ @Pointcut("execution(akka.dispatch.sysmsg.SystemMessage+.new(..)) && this(ctx)")
+ def envelopeCreation(ctx: TraceContextAware): Unit = {}
+
+ @After("envelopeCreation(ctx)")
+ def afterEnvelopeCreation(ctx: TraceContextAware): Unit = {
+ // Necessary to force the initialization of ContextAware at the moment of creation.
+ ctx.traceContext
+ }
+}
+
+@Aspect
+class TraceContextIntoRepointableActorRefMixin {
+
+ @DeclareMixin("akka.actor.RepointableActorRef")
+ def mixinTraceContextAwareToRepointableActorRef: TraceContextAware = TraceContextAware.default
+
+ @Pointcut("execution(akka.actor.RepointableActorRef.new(..)) && this(ctx)")
+ def envelopeCreation(ctx: TraceContextAware): Unit = {}
+
+ @After("envelopeCreation(ctx)")
+ def afterEnvelopeCreation(ctx: TraceContextAware): Unit = {
+ // Necessary to force the initialization of ContextAware at the moment of creation.
+ ctx.traceContext
+ }
+
+ @Pointcut("execution(* akka.actor.RepointableActorRef.point(..)) && this(repointableActorRef)")
+ def repointableActorRefCreation(repointableActorRef: TraceContextAware): Unit = {}
+
+ @Around("repointableActorRefCreation(repointableActorRef)")
+ def afterRepointableActorRefCreation(pjp: ProceedingJoinPoint, repointableActorRef: TraceContextAware): Any = {
+ TraceRecorder.withTraceContext(repointableActorRef.traceContext) {
+ pjp.proceed()
+ }
+ }
+} \ No newline at end of file
diff --git a/kamon-core/src/main/scala/kamon/instrumentation/akka/AskPatternInstrumentation.scala b/kamon-core/src/main/scala/kamon/instrumentation/akka/AskPatternInstrumentation.scala
new file mode 100644
index 00000000..3bf13ce2
--- /dev/null
+++ b/kamon-core/src/main/scala/kamon/instrumentation/akka/AskPatternInstrumentation.scala
@@ -0,0 +1,55 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 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 akka.instrumentation
+
+import akka.actor.ActorRefProvider
+import akka.event.Logging.Warning
+import akka.pattern.{ AskTimeoutException, PromiseActorRef }
+import kamon.Kamon
+import kamon.trace.Trace
+import org.aspectj.lang.annotation.{ AfterReturning, Aspect, Pointcut }
+
+import scala.compat.Platform.EOL
+
+@Aspect
+class AskPatternInstrumentation {
+
+ class StackTraceCaptureException extends Throwable
+
+ @Pointcut(value = "execution(* akka.pattern.PromiseActorRef$.apply(..)) && args(provider, *, *)", argNames = "provider")
+ def promiseActorRefApply(provider: ActorRefProvider): Unit = {}
+
+ @AfterReturning(pointcut = "promiseActorRefApply(provider)", returning = "promiseActor")
+ def hookAskTimeoutWarning(provider: ActorRefProvider, promiseActor: PromiseActorRef): Unit = {
+ val system = promiseActor.provider.guardian.underlying.system
+ val traceExtension = Kamon(Trace)(system)
+
+ if (traceExtension.enableAskPatternTracing) {
+ val future = promiseActor.result.future
+ implicit val ec = system.dispatcher
+ val stack = new StackTraceCaptureException
+
+ future onFailure {
+ case timeout: AskTimeoutException ⇒
+ val stackString = stack.getStackTrace.drop(3).mkString("", EOL, EOL)
+
+ system.eventStream.publish(Warning("AskPatternTracing", classOf[AskPatternInstrumentation],
+ "Timeout triggered for ask pattern registered at: " + stackString))
+ }
+ }
+ }
+}
diff --git a/kamon-core/src/main/scala/kamon/instrumentation/akka/DispatcherInstrumentation.scala b/kamon-core/src/main/scala/kamon/instrumentation/akka/DispatcherInstrumentation.scala
new file mode 100644
index 00000000..db366e8c
--- /dev/null
+++ b/kamon-core/src/main/scala/kamon/instrumentation/akka/DispatcherInstrumentation.scala
@@ -0,0 +1,163 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 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 akka.instrumentation
+
+import java.lang.reflect.Method
+import java.util.concurrent.ThreadPoolExecutor
+
+import akka.actor.{ ActorSystemImpl, Cancellable }
+import akka.dispatch.{ Dispatcher, Dispatchers, ExecutorServiceDelegate, MessageDispatcher }
+import akka.instrumentation.DispatcherMetricsCollector.DispatcherMetricsMeasurement
+import kamon.Kamon
+import kamon.metric.DispatcherMetrics.DispatcherMetricRecorder
+import kamon.metric.{ DispatcherMetrics, Metrics }
+import org.aspectj.lang.annotation._
+
+import scala.concurrent.forkjoin.ForkJoinPool
+
+@Aspect
+class DispatcherInstrumentation {
+
+ @Pointcut("execution(akka.dispatch.Dispatchers.new(..)) && this(dispatchers) && cflow(execution(akka.actor.ActorSystemImpl.new(..)) && this(system))")
+ def onActorSystemStartup(dispatchers: Dispatchers, system: ActorSystemImpl) = {}
+
+ @Before("onActorSystemStartup(dispatchers, system)")
+ def beforeActorSystemStartup(dispatchers: Dispatchers, system: ActorSystemImpl): Unit = {
+ val currentDispatchers = dispatchers.asInstanceOf[DispatchersWithActorSystem]
+ currentDispatchers.actorSystem = system
+ }
+
+ @Pointcut("execution(* akka.dispatch.Dispatchers.lookup(..)) && this(dispatchers)")
+ def onDispatchersLookup(dispatchers: Dispatchers) = {}
+
+ @AfterReturning(pointcut = "onDispatchersLookup(dispatchers)", returning = "dispatcher")
+ def afterReturningLookup(dispatchers: Dispatchers, dispatcher: Dispatcher): Unit = {
+ val dispatchersWithActorSystem = dispatchers.asInstanceOf[DispatchersWithActorSystem]
+ val dispatcherWithMetrics = dispatcher.asInstanceOf[DispatcherMetricCollectionInfo]
+
+ dispatcherWithMetrics.actorSystem = dispatchersWithActorSystem.actorSystem
+ }
+
+ @Pointcut("call(* akka.dispatch.ExecutorServiceFactory.createExecutorService(..))")
+ def onCreateExecutorService(): Unit = {}
+
+ @Pointcut("cflow((execution(* akka.dispatch.MessageDispatcher.registerForExecution(..)) || execution(* akka.dispatch.MessageDispatcher.executeTask(..))) && this(dispatcher))")
+ def onCflowMessageDispatcher(dispatcher: Dispatcher): Unit = {}
+
+ @Pointcut("onCreateExecutorService() && onCflowMessageDispatcher(dispatcher)")
+ def onDispatcherStartup(dispatcher: Dispatcher): Unit = {}
+
+ @After("onDispatcherStartup(dispatcher)")
+ def afterDispatcherStartup(dispatcher: MessageDispatcher): Unit = {
+
+ val dispatcherWithMetrics = dispatcher.asInstanceOf[DispatcherMetricCollectionInfo]
+ val metricsExtension = Kamon(Metrics)(dispatcherWithMetrics.actorSystem)
+ val metricIdentity = DispatcherMetrics(dispatcher.id)
+
+ dispatcherWithMetrics.metricIdentity = metricIdentity
+ dispatcherWithMetrics.dispatcherMetricsRecorder = metricsExtension.register(metricIdentity, DispatcherMetrics.Factory)
+
+ if (dispatcherWithMetrics.dispatcherMetricsRecorder.isDefined) {
+ dispatcherWithMetrics.dispatcherCollectorCancellable = metricsExtension.scheduleGaugeRecorder {
+ dispatcherWithMetrics.dispatcherMetricsRecorder.map {
+ dm ⇒
+ val DispatcherMetricsMeasurement(maximumPoolSize, runningThreadCount, queueTaskCount, poolSize) =
+ DispatcherMetricsCollector.collect(dispatcher)
+
+ dm.maximumPoolSize.record(maximumPoolSize)
+ dm.runningThreadCount.record(runningThreadCount)
+ dm.queueTaskCount.record(queueTaskCount)
+ dm.poolSize.record(poolSize)
+ }
+ }
+ }
+ }
+
+ @Pointcut("execution(* akka.dispatch.MessageDispatcher.shutdown(..)) && this(dispatcher)")
+ def onDispatcherShutdown(dispatcher: MessageDispatcher): Unit = {}
+
+ @After("onDispatcherShutdown(dispatcher)")
+ def afterDispatcherShutdown(dispatcher: MessageDispatcher): Unit = {
+ val dispatcherWithMetrics = dispatcher.asInstanceOf[DispatcherMetricCollectionInfo]
+
+ dispatcherWithMetrics.dispatcherMetricsRecorder.map {
+ dispatcher ⇒
+ dispatcherWithMetrics.dispatcherCollectorCancellable.cancel()
+ Kamon(Metrics)(dispatcherWithMetrics.actorSystem).unregister(dispatcherWithMetrics.metricIdentity)
+ }
+ }
+}
+
+@Aspect
+class DispatcherMetricCollectionInfoIntoDispatcherMixin {
+
+ @DeclareMixin("akka.dispatch.Dispatcher")
+ def mixinDispatcherMetricsToMessageDispatcher: DispatcherMetricCollectionInfo = new DispatcherMetricCollectionInfo {}
+
+ @DeclareMixin("akka.dispatch.Dispatchers")
+ def mixinDispatchersToDispatchersWithActorSystem: DispatchersWithActorSystem = new DispatchersWithActorSystem {}
+}
+
+trait DispatcherMetricCollectionInfo {
+ var metricIdentity: DispatcherMetrics = _
+ var dispatcherMetricsRecorder: Option[DispatcherMetricRecorder] = _
+ var dispatcherCollectorCancellable: Cancellable = _
+ var actorSystem: ActorSystemImpl = _
+}
+
+trait DispatchersWithActorSystem {
+ var actorSystem: ActorSystemImpl = _
+}
+
+object DispatcherMetricsCollector {
+
+ case class DispatcherMetricsMeasurement(maximumPoolSize: Long, runningThreadCount: Long, queueTaskCount: Long, poolSize: Long)
+
+ private def collectForkJoinMetrics(pool: ForkJoinPool): DispatcherMetricsMeasurement = {
+ DispatcherMetricsMeasurement(pool.getParallelism, pool.getActiveThreadCount,
+ (pool.getQueuedTaskCount + pool.getQueuedSubmissionCount), pool.getPoolSize)
+ }
+
+ private def collectExecutorMetrics(pool: ThreadPoolExecutor): DispatcherMetricsMeasurement = {
+ DispatcherMetricsMeasurement(pool.getMaximumPoolSize, pool.getActiveCount, pool.getQueue.size(), pool.getPoolSize)
+ }
+
+ private val executorServiceMethod: Method = {
+ // executorService is protected
+ val method = classOf[Dispatcher].getDeclaredMethod("executorService")
+ method.setAccessible(true)
+ method
+ }
+
+ def collect(dispatcher: MessageDispatcher): DispatcherMetricsMeasurement = {
+ dispatcher match {
+ case x: Dispatcher ⇒ {
+ val executor = executorServiceMethod.invoke(x) match {
+ case delegate: ExecutorServiceDelegate ⇒ delegate.executor
+ case other ⇒ other
+ }
+
+ executor match {
+ case fjp: ForkJoinPool ⇒ collectForkJoinMetrics(fjp)
+ case tpe: ThreadPoolExecutor ⇒ collectExecutorMetrics(tpe)
+ case anything ⇒ DispatcherMetricsMeasurement(0L, 0L, 0L, 0L)
+ }
+ }
+ case _ ⇒ new DispatcherMetricsMeasurement(0L, 0L, 0L, 0L)
+ }
+ }
+}
diff --git a/kamon-core/src/main/scala/kamon/instrumentation/hdrhistogram/AtomicHistogramFieldsAccessor.scala b/kamon-core/src/main/scala/kamon/instrumentation/hdrhistogram/AtomicHistogramFieldsAccessor.scala
new file mode 100644
index 00000000..e79090a8
--- /dev/null
+++ b/kamon-core/src/main/scala/kamon/instrumentation/hdrhistogram/AtomicHistogramFieldsAccessor.scala
@@ -0,0 +1,35 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 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 org.HdrHistogram
+
+import java.util.concurrent.atomic.{ AtomicLongArray, AtomicLongFieldUpdater }
+
+trait AtomicHistogramFieldsAccessor {
+ self: AtomicHistogram ⇒
+
+ def countsArray(): AtomicLongArray = self.counts
+
+ def unitMagnitude(): Int = self.unitMagnitude
+
+ def subBucketHalfCount(): Int = self.subBucketHalfCount
+
+ def subBucketHalfCountMagnitude(): Int = self.subBucketHalfCountMagnitude
+}
+
+object AtomicHistogramFieldsAccessor {
+ def totalCountUpdater(): AtomicLongFieldUpdater[AtomicHistogram] = AtomicHistogram.totalCountUpdater
+}
diff --git a/kamon-core/src/main/scala/kamon/instrumentation/FutureTracing.scala b/kamon-core/src/main/scala/kamon/instrumentation/scala/FutureInstrumentation.scala
index b9424579..bda2da78 100644
--- a/kamon-core/src/main/scala/kamon/instrumentation/FutureTracing.scala
+++ b/kamon-core/src/main/scala/kamon/instrumentation/scala/FutureInstrumentation.scala
@@ -1,26 +1,27 @@
-/* ===================================================
- * Copyright © 2013 the kamon project <http://kamon.io/>
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 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
+ * 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
+ * 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.instrumentation
+ * 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.instrumentation.scala
-import org.aspectj.lang.annotation._
-import org.aspectj.lang.ProceedingJoinPoint
import kamon.trace.{ TraceContextAware, TraceRecorder }
+import org.aspectj.lang.ProceedingJoinPoint
+import org.aspectj.lang.annotation._
@Aspect
-class FutureTracing {
+class FutureInstrumentation {
@DeclareMixin("scala.concurrent.impl.CallbackRunnable || scala.concurrent.impl.Future.PromiseCompletingRunnable")
def mixinTraceContextAwareToFutureRelatedRunnable: TraceContextAware = TraceContextAware.default