aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kamon-core-tests/src/test/scala/kamon/trace/LocalSpanSpec.scala2
-rw-r--r--kamon-core-tests/src/test/scala/kamon/trace/SpanMetrics.scala31
-rw-r--r--kamon-core/src/main/scala/kamon/trace/Span.scala38
3 files changed, 58 insertions, 13 deletions
diff --git a/kamon-core-tests/src/test/scala/kamon/trace/LocalSpanSpec.scala b/kamon-core-tests/src/test/scala/kamon/trace/LocalSpanSpec.scala
index 966fdbad..05c1c53a 100644
--- a/kamon-core-tests/src/test/scala/kamon/trace/LocalSpanSpec.scala
+++ b/kamon-core-tests/src/test/scala/kamon/trace/LocalSpanSpec.scala
@@ -44,7 +44,7 @@ class LocalSpanSpec extends WordSpec with Matchers with BeforeAndAfterAll with E
}
}
- "pass all the tags, annotations and baggage to the FinishedSpan instance when started and finished" in {
+ "pass all the tags to the FinishedSpan instance when started and finished" in {
Kamon.buildSpan("full-span")
.withTag("builder-string-tag", "value")
.withTag("builder-boolean-tag-true", true)
diff --git a/kamon-core-tests/src/test/scala/kamon/trace/SpanMetrics.scala b/kamon-core-tests/src/test/scala/kamon/trace/SpanMetrics.scala
index 40813a25..4425ac92 100644
--- a/kamon-core-tests/src/test/scala/kamon/trace/SpanMetrics.scala
+++ b/kamon-core-tests/src/test/scala/kamon/trace/SpanMetrics.scala
@@ -19,6 +19,8 @@ import kamon.Kamon.buildSpan
import kamon.testkit.{MetricInspection, Reconfigure}
import org.scalatest.{Matchers, WordSpecLike}
+import scala.util.control.NoStackTrace
+
class SpanMetrics extends WordSpecLike with Matchers with MetricInspection with Reconfigure {
sampleAlways()
@@ -46,14 +48,19 @@ class SpanMetrics extends WordSpecLike with Matchers with MetricInspection with
buildSpan(operation)
.start()
- .addTag("error", true)
+ .addError("Terrible Error")
+ .finish()
+
+ buildSpan(operation)
+ .start()
+ .addError("Terrible Error with Throwable", new Throwable with NoStackTrace)
.finish()
val histogram = Span.Metrics.ProcessingTime.refine(Map(operationTag, noErrorTag))
histogram.distribution().count shouldBe 0
val errorHistogram = Span.Metrics.ProcessingTime.refine(Map(operationTag, errorTag))
- errorHistogram.distribution().count shouldBe 1
+ errorHistogram.distribution().count shouldBe 2
}
"add a parentOperation tag to the metrics if span metrics scoping is enabled" in {
@@ -66,20 +73,25 @@ class SpanMetrics extends WordSpecLike with Matchers with MetricInspection with
buildSpan(operation)
.asChildOf(parent)
.start()
- .addTag("error", false)
.finish()
buildSpan(operation)
.asChildOf(parent)
.start()
- .addTag("error", true)
+ .addError("Terrible Error")
+ .finish()
+
+ buildSpan(operation)
+ .asChildOf(parent)
+ .start()
+ .addError("Terrible Error with Throwable", new Throwable with NoStackTrace)
.finish()
val histogram = Span.Metrics.ProcessingTime.refine(Map(operationTag, noErrorTag, parentOperationTag))
histogram.distribution().count shouldBe 1
val errorHistogram = Span.Metrics.ProcessingTime.refine(Map(operationTag, errorTag, parentOperationTag))
- errorHistogram.distribution().count shouldBe 1
+ errorHistogram.distribution().count shouldBe 2
}
"not add any parentOperation tag to the metrics if span metrics scoping is disabled" in withoutSpanScopingEnabled {
@@ -92,13 +104,18 @@ class SpanMetrics extends WordSpecLike with Matchers with MetricInspection with
buildSpan(operation)
.asChildOf(parent)
.start()
- .addTag("error", false)
.finish()
buildSpan(operation)
.asChildOf(parent)
.start()
- .addTag("error", true)
+ .addError("Terrible Error")
+ .finish()
+
+ buildSpan(operation)
+ .asChildOf(parent)
+ .start()
+ .addError("Terrible Error with Throwable", new Throwable with NoStackTrace)
.finish()
val histogram = Span.Metrics.ProcessingTime.refine(Map(operationTag, noErrorTag, parentOperationTag))
diff --git a/kamon-core/src/main/scala/kamon/trace/Span.scala b/kamon-core/src/main/scala/kamon/trace/Span.scala
index cb1be8dc..dcaf0a84 100644
--- a/kamon-core/src/main/scala/kamon/trace/Span.scala
+++ b/kamon-core/src/main/scala/kamon/trace/Span.scala
@@ -41,6 +41,10 @@ trait Span {
def addMetricTag(key: String, value: String): Span
+ def addError(error: String): Span
+
+ def addError(error: String, throwable: Throwable): Span
+
def setOperationName(name: String): Span
def disableMetricsCollection(): Span
@@ -64,6 +68,8 @@ object Span {
override def addTag(key: String, value: Long): Span = this
override def addTag(key: String, value: Boolean): Span = this
override def addMetricTag(key: String, value: String): Span = this
+ override def addError(error: String): Span = this
+ override def addError(error: String, throwable: Throwable): Span = this
override def setOperationName(name: String): Span = this
override def disableMetricsCollection(): Span = this
override def finish(finishTimestampMicros: Long): Unit = {}
@@ -83,6 +89,7 @@ object Span {
private var collectMetrics: Boolean = true
private var open: Boolean = true
private val sampled: Boolean = spanContext.samplingDecision == SamplingDecision.Sample
+ private var hasError: Boolean = false
private var operationName: String = initialOperationName
private var spanTags: Map[String, Span.TagValue] = initialSpanTags
@@ -121,6 +128,28 @@ object Span {
this
}
+ override def addError(error: String): Span = synchronized {
+ if(sampled && open) {
+ hasError = true
+ spanTags = spanTags ++ Map(
+ "error" -> TagValue.True,
+ "error.object" -> TagValue.String(error)
+ )
+ }
+ this
+ }
+
+ override def addError(error: String, throwable: Throwable): Span = synchronized {
+ if(sampled && open) {
+ hasError = true
+ spanTags = spanTags ++ Map(
+ "error" -> TagValue.True,
+ "error.object" -> TagValue.String(throwable.getMessage())
+ )
+ }
+ this
+ }
+
override def disableMetricsCollection(): Span = synchronized {
collectMetrics = false
this
@@ -152,17 +181,14 @@ object Span {
private def recordSpanMetrics(endTimestampMicros: Long): Unit = {
val elapsedTime = endTimestampMicros - startTimestampMicros
- val isError = spanTags.get("error").map {
- case boolean: TagValue.Boolean => boolean.text
- case _ => TagValue.False.text
- } getOrElse(TagValue.False.text)
+ val isErrorText = if(hasError) TagValue.True.text else TagValue.False.text
if(scopeSpanMetrics)
parent.foreach(parentSpan => customMetricTags = customMetricTags + ("parentOperation" -> parentSpan.asInstanceOf[Local].operationName))
val metricTags = Map(
"operation" -> operationName,
- "error" -> isError
+ "error" -> isErrorText
) ++ customMetricTags
Span.Metrics.ProcessingTime.refine(metricTags).record(elapsedTime)
@@ -184,6 +210,8 @@ object Span {
override def addTag(key: String, value: Long): Span = this
override def addTag(key: String, value: Boolean): Span = this
override def addMetricTag(key: String, value: String): Span = this
+ override def addError(error: String): Span = this
+ override def addError(error: String, throwable: Throwable): Span = this
override def setOperationName(name: String): Span = this
override def disableMetricsCollection(): Span = this
override def finish(finishTimestampMicros: Long): Unit = {}