From 30ec5adec206f82367020de74e79cd2aa124bf9b Mon Sep 17 00:00:00 2001 From: Ivan Topolnjak Date: Sun, 15 Feb 2015 11:16:21 +0100 Subject: ! core: move the TraceContext manipulation API to the Tracer companion object. --- .../src/main/scala/kamon/trace/TraceContext.scala | 37 +++++------------- .../src/main/scala/kamon/trace/TraceLocal.scala | 4 +- kamon-core/src/main/scala/kamon/trace/Tracer.scala | 22 +++++++++++ .../trace/logging/LogbackTraceTokenConverter.scala | 12 ++---- .../scala/kamon/trace/logging/MdcKeysSupport.scala | 4 +- .../test/scala/kamon/metric/TraceMetricsSpec.scala | 18 ++++----- .../test/scala/kamon/trace/SimpleTraceSpec.scala | 16 ++++---- .../kamon/trace/TraceContextManipulationSpec.scala | 44 +++++++++++----------- .../test/scala/kamon/trace/TraceLocalSpec.scala | 14 +++---- 9 files changed, 85 insertions(+), 86 deletions(-) (limited to 'kamon-core') diff --git a/kamon-core/src/main/scala/kamon/trace/TraceContext.scala b/kamon-core/src/main/scala/kamon/trace/TraceContext.scala index 48e56153..613e97e6 100644 --- a/kamon-core/src/main/scala/kamon/trace/TraceContext.scala +++ b/kamon-core/src/main/scala/kamon/trace/TraceContext.scala @@ -17,6 +17,7 @@ package kamon.trace import java.io.ObjectStreamException +import java.util.function.Function import kamon.trace.TraceContextAware.DefaultTraceContextAware import kamon.util.RelativeNanoTimestamp @@ -35,36 +36,16 @@ trait TraceContext { def addMetadata(key: String, value: String) def startTimestamp: RelativeNanoTimestamp -} - -object TraceContext { - private[kamon] val _traceContextStorage = new ThreadLocal[TraceContext] { - override def initialValue(): TraceContext = EmptyTraceContext - } - - def currentContext: TraceContext = - _traceContextStorage.get() - - def setCurrentContext(context: TraceContext): Unit = - _traceContextStorage.set(context) - - def clearCurrentContext: Unit = - _traceContextStorage.remove() - def withContext[T](context: TraceContext)(code: ⇒ T): T = { - val oldContext = _traceContextStorage.get() - _traceContextStorage.set(context) - - try code finally _traceContextStorage.set(oldContext) - } - - def map[T](f: TraceContext ⇒ T): Option[T] = { - val current = currentContext - if (current.nonEmpty) - Some(f(current)) + def collect[T](f: TraceContext ⇒ T): Option[T] = + if (nonEmpty) + Some(f(this)) else None - } + def collect[T](f: Function[TraceContext, T]): Option[T] = + if (nonEmpty) + Some(f(this)) + else None } trait Segment { @@ -132,7 +113,7 @@ object TraceContextAware { def default: TraceContextAware = new DefaultTraceContextAware class DefaultTraceContextAware extends TraceContextAware { - @transient val traceContext = TraceContext.currentContext + @transient val traceContext = Tracer.currentContext // // Beware of this hack, it might bite us in the future! diff --git a/kamon-core/src/main/scala/kamon/trace/TraceLocal.scala b/kamon-core/src/main/scala/kamon/trace/TraceLocal.scala index 057f564e..0a0a120a 100644 --- a/kamon-core/src/main/scala/kamon/trace/TraceLocal.scala +++ b/kamon-core/src/main/scala/kamon/trace/TraceLocal.scala @@ -42,12 +42,12 @@ object TraceLocal { object HttpContextKey extends TraceLocal.TraceLocalKey { type ValueType = HttpContext } - def store(key: TraceLocalKey)(value: key.ValueType): Unit = TraceContext.currentContext match { + def store(key: TraceLocalKey)(value: key.ValueType): Unit = Tracer.currentContext match { case ctx: MetricsOnlyContext ⇒ ctx.traceLocalStorage.store(key)(value) case EmptyTraceContext ⇒ // Can't store in the empty context. } - def retrieve(key: TraceLocalKey): Option[key.ValueType] = TraceContext.currentContext match { + def retrieve(key: TraceLocalKey): Option[key.ValueType] = Tracer.currentContext match { case ctx: MetricsOnlyContext ⇒ ctx.traceLocalStorage.retrieve(key) case EmptyTraceContext ⇒ None // Can't retrieve anything from the empty context. } diff --git a/kamon-core/src/main/scala/kamon/trace/Tracer.scala b/kamon-core/src/main/scala/kamon/trace/Tracer.scala index 49ab518f..cf83b36b 100644 --- a/kamon-core/src/main/scala/kamon/trace/Tracer.scala +++ b/kamon-core/src/main/scala/kamon/trace/Tracer.scala @@ -35,6 +35,28 @@ trait Tracer { def unsubscribe(subscriber: ActorRef): Unit } +object Tracer { + private[kamon] val _traceContextStorage = new ThreadLocal[TraceContext] { + override def initialValue(): TraceContext = EmptyTraceContext + } + + def currentContext: TraceContext = + _traceContextStorage.get() + + def setCurrentContext(context: TraceContext): Unit = + _traceContextStorage.set(context) + + def clearCurrentContext: Unit = + _traceContextStorage.remove() + + def withContext[T](context: TraceContext)(code: ⇒ T): T = { + val oldContext = _traceContextStorage.get() + _traceContextStorage.set(context) + + try code finally _traceContextStorage.set(oldContext) + } +} + private[kamon] class TracerImpl(metricsExtension: Metrics, config: Config) extends Tracer { private val _settings = TraceSettings(config) private val _hostnamePrefix = Try(InetAddress.getLocalHost.getHostName).getOrElse("unknown-localhost") diff --git a/kamon-core/src/main/scala/kamon/trace/logging/LogbackTraceTokenConverter.scala b/kamon-core/src/main/scala/kamon/trace/logging/LogbackTraceTokenConverter.scala index 961c3099..8177ed14 100644 --- a/kamon-core/src/main/scala/kamon/trace/logging/LogbackTraceTokenConverter.scala +++ b/kamon-core/src/main/scala/kamon/trace/logging/LogbackTraceTokenConverter.scala @@ -17,14 +17,10 @@ package kamon.trace.logging import ch.qos.logback.classic.pattern.ClassicConverter import ch.qos.logback.classic.spi.ILoggingEvent -import kamon.trace.TraceContext +import kamon.trace.Tracer class LogbackTraceTokenConverter extends ClassicConverter { - def convert(event: ILoggingEvent): String = { - val ctx = TraceContext.currentContext - if (ctx.isEmpty) - "undefined" - else - ctx.token - } + + def convert(event: ILoggingEvent): String = + Tracer.currentContext.collect(_.token).getOrElse("undefined") } diff --git a/kamon-core/src/main/scala/kamon/trace/logging/MdcKeysSupport.scala b/kamon-core/src/main/scala/kamon/trace/logging/MdcKeysSupport.scala index 4970d97e..5097fe6b 100644 --- a/kamon-core/src/main/scala/kamon/trace/logging/MdcKeysSupport.scala +++ b/kamon-core/src/main/scala/kamon/trace/logging/MdcKeysSupport.scala @@ -17,14 +17,14 @@ package kamon.trace.logging import kamon.trace.TraceLocal.AvailableToMdc -import kamon.trace.{ EmptyTraceContext, MetricsOnlyContext, TraceContext } +import kamon.trace.{ Tracer, EmptyTraceContext, MetricsOnlyContext, TraceContext } import org.slf4j.MDC trait MdcKeysSupport { def withMdc[A](thunk: ⇒ A): A = { - val keys = copyToMdc(TraceContext.currentContext) + val keys = copyToMdc(Tracer.currentContext) try thunk finally keys.foreach(key ⇒ MDC.remove(key)) } diff --git a/kamon-core/src/test/scala/kamon/metric/TraceMetricsSpec.scala b/kamon-core/src/test/scala/kamon/metric/TraceMetricsSpec.scala index 6c13cdb6..03a09b7f 100644 --- a/kamon-core/src/test/scala/kamon/metric/TraceMetricsSpec.scala +++ b/kamon-core/src/test/scala/kamon/metric/TraceMetricsSpec.scala @@ -19,7 +19,7 @@ package kamon.metric import akka.testkit.ImplicitSender import com.typesafe.config.ConfigFactory import kamon.testkit.BaseKamonSpec -import kamon.trace.TraceContext +import kamon.trace.Tracer import kamon.metric.instrument.Histogram class TraceMetricsSpec extends BaseKamonSpec("trace-metrics-spec") with ImplicitSender { @@ -44,8 +44,8 @@ class TraceMetricsSpec extends BaseKamonSpec("trace-metrics-spec") with Implicit "the TraceMetrics" should { "record the elapsed time between a trace creation and finish" in { for (repetitions ← 1 to 10) { - TraceContext.withContext(newContext("record-elapsed-time")) { - TraceContext.currentContext.finish() + Tracer.withContext(newContext("record-elapsed-time")) { + Tracer.currentContext.finish() } } @@ -54,10 +54,10 @@ class TraceMetricsSpec extends BaseKamonSpec("trace-metrics-spec") with Implicit } "record the elapsed time for segments that occur inside a given trace" in { - TraceContext.withContext(newContext("trace-with-segments")) { - val segment = TraceContext.currentContext.startSegment("test-segment", "test-category", "test-library") + Tracer.withContext(newContext("trace-with-segments")) { + val segment = Tracer.currentContext.startSegment("test-segment", "test-category", "test-library") segment.finish() - TraceContext.currentContext.finish() + Tracer.currentContext.finish() } val snapshot = takeSnapshotOf("trace-with-segments", "trace") @@ -67,9 +67,9 @@ class TraceMetricsSpec extends BaseKamonSpec("trace-metrics-spec") with Implicit } "record the elapsed time for segments that finish after their correspondent trace has finished" in { - val segment = TraceContext.withContext(newContext("closing-segment-after-trace")) { - val s = TraceContext.currentContext.startSegment("test-segment", "test-category", "test-library") - TraceContext.currentContext.finish() + val segment = Tracer.withContext(newContext("closing-segment-after-trace")) { + val s = Tracer.currentContext.startSegment("test-segment", "test-category", "test-library") + Tracer.currentContext.finish() s } diff --git a/kamon-core/src/test/scala/kamon/trace/SimpleTraceSpec.scala b/kamon-core/src/test/scala/kamon/trace/SimpleTraceSpec.scala index 1d270106..c8f1ebf6 100644 --- a/kamon-core/src/test/scala/kamon/trace/SimpleTraceSpec.scala +++ b/kamon-core/src/test/scala/kamon/trace/SimpleTraceSpec.scala @@ -42,10 +42,10 @@ class SimpleTraceSpec extends BaseKamonSpec("simple-trace-spec") { "send a TraceInfo when the trace has finished and all segments are finished" in { Kamon.tracer.subscribe(testActor) - TraceContext.withContext(newContext("simple-trace-without-segments")) { - TraceContext.currentContext.startSegment("segment-one", "test-segment", "test").finish() - TraceContext.currentContext.startSegment("segment-two", "test-segment", "test").finish() - TraceContext.currentContext.finish() + Tracer.withContext(newContext("simple-trace-without-segments")) { + Tracer.currentContext.startSegment("segment-one", "test-segment", "test").finish() + Tracer.currentContext.startSegment("segment-two", "test-segment", "test").finish() + Tracer.currentContext.finish() } val traceInfo = expectMsgType[TraceInfo] @@ -60,10 +60,10 @@ class SimpleTraceSpec extends BaseKamonSpec("simple-trace-spec") { "incubate the tracing context if there are open segments after finishing" in { Kamon.tracer.subscribe(testActor) - val secondSegment = TraceContext.withContext(newContext("simple-trace-without-segments")) { - TraceContext.currentContext.startSegment("segment-one", "test-segment", "test").finish() - val segment = TraceContext.currentContext.startSegment("segment-two", "test-segment", "test") - TraceContext.currentContext.finish() + val secondSegment = Tracer.withContext(newContext("simple-trace-without-segments")) { + Tracer.currentContext.startSegment("segment-one", "test-segment", "test").finish() + val segment = Tracer.currentContext.startSegment("segment-two", "test-segment", "test") + Tracer.currentContext.finish() segment } diff --git a/kamon-core/src/test/scala/kamon/trace/TraceContextManipulationSpec.scala b/kamon-core/src/test/scala/kamon/trace/TraceContextManipulationSpec.scala index d7cb7ea3..46620461 100644 --- a/kamon-core/src/test/scala/kamon/trace/TraceContextManipulationSpec.scala +++ b/kamon-core/src/test/scala/kamon/trace/TraceContextManipulationSpec.scala @@ -37,22 +37,22 @@ class TraceContextManipulationSpec extends BaseKamonSpec("trace-metrics-spec") { "the TraceContext api" should { "allow starting a trace within a specified block of code, and only within that block of code" in { - val createdContext = TraceContext.withContext(newContext("start-context")) { - TraceContext.currentContext should not be empty - TraceContext.currentContext + val createdContext = Tracer.withContext(newContext("start-context")) { + Tracer.currentContext should not be empty + Tracer.currentContext } - TraceContext.currentContext shouldBe empty + Tracer.currentContext shouldBe empty createdContext.name shouldBe ("start-context") } "allow starting a trace within a specified block of code, providing a trace-token and only within that block of code" in { - val createdContext = TraceContext.withContext(newContext("start-context-with-token", "token-1")) { - TraceContext.currentContext should not be empty - TraceContext.currentContext + val createdContext = Tracer.withContext(newContext("start-context-with-token", "token-1")) { + Tracer.currentContext should not be empty + Tracer.currentContext } - TraceContext.currentContext shouldBe empty + Tracer.currentContext shouldBe empty createdContext.name shouldBe ("start-context-with-token") createdContext.token should be("token-1") } @@ -60,37 +60,37 @@ class TraceContextManipulationSpec extends BaseKamonSpec("trace-metrics-spec") { "allow providing a TraceContext and make it available within a block of code" in { val createdContext = newContext("manually-provided-trace-context") - TraceContext.currentContext shouldBe empty - TraceContext.withContext(createdContext) { - TraceContext.currentContext should be(createdContext) + Tracer.currentContext shouldBe empty + Tracer.withContext(createdContext) { + Tracer.currentContext should be(createdContext) } - TraceContext.currentContext shouldBe empty + Tracer.currentContext shouldBe empty } "allow renaming a trace" in { - val createdContext = TraceContext.withContext(newContext("trace-before-rename")) { - TraceContext.currentContext.rename("renamed-trace") - TraceContext.currentContext + val createdContext = Tracer.withContext(newContext("trace-before-rename")) { + Tracer.currentContext.rename("renamed-trace") + Tracer.currentContext } - TraceContext.currentContext shouldBe empty + Tracer.currentContext shouldBe empty createdContext.name shouldBe ("renamed-trace") } "allow creating a segment within a trace" in { - val createdContext = TraceContext.withContext(newContext("trace-with-segments")) { - val segment = TraceContext.currentContext.startSegment("segment-1", "segment-1-category", "segment-library") - TraceContext.currentContext + val createdContext = Tracer.withContext(newContext("trace-with-segments")) { + val segment = Tracer.currentContext.startSegment("segment-1", "segment-1-category", "segment-library") + Tracer.currentContext } - TraceContext.currentContext shouldBe empty + Tracer.currentContext shouldBe empty createdContext.name shouldBe ("trace-with-segments") } "allow renaming a segment" in { - TraceContext.withContext(newContext("trace-with-renamed-segment")) { - val segment = TraceContext.currentContext.startSegment("original-segment-name", "segment-label", "segment-library") + Tracer.withContext(newContext("trace-with-renamed-segment")) { + val segment = Tracer.currentContext.startSegment("original-segment-name", "segment-label", "segment-library") segment.name should be("original-segment-name") segment.rename("new-segment-name") diff --git a/kamon-core/src/test/scala/kamon/trace/TraceLocalSpec.scala b/kamon-core/src/test/scala/kamon/trace/TraceLocalSpec.scala index 8bacca83..b58b247f 100644 --- a/kamon-core/src/test/scala/kamon/trace/TraceLocalSpec.scala +++ b/kamon-core/src/test/scala/kamon/trace/TraceLocalSpec.scala @@ -30,7 +30,7 @@ class TraceLocalSpec extends BaseKamonSpec("trace-local-spec") with PatienceConf "the TraceLocal storage" should { "allow storing and retrieving values" in { - TraceContext.withContext(newContext("store-and-retrieve-trace-local")) { + Tracer.withContext(newContext("store-and-retrieve-trace-local")) { val testString = "Hello World" TraceLocal.store(SampleTraceLocalKey)(testString) @@ -39,7 +39,7 @@ class TraceLocalSpec extends BaseKamonSpec("trace-local-spec") with PatienceConf } "return None when retrieving a non existent key" in { - TraceContext.withContext(newContext("non-existent-key")) { + Tracer.withContext(newContext("non-existent-key")) { TraceLocal.retrieve(SampleTraceLocalKey) should equal(None) } } @@ -50,22 +50,22 @@ class TraceLocalSpec extends BaseKamonSpec("trace-local-spec") with PatienceConf "be attached to the TraceContext when it is propagated" in { val testString = "Hello World" - val testContext = TraceContext.withContext(newContext("manually-propagated-trace-local")) { + val testContext = Tracer.withContext(newContext("manually-propagated-trace-local")) { TraceLocal.store(SampleTraceLocalKey)(testString) TraceLocal.retrieve(SampleTraceLocalKey).value should equal(testString) - TraceContext.currentContext + Tracer.currentContext } /** No TraceLocal should be available here */ TraceLocal.retrieve(SampleTraceLocalKey) should equal(None) - TraceContext.withContext(testContext) { + Tracer.withContext(testContext) { TraceLocal.retrieve(SampleTraceLocalKey).value should equal(testString) } } "allow retrieve a value from the MDC when was created a key with AvailableToMdc(cool-key)" in { - TraceContext.withContext(newContext("store-and-retrieve-trace-local-and-copy-to-mdc")) { + Tracer.withContext(newContext("store-and-retrieve-trace-local-and-copy-to-mdc")) { val testString = "Hello MDC" TraceLocal.store(SampleTraceLocalKeyAvailableToMDC)(testString) @@ -78,7 +78,7 @@ class TraceLocalSpec extends BaseKamonSpec("trace-local-spec") with PatienceConf } "allow retrieve a value from the MDC when was created a key with AvailableToMdc.storeForMdc(String, String)" in { - TraceContext.withContext(newContext("store-and-retrieve-trace-local-and-copy-to-mdc")) { + Tracer.withContext(newContext("store-and-retrieve-trace-local-and-copy-to-mdc")) { val testString = "Hello MDC" TraceLocal.storeForMdc("someKey", testString) -- cgit v1.2.3