From 91b01c6bdc905db9db7874fb0a66574463a0d484 Mon Sep 17 00:00:00 2001 From: Ivan Topolnjak Date: Fri, 2 Feb 2018 03:35:02 +0100 Subject: allow arbitrary header names for automatic broadcast string keys --- kamon-core-tests/src/test/resources/reference.conf | 5 +++++ .../scala/kamon/context/ContextCodecSpec.scala | 8 ++++++++ kamon-core/src/main/resources/reference.conf | 19 ++++++++++++++++++- .../src/main/scala/kamon/context/Codecs.scala | 22 +++++++++++----------- kamon-testkit/src/main/resources/reference.conf | 4 +++- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/kamon-core-tests/src/test/resources/reference.conf b/kamon-core-tests/src/test/resources/reference.conf index e69de29b..0d7ae9e2 100644 --- a/kamon-core-tests/src/test/resources/reference.conf +++ b/kamon-core-tests/src/test/resources/reference.conf @@ -0,0 +1,5 @@ +kamon { + context.codecs.string-keys { + request-id = "X-Request-ID" + } +} \ No newline at end of file diff --git a/kamon-core-tests/src/test/scala/kamon/context/ContextCodecSpec.scala b/kamon-core-tests/src/test/scala/kamon/context/ContextCodecSpec.scala index bc46c998..f7bd7e56 100644 --- a/kamon-core-tests/src/test/scala/kamon/context/ContextCodecSpec.scala +++ b/kamon-core-tests/src/test/scala/kamon/context/ContextCodecSpec.scala @@ -48,6 +48,14 @@ class ContextCodecSpec extends WordSpec with Matchers with ContextTesting with O decodedContext.get(StringKey) shouldBe empty decodedContext.get(StringBroadcastKey).value shouldBe "this-should-be-round-tripped" } + + "read string broadcast keys using the configured header name" in { + val textMap = TextMap.Default() + textMap.put("X-Request-ID", "123456") + val decodedContext = ContextCodec.HttpHeaders.decode(textMap) + + decodedContext.get(Key.broadcastString("request-id")).value shouldBe "123456" + } } "encoding/decoding to Binary" should { diff --git a/kamon-core/src/main/resources/reference.conf b/kamon-core/src/main/resources/reference.conf index 2d37780d..659114ca 100644 --- a/kamon-core/src/main/resources/reference.conf +++ b/kamon-core/src/main/resources/reference.conf @@ -150,7 +150,24 @@ kamon { # Size of the encoding buffer for the Binary Codec. binary-buffer-size = 256 - string-keys = [ ] + # Declarative definition of broadcast context keys with type Option[String]. The setting key represents the actual + # key name and the value is the HTTP header name to be used to encode/decode the context key. The key name will + # be used when coding for binary transport. The most common use case for string keys is effortless propagation of + # correlation keys or request related data (locale, user ID, etc). E.g. if wanting to propagate a "X-Request-ID" + # header this config should suffice: + # + # kamon.context.codecs.string-keys { + # request-id = "X-Request-ID" + # } + # + # If the application must read this context key they can define key with a matching name and read the value from + # the context: + # val requestIDKey = Key.broadcastString("request-id") // Do this only once, keep a reference. + # val requestID = Kamon.currentContext().get(requestIDKey) + # + string-keys { + + } # Codecs to be used when propagating a Context through a HTTP Headers transport. http-headers-keys { diff --git a/kamon-core/src/main/scala/kamon/context/Codecs.scala b/kamon-core/src/main/scala/kamon/context/Codecs.scala index 8ba70157..c5d237a9 100644 --- a/kamon-core/src/main/scala/kamon/context/Codecs.scala +++ b/kamon-core/src/main/scala/kamon/context/Codecs.scala @@ -43,7 +43,7 @@ class Codecs(initialConfig: Config) { import scala.collection.JavaConverters._ try { val codecsConfig = config.getConfig("kamon.context.codecs") - val stringKeys = codecsConfig.getStringList("string-keys").asScala + val stringKeys = readStringKeysConfig(codecsConfig.getConfig("string-keys")) val knownHttpHeaderCodecs = readEntryCodecs[TextMap]("http-headers-keys", codecsConfig) ++ stringHeaderCodecs(stringKeys) val knownBinaryCodecs = readEntryCodecs[ByteBuffer]("binary-keys", codecsConfig) ++ stringBinaryCodecs(stringKeys) @@ -72,13 +72,14 @@ class Codecs(initialConfig: Config) { entries.result() } - private def stringHeaderCodecs(keys: Seq[String]): Map[String, Codecs.ForEntry[TextMap]] = { - keys.map(key => (key, new Codecs.StringHeadersCodec(key))).toMap - } + private def readStringKeysConfig(config: Config): Map[String, String] = + config.topLevelKeys.map(key => (key, config.getString(key))).toMap - private def stringBinaryCodecs(keys: Seq[String]): Map[String, Codecs.ForEntry[ByteBuffer]] = { - keys.map(key => (key, new Codecs.StringBinaryCodec(key))).toMap - } + private def stringHeaderCodecs(keys: Map[String, String]): Map[String, Codecs.ForEntry[TextMap]] = + keys.map { case (key, header) => (key, new Codecs.StringHeadersCodec(key, header)) } + + private def stringBinaryCodecs(keys: Map[String, String]): Map[String, Codecs.ForEntry[ByteBuffer]] = + keys.map { case (key, _) => (key, new Codecs.StringBinaryCodec(key)) } } object Codecs { @@ -224,21 +225,20 @@ object Codecs { } } - private class StringHeadersCodec(key: String) extends Codecs.ForEntry[TextMap] { - private val dataKey = "X-KamonContext-" + key + private class StringHeadersCodec(key: String, headerName: String) extends Codecs.ForEntry[TextMap] { private val contextKey = Key.broadcast[Option[String]](key, None) override def encode(context: Context): TextMap = { val textMap = TextMap.Default() context.get(contextKey).foreach { value => - textMap.put(dataKey, value) + textMap.put(headerName, value) } textMap } override def decode(carrier: TextMap, context: Context): Context = { - carrier.get(dataKey) match { + carrier.get(headerName) match { case value @ Some(_) => context.withKey(contextKey, value) case None => context } diff --git a/kamon-testkit/src/main/resources/reference.conf b/kamon-testkit/src/main/resources/reference.conf index 44abb535..2bd3c82e 100644 --- a/kamon-testkit/src/main/resources/reference.conf +++ b/kamon-testkit/src/main/resources/reference.conf @@ -1,5 +1,7 @@ kamon { context.codecs { - string-keys = [ "string-broadcast-key" ] + string-keys { + string-broadcast-key = "X-string-broadcast-key" + } } } \ No newline at end of file -- cgit v1.2.3