Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,26 @@ public class TracingHook extends Hook {
static final String INSTRUMENTATION_NAME = "launchdarkly-client";
static final String DATA_KEY_SPAN = "variationSpan";
static final String EVENT_NAME = "feature_flag";
static final String SEMCONV_FEATURE_FLAG_PROVIDER_NAME = "feature_flag.provider_name";
static final String SEMCONV_FEATURE_FLAG_PROVIDER_NAME = "feature_flag.provider.name";
static final String SEMCONV_FEATURE_FLAG_KEY = "feature_flag.key";
static final String SEMCONV_FEATURE_FLAG_VARIANT = "feature_flag.variant";
static final String CUSTOM_CONTEXT_KEY_ATTRIBUTE_NAME = "feature_flag.context.key";
static final String SEMCONV_FEATURE_FLAG_VALUE = "feature_flag.result.value";
static final String SEMCONV_FEATURE_FLAG_CONTEXT_ID = "feature_flag.context.id";
static final String SEMCONV_FEATURE_FLAG_VARIATION_INDEX = "feature_flag.result.variationIndex";
static final String SEMCONV_FEATURE_FLAG_IN_EXPERIMENT = "feature_flag.result.reason.inExperiment";

private final boolean withSpans;
private final boolean withVariant;
private final boolean withValue;

/**
* Creates a {@link TracingHook}
*
* @param withSpans will include child spans for the various hook series when they happen
* @param withVariant will include the variant of the feature flag in the recorded evaluation events
* @param withValue will include the value of the feature flag in the recorded evaluation events
*/
TracingHook(boolean withSpans, boolean withVariant) {
TracingHook(boolean withSpans, boolean withValue) {
super(HOOK_NAME);
this.withSpans = withSpans;
this.withVariant = withVariant;
this.withValue = withValue;
}

@Override
Expand All @@ -60,6 +62,7 @@ Map<String, Object> beforeEvaluationInternal(Tracer tracer, EvaluationSeriesCont
AttributesBuilder attrBuilder = Attributes.builder();
attrBuilder.put(SEMCONV_FEATURE_FLAG_KEY, seriesContext.flagKey);
attrBuilder.put(SEMCONV_FEATURE_FLAG_PROVIDER_NAME, PROVIDER_NAME);
attrBuilder.put(SEMCONV_FEATURE_FLAG_CONTEXT_ID, seriesContext.context.getFullyQualifiedKey());
builder.setAllAttributes(attrBuilder.build());
Span span = builder.startSpan();
Map<String, Object> retSeriesData = new HashMap<>(seriesData);
Expand All @@ -78,9 +81,17 @@ public Map<String, Object> afterEvaluation(EvaluationSeriesContext seriesContext
AttributesBuilder attrBuilder = Attributes.builder();
attrBuilder.put(SEMCONV_FEATURE_FLAG_KEY, seriesContext.flagKey);
attrBuilder.put(SEMCONV_FEATURE_FLAG_PROVIDER_NAME, PROVIDER_NAME);
attrBuilder.put(CUSTOM_CONTEXT_KEY_ATTRIBUTE_NAME, seriesContext.context.getFullyQualifiedKey());
if (withVariant) {
attrBuilder.put(SEMCONV_FEATURE_FLAG_VARIANT, evaluationDetail.getValue().toJsonString());
attrBuilder.put(SEMCONV_FEATURE_FLAG_CONTEXT_ID, seriesContext.context.getFullyQualifiedKey());
if (withValue) {
attrBuilder.put(SEMCONV_FEATURE_FLAG_VALUE, evaluationDetail.getValue().toJsonString());
}

if (evaluationDetail.getReason().isInExperiment()) {
attrBuilder.put(SEMCONV_FEATURE_FLAG_IN_EXPERIMENT, true);
}

if (evaluationDetail.getVariationIndex() != EvaluationDetail.NO_VARIATION) {
attrBuilder.put(SEMCONV_FEATURE_FLAG_VARIATION_INDEX, evaluationDetail.getVariationIndex());
}

// Here we make best effort the log the event and let the library handle the "no current span" case; which at the
Expand All @@ -94,7 +105,7 @@ public Map<String, Object> afterEvaluation(EvaluationSeriesContext seriesContext
*/
public static class Builder {
private boolean withSpans = false;
private boolean withVariant = false;
private boolean withValue = false;

/**
* The {@link TracingHook} will include child spans for the various hook series when they happen
Expand All @@ -105,20 +116,31 @@ public Builder withSpans() {
return this;
}

/**
* The {@link TracingHook} will include the value of the feature flag in the recorded evaluation events
* @return the builder
*/
public Builder withValue() {
this.withValue = true;
return this;
}

/**
* The {@link TracingHook} will include the variant of the feature flag in the recorded evaluation events
* @return the builder
* @deprecated Use {@link #withValue()} instead
*/
@Deprecated
public Builder withVariant() {
this.withVariant = true;
this.withValue = true;
return this;
}

/**
* @return the {@link TracingHook}
*/
public TracingHook build() {
return new TracingHook(withSpans, withVariant);
return new TracingHook(withSpans, withValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
import java.util.List;
import java.util.Map;

import static com.launchdarkly.integrations.TracingHook.CUSTOM_CONTEXT_KEY_ATTRIBUTE_NAME;
import static com.launchdarkly.integrations.TracingHook.SEMCONV_FEATURE_FLAG_CONTEXT_ID;
import static com.launchdarkly.integrations.TracingHook.PROVIDER_NAME;
import static com.launchdarkly.integrations.TracingHook.SEMCONV_FEATURE_FLAG_KEY;
import static com.launchdarkly.integrations.TracingHook.SEMCONV_FEATURE_FLAG_PROVIDER_NAME;
import static com.launchdarkly.integrations.TracingHook.SEMCONV_FEATURE_FLAG_VARIANT;
import static com.launchdarkly.integrations.TracingHook.SEMCONV_FEATURE_FLAG_VALUE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

Expand Down Expand Up @@ -59,11 +59,11 @@ public void testAddsEventToParentSpanWtihoutVariation() {
assertEquals(1, spanData.getEvents().size());

Attributes attributes = spanData.getEvents().get(0).getAttributes();
assertEquals(3, attributes.size());
assertEquals(4, attributes.size());
assertEquals(PROVIDER_NAME, attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_PROVIDER_NAME)));
assertEquals("testKey", attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_KEY)));
assertNull(attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_VARIANT)));
assertEquals("testContextKey", attributes.get(AttributeKey.stringKey(CUSTOM_CONTEXT_KEY_ATTRIBUTE_NAME)));
assertNull(attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_VALUE)));
assertEquals("testContextKey", attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_CONTEXT_ID)));
}

@Test
Expand All @@ -90,11 +90,11 @@ public void testAddsEventToParentSpanWtihVariation() {
assertEquals(1, spanData.getEvents().size());

Attributes attributes = spanData.getEvents().get(0).getAttributes();
assertEquals(4, attributes.size());
assertEquals(5, attributes.size());
assertEquals(PROVIDER_NAME, attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_PROVIDER_NAME)));
assertEquals("testKey", attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_KEY)));
assertEquals("{\"evalKey\":\"evalValue\"}", attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_VARIANT)));
assertEquals("testContextKey", attributes.get(AttributeKey.stringKey(CUSTOM_CONTEXT_KEY_ATTRIBUTE_NAME)));
assertEquals("{\"evalKey\":\"evalValue\"}", attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_VALUE)));
assertEquals("testContextKey", attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_CONTEXT_ID)));
}

@Test
Expand All @@ -118,10 +118,10 @@ public void testCreatesChildSpanEventStillOnParent() {
assertEquals("LDClient.testMethod", spanDataList.get(0).getName());
assertEquals("rootSpan", spanDataList.get(1).getName());
Attributes attributes = spanDataList.get(1).getEvents().get(0).getAttributes();
assertEquals(3, attributes.size());
assertEquals(4, attributes.size());
assertEquals("testKey", attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_KEY)));
assertEquals(PROVIDER_NAME, attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_PROVIDER_NAME)));
assertEquals("testContextKey", attributes.get(AttributeKey.stringKey(CUSTOM_CONTEXT_KEY_ATTRIBUTE_NAME)));
assertEquals("testContextKey", attributes.get(AttributeKey.stringKey(SEMCONV_FEATURE_FLAG_CONTEXT_ID)));
}

@Test
Expand Down