aboutsummaryrefslogtreecommitdiff
path: root/kamon-core/src/main/scala/kamon/context/Context.scala
blob: f7c7838894d48b2243e13039d5bed7b9dcee2e36 (plain) (blame)
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
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]
}*/