blob: f7c7838894d48b2243e13039d5bed7b9dcee2e36 (
plain) (
tree)
|
|
package kamon.context
class Context private (private val keys: Map[Key[_], Any]) {
def get[T](key: Key[T]): T =
keys.get(key).getOrElse(key.emptyValue).asInstanceOf[T]
def withKey[T](key: Key[T], value: T): Context =
new Context(keys.updated(key, value))
}
object Context {
val Empty = new Context(Map.empty)
def apply(): Context = Empty
def create(): Context = Empty
}
trait Key[T] {
def name: String
def emptyValue: T
def broadcast: Boolean
}
object Key {
def local[T](name: String, emptyValue: T): Key[T] =
new Default[T](name, emptyValue, false)
def broadcast[T](name: String, emptyValue: T): Key[T] =
new Default[T](name, emptyValue, true)
private class Default[T](val name: String, val emptyValue: T, val broadcast: Boolean) extends Key[T] {
override def hashCode(): Int =
name.hashCode
override def equals(that: Any): Boolean =
that.isInstanceOf[Default[_]] && that.asInstanceOf[Default[_]].name == this.name
}
}
trait Storage {
def current(): Context
def store(context: Context): Scope
trait Scope {
def context: Context
def close(): Unit
}
}
object Storage {
class ThreadLocal extends Storage {
private val tls = new java.lang.ThreadLocal[Context]() {
override def initialValue(): Context = Context.Empty
}
override def current(): Context =
tls.get()
override def store(context: Context): Scope = {
val newContext = context
val previousContext = tls.get()
tls.set(newContext)
new Scope {
override def context: Context = newContext
override def close(): Unit = tls.set(previousContext)
}
}
}
}
trait KeyCodec[T] {
def encode(context: Context): T
def decode(carrier: T, context: Context): Context
}
/*
object Example {
// this is defined somewhere statically, only once.
val User = Key.local[Option[User]]("user", None)
val Client = Key.local[Option[User]]("client", null)
val Span = Key.broadcast[Span]("span", EmptySpan)
val storage = Kamon.contextStorage // or something similar.
storage.get(Span) // returns a Span instance or EmptySpan.
storage.get(User) // Returns Option[User] or None if not set.
storage.get(Client) // Returns Option[Client] or null if not set.
// Context Propagation works the very same way as before.
val scope = storage.store(context)
// do something here
scope.close()
// Configuration for codecs would be handled sort of like this:
// kamon.context.propagation {
// http-header-codecs {
// "span" = kamon.trace.propagation.B3
// }
//
// binary-codecs {
// "span" = kamon.trace.propagation.Binary
// }
// }
}*/
/*
class Context(private val keys: Map[Key[_], Any]) {
}
object Context {
}
sealed trait Key[T] {
def name: String
}
object Key {
def local[T](name: String): Key[T] = Local(name)
case class Local[T](name: String) extends Key[T]
}*/
|