Skip to content

Commit

Permalink
+ core: include Tags and Status in TraceInfo and SegmentInfo and closes
Browse files Browse the repository at this point in the history
  • Loading branch information
dpsoft committed Jul 27, 2016
1 parent b4bd658 commit 3a57f32
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 9 deletions.
Expand Up @@ -61,7 +61,7 @@ private[kamon] class MetricsOnlyContext(traceName: String,
_elapsedTime = traceElapsedTime

if (Kamon.metrics.shouldTrack(name, TraceMetrics.category)) {
val traceEntity = Kamon.metrics.entity(TraceMetrics, name)
val traceEntity = Kamon.metrics.entity(TraceMetrics, name, _tags.toMap)
traceEntity.elapsedTime.record(traceElapsedTime.nanos)
if (withError) traceEntity.errors.increment()
}
Expand Down Expand Up @@ -125,7 +125,7 @@ private[kamon] class MetricsOnlyContext(traceName: String,
segmentTags: Map[String, String]) extends Segment {

private val _startTimestamp = RelativeNanoTimestamp.now
protected val _tags = TrieMap.empty[String, String] ++= segmentTags
private val _tags = TrieMap.empty[String, String] ++= segmentTags

@volatile private var _segmentName = segmentName
@volatile private var _elapsedTime = NanoInterval.default
Expand Down
2 changes: 0 additions & 2 deletions kamon-core/src/main/scala/kamon/trace/TraceContext.scala
Expand Up @@ -110,9 +110,7 @@ case object EmptyTraceContext extends TraceContext {
def startSegment(segmentName: String, category: String, library: String, tags: Map[String, String]): Segment = EmptySegment
def addMetadata(key: String, value: String): Unit = {}
def startTimestamp = new RelativeNanoTimestamp(0L)
def addTags(tags: Map[String, String]): Unit = {}
def addTag(key: String, value: String): Unit = {}
def removeTags(tags: Map[String, String]): Unit = {}
def removeTag(key: String, value: String): Boolean = false

case object EmptySegment extends Segment {
Expand Down
4 changes: 2 additions & 2 deletions kamon-core/src/main/scala/kamon/trace/TracerModule.scala
Expand Up @@ -194,5 +194,5 @@ private[kamon] object TracerModuleImpl {
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], tags: Map[String, String])
case class TraceInfo(name: String, token: String, timestamp: NanoTimestamp, elapsedTime: NanoInterval, metadata: Map[String, String], tags: Map[String, String], segments: List[SegmentInfo], status: Status)
case class SegmentInfo(name: String, category: String, library: String, timestamp: NanoTimestamp, elapsedTime: NanoInterval, metadata: Map[String, String], tags: Map[String, String], status: Status)
11 changes: 8 additions & 3 deletions kamon-core/src/main/scala/kamon/trace/TracingContext.scala
@@ -1,6 +1,6 @@
/*
* =========================================================================================
* Copyright © 2013-2014 the kamon project <http://kamon.io/>
* Copyright © 2013-2016 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
Expand Down Expand Up @@ -57,6 +57,11 @@ private[trace] class TracingContext(traceName: String,
traceInfoSink(this)
}

override def finishWithError(cause: Throwable): Unit = {
super.finishWithError(cause)
traceInfoSink(this)
}

override def finishSegment(segmentName: String, category: String, library: String, duration: NanoInterval, tags: Map[String, String], isFinishedWithError: Boolean = false): Unit = {
_openSegments.decrementAndGet()
super.finishSegment(segmentName, category, library, duration, tags, isFinishedWithError)
Expand All @@ -79,7 +84,7 @@ private[trace] class TracingContext(traceName: String,
log.warning("Segment [{}] will be left out of TraceInfo because it was still open.", segment.name)
}

TraceInfo(name, token, _startTimestamp, elapsedTime, _metadata.toMap, segmentsInfo.result())
TraceInfo(name, token, _startTimestamp, elapsedTime, _metadata.toMap, tags, segmentsInfo.result(), status)
}

class TracingSegment(segmentName: String,
Expand All @@ -98,7 +103,7 @@ private[trace] class TracingContext(traceName: String,
// expensive and inaccurate, but we can do that once for the trace and calculate all the segments relative to it.
val segmentStartTimestamp = new NanoTimestamp((this.startTimestamp.nanos - traceRelativeTimestamp.nanos) + traceStartTimestamp.nanos)

SegmentInfo(this.name, category, library, segmentStartTimestamp, this.elapsedTime, metadata.toMap, _tags.toMap)
SegmentInfo(this.name, category, library, segmentStartTimestamp, this.elapsedTime, metadata.toMap, tags, status)
}
}
}
69 changes: 69 additions & 0 deletions kamon-core/src/test/scala/kamon/trace/SimpleTraceSpec.scala
Expand Up @@ -20,6 +20,7 @@ import kamon.Kamon
import kamon.testkit.BaseKamonSpec

import scala.concurrent.duration._
import scala.util.control.NoStackTrace

class SimpleTraceSpec extends BaseKamonSpec("simple-trace-spec") {

Expand All @@ -42,6 +43,71 @@ class SimpleTraceSpec extends BaseKamonSpec("simple-trace-spec") {
traceInfo.segments.find(_.name == "segment-two") should be('defined)
}

"send a TraceInfo when the trace has finished with error and all segments are finished" in {
Kamon.tracer.subscribe(testActor)

Tracer.withContext(newContext("simple-trace-with-error-and-without-segments")) {
Tracer.currentContext.startSegment("segment-one", "test-segment", "test").finish()
Tracer.currentContext.startSegment("segment-two", "test-segment", "test").finish()
Tracer.currentContext.finishWithError(TraceException("awesome-trace-error"))
}

val traceInfo = expectMsgType[TraceInfo]
Kamon.tracer.unsubscribe(testActor)

traceInfo.name should be("simple-trace-with-error-and-without-segments")
traceInfo.status should be(Status.FinishedWithError)
traceInfo.segments.size should be(2)
traceInfo.segments.find(_.name == "segment-one") should be('defined)
traceInfo.segments.find(_.name == "segment-two") should be('defined)
}

"send a TraceInfo when the trace has finished with error and all segments are finished with error" in {
Kamon.tracer.subscribe(testActor)

Tracer.withContext(newContext("simple-trace-with-error-and-without-segments")) {
Tracer.currentContext.startSegment("segment-one-finished-with-error", "test-segment", "test").finishWithError(SegmentException("awesome-segment-exception"))
Tracer.currentContext.startSegment("segment-two-finished-with-error", "test-segment", "test").finishWithError(SegmentException("awesome-segment-exception"))
Tracer.currentContext.finishWithError(TraceException("awesome-trace-error"))
}

val traceInfo = expectMsgType[TraceInfo]
Kamon.tracer.unsubscribe(testActor)

traceInfo.name should be("simple-trace-with-error-and-without-segments")
traceInfo.status should be(Status.FinishedWithError)
traceInfo.segments.size should be(2)

val segmentOne = traceInfo.segments.find(_.name == "segment-one-finished-with-error")
val segmentTwo = traceInfo.segments.find(_.name == "segment-two-finished-with-error")

segmentOne.get.status should be(Status.FinishedWithError)
segmentTwo.get.status should be(Status.FinishedWithError)
}

"send a TraceInfo when the trace has finished and all segments are finished and both contains tags" in {
Kamon.tracer.subscribe(testActor)

Tracer.withContext(newContext("simple-trace-without-segments", "awesome-token", Map("environment" -> "production"))) {
Tracer.currentContext.startSegment("segment-one", "test-segment", "test", Map("segment-one-info" -> "info")).finish()
Tracer.currentContext.startSegment("segment-two", "test-segment", "test", Map("segment-two-info" -> "info")).finish()
Tracer.currentContext.finish()
}

val traceInfo = expectMsgType[TraceInfo]
Kamon.tracer.unsubscribe(testActor)

traceInfo.name should be("simple-trace-without-segments")
traceInfo.tags should be(Map("environment" -> "production"))
traceInfo.segments.size should be(2)

val segmentOne = traceInfo.segments.find(_.name == "segment-one")
val segmentTwo = traceInfo.segments.find(_.name == "segment-two")

segmentOne.get.tags should be(Map("segment-one-info" -> "info"))
segmentTwo.get.tags should be(Map("segment-two-info" -> "info"))
}

"incubate the tracing context if there are open segments after finishing" in {
Kamon.tracer.subscribe(testActor)

Expand All @@ -68,3 +134,6 @@ class SimpleTraceSpec extends BaseKamonSpec("simple-trace-spec") {

}
}

case class TraceException(message: String) extends RuntimeException(message) with NoStackTrace
case class SegmentException(message: String) extends RuntimeException(message) with NoStackTrace

0 comments on commit 3a57f32

Please sign in to comment.