aboutsummaryrefslogblamecommitdiff
path: root/kamon-core/src/main/scala/kamon/metric/Metrics.scala
blob: b904ec565be78369c803865965d246b741158a5a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                                           

                    
                                    
                          
                           
                                                                                     
                                          
 
                
                                                   
 
                                                                                                      
                                                       
 
                                                     
                                               
 


                                               






                                                                                




                                                                                    

 




                        

                                                                                                                           


                                                                                                            



                                                                                       



                                                           

 

                                                                                                             
                 
                               
                                 
 
 



                         

 
                                                        
                                                                    
 
                                                                                                                                                                   
 




                                                                                       

 
 

                                                                                                                

                                                   

                                        
 


                                                                                   
 
                                                                                                        
 





                                                                                 



                                                  

                                                                                

 
                                                 
          
                                     



                                                                         
 

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

import java.util.concurrent.TimeUnit
import akka.actor.ActorRef
import com.codahale.metrics
import com.codahale.metrics.{ MetricFilter, Metric, ConsoleReporter, MetricRegistry }
import scala.collection.concurrent.TrieMap

object Metrics {
  val registry: MetricRegistry = new MetricRegistry

  val consoleReporter = ConsoleReporter.forRegistry(registry).convertDurationsTo(TimeUnit.NANOSECONDS)
  //consoleReporter.build().start(45, TimeUnit.SECONDS)

  //val newrelicReporter = NewRelicReporter(registry)
  //newrelicReporter.start(5, TimeUnit.SECONDS)

  def include(name: String, metric: Metric) = {
    //registry.register(name, metric)
  }

  def exclude(name: String) = {
    registry.removeMatching(new MetricFilter {
      def matches(name: String, metric: Metric): Boolean = name.startsWith(name)
    })
  }

  def deregister(fullName: String) = {
    registry.removeMatching(new MetricFilter {
      def matches(name: String, metric: Metric): Boolean = name.startsWith(fullName)
    })
  }
}

object Watched {
  case object Actor
  case object Dispatcher
}

object MetricDirectory {
  def nameForDispatcher(actorSystem: String, dispatcher: String) = s"/ActorSystem/${actorSystem}/Dispatcher/${dispatcher}/"

  def nameForMailbox(actorSystem: String, actor: String) = s"/ActorSystem/$actorSystem/Actor/$actor/Mailbox"

  def nameForActor(actorRef: ActorRef) = actorRef.path.elements.mkString("/")

  def shouldInstrument(actorSystem: String): Boolean = !actorSystem.startsWith("kamon")

  def shouldInstrumentActor(actorPath: String): Boolean = {
    !(actorPath.isEmpty || actorPath.startsWith("system"))
  }

}

case class DispatcherMetricCollector(activeThreadCount: Histogram, poolSize: Histogram, queueSize: Histogram)

trait Histogram {
  def update(value: Long): Unit
  def snapshot: HistogramSnapshot
}

trait HistogramSnapshot {
  def median: Double
  def max: Double
  def min: Double
}

case class ActorSystemMetrics(actorSystemName: String) {
  val dispatchers = TrieMap.empty[String, DispatcherMetricCollector]

  private[this] def createDispatcherCollector: DispatcherMetricCollector = DispatcherMetricCollector(CodahaleHistogram(), CodahaleHistogram(), CodahaleHistogram())

  def registerDispatcher(dispatcherName: String): Option[DispatcherMetricCollector] = {
    val stats = createDispatcherCollector
    dispatchers.put(dispatcherName, stats)
    Some(stats)
  }

}

case class CodahaleHistogram() extends Histogram {
  private[this] val histogram = new com.codahale.metrics.Histogram(new metrics.ExponentiallyDecayingReservoir())

  def update(value: Long) = histogram.update(value)
  def snapshot: HistogramSnapshot = {
    val snapshot = histogram.getSnapshot

    CodahaleHistogramSnapshot(snapshot.getMedian, snapshot.getMax, snapshot.getMin)
  }
}

case class CodahaleHistogramSnapshot(median: Double, max: Double, min: Double) extends HistogramSnapshot

/**
 *  Dispatcher Metrics that we care about currently with a histogram-like nature:
 *    - Work Queue Size
 *    - Total/Active Thread Count
 */

import annotation.tailrec
import java.util.concurrent.atomic.AtomicReference

object Atomic {
  def apply[T](obj: T) = new Atomic(new AtomicReference(obj))
  implicit def toAtomic[T](ref: AtomicReference[T]): Atomic[T] = new Atomic(ref)
}

class Atomic[T](val atomic: AtomicReference[T]) {
  @tailrec
  final def update(f: T  T): T = {
    val oldValue = atomic.get()
    val newValue = f(oldValue)
    if (atomic.compareAndSet(oldValue, newValue)) newValue else update(f)
  }

  def get() = atomic.get()
}