diff --git a/libraryValidations/Spring/validation-tests/pom.xml b/libraryValidations/Spring/validation-tests/pom.xml
index b13988a..7736b2b 100644
--- a/libraryValidations/Spring/validation-tests/pom.xml
+++ b/libraryValidations/Spring/validation-tests/pom.xml
@@ -5,7 +5,7 @@
org.springframework.boot
spring-boot-starter-parent
- 3.3.3
+ 3.5.5
com.microsoft
@@ -37,7 +37,7 @@
com.azure.spring
spring-cloud-azure-feature-management
- 5.17.0
+ 6.0.0-beta.2
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/BasicTelemetryTests.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/BasicTelemetryTests.java
new file mode 100644
index 0000000..7444a03
--- /dev/null
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/BasicTelemetryTests.java
@@ -0,0 +1,81 @@
+package com.microsoft.validation_tests;
+
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockitoAnnotations;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+import com.azure.spring.cloud.feature.management.telemetry.LoggerTelemetryPublisher;
+
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.read.ListAppender;
+
+@SpringJUnitConfig
+@TestPropertySource(locations = "file:./../../../Samples/BasicTelemetry.sample.json", factory = YamlPropertySourceFactory.class)
+@SpringBootTest(classes = { SpringBootTest.class, Filters.class })
+@EnableConfigurationProperties
+@ComponentScan(basePackages = { "com.azure.spring.cloud.feature.management" })
+class BasicTelemetryTests extends ValidationTestsApplicationTests {
+
+ private Logger publisherLogger;
+
+ private ListAppender listAppender;
+
+ @BeforeAll
+ public static void setUpLogging() {
+ // Force SLF4J to initialize
+ LoggerFactory.getLogger(BasicTelemetryTests.class).info("Initializing SLF4J in test");
+ }
+
+
+ @BeforeEach
+ public void setup() {
+ MockitoAnnotations.openMocks(this);
+
+ org.slf4j.Logger slf4jLogger = LoggerFactory.getLogger(LoggerTelemetryPublisher.class);
+
+ // Check if we can cast to Logback's Logger
+ if (slf4jLogger instanceof ch.qos.logback.classic.Logger) {
+ publisherLogger = (ch.qos.logback.classic.Logger) slf4jLogger;
+
+ // Create a new ListAppender for each test
+ listAppender = new ListAppender<>();
+ listAppender.start();
+
+ // Remove any existing appenders of this type first
+ for (Iterator> it = publisherLogger.iteratorForAppenders(); it.hasNext();) {
+ Appender appender = it.next();
+ if (appender instanceof ListAppender) {
+ publisherLogger.detachAppender(appender);
+ }
+ }
+
+ // Add the fresh appender
+ publisherLogger.addAppender(listAppender);
+ } else {
+ assumeTrue(
+ false,
+ "Tests require Logback implementation, but found: " + slf4jLogger.getClass().getName()
+ );
+ }
+ }
+
+ @Test
+ void validateTest() throws IOException {
+ runTests("BasicTelemetry", listAppender);
+ }
+
+}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/BasicVariantTests.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/BasicVariantTests.java
index 03534a6..e871552 100644
--- a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/BasicVariantTests.java
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/BasicVariantTests.java
@@ -18,7 +18,7 @@ class BasicVariantTests extends ValidationTestsApplicationTests {
@Test
void validateTest() throws IOException {
- runTests("BasicVariant");
+ runTests("BasicVariant", null);
}
}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/NoFiltersTests.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/NoFiltersTests.java
index 8c86301..330d878 100644
--- a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/NoFiltersTests.java
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/NoFiltersTests.java
@@ -18,7 +18,7 @@ class NoFiltersTests extends ValidationTestsApplicationTests {
@Test
void validateTest() throws IOException {
- runTests("NoFilters");
+ runTests("NoFilters", null);
}
}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/RequirementTypeTests.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/RequirementTypeTests.java
index 41ef5e4..624b84b 100644
--- a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/RequirementTypeTests.java
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/RequirementTypeTests.java
@@ -18,7 +18,7 @@ class RequirementTypeTests extends ValidationTestsApplicationTests {
@Test
void validateTest() throws IOException {
- runTests("RequirementType");
+ runTests("RequirementType", null);
}
}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterModifiedTests.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterModifiedTests.java
index 9f08493..41884b5 100644
--- a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterModifiedTests.java
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterModifiedTests.java
@@ -18,7 +18,7 @@ class TargetingFilterModifiedTests extends ValidationTestsApplicationTests {
@Test
void validateTest() throws IOException {
- runTests("TargetingFilter.modified");
+ runTests("TargetingFilter.modified", null);
}
}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterTests.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterTests.java
index d14306a..ecd9f3c 100644
--- a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterTests.java
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterTests.java
@@ -18,7 +18,7 @@ class TargetingFilterTests extends ValidationTestsApplicationTests {
@Test
void validateTest() throws IOException {
- runTests("TargetingFilter");
+ runTests("TargetingFilter", null);
}
}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TimeWindowFilterTests.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TimeWindowFilterTests.java
index 31eccbb..c87f83a 100644
--- a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TimeWindowFilterTests.java
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TimeWindowFilterTests.java
@@ -18,7 +18,7 @@ class TimeWindowFilterTests extends ValidationTestsApplicationTests {
@Test
void validateTest() throws IOException {
- runTests("TimeWindowFilter");
+ runTests("TimeWindowFilter", null);
}
}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/ValidationTestsApplicationTests.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/ValidationTestsApplicationTests.java
index 3f79a85..25bb72b 100644
--- a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/ValidationTestsApplicationTests.java
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/ValidationTestsApplicationTests.java
@@ -1,13 +1,14 @@
package com.microsoft.validation_tests;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -15,13 +16,17 @@
import com.azure.spring.cloud.feature.management.FeatureManager;
import com.azure.spring.cloud.feature.management.models.Variant;
-import com.azure.spring.cloud.feature.management.validation_tests.models.ValidationTestCase;
-import com.azure.spring.cloud.feature.management.validation_tests.models.VariantResult;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.microsoft.validation_tests.models.ValidationTestCase;
+import com.microsoft.validation_tests.models.VariantResult;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.read.ListAppender;
class ValidationTestsApplicationTests {
@@ -37,13 +42,27 @@ class ValidationTestsApplicationTests {
private final String inputsUser = "User";
private final String inputsGroups = "Groups";
+
+ static final String EVENT_NAME = "FeatureEvaluation";
+
+ static final String FEATURE_NAME = "FeatureName";
+
+ static final String ENABLED = "Enabled";
+
+ static final String REASON = "VariantAssignmentReason";
+
+ static final String VERSION = "Version";
+
+ static final String EVALUATION_EVENT_VERSION = "1.1.0";
+
+ static final String APPLICATION_INSIGHTS_CUSTOM_EVENT_KEY = "microsoft.custom_event.name";
@Autowired
private FeatureManager featureManager;
@Autowired
private TargetingFilterTestContextAccessor accessor;
- void runTests(String name) throws IOException {
+ void runTests(String name, ListAppender listAppender) throws IOException {
LOGGER.debug("Running test case from file: " + name);
final File testsFile = new File(PATH + name + TEST_FILE_POSTFIX);
List testCases = readTestcasesFromFile(testsFile);
@@ -76,6 +95,21 @@ void runTests(String name) throws IOException {
assertEquals(variantResult.getResult().getConfigurationValue(), getVariantResult.getValue());
}
+
+ if (testCase.getTelemetry() != null) {
+ ILoggingEvent logEvent = getEvent(listAppender.list, testCase.getFeatureFlagName());
+ Map mdcMap = logEvent.getMDCPropertyMap();
+ Map expectedProperties = testCase.getTelemetry().getEventProperties();
+
+ assertEquals(EVENT_NAME, logEvent.getMessage());
+ assertEquals(Level.INFO, logEvent.getLevel());
+ assertEquals(expectedProperties.get(REASON), mdcMap.get(REASON));
+ assertEquals(testCase.getFeatureFlagName(), mdcMap.get(FEATURE_NAME));
+ assertEquals("false", mdcMap.get(ENABLED));
+ assertEquals(EVALUATION_EVENT_VERSION, mdcMap.get(VERSION));
+ assertEquals(EVENT_NAME, mdcMap.get(APPLICATION_INSIGHTS_CUSTOM_EVENT_KEY));
+
+ }
}
}
@@ -96,5 +130,18 @@ private List readTestcasesFromFile(File testFile) throws IOE
ValidationTestCase.class);
return OBJECT_MAPPER.readValue(jsonString, typeReference);
}
+
+ ILoggingEvent getEvent(List events, String featureName) {
+ for (ILoggingEvent event : events) {
+ if (featureName.equals(event.getMDCPropertyMap().get(FEATURE_NAME))) {
+ return event;
+ }
+ }
+ assumeTrue(
+ false,
+ "Log event not found for feature: " + featureName
+ );
+ return null; // This line will never be reached due to the assumption above
+ }
}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/VariantAssignmentTests.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/VariantAssignmentTests.java
index 56d1121..824fbaf 100644
--- a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/VariantAssignmentTests.java
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/VariantAssignmentTests.java
@@ -18,7 +18,7 @@ class VariantAssignmentTests extends ValidationTestsApplicationTests {
@Test
void validateTest() throws IOException {
- runTests("VariantAssignment");
+ runTests("VariantAssignment", null);
}
}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/models/TelemetryResult.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/models/TelemetryResult.java
new file mode 100644
index 0000000..5efeb91
--- /dev/null
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/models/TelemetryResult.java
@@ -0,0 +1,34 @@
+package com.microsoft.validation_tests.models;
+
+import java.util.Map;
+
+public class TelemetryResult {
+
+ private String eventName;
+ private Map eventProperties;
+ /**
+ * @return the eventName
+ */
+ public String getEventName() {
+ return eventName;
+ }
+ /**
+ * @param eventName the eventName to set
+ */
+ public void setEventName(String eventName) {
+ this.eventName = eventName;
+ }
+ /**
+ * @return the eventProperties
+ */
+ public Map getEventProperties() {
+ return eventProperties;
+ }
+ /**
+ * @param eventProperties the eventProperties to set
+ */
+ public void setEventProperties(Map eventProperties) {
+ this.eventProperties = eventProperties;
+ }
+
+}
diff --git a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/models/ValidationTestCase.java b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/models/ValidationTestCase.java
index 218d1c5..ce3b211 100644
--- a/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/models/ValidationTestCase.java
+++ b/libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/models/ValidationTestCase.java
@@ -6,94 +6,115 @@
public class ValidationTestCase {
private String friendlyName;
+
private String featureFlagName;
+
private LinkedHashMap inputs;
+
private IsEnabled isEnabled;
+
private VariantResult variant;
+
private String description;
+ private TelemetryResult telemetry;
+
/**
* @return friendly name of test case
- * */
+ */
public String getFriendlyName() {
return friendlyName;
}
/**
* @param friendlyName the friendly name of test case
- * */
+ */
public void setFriendlyName(String friendlyName) {
this.friendlyName = friendlyName;
}
/**
* @return the name of feature flag
- * */
+ */
public String getFeatureFlagName() {
return featureFlagName;
}
/**
* @param featureFlagName the name of feature flag
- * */
+ */
public void setFeatureFlagName(String featureFlagName) {
this.featureFlagName = featureFlagName;
}
/**
* @return the inputs of feature flag
- * */
+ */
public LinkedHashMap getInputs() {
return inputs;
}
/**
* @param inputs the inputs of feature flag
- * */
+ */
public void setInputs(LinkedHashMap inputs) {
this.inputs = inputs;
}
/**
* @return IsEnabled object to represent result of feature flag, enabled or exception
- * */
+ */
public IsEnabled getIsEnabled() {
return isEnabled;
}
/**
* @param isEnabled the result of feature flag, enabled or exception
- * */
+ */
public void setIsEnabled(IsEnabled isEnabled) {
this.isEnabled = isEnabled;
}
/**
* @return variant
- * */
+ */
public VariantResult getVariant() {
return variant;
}
/**
* @param variant the variant of test case
- * */
+ */
public void setVariant(VariantResult variant) {
this.variant = variant;
}
/**
* @return description
- * */
+ */
public String getDescription() {
return description;
}
/**
* @param description the description of test case
- * */
+ */
public void setDescription(String description) {
this.description = description;
}
-}
+ /**
+ * @return the telemetry
+ */
+ public TelemetryResult getTelemetry() {
+ return telemetry;
+ }
+
+ /**
+ * @param telemetry the telemetry to set
+ */
+ public void setTelemetry(TelemetryResult telemetry) {
+ this.telemetry = telemetry;
+ }
+
+}