-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
340 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
opencensus/src/main/scala/zio/telemetry/opencensus/Attribute.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package zio.telemetry.opencensus | ||
|
||
import io.opencensus.trace.AttributeValue | ||
|
||
object Attributes { | ||
trait implicits { | ||
import scala.language.implicitConversions | ||
|
||
implicit def boolToAttribute(b: Boolean): AttributeValue = | ||
AttributeValue.booleanAttributeValue(b) | ||
|
||
implicit def stringToAttribute(s: String): AttributeValue = | ||
AttributeValue.stringAttributeValue(s) | ||
|
||
implicit def longToAttribute(l: Long): AttributeValue = | ||
AttributeValue.longAttributeValue(l) | ||
|
||
implicit def doubleToAttribute(d: Double): AttributeValue = | ||
AttributeValue.doubleAttributeValue(d) | ||
} | ||
} |
147 changes: 147 additions & 0 deletions
147
opencensus/src/main/scala/zio/telemetry/opencensus/Live.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package zio.telemetry.opencensus | ||
|
||
import zio._ | ||
|
||
import io.opencensus.trace.AttributeValue | ||
import io.opencensus.trace.BlankSpan | ||
import io.opencensus.trace.Span | ||
import io.opencensus.trace.SpanContext | ||
import io.opencensus.trace.Status | ||
import io.opencensus.trace.propagation.TextFormat | ||
import io.opencensus.trace.Tracer | ||
|
||
object Live { | ||
val live: URLayer[Has[Tracer], Tracing] = | ||
ZLayer.fromManaged(for { | ||
tracer <- ZIO.access[Has[Tracer]](_.get).toManaged_ | ||
tracing = FiberRef.make[Span](BlankSpan.INSTANCE).map(new Live(tracer, _)) | ||
managed <- ZManaged.make(tracing)(_.end) | ||
} yield managed) | ||
} | ||
|
||
class Live(tracer: Tracer, root: FiberRef[Span]) extends Tracing.Service { | ||
val currentSpan_ = root | ||
|
||
def currentSpan: UIO[Span] = currentSpan_.get | ||
|
||
def span[R, E, A]( | ||
name: String, | ||
kind: Span.Kind = Span.Kind.SERVER, | ||
toErrorStatus: ErrorMapper[E], | ||
attributes: Map[String, AttributeValue] | ||
)(effect: ZIO[R, E, A]): ZIO[R, E, A] = | ||
for { | ||
parent <- currentSpan_.get | ||
res <- createSpan(parent, name, kind).use( | ||
finalizeSpanUsingEffect( | ||
putAttributes(attributes) *> effect, | ||
toErrorStatus | ||
) | ||
) | ||
} yield res | ||
|
||
def root[R, E, A]( | ||
name: String, | ||
kind: Span.Kind, | ||
toErrorStatus: ErrorMapper[E], | ||
attributes: Map[String, AttributeValue] | ||
)(effect: ZIO[R, E, A]): ZIO[R, E, A] = | ||
for { | ||
res <- createSpan(BlankSpan.INSTANCE, name, kind).use( | ||
finalizeSpanUsingEffect( | ||
putAttributes(attributes) *> effect, | ||
toErrorStatus | ||
) | ||
) | ||
} yield res | ||
|
||
def fromRemoteSpan[R, E, A]( | ||
remote: SpanContext, | ||
name: String, | ||
kind: Span.Kind, | ||
toErrorStatus: ErrorMapper[E], | ||
attributes: Map[String, AttributeValue] | ||
)(effect: ZIO[R, E, A]): ZIO[R, E, A] = | ||
for { | ||
res <- createSpanFromRemote(remote, name, kind).use( | ||
finalizeSpanUsingEffect( | ||
putAttributes(attributes) *> effect, | ||
toErrorStatus | ||
) | ||
) | ||
} yield res | ||
|
||
def putAttributes( | ||
attributes: Map[String, AttributeValue] | ||
): ZIO[Any, Nothing, Unit] = | ||
for { | ||
current <- currentSpan_.get | ||
_ <- UIO(attributes.foreach({ | ||
case ((k, v)) => current.putAttribute(k, v) | ||
})) | ||
} yield () | ||
|
||
private def createSpan( | ||
parent: Span, | ||
name: String, | ||
kind: Span.Kind | ||
): UManaged[Span] = | ||
ZManaged.make( | ||
UIO( | ||
tracer | ||
.spanBuilderWithExplicitParent(name, parent) | ||
.setSpanKind(kind) | ||
.startSpan() | ||
) | ||
)(span => UIO(span.end)) | ||
|
||
private def createSpanFromRemote( | ||
parent: SpanContext, | ||
name: String, | ||
kind: Span.Kind | ||
): UManaged[Span] = | ||
ZManaged.make( | ||
UIO( | ||
tracer | ||
.spanBuilderWithRemoteParent(name, parent) | ||
.setSpanKind(kind) | ||
.startSpan() | ||
) | ||
)(span => UIO(span.end)) | ||
|
||
private def finalizeSpanUsingEffect[R, E, A]( | ||
effect: ZIO[R, E, A], | ||
toErrorStatus: ErrorMapper[E] | ||
)(span: Span): ZIO[R, E, A] = | ||
for { | ||
r <- currentSpan_ | ||
.locally(span)(effect) | ||
.tapCause(setErrorStatus(span, _, toErrorStatus)) | ||
} yield r | ||
|
||
def inject[C, R, E, A]( | ||
format: TextFormat, | ||
carrier: C, | ||
setter: TextFormat.Setter[C] | ||
): UIO[Unit] = | ||
for { | ||
current <- currentSpan | ||
_ <- URIO(format.inject(current.getContext(), carrier, setter)) | ||
} yield () | ||
|
||
private[opencensus] def end: UIO[Unit] = | ||
for { | ||
span <- currentSpan_.get | ||
_ <- UIO(span.end()) | ||
} yield () | ||
|
||
private def setErrorStatus[E]( | ||
span: Span, | ||
cause: Cause[E], | ||
toErrorStatus: ErrorMapper[E] | ||
): UIO[Unit] = { | ||
val errorStatus = | ||
cause.failureOption.flatMap(toErrorStatus.lift).getOrElse(Status.UNKNOWN) | ||
UIO(span.setStatus(errorStatus)) | ||
} | ||
} |
108 changes: 108 additions & 0 deletions
108
opencensus/src/main/scala/zio/telemetry/opencensus/Tracing.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package zio.telemetry.opencensus | ||
|
||
import zio._ | ||
|
||
import io.opencensus.trace.Span | ||
import io.opencensus.trace.AttributeValue | ||
import io.opencensus.trace.SpanContext | ||
import io.opencensus.trace.propagation.TextFormat | ||
|
||
object Tracing { | ||
def defaultMapper[E]: ErrorMapper[E] = Map.empty | ||
|
||
trait Service { | ||
def span[R, E, A]( | ||
name: String, | ||
kind: Span.Kind = null, | ||
toErrorStatus: ErrorMapper[E] = defaultMapper[E], | ||
attributes: Map[String, AttributeValue] = Map() | ||
)(effect: ZIO[R, E, A]): ZIO[R, E, A] | ||
|
||
def root[R, E, A]( | ||
name: String, | ||
kind: Span.Kind = null, | ||
toErrorStatus: ErrorMapper[E] = defaultMapper[E], | ||
attributes: Map[String, AttributeValue] = Map() | ||
)(effect: ZIO[R, E, A]): ZIO[R, E, A] | ||
|
||
def fromRemoteSpan[R, E, A]( | ||
remote: SpanContext, | ||
name: String, | ||
kind: Span.Kind = Span.Kind.SERVER, | ||
toErrorStatus: ErrorMapper[E] = defaultMapper[E], | ||
attributes: Map[String, AttributeValue] = Map() | ||
)(effect: ZIO[R, E, A]): ZIO[R, E, A] | ||
|
||
def inject[C, R, E, A]( | ||
format: TextFormat, | ||
carrier: C, | ||
setter: TextFormat.Setter[C] | ||
): UIO[Unit] | ||
|
||
def putAttributes( | ||
attrs: Map[String, AttributeValue] | ||
): ZIO[Any, Nothing, Unit] | ||
|
||
private[opencensus] def end: UIO[Unit] | ||
} | ||
|
||
def span[R, E, A]( | ||
name: String, | ||
kind: Span.Kind = null, | ||
toErrorStatus: ErrorMapper[E] = defaultMapper[E], | ||
attributes: Map[String, AttributeValue] = Map() | ||
)(effect: ZIO[R, E, A]): ZIO[R with Tracing, E, A] = | ||
ZIO.accessM(_.get.span(name, kind, toErrorStatus, attributes)(effect)) | ||
|
||
def root[R, E, A]( | ||
name: String, | ||
kind: Span.Kind = null, | ||
toErrorStatus: ErrorMapper[E] = defaultMapper[E], | ||
attributes: Map[String, AttributeValue] = Map() | ||
)(effect: ZIO[R, E, A]): ZIO[R with Tracing, E, A] = | ||
ZIO.accessM(_.get.root(name, kind, toErrorStatus, attributes)(effect)) | ||
|
||
def fromRemoteSpan[R, E, A]( | ||
remote: SpanContext, | ||
name: String, | ||
kind: Span.Kind = null, | ||
toErrorStatus: ErrorMapper[E] = defaultMapper[E], | ||
attributes: Map[String, AttributeValue] = Map() | ||
)(effect: ZIO[R, E, A]): ZIO[R with Tracing, E, A] = | ||
ZIO.accessM( | ||
_.get.fromRemoteSpan(remote, name, kind, toErrorStatus, attributes)( | ||
effect | ||
) | ||
) | ||
|
||
def putAttributes( | ||
attributes: (String, AttributeValue)* | ||
): ZIO[Tracing, Nothing, Unit] = | ||
ZIO.accessM(_.get.putAttributes(attributes.toMap)) | ||
|
||
def withAttributes[R, E, A]( | ||
attributes: (String, AttributeValue)* | ||
)(eff: ZIO[R, E, A]): ZIO[R with Tracing, E, A] = | ||
ZIO.accessM[Tracing](_.get.putAttributes(attributes.toMap)) *> eff | ||
|
||
def fromRootSpan[C, R, E, A]( | ||
format: TextFormat, | ||
carrier: C, | ||
getter: TextFormat.Getter[C], | ||
name: String, | ||
kind: Span.Kind = Span.Kind.SERVER, | ||
toErrorStatus: ErrorMapper[E] = defaultMapper[E], | ||
attributes: Map[String, AttributeValue] = Map() | ||
)(effect: ZIO[R, E, A]): ZIO[R with Tracing, E, A] = | ||
Task(format.extract(carrier, getter)).foldM( | ||
_ => root(name, kind, toErrorStatus)(effect), | ||
remote => fromRemoteSpan(remote, name, kind, toErrorStatus, attributes)(effect) | ||
) | ||
|
||
def inject[C, R, E, A]( | ||
format: TextFormat, | ||
carrier: C, | ||
setter: TextFormat.Setter[C] | ||
): URIO[R with Tracing, Unit] = | ||
ZIO.accessM(_.get.inject(format, carrier, setter)) | ||
} |
11 changes: 11 additions & 0 deletions
11
opencensus/src/main/scala/zio/telemetry/opencensus/package.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package zio.telemetry | ||
|
||
import io.opencensus.trace.Status | ||
|
||
import zio.Has | ||
package object opencensus { | ||
object implicits extends Attributes.implicits | ||
|
||
type Tracing = Has[Tracing.Service] | ||
type ErrorMapper[E] = PartialFunction[E, Status] | ||
} |
41 changes: 41 additions & 0 deletions
41
opencensus/src/main/scala/zio/telemetry/opencensus/syntax.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package zio.telemetry.opencensus | ||
|
||
import zio._ | ||
|
||
import io.opencensus.trace.AttributeValue | ||
import io.opencensus.trace.SpanContext | ||
import io.opencensus.trace.Span | ||
|
||
object syntax { | ||
implicit final class OpenCensusZioOps[R, E, A](val effect: ZIO[R, E, A]) extends AnyVal { | ||
def span( | ||
name: String, | ||
kind: Span.Kind = null, | ||
toErrorStatus: ErrorMapper[E] = Tracing.defaultMapper[E], | ||
attributes: Map[String, AttributeValue] | ||
): ZIO[R with Tracing, E, A] = | ||
Tracing.span(name, kind, toErrorStatus, attributes)(effect) | ||
|
||
def root( | ||
name: String, | ||
kind: Span.Kind = null, | ||
toErrorStatus: ErrorMapper[E] = Tracing.defaultMapper[E], | ||
attributes: Map[String, AttributeValue] | ||
): ZIO[R with Tracing, E, A] = | ||
Tracing.root(name, kind, toErrorStatus, attributes)(effect) | ||
|
||
def fromRemoteSpan( | ||
remote: SpanContext, | ||
name: String, | ||
kind: Span.Kind, | ||
toErrorStatus: ErrorMapper[E], | ||
attributes: Map[String, AttributeValue] | ||
): ZIO[R with Tracing, E, A] = | ||
Tracing.fromRemoteSpan(remote, name, kind, toErrorStatus, attributes)(effect) | ||
|
||
def withAttributes( | ||
attributes: (String, AttributeValue)* | ||
): ZIO[R with Tracing, E, A] = | ||
Tracing.withAttributes(attributes: _*)(effect) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters