Skip to content

Commit 05b825c

Browse files
Copilottrask
andcommitted
Add smoke test for exception message handling
Co-authored-by: trask <[email protected]>
1 parent 879c66b commit 05b825c

File tree

5 files changed

+171
-0
lines changed

5 files changed

+171
-0
lines changed

settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ hideFromDependabot(":smoke-tests:apps:CoreAndFilter3xUsingOld3xAgent")
7777
hideFromDependabot(":smoke-tests:apps:CustomDimensions")
7878
hideFromDependabot(":smoke-tests:apps:CustomInstrumentation")
7979
hideFromDependabot(":smoke-tests:apps:DetectUnexpectedOtelMetrics")
80+
hideFromDependabot(":smoke-tests:apps:ExceptionMessageHandling")
8081
hideFromDependabot(":smoke-tests:apps:Diagnostics")
8182
hideFromDependabot(":smoke-tests:apps:Diagnostics:JfrFileReader")
8283
hideFromDependabot(":smoke-tests:apps:DiagnosticExtension:MockExtension")
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
plugins {
2+
id("ai.smoke-test-war")
3+
}
4+
5+
dependencies {
6+
implementation("org.springframework.boot:spring-boot-starter-web:2.5.12") {
7+
exclude("org.springframework.boot", "spring-boot-starter-tomcat")
8+
}
9+
// this dependency is needed to make wildfly happy
10+
implementation("org.reactivestreams:reactive-streams:1.0.3")
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.applicationinsights.smoketestapp;
5+
6+
import org.springframework.boot.autoconfigure.SpringBootApplication;
7+
import org.springframework.boot.builder.SpringApplicationBuilder;
8+
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
9+
10+
@SpringBootApplication
11+
public class SpringBootApp extends SpringBootServletInitializer {
12+
@Override
13+
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
14+
return applicationBuilder.sources(SpringBootApp.class);
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.applicationinsights.smoketestapp;
5+
6+
import javax.servlet.http.HttpServletResponse;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
import org.springframework.web.bind.annotation.GetMapping;
10+
import org.springframework.web.bind.annotation.RestController;
11+
12+
@RestController
13+
public class TestController {
14+
15+
private static final Logger logger = LoggerFactory.getLogger("smoketestapp");
16+
17+
@GetMapping("/")
18+
public String root() {
19+
return "OK";
20+
}
21+
22+
@GetMapping("/testExceptionWithoutMessage")
23+
public String testExceptionWithoutMessage(HttpServletResponse response) {
24+
// This reproduces the original issue: exceptions without messages
25+
// that would cause 206 errors from Application Insights service
26+
logger.error("Exception without message test", new NullPointerException());
27+
return "Exception logged";
28+
}
29+
30+
@GetMapping("/testExceptionWithEmptyMessage")
31+
public String testExceptionWithEmptyMessage(HttpServletResponse response) {
32+
// Test exception with empty message
33+
logger.error("Exception with empty message test", new RuntimeException(""));
34+
return "Exception logged";
35+
}
36+
37+
@GetMapping("/testExceptionWithWhitespaceMessage")
38+
public String testExceptionWithWhitespaceMessage(HttpServletResponse response) {
39+
// Test exception with whitespace-only message
40+
logger.error("Exception with whitespace message test", new IllegalArgumentException(" "));
41+
return "Exception logged";
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.applicationinsights.smoketest;
5+
6+
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.TOMCAT_8_JAVA_11;
7+
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.TOMCAT_8_JAVA_17;
8+
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.TOMCAT_8_JAVA_21;
9+
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.TOMCAT_8_JAVA_8;
10+
import static org.assertj.core.api.Assertions.assertThat;
11+
12+
import com.microsoft.applicationinsights.smoketest.schemav2.Data;
13+
import com.microsoft.applicationinsights.smoketest.schemav2.Envelope;
14+
import com.microsoft.applicationinsights.smoketest.schemav2.ExceptionData;
15+
import com.microsoft.applicationinsights.smoketest.schemav2.SeverityLevel;
16+
import java.util.List;
17+
import org.junit.jupiter.api.Test;
18+
import org.junit.jupiter.api.extension.RegisterExtension;
19+
20+
@UseAgent
21+
abstract class ExceptionMessageHandlingTest {
22+
23+
@RegisterExtension static final SmokeTestExtension testing = SmokeTestExtension.create();
24+
25+
@Test
26+
@TargetUri("/testExceptionWithoutMessage")
27+
void testExceptionWithoutMessage() throws Exception {
28+
List<Envelope> rdList = testing.mockedIngestion.waitForItems("RequestData", 1);
29+
30+
Envelope rdEnvelope = rdList.get(0);
31+
String operationId = rdEnvelope.getTags().get("ai.operation.id");
32+
List<Envelope> edList =
33+
testing.mockedIngestion.waitForItemsInOperation("ExceptionData", 1, operationId);
34+
35+
Envelope edEnvelope = edList.get(0);
36+
ExceptionData ed = (ExceptionData) ((Data<?>) edEnvelope.getData()).getBaseData();
37+
38+
// Verify that exceptions without messages have their class name as the message
39+
// This prevents the 206 error: "Field 'message' on type 'ExceptionDetails' is required but
40+
// missing or empty"
41+
assertThat(ed.getExceptions().get(0).getTypeName()).isEqualTo("java.lang.NullPointerException");
42+
assertThat(ed.getExceptions().get(0).getMessage()).isEqualTo("java.lang.NullPointerException");
43+
assertThat(ed.getExceptions().get(0).getMessage()).isNotEmpty();
44+
assertThat(ed.getSeverityLevel()).isEqualTo(SeverityLevel.ERROR);
45+
}
46+
47+
@Test
48+
@TargetUri("/testExceptionWithEmptyMessage")
49+
void testExceptionWithEmptyMessage() throws Exception {
50+
List<Envelope> rdList = testing.mockedIngestion.waitForItems("RequestData", 1);
51+
52+
Envelope rdEnvelope = rdList.get(0);
53+
String operationId = rdEnvelope.getTags().get("ai.operation.id");
54+
List<Envelope> edList =
55+
testing.mockedIngestion.waitForItemsInOperation("ExceptionData", 1, operationId);
56+
57+
Envelope edEnvelope = edList.get(0);
58+
ExceptionData ed = (ExceptionData) ((Data<?>) edEnvelope.getData()).getBaseData();
59+
60+
// Verify that exceptions with empty messages have their class name as the message
61+
assertThat(ed.getExceptions().get(0).getTypeName()).isEqualTo("java.lang.RuntimeException");
62+
assertThat(ed.getExceptions().get(0).getMessage()).isEqualTo("java.lang.RuntimeException");
63+
assertThat(ed.getExceptions().get(0).getMessage()).isNotEmpty();
64+
assertThat(ed.getSeverityLevel()).isEqualTo(SeverityLevel.ERROR);
65+
}
66+
67+
@Test
68+
@TargetUri("/testExceptionWithWhitespaceMessage")
69+
void testExceptionWithWhitespaceMessage() throws Exception {
70+
List<Envelope> rdList = testing.mockedIngestion.waitForItems("RequestData", 1);
71+
72+
Envelope rdEnvelope = rdList.get(0);
73+
String operationId = rdEnvelope.getTags().get("ai.operation.id");
74+
List<Envelope> edList =
75+
testing.mockedIngestion.waitForItemsInOperation("ExceptionData", 1, operationId);
76+
77+
Envelope edEnvelope = edList.get(0);
78+
ExceptionData ed = (ExceptionData) ((Data<?>) edEnvelope.getData()).getBaseData();
79+
80+
// Verify that exceptions with whitespace-only messages have their class name as the message
81+
assertThat(ed.getExceptions().get(0).getTypeName())
82+
.isEqualTo("java.lang.IllegalArgumentException");
83+
assertThat(ed.getExceptions().get(0).getMessage())
84+
.isEqualTo("java.lang.IllegalArgumentException");
85+
assertThat(ed.getExceptions().get(0).getMessage()).isNotEmpty();
86+
assertThat(ed.getSeverityLevel()).isEqualTo(SeverityLevel.ERROR);
87+
}
88+
89+
@Environment(TOMCAT_8_JAVA_8)
90+
static class Tomcat8Java8Test extends ExceptionMessageHandlingTest {}
91+
92+
@Environment(TOMCAT_8_JAVA_11)
93+
static class Tomcat8Java11Test extends ExceptionMessageHandlingTest {}
94+
95+
@Environment(TOMCAT_8_JAVA_17)
96+
static class Tomcat8Java17Test extends ExceptionMessageHandlingTest {}
97+
98+
@Environment(TOMCAT_8_JAVA_21)
99+
static class Tomcat8Java21Test extends ExceptionMessageHandlingTest {}
100+
}

0 commit comments

Comments
 (0)