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
|
package kamon
import java.util.UUID
import akka.actor._
import java.util.concurrent.atomic.AtomicLong
import kamon.trace.UowTraceAggregator
import scala.concurrent.duration._
import kamon.newrelic.NewRelicReporting
import kamon.trace.UowTracing.Start
// TODO: Decide if we need or not an ID, generating it takes time and it doesn't seem necessary.
case class TraceContext(id: Long, tracer: ActorRef, uow: String = "", userContext: Option[Any] = None)
object TraceContext {
val reporter = Kamon.actorSystem.actorOf(Props[NewRelicReporting])
val traceIdCounter = new AtomicLong
def apply()(implicit system: ActorSystem) = {
val n = traceIdCounter.incrementAndGet()
val actor = system.actorOf(UowTraceAggregator.props(reporter, 30 seconds), s"tracer-${n}")
actor ! Start()
new TraceContext(n, actor) // TODO: Move to a kamon specific supervisor, like /user/kamon/tracer
}
}
class TraceAccumulator extends Actor {
def receive = {
case a => println("Trace Accumulated: "+a)
}
}
trait TraceEntry
case class CodeBlockExecutionTime(name: String, begin: Long, end: Long) extends TraceEntry
case class TransactionTrace(id: UUID, start: Long, end: Long, entries: Seq[TraceEntry])
object Collector
trait TraceEntryStorage {
def store(entry: TraceEntry): Boolean
}
class TransactionContext(val id: UUID, private val storage: TraceEntryStorage) {
def store(entry: TraceEntry) = storage.store(entry)
}
object ThreadLocalTraceEntryStorage extends TraceEntryStorage {
private val storage = new ThreadLocal[List[TraceEntry]] {
override def initialValue(): List[TraceEntry] = Nil
}
def update(f: List[TraceEntry] => List[TraceEntry]) = storage set f(storage.get)
def store(entry: TraceEntry): Boolean = {
update(entry :: _)
true
}
}
|