-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Tracing #177
Improve Tracing #177
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,16 @@ | ||
package com.dwolla.consul.examples | ||
|
||
import cats.effect._ | ||
import natchez.Trace | ||
import natchez.noop.NoopSpan | ||
import natchez.Span | ||
import natchez.mtl.natchezMtlTraceForLocal | ||
import natchez.noop.NoopEntrypoint | ||
import org.typelevel.log4cats.LoggerFactory | ||
import org.typelevel.log4cats.noop.NoOpFactory | ||
|
||
trait ConsulMiddlewareAppPlatform extends IOApp.Simple { | ||
trait ConsulMiddlewareAppPlatform extends IOApp.Simple with LocalTracing { | ||
private implicit val noOpFactory: LoggerFactory[IO] = NoOpFactory[IO] | ||
|
||
override def run: IO[Unit] = Trace.ioTrace(NoopSpan[IO]()).flatMap { implicit trace => | ||
new ConsulMiddlewareApp[IO].run | ||
override def run: IO[Unit] = IOLocal(Span.noop[IO]).map(catsMtlEffectLocalForIO(_)).flatMap { implicit L => | ||
new ConsulMiddlewareApp[IO](NoopEntrypoint[IO]()).run | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,16 @@ | ||
package com.dwolla.consul.examples | ||
|
||
import cats.effect._ | ||
import natchez.Trace | ||
import natchez.noop.NoopSpan | ||
import natchez.Span | ||
import natchez.mtl.natchezMtlTraceForLocal | ||
import natchez.noop.NoopEntrypoint | ||
import org.typelevel.log4cats.LoggerFactory | ||
import org.typelevel.log4cats.noop.NoOpFactory | ||
|
||
trait ConsulServiceDiscoveryAlgAppPlatform extends IOApp.Simple { | ||
trait ConsulServiceDiscoveryAlgAppPlatform extends IOApp.Simple with LocalTracing { | ||
private implicit val noOpFactory: LoggerFactory[IO] = NoOpFactory[IO] | ||
|
||
override def run: IO[Unit] = Trace.ioTrace(NoopSpan[IO]()).flatMap { implicit trace => | ||
new ConsulServiceDiscoveryAlgApp[IO].run | ||
override def run: IO[Unit] = IOLocal(Span.noop[IO]).map(catsMtlEffectLocalForIO(_)).flatMap { implicit L => | ||
new ConsulServiceDiscoveryAlgApp[IO](NoopEntrypoint[IO]()).run | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,18 @@ | ||
package com.dwolla.consul | ||
|
||
import cats.effect.kernel.Resource.ExitCase | ||
import cats.{Monad, ~>} | ||
import cats.effect.std.Random | ||
import cats.effect.syntax.all._ | ||
import cats.effect.{Trace => _, _} | ||
import cats.mtl.Local | ||
import cats.syntax.all._ | ||
import cats.{Monad, ~>} | ||
import com.dwolla.consul.ThirdPartyTypeCodecs._ | ||
import fs2.Stream | ||
import io.circe.optics.JsonPath.root | ||
import io.circe.{Decoder, Json} | ||
import monocle.Traversal | ||
import natchez.Trace | ||
import natchez.{EntryPoint, Span, Trace} | ||
import org.http4s.Method.GET | ||
import org.http4s._ | ||
import org.http4s.circe.jsonOf | ||
|
@@ -54,7 +55,9 @@ trait ConsulServiceDiscoveryAlg[F[_]] { self => | |
object ConsulServiceDiscoveryAlg { | ||
def apply[F[_] : Temporal : LoggerFactory : Random : Trace](consulBaseUri: Uri, | ||
longPollTimeout: FiniteDuration, | ||
client: Client[F]): F[ConsulServiceDiscoveryAlg[F]] = | ||
client: Client[F], | ||
entryPoint: EntryPoint[F]) | ||
(implicit L: Local[F, Span[F]]): F[ConsulServiceDiscoveryAlg[F]] = | ||
LoggerFactory[F] | ||
.create(LoggerName("com.dwolla.consul.ConsulServiceDiscoveryAlg")) | ||
.map { implicit l => | ||
|
@@ -63,7 +66,7 @@ object ConsulServiceDiscoveryAlg { | |
lookup[F](serviceName, consulBaseUri, None, longPollTimeout, client) | ||
.toResource | ||
.flatMap { case (initialValue, initialConsulIndex) => | ||
continuallyUpdating(serviceName, initialValue, initialConsulIndex, consulBaseUri, longPollTimeout, client) | ||
continuallyUpdating(serviceName, initialValue, initialConsulIndex, consulBaseUri, longPollTimeout, client, entryPoint) | ||
} | ||
.onFinalize(Logger[F].trace(s"👋 shutting down authoritiesForService($serviceName)")) | ||
} | ||
|
@@ -145,25 +148,42 @@ object ConsulServiceDiscoveryAlg { | |
initialConsulIndex: Option[ConsulIndex], | ||
consulBase: Uri, | ||
longPollTimeout: FiniteDuration, | ||
client: Client[F]): Resource[F, F[Vector[Uri.Authority]]] = | ||
client: Client[F], | ||
entryPoint: EntryPoint[F], | ||
) | ||
(implicit L: Local[F, Span[F]]): Resource[F, F[Vector[Uri.Authority]]] = | ||
Stream.unfoldEval(initialConsulIndex) { maybeIndex => | ||
// since this is a background task, it doesn't make sense to attach it to the trace that initially started it | ||
import natchez.Trace.Implicits.noop | ||
|
||
lookup[F](serviceName, consulBase, maybeIndex, longPollTimeout, client) | ||
.map(_.leftMap(_.some)) // if we successfully got values, wrap them in Some so we can unNone later | ||
.handleErrorWith { | ||
// TODO maybe we should introduce some kind of escalating delay here? | ||
Logger[F].warn(_)("🔥 An exception occurred getting service details from Consul; retrying") | ||
.as((none[Vector[Uri.Authority]], maybeIndex)) // continue successfully, but emit None so the failure can be filtered out later | ||
} | ||
.map(_.some) // this stream will unfold forever (well, until its Resource is finalized) | ||
inNewLinkedRootSpan(entryPoint) { // since this is a background task, it doesn't make sense | ||
import natchez.mtl._ // to directly attach it to the trace that initially started it, | ||
// but linking it to the new root span is helpful | ||
|
||
lookup[F](serviceName, consulBase, maybeIndex, longPollTimeout, client) | ||
.map(_.leftMap(_.some)) // if we successfully got values, wrap them in Some so we can unNone later | ||
.handleErrorWith { | ||
// TODO maybe we should introduce some kind of escalating delay here? | ||
Logger[F].warn(_)("🔥 An exception occurred getting service details from Consul; retrying") | ||
.as((none[Vector[Uri.Authority]], maybeIndex)) // continue successfully, but emit None so the failure can be filtered out later | ||
} | ||
.map(_.some) // this stream will unfold forever (well, until its Resource is finalized) | ||
} | ||
} | ||
.unNone // errors returned by `lookup` are emitted as None, so filter them out | ||
.unNone // errors returned by `lookup` are emitted as None, so filter them out | ||
.holdResource(initialValue) | ||
.onFinalize(Logger[F].trace(s"👋 shutting down continuallyUpdating($serviceName, …)")) | ||
.map(_.get) | ||
|
||
private def inNewLinkedRootSpan[F[_] : MonadCancelThrow, A](entryPoint: EntryPoint[F]) | ||
(fa: F[A]) | ||
(implicit L: Local[F, Span[F]]): F[A] = | ||
natchez.mtl.natchezMtlTraceForLocal | ||
.kernel | ||
.map(Span.Options.Defaults.withLink) | ||
.flatMap { | ||
entryPoint | ||
.root("com.dwolla.consul.ConsulServiceDiscoveryAlg.continuallyUpdating", _) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We technically don't need to create a new root span here; we could use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And AFAICT we really do need |
||
.use(Local[F, Span[F]].scope(fa)) | ||
} | ||
|
||
private[consul] def serviceListUri(consulBase: Uri, | ||
serviceName: ServiceName, | ||
index: Option[ConsulIndex], | ||
|
@@ -172,15 +192,6 @@ object ConsulServiceDiscoveryAlg { | |
consulBase / "v1" / "health" / "service" / serviceName +? OnlyHealthyServices +?? index +?? index.as(WaitPeriod(longPollTimeout)) | ||
|
||
private implicit def jsonEntityDecoder[F[_] : Concurrent, A: Decoder]: EntityDecoder[F, A] = jsonOf[F, A] | ||
|
||
@deprecated("used traced version", "0.2.0") | ||
def apply[F[_]](consulBaseUri: Uri, | ||
longPollTimeout: FiniteDuration, | ||
client: Client[F], | ||
F: Temporal[F], | ||
L: LoggerFactory[F], | ||
R: Random[F]): F[ConsulServiceDiscoveryAlg[F]] = | ||
ConsulServiceDiscoveryAlg(consulBaseUri, longPollTimeout, client)(F, L, R, natchez.Trace.Implicits.noop(F)) | ||
} | ||
|
||
abstract class AbstractConsulServiceDiscoveryAlg[F[_] : Random : Monad] extends ConsulServiceDiscoveryAlg[F] { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
noop
Trace[F]
previously passed tolookup
prevented the span creation immediately withinlookup
(e.g. the span namedcom.dwolla.consul.ConsulServiceDiscoveryAlg.lookup
) but the issue is observable when using aClient[F]
that has been wrapped in the Natchez middleware from natchez-http4s. Assuming it's using aLocal[F, Span[F]]
-based MTLTrace[F]
, the span referenced by the Natchez middleware is not the noop span, but the current value of theLocal
instance, meaning the middleware creates a new span and sends that trace's kernel as part of the request being made.