Add missing observability tests
Some tests were missing from gh-3003, this change adds them See gh-3003
This commit is contained in:
committed by
Christian Tzolov
parent
0bcb2e138b
commit
3fb66928f5
@@ -18,12 +18,20 @@ package org.springframework.ai.model.chat.client.autoconfigure;
|
||||
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.ai.chat.client.observation.ChatClientObservationContext;
|
||||
import org.springframework.ai.chat.client.observation.ChatClientPromptContentObservationHandler;
|
||||
import org.springframework.ai.observation.TracingAwareLoggingObservationHandler;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.system.CapturedOutput;
|
||||
import org.springframework.boot.test.system.OutputCaptureExtension;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ChatClientAutoConfiguration} observability support.
|
||||
@@ -32,22 +40,127 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Thomas Vitale
|
||||
* @author Jonatan Ivanov
|
||||
*/
|
||||
@ExtendWith(OutputCaptureExtension.class)
|
||||
class ChatClientObservationAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ChatClientAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void promptContentHandlerDefault() {
|
||||
this.contextRunner
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatClientPromptContentObservationHandler.class));
|
||||
void promptContentHandlerNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatClientPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptContentHandlerEnabled() {
|
||||
void promptContentHandlerWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatClientPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptContentHandlerEnabledNoTracer(CapturedOutput output) {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.chat.client.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ChatClientPromptContentObservationHandler.class));
|
||||
.run(context -> assertThat(context).hasSingleBean(ChatClientPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out the ChatClient prompt content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptContentHandlerEnabledWithTracer(CapturedOutput output) {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.client.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatClientPromptContentObservationHandler.class)
|
||||
.hasSingleBean(TracingAwareLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out the ChatClient prompt content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptContentHandlerDisabledNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.chat.client.observations.log-prompt=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatClientPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptContentHandlerDisabledWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.client.observations.log-prompt=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatClientPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customChatClientPromptContentObservationHandlerNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withUserConfiguration(CustomChatClientPromptContentObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.client.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ChatClientPromptContentObservationHandler.class)
|
||||
.hasBean("customChatClientPromptContentObservationHandler")
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customChatClientPromptContentObservationHandlerWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomChatClientPromptContentObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.client.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ChatClientPromptContentObservationHandler.class)
|
||||
.hasBean("customChatClientPromptContentObservationHandler")
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customTracingAwareLoggingObservationHandler() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomTracingAwareLoggingObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.client.observations.log-prompt=true")
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(TracingAwareLoggingObservationHandler.class)
|
||||
.hasBean("chatClientPromptContentObservationHandler")
|
||||
.doesNotHaveBean(ChatClientPromptContentObservationHandler.class);
|
||||
assertThat(context.getBean(TracingAwareLoggingObservationHandler.class))
|
||||
.isSameAs(CustomTracingAwareLoggingObservationHandlerConfiguration.handlerInstance);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TracerConfiguration {
|
||||
|
||||
@Bean
|
||||
Tracer tracer() {
|
||||
return mock(Tracer.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomChatClientPromptContentObservationHandlerConfiguration {
|
||||
|
||||
@Bean
|
||||
ChatClientPromptContentObservationHandler customChatClientPromptContentObservationHandler() {
|
||||
return new ChatClientPromptContentObservationHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomTracingAwareLoggingObservationHandlerConfiguration {
|
||||
|
||||
static TracingAwareLoggingObservationHandler<ChatClientObservationContext> handlerInstance = new TracingAwareLoggingObservationHandler<>(
|
||||
new ChatClientPromptContentObservationHandler(), null);
|
||||
|
||||
@Bean
|
||||
TracingAwareLoggingObservationHandler<ChatClientObservationContext> chatClientPromptContentObservationHandler() {
|
||||
return handlerInstance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,15 +19,26 @@ package org.springframework.ai.model.chat.observation.autoconfigure;
|
||||
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.ai.chat.client.observation.ChatClientObservationContext;
|
||||
import org.springframework.ai.chat.observation.ChatModelCompletionObservationHandler;
|
||||
import org.springframework.ai.chat.observation.ChatModelMeterObservationHandler;
|
||||
import org.springframework.ai.chat.observation.ChatModelObservationContext;
|
||||
import org.springframework.ai.chat.observation.ChatModelPromptContentObservationHandler;
|
||||
import org.springframework.ai.model.observation.ErrorLoggingObservationHandler;
|
||||
import org.springframework.ai.observation.TracingAwareLoggingObservationHandler;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.system.CapturedOutput;
|
||||
import org.springframework.boot.test.system.OutputCaptureExtension;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ChatObservationAutoConfiguration}.
|
||||
@@ -35,6 +46,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Thomas Vitale
|
||||
* @author Jonatan Ivanov
|
||||
*/
|
||||
@ExtendWith(OutputCaptureExtension.class)
|
||||
class ChatObservationAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
@@ -52,41 +64,308 @@ class ChatObservationAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptHandlerDefault() {
|
||||
this.contextRunner
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class));
|
||||
void handlersNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptHandlerEnabled() {
|
||||
void handlersWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptContentHandlerEnabledNoTracer(CapturedOutput output) {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.chat.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ChatModelPromptContentObservationHandler.class));
|
||||
.run(context -> assertThat(context).hasSingleBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out the prompt content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptHandlerDisabled() {
|
||||
this.contextRunner.withPropertyValues("spring.ai.chat.observations.log-prompt=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class));
|
||||
void promptContentHandlerEnabledWithTracer(CapturedOutput output) {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.hasSingleBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out the prompt content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void completionHandlerDefault() {
|
||||
this.contextRunner
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelCompletionObservationHandler.class));
|
||||
void promptContentHandlerDisabledNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.chat.observations.log-prompt=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void completionHandlerEnabled() {
|
||||
void promptContentHandlerDisabledWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-prompt=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void completionHandlerEnabledNoTracer(CapturedOutput output) {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.chat.observations.log-completion=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ChatModelCompletionObservationHandler.class));
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.hasSingleBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out the completion content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void completionHandlerDisabled() {
|
||||
this.contextRunner.withPropertyValues("spring.ai.chat.observations.log-completion=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelCompletionObservationHandler.class));
|
||||
void completionHandlerEnabledWithTracer(CapturedOutput output) {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-completion=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.hasSingleBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out the completion content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void completionHandlerDisabledNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.chat.observations.log-completion=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void completionHandlerDisabledWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-completion=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void errorLoggingHandlerEnabledNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.chat.observations.include-error-logging=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void errorLoggingHandlerEnabledWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.include-error-logging=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.hasSingleBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void errorLoggingHandlerDisabledNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.chat.observations.include-error-logging=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void errorLoggingHandlerDisabledWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.include-error-logging=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customChatModelPromptContentObservationHandlerNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withUserConfiguration(CustomChatModelPromptContentObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ChatModelPromptContentObservationHandler.class)
|
||||
.hasBean("customChatModelPromptContentObservationHandler")
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customChatModelPromptContentObservationHandlerWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomChatModelPromptContentObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ChatModelPromptContentObservationHandler.class)
|
||||
.hasBean("customChatModelPromptContentObservationHandler")
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customTracingAwareLoggingObservationHandlerForChatModelPromptContent() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(
|
||||
CustomTracingAwareLoggingObservationHandlerForChatModelPromptContentConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-prompt=true")
|
||||
.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.hasSingleBean(TracingAwareLoggingObservationHandler.class)
|
||||
.hasBean("chatModelPromptContentObservationHandler")
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class);
|
||||
assertThat(context.getBean(TracingAwareLoggingObservationHandler.class)).isSameAs(
|
||||
CustomTracingAwareLoggingObservationHandlerForChatModelPromptContentConfiguration.handlerInstance);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void customChatModelCompletionObservationHandlerNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withUserConfiguration(CustomChatModelCompletionObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-completion=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.hasSingleBean(ChatModelCompletionObservationHandler.class)
|
||||
.hasBean("customChatModelCompletionObservationHandler")
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customChatModelCompletionObservationHandlerWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomChatModelCompletionObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-completion=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.hasSingleBean(ChatModelCompletionObservationHandler.class)
|
||||
.hasBean("customChatModelCompletionObservationHandler")
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customTracingAwareLoggingObservationHandlerForChatModelCompletion() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomTracingAwareLoggingObservationHandlerForChatModelCompletionConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.log-completion=true")
|
||||
.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.hasSingleBean(TracingAwareLoggingObservationHandler.class)
|
||||
.hasBean("chatModelCompletionObservationHandler")
|
||||
.doesNotHaveBean(ErrorLoggingObservationHandler.class);
|
||||
assertThat(context.getBean(TracingAwareLoggingObservationHandler.class)).isSameAs(
|
||||
CustomTracingAwareLoggingObservationHandlerForChatModelCompletionConfiguration.handlerInstance);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void customErrorLoggingObservationHandler() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomErrorLoggingObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.chat.observations.include-error-logging=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ChatModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(ChatModelCompletionObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class)
|
||||
.hasSingleBean(ErrorLoggingObservationHandler.class)
|
||||
.hasBean("customErrorLoggingObservationHandler"));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TracerConfiguration {
|
||||
|
||||
@Bean
|
||||
Tracer tracer() {
|
||||
return mock(Tracer.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomChatModelPromptContentObservationHandlerConfiguration {
|
||||
|
||||
@Bean
|
||||
ChatModelPromptContentObservationHandler customChatModelPromptContentObservationHandler() {
|
||||
return new ChatModelPromptContentObservationHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomTracingAwareLoggingObservationHandlerForChatModelPromptContentConfiguration {
|
||||
|
||||
static TracingAwareLoggingObservationHandler<ChatModelObservationContext> handlerInstance = new TracingAwareLoggingObservationHandler<>(
|
||||
new ChatModelPromptContentObservationHandler(), null);
|
||||
|
||||
@Bean
|
||||
TracingAwareLoggingObservationHandler<ChatModelObservationContext> chatModelPromptContentObservationHandler() {
|
||||
return handlerInstance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomChatModelCompletionObservationHandlerConfiguration {
|
||||
|
||||
@Bean
|
||||
ChatModelCompletionObservationHandler customChatModelCompletionObservationHandler() {
|
||||
return new ChatModelCompletionObservationHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomTracingAwareLoggingObservationHandlerForChatModelCompletionConfiguration {
|
||||
|
||||
static TracingAwareLoggingObservationHandler<ChatModelObservationContext> handlerInstance = new TracingAwareLoggingObservationHandler<>(
|
||||
new ChatModelCompletionObservationHandler(), null);
|
||||
|
||||
@Bean
|
||||
TracingAwareLoggingObservationHandler<ChatModelObservationContext> chatModelCompletionObservationHandler() {
|
||||
return handlerInstance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomErrorLoggingObservationHandlerConfiguration {
|
||||
|
||||
@Bean
|
||||
ErrorLoggingObservationHandler customErrorLoggingObservationHandler(Tracer tracer) {
|
||||
return new ErrorLoggingObservationHandler(tracer, List.of(ChatClientObservationContext.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,13 +18,20 @@ package org.springframework.ai.model.image.observation.autoconfigure;
|
||||
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.ai.image.observation.ImageModelObservationContext;
|
||||
import org.springframework.ai.image.observation.ImageModelPromptContentObservationHandler;
|
||||
import org.springframework.ai.observation.TracingAwareLoggingObservationHandler;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.system.CapturedOutput;
|
||||
import org.springframework.boot.test.system.OutputCaptureExtension;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ImageObservationAutoConfiguration}.
|
||||
@@ -32,22 +39,129 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Thomas Vitale
|
||||
* @author Jonatan Ivanov
|
||||
*/
|
||||
@ExtendWith(OutputCaptureExtension.class)
|
||||
class ImageObservationAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ImageObservationAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void promptHandlerDefault() {
|
||||
this.contextRunner
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ImageModelPromptContentObservationHandler.class));
|
||||
void imageModelPromptContentHandlerNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ImageModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void promptHandlerEnabled() {
|
||||
void imageModelPromptContentHandlerWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ImageModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void imageModelPromptContentHandlerEnabledNoTracer(CapturedOutput output) {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.image.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ImageModelPromptContentObservationHandler.class));
|
||||
.run(context -> assertThat(context).hasSingleBean(ImageModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out the image prompt content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void imageModelPromptContentHandlerEnabledWithTracer(CapturedOutput output) {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.image.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ImageModelPromptContentObservationHandler.class)
|
||||
.hasSingleBean(TracingAwareLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out the image prompt content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void imageModelPromptContentHandlerDisabledNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.image.observations.log-prompt=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ImageModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void imageModelPromptContentHandlerDisabledWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.image.observations.log-prompt=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(ImageModelPromptContentObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customChatClientPromptContentObservationHandlerNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withUserConfiguration(CustomImageModelPromptContentObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.image.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ImageModelPromptContentObservationHandler.class)
|
||||
.hasBean("customImageModelPromptContentObservationHandler")
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void customChatClientPromptContentObservationHandlerWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomImageModelPromptContentObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.image.observations.log-prompt=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(ImageModelPromptContentObservationHandler.class)
|
||||
.hasBean("customImageModelPromptContentObservationHandler")
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customTracingAwareLoggingObservationHandler() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomTracingAwareLoggingObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.image.observations.log-prompt=true")
|
||||
.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(ImageModelPromptContentObservationHandler.class)
|
||||
.hasSingleBean(TracingAwareLoggingObservationHandler.class)
|
||||
.hasBean("imageModelPromptContentObservationHandler");
|
||||
assertThat(context.getBean(TracingAwareLoggingObservationHandler.class))
|
||||
.isSameAs(CustomTracingAwareLoggingObservationHandlerConfiguration.handlerInstance);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TracerConfiguration {
|
||||
|
||||
@Bean
|
||||
Tracer tracer() {
|
||||
return mock(Tracer.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomImageModelPromptContentObservationHandlerConfiguration {
|
||||
|
||||
@Bean
|
||||
ImageModelPromptContentObservationHandler customImageModelPromptContentObservationHandler() {
|
||||
return new ImageModelPromptContentObservationHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomTracingAwareLoggingObservationHandlerConfiguration {
|
||||
|
||||
static TracingAwareLoggingObservationHandler<ImageModelObservationContext> handlerInstance = new TracingAwareLoggingObservationHandler<>(
|
||||
new ImageModelPromptContentObservationHandler(), null);
|
||||
|
||||
@Bean
|
||||
TracingAwareLoggingObservationHandler<ImageModelObservationContext> imageModelPromptContentObservationHandler() {
|
||||
return handlerInstance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,13 +18,20 @@ package org.springframework.ai.vectorstore.observation.autoconfigure;
|
||||
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.ai.observation.TracingAwareLoggingObservationHandler;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext;
|
||||
import org.springframework.ai.vectorstore.observation.VectorStoreQueryResponseObservationHandler;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.test.system.CapturedOutput;
|
||||
import org.springframework.boot.test.system.OutputCaptureExtension;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link VectorStoreObservationAutoConfiguration}.
|
||||
@@ -32,28 +39,127 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Christian Tzolov
|
||||
* @author Jonatan Ivanov
|
||||
*/
|
||||
@ExtendWith(OutputCaptureExtension.class)
|
||||
class VectorStoreObservationAutoConfigurationTests {
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(VectorStoreObservationAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void queryResponseHandlerDefault() {
|
||||
this.contextRunner
|
||||
.run(context -> assertThat(context).doesNotHaveBean(VectorStoreQueryResponseObservationHandler.class));
|
||||
void queryResponseHandlerNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.run(context -> assertThat(context).doesNotHaveBean(VectorStoreQueryResponseObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryResponseHandlerEnabled() {
|
||||
void queryResponseHandlerWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.run(context -> assertThat(context).doesNotHaveBean(VectorStoreQueryResponseObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryResponseHandlerEnabledNoTracer(CapturedOutput output) {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.vectorstore.observations.log-query-response=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(VectorStoreQueryResponseObservationHandler.class));
|
||||
.run(context -> assertThat(context).hasSingleBean(VectorStoreQueryResponseObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out of the query response content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryResponseHandlerDisabled() {
|
||||
this.contextRunner.withPropertyValues("spring.ai.vectorstore.observations.log-query-response=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(VectorStoreQueryResponseObservationHandler.class));
|
||||
void queryResponseHandlerEnabledWithTracer(CapturedOutput output) {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.vectorstore.observations.log-query-response=true")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(VectorStoreQueryResponseObservationHandler.class)
|
||||
.hasSingleBean(TracingAwareLoggingObservationHandler.class));
|
||||
assertThat(output).contains(
|
||||
"You have enabled logging out of the query response content with the risk of exposing sensitive or private information. Please, be careful!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryResponseHandlerDisabledNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withPropertyValues("spring.ai.vectorstore.observations.log-query-response=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(VectorStoreQueryResponseObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryResponseHandlerDisabledWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.vectorstore.observations.log-query-response=false")
|
||||
.run(context -> assertThat(context).doesNotHaveBean(VectorStoreQueryResponseObservationHandler.class)
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customQueryResponseHandlerNoTracer() {
|
||||
this.contextRunner.withClassLoader(new FilteredClassLoader(Tracer.class))
|
||||
.withUserConfiguration(CustomVectorStoreQueryResponseObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.vectorstore.observations.log-query-response=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(VectorStoreQueryResponseObservationHandler.class)
|
||||
.hasBean("customVectorStoreQueryResponseObservationHandler")
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customQueryResponseHandlerWithTracer() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomVectorStoreQueryResponseObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.vectorstore.observations.log-query-response=true")
|
||||
.run(context -> assertThat(context).hasSingleBean(VectorStoreQueryResponseObservationHandler.class)
|
||||
.hasBean("customVectorStoreQueryResponseObservationHandler")
|
||||
.doesNotHaveBean(TracingAwareLoggingObservationHandler.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void customTracingAwareLoggingObservationHandler() {
|
||||
this.contextRunner.withUserConfiguration(TracerConfiguration.class)
|
||||
.withUserConfiguration(CustomTracingAwareLoggingObservationHandlerConfiguration.class)
|
||||
.withPropertyValues("spring.ai.vectorstore.observations.log-query-response=true")
|
||||
.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(VectorStoreQueryResponseObservationHandler.class)
|
||||
.hasSingleBean(TracingAwareLoggingObservationHandler.class)
|
||||
.hasBean("vectorStoreQueryResponseObservationHandler");
|
||||
assertThat(context.getBean(TracingAwareLoggingObservationHandler.class))
|
||||
.isSameAs(CustomTracingAwareLoggingObservationHandlerConfiguration.handlerInstance);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TracerConfiguration {
|
||||
|
||||
@Bean
|
||||
Tracer tracer() {
|
||||
return mock(Tracer.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomVectorStoreQueryResponseObservationHandlerConfiguration {
|
||||
|
||||
@Bean
|
||||
VectorStoreQueryResponseObservationHandler customVectorStoreQueryResponseObservationHandler() {
|
||||
return new VectorStoreQueryResponseObservationHandler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomTracingAwareLoggingObservationHandlerConfiguration {
|
||||
|
||||
static TracingAwareLoggingObservationHandler<VectorStoreObservationContext> handlerInstance = new TracingAwareLoggingObservationHandler<>(
|
||||
new VectorStoreQueryResponseObservationHandler(), null);
|
||||
|
||||
@Bean
|
||||
TracingAwareLoggingObservationHandler<VectorStoreObservationContext> vectorStoreQueryResponseObservationHandler() {
|
||||
return handlerInstance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2023-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ai.observation;
|
||||
|
||||
import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationHandler;
|
||||
import io.micrometer.tracing.CurrentTraceContext;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.TraceContext;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import io.micrometer.tracing.handler.TracingObservationHandler;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* Tests for {@link TracingAwareLoggingObservationHandler}.
|
||||
*
|
||||
* @author Jonatan Ivanov
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TracingAwareLoggingObservationHandlerTests {
|
||||
|
||||
@Mock
|
||||
private ObservationHandler<Observation.Context> delegate;
|
||||
|
||||
@Mock
|
||||
private Tracer tracer;
|
||||
|
||||
@InjectMocks
|
||||
private TracingAwareLoggingObservationHandler<Observation.Context> handler;
|
||||
|
||||
@Test
|
||||
void callsShouldBeDelegated() {
|
||||
Observation.Context context = new Observation.Context();
|
||||
context.put(TracingObservationHandler.TracingContext.class, new TracingObservationHandler.TracingContext());
|
||||
|
||||
handler.onStart(context);
|
||||
verify(delegate).onStart(context);
|
||||
|
||||
handler.onError(context);
|
||||
verify(delegate).onError(context);
|
||||
|
||||
Observation.Event event = Observation.Event.of("test");
|
||||
handler.onEvent(event, context);
|
||||
verify(delegate).onEvent(event, context);
|
||||
|
||||
handler.onScopeOpened(context);
|
||||
verify(delegate).onScopeOpened(context);
|
||||
|
||||
handler.onStop(context);
|
||||
verify(delegate).onStop(context);
|
||||
|
||||
handler.onScopeClosed(context);
|
||||
verify(delegate).onScopeClosed(context);
|
||||
|
||||
handler.onScopeReset(context);
|
||||
verify(delegate).onScopeReset(context);
|
||||
|
||||
handler.supportsContext(context);
|
||||
verify(delegate).supportsContext(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
void spanShouldBeAvailableOnStop() {
|
||||
Observation.Context observationContext = new Observation.Context();
|
||||
TracingObservationHandler.TracingContext tracingContext = new TracingObservationHandler.TracingContext();
|
||||
observationContext.put(TracingObservationHandler.TracingContext.class, tracingContext);
|
||||
|
||||
Span span = mock(Span.class);
|
||||
tracingContext.setSpan(span);
|
||||
TraceContext traceContext = mock(TraceContext.class);
|
||||
CurrentTraceContext currentTraceContext = mock(CurrentTraceContext.class);
|
||||
CurrentTraceContext.Scope scope = mock(CurrentTraceContext.Scope.class);
|
||||
|
||||
when(span.context()).thenReturn(traceContext);
|
||||
when(tracer.currentTraceContext()).thenReturn(currentTraceContext);
|
||||
when(currentTraceContext.maybeScope(traceContext)).thenReturn(scope);
|
||||
|
||||
handler.onStop(observationContext);
|
||||
|
||||
verify(scope).close();
|
||||
verify(currentTraceContext).maybeScope(traceContext);
|
||||
verify(delegate).onStop(observationContext);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user