forked from trace4cats/trace4cats
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNatchezExample.scala
80 lines (72 loc) · 3.09 KB
/
NatchezExample.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// Adapted from Natchez
// Copyright (c) 2019 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT
package io.janstenpickle.trace4cats.example
import cats.data.Kleisli
import cats.effect.{Blocker, Concurrent, ContextShift, ExitCode, IO, IOApp, Resource, Sync, Timer}
import cats.instances.int._
import cats.syntax.apply._
import cats.syntax.flatMap._
import cats.syntax.functor._
import cats.syntax.parallel._
import cats.syntax.partialOrder._
import cats.{Monad, Order, Parallel}
import io.janstenpickle.trace4cats.`export`.CompleterConfig
import io.janstenpickle.trace4cats.avro.AvroSpanCompleter
import io.janstenpickle.trace4cats.inject.{Trace => T4CTrace}
import io.janstenpickle.trace4cats.kernel.SpanSampler
import io.janstenpickle.trace4cats.model.TraceProcess
import io.janstenpickle.trace4cats.natchez.Trace4CatsTracer
import io.janstenpickle.trace4cats.natchez.conversions.fromNatchez._
import natchez.{EntryPoint, Trace, Span => NatchezSpan}
import scala.concurrent.duration._
import scala.util.Random
/** Adapted from https://github.com/tpolecat/natchez/blob/b995b0ebf7b180666810f4edef46dce959596ace/modules/examples/src/main/scala/Example.scala
*
* This example demonstrates how to use Natchez to implicitly pass spans around the callstack.
*/
object NatchezExample extends IOApp {
def entryPoint[F[_]: Concurrent: ContextShift: Timer](
blocker: Blocker,
process: TraceProcess
): Resource[F, EntryPoint[F]] =
AvroSpanCompleter.udp[F](blocker, process, config = CompleterConfig(batchTimeout = 50.millis)).map { completer =>
Trace4CatsTracer.entryPoint[F](SpanSampler.probabilistic[F](0.05), completer)
}
// Intentionally slow parallel quicksort, to demonstrate branching. If we run too quickly it seems
// to break Jaeger with "skipping clock skew adjustment" so let's pause a bit each time.
def qsort[F[_]: Monad: Parallel: Trace: Timer, A: Order](as: List[A]): F[List[A]] =
Trace[F].span(as.mkString(",")) {
Timer[F].sleep(10.milli) *> {
as match {
case Nil => Monad[F].pure(Nil)
case h :: t =>
val (a, b) = t.partition(_ <= h)
(qsort[F, A](a), qsort[F, A](b)).parMapN(_ ++ List(h) ++ _)
}
}
}
// Demonstrate implicit conversion from Natchez trace to Trace4Cats
// use io.janstenpickle.trace4cats.natchez.conversions._ to do this
def convertedTrace[F[_]: T4CTrace]: F[Unit] = T4CTrace[F].put("attribute", "test")
def runF[F[_]: Sync: Trace: Parallel: Timer]: F[Unit] =
Trace[F].span("Sort some stuff!") {
for {
as <- Sync[F].delay(List.fill(100)(Random.nextInt(1000)))
_ <- qsort[F, Int](as)
_ <- convertedTrace[F]
} yield ()
}
override def run(args: List[String]): IO[ExitCode] =
(for {
blocker <- Blocker[IO]
ep <- entryPoint[IO](blocker, TraceProcess("natchez"))
} yield ep)
.use { ep =>
ep.root("this is the root span").use { span =>
runF[Kleisli[IO, NatchezSpan[IO], *]].run(span)
}
}
.as(ExitCode.Success)
}