diff options
author | Ivan Topolnjak <ivantopo@gmail.com> | 2017-07-25 16:21:13 +0200 |
---|---|---|
committer | Ivan Topolnjak <ivantopo@gmail.com> | 2017-07-25 16:21:13 +0200 |
commit | 0930e36def6ce62c55d30d744b41ef475374a541 (patch) | |
tree | b3699d8932608ad48cdc8e91a16b0d5ee7541e4d /kamon-core/src/main | |
parent | 5c8a8d169858b83a059c89e48cb43a41040788b8 (diff) | |
download | Kamon-0930e36def6ce62c55d30d744b41ef475374a541.tar.gz Kamon-0930e36def6ce62c55d30d744b41ef475374a541.tar.bz2 Kamon-0930e36def6ce62c55d30d744b41ef475374a541.zip |
try an alternative approach to active span management
Diffstat (limited to 'kamon-core/src/main')
-rw-r--r-- | kamon-core/src/main/scala/kamon/Kamon.scala | 46 | ||||
-rw-r--r-- | kamon-core/src/main/scala/kamon/trace/ActiveSpan.scala | 78 | ||||
-rw-r--r-- | kamon-core/src/main/scala/kamon/trace/ActiveSpanSource.scala | 46 | ||||
-rw-r--r-- | kamon-core/src/main/scala/kamon/trace/Continuation.scala | 39 | ||||
-rw-r--r-- | kamon-core/src/main/scala/kamon/trace/Span.scala | 14 | ||||
-rw-r--r-- | kamon-core/src/main/scala/kamon/trace/Tracer.scala | 32 | ||||
-rw-r--r-- | kamon-core/src/main/scala/kamon/util/Mixin.scala | 29 |
7 files changed, 82 insertions, 202 deletions
diff --git a/kamon-core/src/main/scala/kamon/Kamon.scala b/kamon-core/src/main/scala/kamon/Kamon.scala index fa9e78fe..6de45e25 100644 --- a/kamon-core/src/main/scala/kamon/Kamon.scala +++ b/kamon-core/src/main/scala/kamon/Kamon.scala @@ -17,7 +17,7 @@ package kamon import com.typesafe.config.{Config, ConfigFactory} import kamon.metric._ -import kamon.trace.{ActiveSpan, Span, SpanContext, Tracer, Continuation} +import kamon.trace._ import kamon.util.{Filters, MeasurementUnit, Registration} import scala.concurrent.Future @@ -102,52 +102,28 @@ object Kamon extends MetricLookup with ReporterRegistry with Tracer { override def inject[C](spanContext: SpanContext, format: Format[C]): C = _tracer.inject(spanContext, format) - override def activeSpan(): ActiveSpan = + override def activeSpan(): Span = _tracer.activeSpan() - override def makeActive(span: Span): ActiveSpan = - _tracer.makeActive(span) + override def activate(span: Span): Scope = + _tracer.activate(span) + override def activate(span: Span, finishOnClose: Boolean): Scope = + _tracer.activate(span, finishOnClose) /** * Makes the provided Span active before code is evaluated and deactivates it afterwards. */ - def withSpan[T](span: Span)(code: => T): T = { - val activeSpan = makeActive(span) - val evaluatedCode = code - activeSpan.deactivate() - evaluatedCode - } + def withActiveSpan[T](span: Span)(code: => T): T = { + val scope = activate(span) - /** - * Actives the provided Continuation before code is evaluated and deactivates it afterwards. - */ - def withContinuation[T](continuation: Continuation)(code: => T): T = { - if(continuation == null) + try { code - else { - val activeSpan = continuation.activate() - val evaluatedCode = code - activeSpan.deactivate() - evaluatedCode + } finally { + scope.close() } } - /** - * Captures a continuation from the currently active Span (if any). - */ - def activeSpanContinuation(): Continuation = - activeSpan().capture() - - /** - * Runs the provided closure with the currently active Span (if any). - */ - def onActiveSpan[T](code: ActiveSpan => T): Unit = { - val activeSpan = Kamon.activeSpan() - if(activeSpan != null) - code(activeSpan) - } - override def loadReportersFromConfig(): Unit = _reporters.loadReportersFromConfig() diff --git a/kamon-core/src/main/scala/kamon/trace/ActiveSpan.scala b/kamon-core/src/main/scala/kamon/trace/ActiveSpan.scala deleted file mode 100644 index b6e5d5e9..00000000 --- a/kamon-core/src/main/scala/kamon/trace/ActiveSpan.scala +++ /dev/null @@ -1,78 +0,0 @@ -package kamon.trace - -/** - * Wraps a [[kamon.trace.Span]] that has been activated in the current Thread. By activated we really mean, it is - * stored in a ThreadLocal value inside the tracer until [[kamon.trace.ActiveSpan#deactivate()]] is called. - * - * When a [[kamon.trace.Span]] is activated it will keep a reference to the previously active Span on the current - * Thread, take it's place as the currently active Span and put the original one once this ActiveSpan gets deactivated. - * - */ -trait ActiveSpan extends Span { - - /** - * Sets the currently active Span to whatever Span was active when this Span was activated. - * - */ - def deactivate(): Span -} - -object ActiveSpan { - - final class Default(wrappedSpan: Span, restoreOnDeactivate: ActiveSpan, tl: ThreadLocal[ActiveSpan]) - extends ActiveSpan { - - override def deactivate(): Span = { - tl.set(restoreOnDeactivate) - wrappedSpan - } - - // - // Forward all other members to the wrapped Span. - // - - override def annotate(annotation: Span.Annotation): Span = - wrappedSpan.annotate(annotation) - - override def addSpanTag(key: String, value: String): Span = - wrappedSpan.addSpanTag(key, value) - - override def addSpanTag(key: String, value: Long): Span = - wrappedSpan.addSpanTag(key, value) - - override def addSpanTag(key: String, value: Boolean): Span = - wrappedSpan.addSpanTag(key, value) - - override def addMetricTag(key: String, value: String): Span = - wrappedSpan.addMetricTag(key, value) - - override def addBaggage(key: String, value: String): Span = - wrappedSpan.addBaggage(key, value) - - override def getBaggage(key: String): Option[String] = - wrappedSpan.getBaggage(key) - - override def disableMetricsCollection(): Span = - wrappedSpan.disableMetricsCollection() - - override def context(): SpanContext = - wrappedSpan.context() - - override def setOperationName(operationName: String): Span = - wrappedSpan.setOperationName(operationName) - - override def finish(finishMicros: Long): Unit = - wrappedSpan.finish(finishMicros) - - override def capture(): Continuation = - wrappedSpan.capture() - - override def capture(activeSpanSource: ActiveSpanSource): Continuation = - wrappedSpan.capture(activeSpanSource) - } - - object Default { - def apply(wrappedSpan: Span, restoreOnDeactivate: ActiveSpan, tl: ThreadLocal[ActiveSpan]): Default = - new Default(wrappedSpan, restoreOnDeactivate, tl) - } -}
\ No newline at end of file diff --git a/kamon-core/src/main/scala/kamon/trace/ActiveSpanSource.scala b/kamon-core/src/main/scala/kamon/trace/ActiveSpanSource.scala new file mode 100644 index 00000000..f4a363a6 --- /dev/null +++ b/kamon-core/src/main/scala/kamon/trace/ActiveSpanSource.scala @@ -0,0 +1,46 @@ +package kamon.trace + + +trait Scope extends AutoCloseable { + def close(): Unit +} + +trait ActiveSpanSource { + def activeSpan(): Span + + def activate(span: Span): Scope + def activate(span: Span, finishOnClose: Boolean): Scope +} + +object ActiveSpanSource { + + final class ThreadLocalBased extends ActiveSpanSource { + private val emptySpan = Span.Empty(this) + private val storage: ThreadLocal[Span] = new ThreadLocal[Span] { + override def initialValue(): Span = emptySpan + } + + override def activeSpan(): Span = + storage.get() + + override def activate(span: Span): Scope = + activate(span, finishOnClose = false) + + override def activate(span: Span, finishOnClose: Boolean): Scope = { + val previouslyActiveSpan = storage.get() + storage.set(span) + + new Scope { + override def close(): Unit = { + storage.set(previouslyActiveSpan) + if (finishOnClose && span != null) + span.finish() + } + } + } + } + + object ThreadLocalBased { + def apply(): ThreadLocalBased = new ThreadLocalBased() + } +}
\ No newline at end of file diff --git a/kamon-core/src/main/scala/kamon/trace/Continuation.scala b/kamon-core/src/main/scala/kamon/trace/Continuation.scala deleted file mode 100644 index 8029b838..00000000 --- a/kamon-core/src/main/scala/kamon/trace/Continuation.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* ========================================================================================= - * Copyright © 2013-2017 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.trace - - - -trait Continuation { - def activate(): ActiveSpan -} - -object Continuation { - - /** - * - * @param span - * @param activeSpanSource - */ - final class Default(span: Span, activeSpanSource: ActiveSpanSource) extends Continuation { - override def activate(): ActiveSpan = - activeSpanSource.makeActive(span) - } - - object Default { - def apply(span: Span, activeSpanSource: ActiveSpanSource): Default = new Default(span, activeSpanSource) - } -} diff --git a/kamon-core/src/main/scala/kamon/trace/Span.scala b/kamon-core/src/main/scala/kamon/trace/Span.scala index 113ec3de..6b38ae48 100644 --- a/kamon-core/src/main/scala/kamon/trace/Span.scala +++ b/kamon-core/src/main/scala/kamon/trace/Span.scala @@ -29,10 +29,6 @@ trait BaseSpan { def context(): SpanContext - def capture(): Continuation - - def capture(activeSpanSource: ActiveSpanSource): Continuation - def annotate(annotation: Span.Annotation): Span def addSpanTag(key: String, value: String): Span @@ -77,8 +73,6 @@ object Span { final class Empty(activeSpanSource: ActiveSpanSource) extends Span { override val context: SpanContext = SpanContext.EmptySpanContext - override def capture(): Continuation = Continuation.Default(this, activeSpanSource) - override def capture(activeSpanSource: ActiveSpanSource): Continuation = Continuation.Default(this, activeSpanSource) override def annotate(annotation: Annotation): Span = this override def addSpanTag(key: String, value: String): Span = this @@ -93,7 +87,7 @@ object Span { } object Empty { - def apply(tracer: Tracer): Empty = new Empty(tracer) + def apply(activeSpanSource: ActiveSpanSource): Empty = new Empty(activeSpanSource) } /** @@ -182,12 +176,6 @@ object Span { } } - override def capture(): Continuation = - Continuation.Default(this, activeSpanSource) - - override def capture(activeSpanSource: ActiveSpanSource): Continuation = - Continuation.Default(this, activeSpanSource) - private def toFinishedSpan(endTimestampMicros: Long): Span.FinishedSpan = Span.FinishedSpan(spanContext, operationName, startTimestampMicros, endTimestampMicros, spanTags, annotations) diff --git a/kamon-core/src/main/scala/kamon/trace/Tracer.scala b/kamon-core/src/main/scala/kamon/trace/Tracer.scala index 71201871..737a8b8d 100644 --- a/kamon-core/src/main/scala/kamon/trace/Tracer.scala +++ b/kamon-core/src/main/scala/kamon/trace/Tracer.scala @@ -13,7 +13,6 @@ * ========================================================================================= */ - package kamon.trace import java.nio.ByteBuffer @@ -30,13 +29,7 @@ import org.slf4j.LoggerFactory import scala.collection.immutable import scala.util.Try - -trait ActiveSpanSource { - def activeSpan(): ActiveSpan - def makeActive(span: Span): ActiveSpan -} - -trait Tracer extends ActiveSpanSource{ +trait Tracer extends ActiveSpanSource { def buildSpan(operationName: String): SpanBuilder def extract[C](format: SpanContextCodec.Format[C], carrier: C): Option[SpanContext] @@ -48,10 +41,7 @@ object Tracer { final class Default(metrics: MetricLookup, reporterRegistry: ReporterRegistryImpl, initialConfig: Config) extends Tracer { private val logger = LoggerFactory.getLogger(classOf[Tracer]) - private val emptySpan = Span.Empty(this) - private val activeSpanStorage: ThreadLocal[ActiveSpan] = new ThreadLocal[ActiveSpan] { - override def initialValue(): ActiveSpan = ActiveSpan.Default(emptySpan, null, activeSpanStorage) - } + private val activeSpanSource = ActiveSpanSource.ThreadLocalBased() private[Tracer] val tracerMetrics = new TracerMetrics(metrics) @volatile private[Tracer] var joinRemoteParentsWithSameSpanID: Boolean = true @@ -83,15 +73,14 @@ object Tracer { case SpanContextCodec.Format.Binary => ByteBuffer.allocate(0) // TODO: Implement binary encoding. } - override def activeSpan(): ActiveSpan = - activeSpanStorage.get() + override def activeSpan(): Span = + activeSpanSource.activeSpan() - override def makeActive(span: Span): ActiveSpan = { - val currentlyActiveSpan = activeSpanStorage.get() - val newActiveSpan = ActiveSpan.Default(span, currentlyActiveSpan, activeSpanStorage) - activeSpanStorage.set(newActiveSpan) - newActiveSpan - } + override def activate(span: Span): Scope = + activeSpanSource.activate(span) + + override def activate(span: Span, finishOnClose: Boolean): Scope = + activeSpanSource.activate(span, finishOnClose) def sampler: Sampler = configuredSampler @@ -232,9 +221,6 @@ object Tracer { baggage = SpanContext.Baggage(), source = Source.Local ) - - def startActive(): ActiveSpan = - tracer.makeActive(start()) } private final class TracerMetrics(metricLookup: MetricLookup) { diff --git a/kamon-core/src/main/scala/kamon/util/Mixin.scala b/kamon-core/src/main/scala/kamon/util/Mixin.scala index 318679c1..2fd7be24 100644 --- a/kamon-core/src/main/scala/kamon/util/Mixin.scala +++ b/kamon-core/src/main/scala/kamon/util/Mixin.scala @@ -16,30 +16,31 @@ package kamon package util -import kamon.trace.{ActiveSpan, Continuation} +import kamon.trace.Span /** - * Utility trait that marks objects carrying an ActiveSpan.Continuation. + * Utility trait that marks objects carrying a reference to a Span. + * */ -trait HasContinuation { - def continuation: Continuation +trait HasSpan { + def span: Span } -object HasContinuation { - private class Default(val continuation: Continuation) extends HasContinuation +object HasSpan { + private case class Default(span: Span) extends HasSpan /** - * Construct a HasContinuation instance by capturing a continuation from the provided active span. + * Construct a HasSpan instance that references the provided Span. + * */ - def from(activeSpan: ActiveSpan): HasContinuation = { - val continuation = if(activeSpan == null) null else activeSpan.capture() - new Default(continuation) - } + def from(span: Span): HasSpan = + Default(span) /** - * Constructs a new HasContinuation instance using Kamon's tracer currently active span. + * Construct a HasSpan instance that references the currently ActiveSpan in Kamon's tracer. + * */ - def fromTracerActiveSpan(): HasContinuation = - new Default(Kamon.activeSpanContinuation()) + def fromActiveSpan(): HasSpan = + Default(Kamon.activeSpan()) } |