Skip to content

Commit

Permalink
Add Tracer[F].withoutTracing
Browse files Browse the repository at this point in the history
  • Loading branch information
iRevive committed Jul 28, 2022
1 parent cf4d27e commit 57aac04
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,5 @@ private[otel4s] trait TracerMacro[F[_]] {
attributes: Attribute[_]*
): Resource[F, Span.Auto[F]] =
macro TracesMacro.rootSpan

}
18 changes: 12 additions & 6 deletions core/src/main/scala/org/typelevel/otel4s/trace/Span.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,19 @@ trait Span[F[_]] extends SpanMacro[F] {
backend.setStatus(status, description)

/** Returns trace identifier of the current span.
*
* @return
* `Some` for a valid span and `None` for noop
*/
final def traceId: String =
final def traceId: Option[String] =
backend.traceId

/** Returns span identifier of the current span.
*
* @return
* `Some` for a valid span and `None` for noop
*/
final def spanId: String =
final def spanId: Option[String] =
backend.spanId

}
Expand All @@ -99,8 +105,8 @@ object Span {
def setStatus(status: Status): F[Unit]
def setStatus(status: Status, description: String): F[Unit]

def traceId: String
def spanId: String
def traceId: Option[String]
def spanId: Option[String]

private[otel4s] def child(name: String): SpanBuilder[F]
private[otel4s] def end: F[Unit]
Expand Down Expand Up @@ -131,8 +137,8 @@ object Span {

val meta: InstrumentMeta[F] = InstrumentMeta.disabled

val traceId: String = "00000000000000000000000000000000"
val spanId: String = "0000000000000000"
val traceId: Option[String] = None
val spanId: Option[String] = None

def recordException(
exception: Throwable,
Expand Down
27 changes: 18 additions & 9 deletions core/src/main/scala/org/typelevel/otel4s/trace/Tracer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ trait Tracer[F[_]] extends TracerMacro[F] { self =>
*/
def meta: Tracer.Meta[F]

/** Returns trace identifier of a span that is available in a scope.
*/
def traceId: F[Option[String]]

/** Returns span identifier of a span that is available in a scope.
*/
def spanId: F[Option[String]]

/** Creates a new [[SpanBuilder]]. The builder can be used to make a fully
* customized [[Span]].
*
Expand All @@ -43,20 +51,20 @@ trait Tracer[F[_]] extends TracerMacro[F] { self =>
* {{{
* val tracer: Tracer[F] = ???
* val span: Span[F] = ???
* val customChild: Resource[F, Span[F]] = tracer.childOf(span).
* val customChild: Resource[F, Span[F]] = tracer.childOf(span).span("custom-parent")
* }}}
* @param span
* the parent span
*/
def childOf(span: Span[F]): Tracer[F]

/** Returns trace identifier of a span that is available in a scope.
*/
def traceId: F[Option[String]]

/** Returns span identifier of a span that is available in a scope.
/** Runs the given effect without propagation of the current scope. That
* means, that parent span will not be available inside of the `fa`.
*
* Can be useful, when an effect needs to be executed in the background and
* the parent tracing info is not needed.
*/
def spanId: F[Option[String]]
def withoutTracing[A](fa: F[A]): F[A]

}

Expand Down Expand Up @@ -86,9 +94,10 @@ object Tracer {
new Tracer[F] {
private val builder = SpanBuilder.noop(Span.noopBackend)
val meta: Meta[F] = Meta.disabled
def spanBuilder(name: String): SpanBuilder[F] = builder
def childOf(span: Span[F]): Tracer[F] = this
val traceId: F[Option[String]] = F.pure(None)
val spanId: F[Option[String]] = F.pure(None)
def spanBuilder(name: String): SpanBuilder[F] = builder
def childOf(span: Span[F]): Tracer[F] = this
def withoutTracing[A](fa: F[A]): F[A] = fa
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ private[otel4s] class SpanBackendImpl[F[_]](
private[otel4s] def end(timestamp: FiniteDuration): F[Unit] =
F.delay(jSpan.end(timestamp.length, timestamp.unit))

def traceId: String =
jSpan.getSpanContext.getTraceId
def traceId: Option[String] =
Option(jSpan.getSpanContext).filter(_.isValid).map(_.getTraceId)

def spanId: String =
jSpan.getSpanContext.getSpanId
def spanId: Option[String] =
Option(jSpan.getSpanContext).filter(_.isValid).map(_.getSpanId)
}

object SpanBackendImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ trait TraceScope[F[_]] {
def root: F[JContext]
def current: F[JContext]
def make(span: JSpan): Resource[F, Unit]
def rootScope: Resource[F, Unit]
}

object TraceScope {
Expand All @@ -48,11 +49,19 @@ object TraceScope {
def make(span: JSpan): Resource[F, Unit] =
for {
current <- Resource.eval(lift(local.get))
next <- Resource.pure(current.`with`(span))
_ <- Resource.make(lift(local.getAndSet(next)))(previous =>
lift(local.set(previous))
)
_ <- makeScope(current.`with`(span))
} yield ()

def rootScope: Resource[F, Unit] =
makeScope(default)

private def makeScope(ctx: JContext): Resource[F, Unit] =
Resource
.make(lift(local.getAndSet(ctx))) { previous =>
lift(local.set(previous))
}
.void

}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,27 @@ private[trace] class TracerImpl[F[_]: Sync](
val meta: Tracer.Meta[F] =
Tracer.Meta.enabled

def spanBuilder(name: String): SpanBuilder[F] =
new SpanBuilderImpl[F](jTracer, name, scope)

def childOf(s: Span[F]): Tracer[F] =
new TracerImpl(jTracer, scope) {
override def spanBuilder(name: String): SpanBuilder[F] =
s.backend.child(name)
}

/** Returns trace identifier of a span that is available in a scope.
*/
def traceId: F[Option[String]] =
for {
context <- scope.current
} yield Option(JSpan.fromContextOrNull(context))
.map(_.getSpanContext.getTraceId)

/** Returns span identifier of a span that is available in a scope.
*/
def spanId: F[Option[String]] =
for {
context <- scope.current
} yield Option(JSpan.fromContextOrNull(context))
.map(_.getSpanContext.getSpanId)

def spanBuilder(name: String): SpanBuilder[F] =
new SpanBuilderImpl[F](jTracer, name, scope)

def childOf(s: Span[F]): Tracer[F] =
new TracerImpl(jTracer, scope) {
override def spanBuilder(name: String): SpanBuilder[F] =
s.backend.child(name)
}

def withoutTracing[A](fa: F[A]): F[A] =
scope.rootScope.use(_ => fa)
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2022 Typelevel
*
* 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 org.typelevel.otel4s.java.trace

import cats.effect.IO
Expand Down Expand Up @@ -56,23 +72,30 @@ class TracerSuite extends CatsEffectSuite {
tracer <- sdk.provider.tracer("java.otel.tracer").get
_ <- tracer.traceId.assertEquals(None)
_ <- tracer.spanId.assertEquals(None)
(span, span2) <- tracer.span("span").use { span =>
spanTuple <- tracer.span("span").use { span =>
for {
_ <- tracer.traceId.assertEquals(Some(span.traceId))
_ <- tracer.spanId.assertEquals(Some(span.spanId))
_ <- tracer.traceId.assertEquals(span.traceId)
_ <- tracer.spanId.assertEquals(span.spanId)
span2 <- tracer.span("span-2").use { span2 =>
for {
_ <- tracer.traceId.assertEquals(Some(span2.traceId))
_ <- tracer.spanId.assertEquals(Some(span2.spanId))
_ <- tracer.traceId.assertEquals(span2.traceId)
_ <- tracer.spanId.assertEquals(span2.spanId)
} yield span2
}
} yield (span, span2)
}
spans <- sdk.finishedSpans
} yield {
val (span, span2) = spanTuple
assertEquals(span.traceId, span2.traceId)
assertEquals(spans.map(_.getTraceId), List(span2.traceId, span.traceId))
assertEquals(spans.map(_.getSpanId), List(span2.spanId, span.spanId))
assertEquals(
spans.map(_.getTraceId),
List(span2.traceId, span.traceId).flatten
)
assertEquals(
spans.map(_.getSpanId),
List(span2.spanId, span.spanId).flatten
)
}
}

Expand All @@ -85,8 +108,8 @@ class TracerSuite extends CatsEffectSuite {
span <- tracer.span("span", attribute).use(IO.pure)
spans <- sdk.finishedSpans
} yield {
assertEquals(spans.map(_.getTraceId), List(span.traceId))
assertEquals(spans.map(_.getSpanId), List(span.spanId))
assertEquals(spans.map(_.getTraceId), List(span.traceId).flatten)
assertEquals(spans.map(_.getSpanId), List(span.spanId).flatten)
}
}

Expand Down Expand Up @@ -166,8 +189,54 @@ class TracerSuite extends CatsEffectSuite {
spans <- sdk.finishedSpans
} yield {
assertNotEquals(rootSpan.spanId, span.spanId)
assertEquals(spans.map(_.getTraceId), List(span.traceId, rootSpan.traceId))
assertEquals(spans.map(_.getSpanId), List(span.spanId, rootSpan.spanId))
assertEquals(
spans.map(_.getTraceId),
List(span.traceId, rootSpan.traceId).flatten
)
assertEquals(
spans.map(_.getSpanId),
List(span.spanId, rootSpan.spanId).flatten
)
}
}

test("run effect without tracing") {
for {
sdk <- makeSdk()
tracer <- sdk.provider.tracer("java.otel.tracer").get
_ <- tracer.traceId.assertEquals(None)
_ <- tracer.spanId.assertEquals(None)
spanTuple <- tracer.span("span").use { span =>
for {
_ <- tracer.traceId.assertEquals(span.traceId)
_ <- tracer.spanId.assertEquals(span.spanId)
span2 <- tracer.withoutTracing {
for {
_ <- tracer.traceId.assertEquals(None)
_ <- tracer.spanId.assertEquals(None)
// a new root span should be created
span2 <- tracer.span("span-2").use { span2 =>
for {
_ <- tracer.traceId.assertEquals(span2.traceId)
_ <- tracer.spanId.assertEquals(span2.spanId)
} yield span2
}
} yield span2
}
} yield (span, span2)
}
spans <- sdk.finishedSpans
} yield {
val (span, span2) = spanTuple
assertNotEquals(span.traceId, span2.traceId)
assertEquals(
spans.map(_.getTraceId),
List(span2.traceId, span.traceId).flatten
)
assertEquals(
spans.map(_.getSpanId),
List(span2.spanId, span.spanId).flatten
)
}
}

Expand Down

0 comments on commit 57aac04

Please sign in to comment.