Skip to content

Commit

Permalink
Merge branch 'wip/newrelic-agent-rewrite'
Browse files Browse the repository at this point in the history
  • Loading branch information
ivantopo committed Nov 9, 2014
2 parents 5681a09 + 0111794 commit 6adfad4
Show file tree
Hide file tree
Showing 24 changed files with 670 additions and 399 deletions.
6 changes: 4 additions & 2 deletions kamon-core/src/main/scala/kamon/http/HttpServerMetrics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import kamon.metric._
import scala.collection.concurrent.TrieMap

object HttpServerMetrics extends MetricGroupIdentity {
import Metrics.AtomicGetOrElseUpdateForTriemap

val name: String = "http-server-metrics-recorder"
val category = new MetricGroupCategory {
val name: String = "http-server"
Expand All @@ -32,13 +34,13 @@ object HttpServerMetrics extends MetricGroupIdentity {
def recordResponse(statusCode: StatusCode): Unit = recordResponse(statusCode, 1L)

def recordResponse(statusCode: StatusCode, count: Long): Unit =
counters.getOrElseUpdate(statusCode, Counter()).increment(count)
counters.atomicGetOrElseUpdate(statusCode, Counter()).increment(count)

def recordResponse(traceName: TraceName, statusCode: StatusCode): Unit = recordResponse(traceName, statusCode, 1L)

def recordResponse(traceName: TraceName, statusCode: StatusCode, count: Long): Unit = {
recordResponse(statusCode, count)
countersPerTrace.getOrElseUpdate(traceName, TrieMap()).getOrElseUpdate(statusCode, Counter()).increment(count)
countersPerTrace.atomicGetOrElseUpdate(traceName, TrieMap()).atomicGetOrElseUpdate(statusCode, Counter()).increment(count)
}

def collect(context: CollectionContext): HttpServerMetricsSnapshot = {
Expand Down
12 changes: 11 additions & 1 deletion kamon-core/src/main/scala/kamon/metric/MetricsExtension.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import kamon.metric.Subscriptions.{ Unsubscribe, Subscribe }
import java.util.concurrent.TimeUnit

class MetricsExtension(system: ExtendedActorSystem) extends Kamon.Extension {
import Metrics.AtomicGetOrElseUpdateForTriemap

val metricsExtConfig = system.settings.config.getConfig("kamon.metrics")
printInitializationMessage(system.eventStream, metricsExtConfig.getBoolean("disable-aspectj-weaver-missing-error"))

Expand All @@ -46,7 +48,7 @@ class MetricsExtension(system: ExtendedActorSystem) extends Kamon.Extension {

def register(identity: MetricGroupIdentity, factory: MetricGroupFactory): Option[factory.GroupRecorder] = {
if (shouldTrack(identity))
Some(storage.getOrElseUpdate(identity, factory.create(metricsExtConfig, system)).asInstanceOf[factory.GroupRecorder])
Some(storage.atomicGetOrElseUpdate(identity, factory.create(metricsExtConfig, system)).asInstanceOf[factory.GroupRecorder])
else
None
}
Expand Down Expand Up @@ -131,4 +133,12 @@ object Metrics extends ExtensionId[MetricsExtension] with ExtensionIdProvider {
case class MetricGroupFilter(includes: List[GlobPathFilter], excludes: List[GlobPathFilter]) {
def accept(name: String): Boolean = includes.exists(_.accept(name)) && !excludes.exists(_.accept(name))
}

implicit class AtomicGetOrElseUpdateForTriemap[K, V](trieMap: TrieMap[K, V]) {
def atomicGetOrElseUpdate(key: K, op: V): V =
trieMap.get(key) match {
case Some(v) v
case None val d = op; trieMap.putIfAbsent(key, d).getOrElse(d)
}
}
}
7 changes: 4 additions & 3 deletions kamon-core/src/main/scala/kamon/metric/TraceMetrics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ case class TraceMetrics(name: String) extends MetricGroupIdentity {
}

object TraceMetrics extends MetricGroupCategory {
import Metrics.AtomicGetOrElseUpdateForTriemap

val name = "trace"

case object ElapsedTime extends MetricIdentity { val name = "elapsed-time" }
Expand All @@ -37,7 +39,7 @@ object TraceMetrics extends MetricGroupCategory {
val segments = TrieMap[MetricIdentity, Histogram]()

def segmentRecorder(segmentIdentity: MetricIdentity): Histogram =
segments.getOrElseUpdate(segmentIdentity, segmentRecorderFactory.apply())
segments.atomicGetOrElseUpdate(segmentIdentity, segmentRecorderFactory.apply())

def collect(context: CollectionContext): TraceMetricsSnapshot =
TraceMetricsSnapshot(
Expand All @@ -53,7 +55,7 @@ object TraceMetrics extends MetricGroupCategory {
type GroupSnapshotType = TraceMetricsSnapshot

def merge(that: TraceMetricsSnapshot, context: CollectionContext): TraceMetricsSnapshot =
TraceMetricsSnapshot(elapsedTime.merge(that.elapsedTime, context), Map.empty) // TODO: Merge the segments metrics correctly and test it!
TraceMetricsSnapshot(elapsedTime.merge(that.elapsedTime, context), combineMaps(segments, that.segments)((l, r) l.merge(r, context)))

def metrics: Map[MetricIdentity, MetricSnapshot] = segments + (ElapsedTime -> elapsedTime)
}
Expand All @@ -69,7 +71,6 @@ case object TraceMetricGroupFactory extends MetricGroupFactory {
type GroupRecorder = TraceMetricRecorder

def create(config: Config, system: ActorSystem): TraceMetricRecorder = {

val settings = config.getConfig("precision.trace")
val elapsedTimeConfig = settings.getConfig("elapsed-time")
val segmentConfig = settings.getConfig("segment")
Expand Down
15 changes: 8 additions & 7 deletions kamon-core/src/main/scala/kamon/metric/UserMetrics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import kamon.metric.instrument.{ Gauge, MinMaxCounter, Counter, Histogram }
import scala.concurrent.duration.FiniteDuration

class UserMetricsExtension(system: ExtendedActorSystem) extends Kamon.Extension {
import Metrics.AtomicGetOrElseUpdateForTriemap
import UserMetrics._

lazy val metricsExtension = Kamon(Metrics)(system)
Expand All @@ -18,45 +19,45 @@ class UserMetricsExtension(system: ExtendedActorSystem) extends Kamon.Extension
val defaultGaugePrecisionConfig = precisionConfig.getConfig("default-gauge-precision")

def registerHistogram(name: String, precision: Histogram.Precision, highestTrackableValue: Long): Histogram = {
metricsExtension.storage.getOrElseUpdate(UserHistogram(name), {
metricsExtension.storage.atomicGetOrElseUpdate(UserHistogram(name), {
UserHistogramRecorder(Histogram(highestTrackableValue, precision, Scale.Unit))
}).asInstanceOf[UserHistogramRecorder].histogram
}

def registerHistogram(name: String): Histogram = {
metricsExtension.storage.getOrElseUpdate(UserHistogram(name), {
metricsExtension.storage.atomicGetOrElseUpdate(UserHistogram(name), {
UserHistogramRecorder(Histogram.fromConfig(defaultHistogramPrecisionConfig))
}).asInstanceOf[UserHistogramRecorder].histogram
}

def registerCounter(name: String): Counter = {
metricsExtension.storage.getOrElseUpdate(UserCounter(name), {
metricsExtension.storage.atomicGetOrElseUpdate(UserCounter(name), {
UserCounterRecorder(Counter())
}).asInstanceOf[UserCounterRecorder].counter
}

def registerMinMaxCounter(name: String, precision: Histogram.Precision, highestTrackableValue: Long,
refreshInterval: FiniteDuration): MinMaxCounter = {
metricsExtension.storage.getOrElseUpdate(UserMinMaxCounter(name), {
metricsExtension.storage.atomicGetOrElseUpdate(UserMinMaxCounter(name), {
UserMinMaxCounterRecorder(MinMaxCounter(highestTrackableValue, precision, Scale.Unit, refreshInterval, system))
}).asInstanceOf[UserMinMaxCounterRecorder].minMaxCounter
}

def registerMinMaxCounter(name: String): MinMaxCounter = {
metricsExtension.storage.getOrElseUpdate(UserMinMaxCounter(name), {
metricsExtension.storage.atomicGetOrElseUpdate(UserMinMaxCounter(name), {
UserMinMaxCounterRecorder(MinMaxCounter.fromConfig(defaultMinMaxCounterPrecisionConfig, system))
}).asInstanceOf[UserMinMaxCounterRecorder].minMaxCounter
}

def registerGauge(name: String)(currentValueCollector: Gauge.CurrentValueCollector): Gauge = {
metricsExtension.storage.getOrElseUpdate(UserGauge(name), {
metricsExtension.storage.atomicGetOrElseUpdate(UserGauge(name), {
UserGaugeRecorder(Gauge.fromConfig(defaultGaugePrecisionConfig, system)(currentValueCollector))
}).asInstanceOf[UserGaugeRecorder].gauge
}

def registerGauge(name: String, precision: Histogram.Precision, highestTrackableValue: Long,
refreshInterval: FiniteDuration)(currentValueCollector: Gauge.CurrentValueCollector): Gauge = {
metricsExtension.storage.getOrElseUpdate(UserGauge(name), {
metricsExtension.storage.atomicGetOrElseUpdate(UserGauge(name), {
UserGaugeRecorder(Gauge(precision, highestTrackableValue, Scale.Unit, refreshInterval, system)(currentValueCollector))
}).asInstanceOf[UserGaugeRecorder].gauge
}
Expand Down
3 changes: 2 additions & 1 deletion kamon-core/src/main/scala/kamon/trace/TraceContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ sealed trait TraceContext {
def finish(): Unit
def origin: TraceContextOrigin
def isOpen: Boolean
def isClosed: Boolean = !isOpen
def isEmpty: Boolean
def nonEmpty: Boolean = !isEmpty
def startSegment(segmentName: String, label: String): Segment
Expand Down Expand Up @@ -111,7 +112,7 @@ class DefaultTraceContext(traceName: String, val token: String, izOpen: Boolean,
private def finishSegment(segmentName: String, label: String, duration: Long): Unit = {
finishedSegments.add(SegmentData(SegmentMetricIdentity(segmentName, label), duration))

if (!_isOpen) {
if (isClosed) {
metricsExtension.register(TraceMetrics(name), TraceMetrics.Factory).map { traceMetrics
drainFinishedSegments(traceMetrics)
}
Expand Down
11 changes: 8 additions & 3 deletions kamon-core/src/test/scala/kamon/metric/ActorMetricsSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,18 @@ class ActorMetricsSpec extends TestKitBase with WordSpecLike with Matchers with
| }
| }
| ]
| precision {
| default-histogram-precision {
| precision.actor {
| processing-time {
| highest-trackable-value = 3600000000000
| significant-value-digits = 2
| }
|
| default-min-max-counter-precision {
| time-in-mailbox {
| highest-trackable-value = 3600000000000
| significant-value-digits = 2
| }
|
| mailbox-size {
| refresh-interval = 1 hour
| highest-trackable-value = 999999999
| significant-value-digits = 2
Expand Down
13 changes: 9 additions & 4 deletions kamon-newrelic/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@

kamon {
newrelic {

# General ApdexT that applies to all Trace metrics reported.
apdexT = 1 second

# The application name that will be shown in the New Relic dashboard.
app-name = "Kamon[Development]"
license-key = e7d350b14228f3d28f35bc3140df2c3e565ea5d5

# delay between connection attempts to NewRelic collector
retry-delay = 30 seconds
# Your New Relic license key.
license-key = e7d350b14228f3d28f35bc3140df2c3e565ea5d5

# attempts to send pending metrics in the next tick,
# combining the current metrics plus the pending, after max-retry, deletes all pending metrics
max-retry = 3
max-initialize-retries = 3

# delay between connection attempts to NewRelic collector
initialize-retry-delay = 30 seconds
}
}

Expand Down
Loading

0 comments on commit 6adfad4

Please sign in to comment.