diff --git a/internal-api/src/main/java/datadog/trace/api/BaseHash.java b/internal-api/src/main/java/datadog/trace/api/BaseHash.java index eac65fe1c38..8aa17c4a0ff 100644 --- a/internal-api/src/main/java/datadog/trace/api/BaseHash.java +++ b/internal-api/src/main/java/datadog/trace/api/BaseHash.java @@ -5,12 +5,17 @@ public final class BaseHash { private static volatile long baseHash; private static volatile String baseHashStr; + private static volatile String lastContainerTagsHash; private BaseHash() {} public static void recalcBaseHash(String containerTagsHash) { - long hash = calc(containerTagsHash); - updateBaseHash(hash); + lastContainerTagsHash = containerTagsHash; + updateBaseHash(calc(containerTagsHash)); + } + + static void recalcBaseHash() { + updateBaseHash(calc(lastContainerTagsHash)); } public static void updateBaseHash(long hash) { diff --git a/internal-api/src/main/java/datadog/trace/api/ProcessTags.java b/internal-api/src/main/java/datadog/trace/api/ProcessTags.java index e3f3d91b03f..3efc957bd27 100644 --- a/internal-api/src/main/java/datadog/trace/api/ProcessTags.java +++ b/internal-api/src/main/java/datadog/trace/api/ProcessTags.java @@ -182,6 +182,7 @@ public static void addTag(String key, String value) { Lazy.stringListForm = null; Lazy.utf8ListForm = null; } + BaseHash.recalcBaseHash(); } } @@ -242,6 +243,7 @@ public static void reset(Config config) { empty(); enabled = config.isExperimentalPropagateProcessTagsEnabled(); Lazy.TAGS.putAll(Lazy.loadTags(config)); + BaseHash.recalcBaseHash(); } } } diff --git a/internal-api/src/test/groovy/datadog/trace/api/BaseHashTest.groovy b/internal-api/src/test/groovy/datadog/trace/api/BaseHashTest.groovy index f3de2b39045..1deb7d97103 100644 --- a/internal-api/src/test/groovy/datadog/trace/api/BaseHashTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/api/BaseHashTest.groovy @@ -1,14 +1,26 @@ package datadog.trace.api -import datadog.trace.test.util.DDSpecification - import static datadog.trace.api.config.GeneralConfig.ENV import static datadog.trace.api.config.GeneralConfig.EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED import static datadog.trace.api.config.GeneralConfig.PRIMARY_TAG import static datadog.trace.api.config.GeneralConfig.SERVICE_NAME +import datadog.trace.test.util.DDSpecification + class BaseHashTest extends DDSpecification { + + def setup() { + // start with fresh process tags + ProcessTags.reset() + } + + def cleanup() { + // restore the default enablement + removeSysConfig(EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED) + ProcessTags.reset() + } + def "Service used in hash calculation"() { when: def firstBaseHash = BaseHash.calc(null) @@ -46,17 +58,54 @@ class BaseHashTest extends DDSpecification { when: def firstBaseHash = BaseHash.calc(null) - injectSysConfig(EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED, "true") - ProcessTags.reset() ProcessTags.addTag("000", "first") def secondBaseHash = BaseHash.calc(null) then: firstBaseHash != secondBaseHash assert ProcessTags.getTagsForSerialization().startsWithAny("000:first,") - cleanup: + } + + def "addTag triggers BaseHash recalculation"() { + given: + BaseHash.recalcBaseHash("container-hash-1") + def hashBefore = BaseHash.getBaseHash() + + when: + ProcessTags.addTag("cluster.name", "new-cluster") + + then: + BaseHash.getBaseHash() != hashBefore + } + + def "recalcBaseHash preserves last containerTagsHash across ProcessTags changes"() { + given: + def containerHash = "my-container-hash" + BaseHash.recalcBaseHash(containerHash) + def hashWithContainerTag = BaseHash.getBaseHash() + + when: "a process tag is added" + ProcessTags.addTag("cluster.name", "new-cluster") + + then: "hash differs from before the tag was added" + BaseHash.getBaseHash() != hashWithContainerTag + + and: "hash equals a fresh calc with the same container hash" + BaseHash.getBaseHash() == BaseHash.calc(containerHash) + } + + def "addTag does not recalculate BaseHash when ProcessTags disabled"() { + setup: injectSysConfig(EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED, "false") ProcessTags.reset() + BaseHash.recalcBaseHash(null) + def hashBefore = BaseHash.getBaseHash() + + when: + ProcessTags.addTag("cluster.name", "ignored") + + then: + BaseHash.getBaseHash() == hashBefore } def "ContainerTagsHash used in hash calculation when provided"() { @@ -76,10 +125,6 @@ class BaseHashTest extends DDSpecification { assert secondBaseHash == firstBaseHash } - cleanup: - injectSysConfig(EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED, "false") - ProcessTags.reset() - where: propagateTagsEnabled << [true, false] }