Skip to content

Commit 01d585c

Browse files
mrm9084Copilot
andauthored
Spring Telemetry Validation (#37)
* Spring Telemetry * Update libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/models/TelemetryResult.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 9eb9c4b commit 01d585c

File tree

12 files changed

+209
-26
lines changed

12 files changed

+209
-26
lines changed

libraryValidations/Spring/validation-tests/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.springframework.boot</groupId>
77
<artifactId>spring-boot-starter-parent</artifactId>
8-
<version>3.3.3</version>
8+
<version>3.5.5</version>
99
<relativePath/> <!-- lookup parent from repository -->
1010
</parent>
1111
<groupId>com.microsoft</groupId>
@@ -37,7 +37,7 @@
3737
<dependency>
3838
<groupId>com.azure.spring</groupId>
3939
<artifactId>spring-cloud-azure-feature-management</artifactId>
40-
<version>5.17.0</version>
40+
<version>6.0.0-beta.2</version>
4141
</dependency>
4242

4343
<dependency>
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.microsoft.validation_tests;
2+
3+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
4+
5+
import java.io.IOException;
6+
import java.util.Iterator;
7+
8+
import org.junit.jupiter.api.BeforeAll;
9+
import org.junit.jupiter.api.BeforeEach;
10+
import org.junit.jupiter.api.Test;
11+
import org.mockito.MockitoAnnotations;
12+
import org.slf4j.LoggerFactory;
13+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
14+
import org.springframework.boot.test.context.SpringBootTest;
15+
import org.springframework.context.annotation.ComponentScan;
16+
import org.springframework.test.context.TestPropertySource;
17+
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
18+
19+
import com.azure.spring.cloud.feature.management.telemetry.LoggerTelemetryPublisher;
20+
21+
import ch.qos.logback.classic.Logger;
22+
import ch.qos.logback.classic.spi.ILoggingEvent;
23+
import ch.qos.logback.core.Appender;
24+
import ch.qos.logback.core.read.ListAppender;
25+
26+
@SpringJUnitConfig
27+
@TestPropertySource(locations = "file:./../../../Samples/BasicTelemetry.sample.json", factory = YamlPropertySourceFactory.class)
28+
@SpringBootTest(classes = { SpringBootTest.class, Filters.class })
29+
@EnableConfigurationProperties
30+
@ComponentScan(basePackages = { "com.azure.spring.cloud.feature.management" })
31+
class BasicTelemetryTests extends ValidationTestsApplicationTests {
32+
33+
private Logger publisherLogger;
34+
35+
private ListAppender<ILoggingEvent> listAppender;
36+
37+
@BeforeAll
38+
public static void setUpLogging() {
39+
// Force SLF4J to initialize
40+
LoggerFactory.getLogger(BasicTelemetryTests.class).info("Initializing SLF4J in test");
41+
}
42+
43+
44+
@BeforeEach
45+
public void setup() {
46+
MockitoAnnotations.openMocks(this);
47+
48+
org.slf4j.Logger slf4jLogger = LoggerFactory.getLogger(LoggerTelemetryPublisher.class);
49+
50+
// Check if we can cast to Logback's Logger
51+
if (slf4jLogger instanceof ch.qos.logback.classic.Logger) {
52+
publisherLogger = (ch.qos.logback.classic.Logger) slf4jLogger;
53+
54+
// Create a new ListAppender for each test
55+
listAppender = new ListAppender<>();
56+
listAppender.start();
57+
58+
// Remove any existing appenders of this type first
59+
for (Iterator<Appender<ILoggingEvent>> it = publisherLogger.iteratorForAppenders(); it.hasNext();) {
60+
Appender<ILoggingEvent> appender = it.next();
61+
if (appender instanceof ListAppender) {
62+
publisherLogger.detachAppender(appender);
63+
}
64+
}
65+
66+
// Add the fresh appender
67+
publisherLogger.addAppender(listAppender);
68+
} else {
69+
assumeTrue(
70+
false,
71+
"Tests require Logback implementation, but found: " + slf4jLogger.getClass().getName()
72+
);
73+
}
74+
}
75+
76+
@Test
77+
void validateTest() throws IOException {
78+
runTests("BasicTelemetry", listAppender);
79+
}
80+
81+
}

libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/BasicVariantTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class BasicVariantTests extends ValidationTestsApplicationTests {
1818

1919
@Test
2020
void validateTest() throws IOException {
21-
runTests("BasicVariant");
21+
runTests("BasicVariant", null);
2222
}
2323

2424
}

libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/NoFiltersTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class NoFiltersTests extends ValidationTestsApplicationTests {
1818

1919
@Test
2020
void validateTest() throws IOException {
21-
runTests("NoFilters");
21+
runTests("NoFilters", null);
2222
}
2323

2424
}

libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/RequirementTypeTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class RequirementTypeTests extends ValidationTestsApplicationTests {
1818

1919
@Test
2020
void validateTest() throws IOException {
21-
runTests("RequirementType");
21+
runTests("RequirementType", null);
2222
}
2323

2424
}

libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterModifiedTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class TargetingFilterModifiedTests extends ValidationTestsApplicationTests {
1818

1919
@Test
2020
void validateTest() throws IOException {
21-
runTests("TargetingFilter.modified");
21+
runTests("TargetingFilter.modified", null);
2222
}
2323

2424
}

libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TargetingFilterTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class TargetingFilterTests extends ValidationTestsApplicationTests {
1818

1919
@Test
2020
void validateTest() throws IOException {
21-
runTests("TargetingFilter");
21+
runTests("TargetingFilter", null);
2222
}
2323

2424
}

libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/TimeWindowFilterTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class TimeWindowFilterTests extends ValidationTestsApplicationTests {
1818

1919
@Test
2020
void validateTest() throws IOException {
21-
runTests("TimeWindowFilter");
21+
runTests("TimeWindowFilter", null);
2222
}
2323

2424
}

libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/ValidationTestsApplicationTests.java

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
package com.microsoft.validation_tests;
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
4-
import static org.junit.jupiter.api.Assertions.assertNull;
4+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
55

66
import java.io.File;
77
import java.io.IOException;
88
import java.nio.file.Files;
99
import java.util.LinkedHashMap;
1010
import java.util.List;
11+
import java.util.Map;
1112

1213
import org.slf4j.Logger;
1314
import org.slf4j.LoggerFactory;
1415
import org.springframework.beans.factory.annotation.Autowired;
1516

1617
import com.azure.spring.cloud.feature.management.FeatureManager;
1718
import com.azure.spring.cloud.feature.management.models.Variant;
18-
import com.azure.spring.cloud.feature.management.validation_tests.models.ValidationTestCase;
19-
import com.azure.spring.cloud.feature.management.validation_tests.models.VariantResult;
2019
import com.fasterxml.jackson.databind.MapperFeature;
2120
import com.fasterxml.jackson.databind.ObjectMapper;
2221
import com.fasterxml.jackson.databind.json.JsonMapper;
2322
import com.fasterxml.jackson.databind.type.CollectionType;
2423
import com.fasterxml.jackson.databind.type.TypeFactory;
24+
import com.microsoft.validation_tests.models.ValidationTestCase;
25+
import com.microsoft.validation_tests.models.VariantResult;
26+
27+
import ch.qos.logback.classic.Level;
28+
import ch.qos.logback.classic.spi.ILoggingEvent;
29+
import ch.qos.logback.core.read.ListAppender;
2530

2631
class ValidationTestsApplicationTests {
2732

@@ -37,13 +42,27 @@ class ValidationTestsApplicationTests {
3742
private final String inputsUser = "User";
3843

3944
private final String inputsGroups = "Groups";
45+
46+
static final String EVENT_NAME = "FeatureEvaluation";
47+
48+
static final String FEATURE_NAME = "FeatureName";
49+
50+
static final String ENABLED = "Enabled";
51+
52+
static final String REASON = "VariantAssignmentReason";
53+
54+
static final String VERSION = "Version";
55+
56+
static final String EVALUATION_EVENT_VERSION = "1.1.0";
57+
58+
static final String APPLICATION_INSIGHTS_CUSTOM_EVENT_KEY = "microsoft.custom_event.name";
4059

4160
@Autowired
4261
private FeatureManager featureManager;
4362
@Autowired
4463
private TargetingFilterTestContextAccessor accessor;
4564

46-
void runTests(String name) throws IOException {
65+
void runTests(String name, ListAppender<ILoggingEvent> listAppender) throws IOException {
4766
LOGGER.debug("Running test case from file: " + name);
4867
final File testsFile = new File(PATH + name + TEST_FILE_POSTFIX);
4968
List<ValidationTestCase> testCases = readTestcasesFromFile(testsFile);
@@ -76,6 +95,21 @@ void runTests(String name) throws IOException {
7695
assertEquals(variantResult.getResult().getConfigurationValue(), getVariantResult.getValue());
7796

7897
}
98+
99+
if (testCase.getTelemetry() != null) {
100+
ILoggingEvent logEvent = getEvent(listAppender.list, testCase.getFeatureFlagName());
101+
Map<String, String> mdcMap = logEvent.getMDCPropertyMap();
102+
Map<String, String> expectedProperties = testCase.getTelemetry().getEventProperties();
103+
104+
assertEquals(EVENT_NAME, logEvent.getMessage());
105+
assertEquals(Level.INFO, logEvent.getLevel());
106+
assertEquals(expectedProperties.get(REASON), mdcMap.get(REASON));
107+
assertEquals(testCase.getFeatureFlagName(), mdcMap.get(FEATURE_NAME));
108+
assertEquals("false", mdcMap.get(ENABLED));
109+
assertEquals(EVALUATION_EVENT_VERSION, mdcMap.get(VERSION));
110+
assertEquals(EVENT_NAME, mdcMap.get(APPLICATION_INSIGHTS_CUSTOM_EVENT_KEY));
111+
112+
}
79113

80114
}
81115
}
@@ -96,5 +130,18 @@ private List<ValidationTestCase> readTestcasesFromFile(File testFile) throws IOE
96130
ValidationTestCase.class);
97131
return OBJECT_MAPPER.readValue(jsonString, typeReference);
98132
}
133+
134+
ILoggingEvent getEvent(List<ILoggingEvent> events, String featureName) {
135+
for (ILoggingEvent event : events) {
136+
if (featureName.equals(event.getMDCPropertyMap().get(FEATURE_NAME))) {
137+
return event;
138+
}
139+
}
140+
assumeTrue(
141+
false,
142+
"Log event not found for feature: " + featureName
143+
);
144+
return null; // This line will never be reached due to the assumption above
145+
}
99146

100147
}

libraryValidations/Spring/validation-tests/src/test/java/com/microsoft/validation_tests/VariantAssignmentTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class VariantAssignmentTests extends ValidationTestsApplicationTests {
1818

1919
@Test
2020
void validateTest() throws IOException {
21-
runTests("VariantAssignment");
21+
runTests("VariantAssignment", null);
2222
}
2323

2424
}

0 commit comments

Comments
 (0)