From 89066c698848fe99084e0338cf5fb32bfe8fd0ba Mon Sep 17 00:00:00 2001 From: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com> Date: Thu, 5 Nov 2026 23:24:35 +0800 Subject: [PATCH] test(observability): isolate raw OTel contexts and assert trace coexistence Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com> --- server/skillhub-app/pom.xml | 17 ++++++- .../business/BusinessLogsCollectorTest.java | 1 + .../business/BusinessLogsHttpTest.java | 1 + .../business/BusinessLogsPipelineTest.java | 1 + .../BusinessLogsProducerPostgresTest.java | 1 + .../BusinessLogsTracingCoexistenceTest.java | 47 +++++++++++++++++++ .../business/BusinessLogsTransactionTest.java | 1 + 7 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsTracingCoexistenceTest.java diff --git a/server/skillhub-app/pom.xml b/server/skillhub-app/pom.xml index 224e42d11..428982a51 100644 --- a/server/skillhub-app/pom.xml +++ b/server/skillhub-app/pom.xml @@ -175,7 +175,22 @@ default-test - process-global-diagnostics + process-global-diagnostics,process-global-otel-context + + + + + isolated-otel-context + test + + process-global-otel-context + + **/BusinessLogs*Test.java + + false + 1 + false diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsCollectorTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsCollectorTest.java index dcf5f14e2..898e77f69 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsCollectorTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsCollectorTest.java @@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** Actual production configuration sends protobuf over HTTP to a pinned real Collector/file sink. */ @Testcontainers +@org.junit.jupiter.api.Tag("process-global-otel-context") class BusinessLogsCollectorTest { @Container static final GenericContainer COLLECTOR = new GenericContainer<>("otel/opentelemetry-collector-contrib:0.111.0") diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsHttpTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsHttpTest.java index e7b31b3cc..ee1580d07 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsHttpTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsHttpTest.java @@ -21,6 +21,7 @@ import org.springframework.boot.test.context.runner.ApplicationContextRunner; import static org.assertj.core.api.Assertions.assertThat; +@org.junit.jupiter.api.Tag("process-global-otel-context") class BusinessLogsHttpTest { @Test void truncatedErrorBodyCannotPermanentlyExhaustAdmission() throws Exception { diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsPipelineTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsPipelineTest.java index f0f94df33..cdba9688e 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsPipelineTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsPipelineTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.params.provider.ValueSource; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; +@org.junit.jupiter.api.Tag("process-global-otel-context") class BusinessLogsPipelineTest { @ParameterizedTest @ValueSource(booleans = {true, false}) diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsProducerPostgresTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsProducerPostgresTest.java index 22d182dc8..e4cdb2503 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsProducerPostgresTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsProducerPostgresTest.java @@ -64,6 +64,7 @@ import static org.mockito.Mockito.when; SkillDownloadService.class, SkillSlugResolutionService.class, ReviewService.class, PromotionService.class, ReviewPermissionChecker.class, BusinessLogsProducerPostgresTest.Configuration.class}) @Transactional(propagation = Propagation.NOT_SUPPORTED) +@org.junit.jupiter.api.Tag("process-global-otel-context") class BusinessLogsProducerPostgresTest { @Container static final PostgreSQLContainer POSTGRES = new PostgreSQLContainer<>("postgres:16-alpine") diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsTracingCoexistenceTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsTracingCoexistenceTest.java new file mode 100644 index 000000000..d786bbd01 --- /dev/null +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsTracingCoexistenceTest.java @@ -0,0 +1,47 @@ +package com.iflytek.skillhub.observability.business; + +import com.iflytek.skillhub.observability.tracing.SkillHubTracingConfiguration; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import io.micrometer.tracing.Tracer; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.slf4j.MDC; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import static org.assertj.core.api.Assertions.assertThat; + +/** Production configurations must coexist in the same startup, before any raw test context. */ +@Tag("process-global-otel-context") +class BusinessLogsTracingCoexistenceTest { + @Configuration(proxyBeanMethods = false) + @EnableAutoConfiguration + @Import({SkillHubTracingConfiguration.class, BusinessLogsConfiguration.class}) + static class Application {} + + @Test + void enablingBusinessLogsPreservesTraceAndSpanCorrelation() { + new ApplicationContextRunner().withUserConfiguration(Application.class) + .withBean(SimpleMeterRegistry.class, SimpleMeterRegistry::new) + .withPropertyValues("spring.flyway.enabled=false", "spring.jpa.hibernate.ddl-auto=none", + "skillhub.observability.tracing-mode=otel-sdk", + "management.tracing.sampling.probability=1", + "skillhub.observability.business-logs.enabled=true", + "skillhub.observability.business-logs.endpoint=http://127.0.0.1:4318/v1/logs") + .run(context -> { + assertThat(context).hasNotFailed(); + assertThat(context).hasSingleBean(BusinessLogsPipeline.class); + Tracer tracer = context.getBean(Tracer.class); + var span = tracer.nextSpan().name("business-logs-coexistence").start(); + try (var ignored = tracer.withSpan(span)) { + assertThat(MDC.get("traceId")).isEqualTo(span.context().traceId()).hasSize(32); + assertThat(MDC.get("spanId")).isEqualTo(span.context().spanId()).hasSize(16); + } finally { + span.end(); + MDC.clear(); + } + }); + } +} diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsTransactionTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsTransactionTest.java index c8f800de7..6e19a6744 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsTransactionTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/observability/business/BusinessLogsTransactionTest.java @@ -47,6 +47,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.*; @Testcontainers +@org.junit.jupiter.api.Tag("process-global-otel-context") class BusinessLogsTransactionTest { @Container static final PostgreSQLContainer POSTGRES = new PostgreSQLContainer<>("postgres:16-alpine")