Skip to content

Commit

Permalink
Add translate and mapK API to the tracing components
Browse files Browse the repository at this point in the history
  • Loading branch information
iRevive committed Jul 24, 2023
1 parent 4139fdb commit 5a12d7f
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 174 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.typelevel.otel4s.meta

import cats.Applicative
import cats.~>

trait InstrumentMeta[F[_]] {

Expand All @@ -38,6 +39,18 @@ object InstrumentMeta {
def disabled[F[_]: Applicative]: InstrumentMeta[F] =
make(enabled = false)

implicit final class InstrumentMetaSyntax[F[_]](
private val m: InstrumentMeta[F]
) extends AnyVal {

def mapK[G[_]](fk: F ~> G): InstrumentMeta[G] =
new InstrumentMeta[G] {
def isEnabled: Boolean = m.isEnabled
def unit: G[Unit] = fk(m.unit)
}

}

private def make[F[_]: Applicative](enabled: Boolean): InstrumentMeta[F] =
new InstrumentMeta[F] {
val isEnabled: Boolean = enabled
Expand Down
59 changes: 59 additions & 0 deletions core/trace/src/main/scala/org/typelevel/otel4s/trace/Span.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ package org.typelevel.otel4s
package trace

import cats.Applicative
import cats.Functor
import cats.data.OptionT
import cats.~>
import org.typelevel.otel4s.meta.InstrumentMeta

import scala.concurrent.duration.FiniteDuration
Expand Down Expand Up @@ -151,10 +154,66 @@ object Span {
private[otel4s] def end: F[Unit] = unit
private[otel4s] def end(timestamp: FiniteDuration): F[Unit] = unit
}

implicit final class BackendSyntax[F[_]](
private val backend: Backend[F]
) extends AnyVal {

def mapK[G[_]](fk: F ~> G): Backend[G] =
new Backend[G] {
def meta: InstrumentMeta[G] =
backend.meta.mapK(fk)

def context: SpanContext =
backend.context

def addAttributes(attributes: Attribute[_]*): G[Unit] =
fk(backend.addAttributes(attributes: _*))

def addEvent(name: String, attributes: Attribute[_]*): G[Unit] =
fk(backend.addEvent(name, attributes: _*))

def addEvent(
name: String,
timestamp: FiniteDuration,
attributes: Attribute[_]*
): G[Unit] =
fk(backend.addEvent(name, timestamp, attributes: _*))

def recordException(
exception: Throwable,
attributes: Attribute[_]*
): G[Unit] =
fk(backend.recordException(exception, attributes: _*))

def setStatus(status: Status): G[Unit] =
fk(backend.setStatus(status))

def setStatus(status: Status, description: String): G[Unit] =
fk(backend.setStatus(status, description))

private[otel4s] def end: G[Unit] =
fk(backend.end)

private[otel4s] def end(timestamp: FiniteDuration): G[Unit] =
fk(backend.end(timestamp))
}

}
}

implicit final class SpanSyntax[F[_]](
private val span: Span[F]
) extends AnyVal {

def mapK[G[_]](fk: F ~> G): Span[G] =
Span.fromBackend(span.backend.mapK(fk))

}

private[otel4s] def fromBackend[F[_]](back: Backend[F]): Span[F] =
new Span[F] {
def backend: Backend[F] = back
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ package trace

import cats.Applicative
import cats.arrow.FunctionK
import cats.data.OptionT
import cats.effect.MonadCancel
import cats.effect.Resource
import cats.~>
import org.typelevel.otel4s.trace.SpanFinalizer.Strategy

import scala.concurrent.duration.FiniteDuration

Expand Down Expand Up @@ -152,4 +156,84 @@ object SpanBuilder {
}
}

implicit final class SpanBuilderSyntax[F[_]](
private val builder: SpanBuilder[F]
) extends AnyVal {

def translate[G[_]](fk: F ~> G, gk: G ~> F)(implicit
F: MonadCancel[F, _],
G: MonadCancel[G, _]
): SpanBuilder[G] =
new SpanBuilder[G] {

def addAttribute[A](attribute: Attribute[A]): SpanBuilder[G] =
builder.addAttribute(attribute).translate(fk, gk)

def addAttributes(attributes: Attribute[_]*): SpanBuilder[G] =
builder.addAttributes(attributes: _*).translate(fk, gk)

def addLink(
spanContext: SpanContext,
attributes: Attribute[_]*
): SpanBuilder[G] =
builder.addLink(spanContext, attributes: _*).translate(fk, gk)

def withFinalizationStrategy(strategy: Strategy): SpanBuilder[G] =
builder.withFinalizationStrategy(strategy).translate(fk, gk)

def withSpanKind(spanKind: SpanKind): SpanBuilder[G] =
builder.withSpanKind(spanKind).translate(fk, gk)

def withStartTimestamp(timestamp: FiniteDuration): SpanBuilder[G] =
builder.withStartTimestamp(timestamp).translate(fk, gk)

def root: SpanBuilder[G] =
builder.root.translate(fk, gk)

def withParent(parent: SpanContext): SpanBuilder[G] =
builder.withParent(parent).translate(fk, gk)

def build: SpanOps[G] =
builder.build.translate(fk, gk)
}

}

def liftOptionT[F[_]](builder: SpanBuilder[F])(implicit
F: MonadCancel[F, _]
): SpanBuilder[OptionT[F, *]] =
new SpanBuilder[OptionT[F, *]] {
type Builder = SpanBuilder[OptionT[F, *]]

def addAttribute[A](attribute: Attribute[A]): Builder =
liftOptionT(builder.addAttribute(attribute))

def addAttributes(attributes: Attribute[_]*): Builder =
liftOptionT(builder.addAttributes(attributes: _*))

def addLink(
spanContext: SpanContext,
attributes: Attribute[_]*
): Builder =
liftOptionT(builder.addLink(spanContext, attributes: _*))

def withFinalizationStrategy(strategy: SpanFinalizer.Strategy): Builder =
liftOptionT(builder.withFinalizationStrategy(strategy))

def withSpanKind(spanKind: SpanKind): Builder =
liftOptionT(builder.withSpanKind(spanKind))

def withStartTimestamp(timestamp: FiniteDuration): Builder =
liftOptionT(builder.withStartTimestamp(timestamp))

def root: Builder =
liftOptionT(builder.root)

def withParent(parent: SpanContext): Builder =
liftOptionT(builder.withParent(parent))

def build: SpanOps[OptionT[F, *]] =
SpanOps.liftOptionT(builder.build)
}

}
71 changes: 71 additions & 0 deletions core/trace/src/main/scala/org/typelevel/otel4s/trace/SpanOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

package org.typelevel.otel4s.trace

import cats.data.OptionT
import cats.effect.MonadCancel
import cats.effect.Resource
import cats.syntax.functor._
import cats.~>

trait SpanOps[F[_]] {
Expand Down Expand Up @@ -167,5 +170,73 @@ object SpanOps {
*/
def apply[F[_]](span: Span[F], trace: F ~> F): Res[F] =
Impl(span, trace)

implicit final class SpanOpsResSyntax[F[_]](
private val res: Res[F]
) extends AnyVal {

def translate[G[_]](fk: F ~> G, gk: G ~> F): Res[G] =
new Res[G] {
def span: Span[G] = res.span.mapK(fk)
def trace: G ~> G = res.trace.andThen(fk).compose(gk)
}

}
}

implicit final class SpanOpsSyntax[F[_]](
private val ops: SpanOps[F]
) extends AnyVal {

def translate[G[_]](fk: F ~> G, gk: G ~> F)(implicit
F: MonadCancel[F, _],
G: MonadCancel[G, _]
): SpanOps[G] =
new SpanOps[G] {
def startUnmanaged: G[Span[G]] =
fk(ops.startUnmanaged).map(span => span.mapK(fk))

def resource: Resource[G, Res[G]] =
ops.resource.map(res => res.translate(fk, gk)).mapK(fk)

def use[A](f: Span[G] => G[A]): G[A] =
fk(ops.use(span => gk(f(span.mapK(fk)))))

def use_ : G[Unit] =
fk(ops.use_)
}

}

def liftOptionT[F[_]](ops: SpanOps[F])(implicit
F: MonadCancel[F, _]
): SpanOps[OptionT[F, *]] = {
new SpanOps[OptionT[F, *]] {

def startUnmanaged: OptionT[F, Span[OptionT[F, *]]] =
OptionT.liftF(ops.startUnmanaged).map(span => span.mapK(OptionT.liftK))

def resource: Resource[OptionT[F, *], Res[OptionT[F, *]]] =
ops.resource
.map(res =>
new Res[OptionT[F, *]] {
def span: Span[OptionT[F, *]] =
res.span.mapK(OptionT.liftK)

def trace: OptionT[F, *] ~> OptionT[F, *] =
new (OptionT[F, *] ~> OptionT[F, *]) {
def apply[A](fa: OptionT[F, A]): OptionT[F, A] =
OptionT(res.trace.apply(fa.value))
}
}
)
.mapK(OptionT.liftK)

def use[A](f: Span[OptionT[F, *]] => OptionT[F, A]): OptionT[F, A] =
OptionT(ops.use(span => f(span.mapK(OptionT.liftK)).value))

def use_ : OptionT[F, Unit] =
OptionT.liftF(ops.use_)
}
}
}
Loading

0 comments on commit 5a12d7f

Please sign in to comment.