Skip to content
Closed
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ build/

# Visual Studio
.vs

# Compiled class files
*.class
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.agent.internal.classicsdk;

import com.azure.monitor.opentelemetry.autoconfigure.implementation.utils.Strings;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

public class ExceptionMessageBehaviorTest {

@Test
public void testNullPointerExceptionMessageBehavior() {
// Test the exact scenario from the problem statement
NullPointerException exception = new NullPointerException();

// Check the message
String message = exception.getMessage();
assertThat(message).isNull();

// Apply the TelemetryUtil logic
String exceptionMessage = message;
if (Strings.isNullOrEmpty(exceptionMessage)) {
exceptionMessage = exception.getClass().getName();
}

// The final message should be the class name
assertThat(exceptionMessage).isEqualTo("java.lang.NullPointerException");
assertThat(exceptionMessage).isNotEmpty();
assertThat(exceptionMessage).isNotNull();
}

@Test
public void testNullPointerExceptionWithEmptyMessage() {
// Test the scenario with empty string
NullPointerException exception = new NullPointerException("");

// Check the message
String message = exception.getMessage();
assertThat(message).isEqualTo("");

// Apply the TelemetryUtil logic
String exceptionMessage = message;
if (Strings.isNullOrEmpty(exceptionMessage)) {
exceptionMessage = exception.getClass().getName();
}

// The final message should be the class name
assertThat(exceptionMessage).isEqualTo("java.lang.NullPointerException");
assertThat(exceptionMessage).isNotEmpty();
assertThat(exceptionMessage).isNotNull();
}

@Test
public void testRuntimeExceptionMessageBehavior() {
// Test with RuntimeException
RuntimeException exception = new RuntimeException();

// Check the message
String message = exception.getMessage();
assertThat(message).isNull();

// Apply the TelemetryUtil logic
String exceptionMessage = message;
if (Strings.isNullOrEmpty(exceptionMessage)) {
exceptionMessage = exception.getClass().getName();
}

// The final message should be the class name
assertThat(exceptionMessage).isEqualTo("java.lang.RuntimeException");
assertThat(exceptionMessage).isNotEmpty();
assertThat(exceptionMessage).isNotNull();
}

@Test
public void testStringIsNullOrEmptyBehavior() {
// Test the Strings.isNullOrEmpty behavior with various inputs
assertThat(Strings.isNullOrEmpty(null)).isTrue();
assertThat(Strings.isNullOrEmpty("")).isTrue();
assertThat(Strings.isNullOrEmpty(" ")).isFalse(); // Whitespace is not empty
assertThat(Strings.isNullOrEmpty("test")).isFalse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.agent.internal.classicsdk;

import com.azure.monitor.opentelemetry.autoconfigure.implementation.builders.ExceptionDetailBuilder;
import com.azure.monitor.opentelemetry.autoconfigure.implementation.utils.Strings;
import java.util.List;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

public class TelemetryUtilTest {

@Test
public void testStringsIsNullOrEmpty() {
// Test the behavior of Strings.isNullOrEmpty with different inputs

// null should return true
assertThat(Strings.isNullOrEmpty(null)).isTrue();

// empty string should return true
assertThat(Strings.isNullOrEmpty("")).isTrue();

// string with only whitespace should return false (important!)
assertThat(Strings.isNullOrEmpty(" ")).isFalse();

// non-empty string should return false
assertThat(Strings.isNullOrEmpty("test")).isFalse();
}

@Test
public void testExceptionMessageHandling() {
// Create different types of exceptions and test the message logic

// Exception with null message
NullPointerException nullMsgException = new NullPointerException();
assertThat(nullMsgException.getMessage()).isNull();

// Exception with empty message
NullPointerException emptyMsgException = new NullPointerException("");
assertThat(emptyMsgException.getMessage()).isEqualTo("");

// Exception with whitespace message
NullPointerException whitespaceMsgException = new NullPointerException(" ");
assertThat(whitespaceMsgException.getMessage()).isEqualTo(" ");

// Test our logic
String[] testMessages = {null, "", " ", "real message"};
String[] expectedResults = {
"java.lang.NullPointerException",
"java.lang.NullPointerException",
" ",
"real message"
};

for (int i = 0; i < testMessages.length; i++) {
String testMessage = testMessages[i];
String expectedResult = expectedResults[i];

// Simulate TelemetryUtil logic
String exceptionMessage = testMessage;
if (Strings.isNullOrEmpty(exceptionMessage)) {
exceptionMessage = "java.lang.NullPointerException";
}

assertThat(exceptionMessage).isEqualTo(expectedResult);
}
}

@Test
public void testExceptionWithMessage() {
// Create an exception with a message
String testMessage = "Test exception message";
NullPointerException exception = new NullPointerException(testMessage);

// Process the exception
List<ExceptionDetailBuilder> exceptions = TelemetryUtil.getExceptions(exception);

// Should have one exception detail
assertThat(exceptions).hasSize(1);

// Test the logic directly - the message should remain as original
String exceptionMessage = exception.getMessage();
if (Strings.isNullOrEmpty(exceptionMessage)) {
exceptionMessage = exception.getClass().getName();
}
assertThat(exceptionMessage).isEqualTo(testMessage);
}

@Test
public void testExceptionWithEmptyMessage() {
// Create an exception with an empty message
NullPointerException exception = new NullPointerException("");

// Process the exception
List<ExceptionDetailBuilder> exceptions = TelemetryUtil.getExceptions(exception);

// Should have one exception detail
assertThat(exceptions).hasSize(1);

// Test the logic directly - the message should be set to class name
String exceptionMessage = exception.getMessage();
if (Strings.isNullOrEmpty(exceptionMessage)) {
exceptionMessage = exception.getClass().getName();
}
assertThat(exceptionMessage).isEqualTo("java.lang.NullPointerException");
}

@Test
public void testExceptionWithNullMessage() {
// Create an exception with null message (which is the default for most exceptions)
RuntimeException exception = new RuntimeException((String) null);

// Process the exception
List<ExceptionDetailBuilder> exceptions = TelemetryUtil.getExceptions(exception);

// Should have one exception detail
assertThat(exceptions).hasSize(1);

// Test the logic directly - the message should be set to class name
String exceptionMessage = exception.getMessage();
if (Strings.isNullOrEmpty(exceptionMessage)) {
exceptionMessage = exception.getClass().getName();
}
assertThat(exceptionMessage).isEqualTo("java.lang.RuntimeException");
}
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ hideFromDependabot(":smoke-tests:apps:CoreAndFilter3xUsingOld3xAgent")
hideFromDependabot(":smoke-tests:apps:CustomDimensions")
hideFromDependabot(":smoke-tests:apps:CustomInstrumentation")
hideFromDependabot(":smoke-tests:apps:DetectUnexpectedOtelMetrics")
hideFromDependabot(":smoke-tests:apps:ExceptionMessageHandling")
hideFromDependabot(":smoke-tests:apps:Diagnostics")
hideFromDependabot(":smoke-tests:apps:Diagnostics:JfrFileReader")
hideFromDependabot(":smoke-tests:apps:DiagnosticExtension:MockExtension")
Expand Down
11 changes: 11 additions & 0 deletions smoke-tests/apps/ExceptionMessageHandling/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
id("ai.smoke-test-war")
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:2.5.12") {
exclude("org.springframework.boot", "spring-boot-starter-tomcat")
}
// this dependency is needed to make wildfly happy
implementation("org.reactivestreams:reactive-streams:1.0.3")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.smoketestapp;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
public class SpringBootApp extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder applicationBuilder) {
return applicationBuilder.sources(SpringBootApp.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.smoketestapp;

import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

private static final Logger logger = LoggerFactory.getLogger("smoketestapp");

@GetMapping("/")
public String root() {
return "OK";
}

@GetMapping("/testExceptionWithoutMessage")
public String testExceptionWithoutMessage(HttpServletResponse response) {
// This reproduces the original issue: exceptions without messages
// that would cause 206 errors from Application Insights service
logger.error("Exception without message test", new NullPointerException());
return "Exception logged";
}

@GetMapping("/testExceptionWithEmptyMessage")
public String testExceptionWithEmptyMessage(HttpServletResponse response) {
// Test exception with empty message
logger.error("Exception with empty message test", new RuntimeException(""));
return "Exception logged";
}

@GetMapping("/testExceptionWithWhitespaceMessage")
public String testExceptionWithWhitespaceMessage(HttpServletResponse response) {
// Test exception with whitespace-only message
logger.error("Exception with whitespace message test", new IllegalArgumentException(" "));
return "Exception logged";
}

@GetMapping("/throwExceptionWithoutMessage")
public String throwExceptionWithoutMessage() throws Exception {
// This reproduces the original issue by throwing exceptions without messages
// that would cause 206 errors from Application Insights service
throw new NullPointerException();
}

@GetMapping("/throwExceptionWithEmptyMessage")
public String throwExceptionWithEmptyMessage() throws Exception {
// Test throwing exception with empty message
throw new RuntimeException("");
}

@GetMapping("/throwExceptionWithWhitespaceMessage")
public String throwExceptionWithWhitespaceMessage() throws Exception {
// Test throwing exception with whitespace-only message
throw new IllegalArgumentException(" ");
}
}
Loading
Loading