123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
- package io.opentelemetry.smoketest;
- import static org.assertj.core.api.Assertions.assertThat;
- import io.opentelemetry.api.common.AttributeKey;
- import io.opentelemetry.api.common.Attributes;
- import io.opentelemetry.api.trace.SpanKind;
- import io.opentelemetry.instrumentation.spring.autoconfigure.properties.OtelResourceProperties;
- import io.opentelemetry.instrumentation.spring.autoconfigure.properties.OtlpExporterProperties;
- import io.opentelemetry.instrumentation.spring.autoconfigure.properties.PropagationProperties;
- import io.opentelemetry.instrumentation.spring.autoconfigure.properties.SpringConfigProperties;
- import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
- import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
- import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
- import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider;
- import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider;
- import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
- import io.opentelemetry.sdk.logs.data.LogRecordData;
- import io.opentelemetry.sdk.logs.export.LogRecordExporter;
- import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
- import io.opentelemetry.sdk.metrics.data.MetricData;
- import io.opentelemetry.sdk.metrics.export.MetricExporter;
- import io.opentelemetry.sdk.resources.Resource;
- import io.opentelemetry.sdk.testing.assertj.TracesAssert;
- import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter;
- import io.opentelemetry.sdk.testing.exporter.InMemoryMetricExporter;
- import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
- import io.opentelemetry.sdk.trace.data.SpanData;
- import io.opentelemetry.sdk.trace.export.SpanExporter;
- import io.opentelemetry.semconv.SemanticAttributes;
- import io.opentelemetry.spring.smoketest.OtelSpringStarterSmokeTestApplication;
- import io.opentelemetry.spring.smoketest.OtelSpringStarterSmokeTestController;
- import java.util.Collections;
- import java.util.List;
- import org.junit.jupiter.api.Test;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.boot.test.web.client.TestRestTemplate;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.annotation.Order;
- import org.springframework.core.env.Environment;
- @SpringBootTest(
- classes = {
- OtelSpringStarterSmokeTestApplication.class,
- OtelSpringStarterSmokeTest.TestConfiguration.class
- },
- webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
- properties = {
- "otel.traces.exporter=none",
- "otel.metrics.exporter=none",
- "otel.logs.exporter=none",
- "otel.metric.export.interval=100",
- "otel.exporter.otlp.headers=a=1,b=2",
- "otel.traces.exporter=memory",
- "otel.metrics.exporter=memory",
- "otel.logs.exporter=memory"
- // We set the export interval of the metrics to 100 ms. The default value is 1 minute.
- // the headers are simply set here to make sure that headers can be parsed
- })
- class OtelSpringStarterSmokeTest {
- public static final InMemoryMetricExporter METRIC_EXPORTER =
- InMemoryMetricExporter.create(AggregationTemporality.DELTA);
- private static final InMemoryLogRecordExporter LOG_RECORD_EXPORTER =
- InMemoryLogRecordExporter.create();
- public static final InMemorySpanExporter SPAN_EXPORTER = InMemorySpanExporter.create();
- @Autowired private TestRestTemplate testRestTemplate;
- @Autowired private Environment environment;
- @Autowired private PropagationProperties propagationProperties;
- @Autowired private OtelResourceProperties otelResourceProperties;
- @Autowired private OtlpExporterProperties otlpExporterProperties;
- @Configuration(proxyBeanMethods = false)
- static class TestConfiguration {
- @Bean
- ConfigurableMetricExporterProvider otlpMetricExporterProvider() {
- return new ConfigurableMetricExporterProvider() {
- @Override
- public MetricExporter createExporter(ConfigProperties configProperties) {
- return METRIC_EXPORTER;
- }
- @Override
- public String getName() {
- return "memory";
- }
- };
- }
- @Bean
- ConfigurableSpanExporterProvider otlpSpanExporterProvider() {
- return new ConfigurableSpanExporterProvider() {
- @Override
- public SpanExporter createExporter(ConfigProperties configProperties) {
- return SPAN_EXPORTER;
- }
- @Override
- public String getName() {
- return "memory";
- }
- };
- }
- @Bean
- ConfigurableLogRecordExporterProvider otlpLogRecordExporterProvider() {
- return new ConfigurableLogRecordExporterProvider() {
- @Override
- public LogRecordExporter createExporter(ConfigProperties configProperties) {
- return LOG_RECORD_EXPORTER;
- }
- @Override
- public String getName() {
- return "memory";
- }
- };
- }
- @Bean
- @Order(1)
- AutoConfigurationCustomizerProvider hiddenPropagatorCustomizer() {
- return customizer ->
- customizer.addResourceCustomizer(
- (resource, config) ->
- resource.merge(
- Resource.create(
- Attributes.of(
- AttributeKey.booleanKey("keyFromResourceCustomizer"), false))));
- }
- @Bean
- @Order(2)
- AutoConfigurationCustomizerProvider propagatorCustomizer() {
- return customizer ->
- customizer.addResourceCustomizer(
- (resource, config) ->
- resource.merge(
- Resource.create(
- Attributes.of(
- AttributeKey.booleanKey("keyFromResourceCustomizer"), true))));
- }
- }
- @Test
- void propertyConversion() {
- ConfigProperties configProperties =
- SpringConfigProperties.create(
- environment,
- otlpExporterProperties,
- otelResourceProperties,
- propagationProperties,
- DefaultConfigProperties.createFromMap(Collections.emptyMap()));
- assertThat(configProperties.getMap("otel.exporter.otlp.headers"))
- .containsEntry("a", "1")
- .containsEntry("b", "2");
- assertThat(configProperties.getList("otel.propagators")).containsExactly("b3");
- }
- @Test
- void shouldSendTelemetry() throws InterruptedException {
- testRestTemplate.getForObject(OtelSpringStarterSmokeTestController.URL, String.class);
- Thread.sleep(5_000); // Sleep time could be potentially reduced and perhaps removed with
- // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/8962
- // and https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/8963
- List<SpanData> exportedSpans = SPAN_EXPORTER.getFinishedSpanItems();
- // Span
- TracesAssert.assertThat(exportedSpans)
- .hasTracesSatisfyingExactly(
- traceAssert ->
- traceAssert.hasSpansSatisfyingExactly(
- spanDataAssert ->
- spanDataAssert
- .hasKind(SpanKind.CLIENT)
- .hasAttribute(
- SemanticAttributes.DB_STATEMENT,
- "create table test_table (id bigint not null, primary key (id))")),
- traceAssert ->
- traceAssert.hasSpansSatisfyingExactly(
- spanDataAssert ->
- spanDataAssert
- .hasKind(SpanKind.SERVER)
- .hasResourceSatisfying(
- r ->
- r.hasAttribute(
- AttributeKey.booleanKey("keyFromResourceCustomizer"),
- true)
- .hasAttribute(
- AttributeKey.stringKey("attributeFromYaml"), "true"))
- .hasAttribute(SemanticAttributes.HTTP_REQUEST_METHOD, "GET")
- .hasAttribute(SemanticAttributes.HTTP_RESPONSE_STATUS_CODE, 200L)
- .hasAttribute(SemanticAttributes.HTTP_ROUTE, "/ping")));
- // Metric
- List<MetricData> exportedMetrics = METRIC_EXPORTER.getFinishedMetricItems();
- assertThat(exportedMetrics)
- .as("Should contain " + OtelSpringStarterSmokeTestController.TEST_HISTOGRAM + " metric.")
- .anySatisfy(
- metric -> {
- String metricName = metric.getName();
- assertThat(metricName).isEqualTo(OtelSpringStarterSmokeTestController.TEST_HISTOGRAM);
- });
- // Log
- List<LogRecordData> logs = LOG_RECORD_EXPORTER.getFinishedLogRecordItems();
- LogRecordData firstLog = logs.get(0);
- assertThat(firstLog.getBody().asString())
- .as("Should instrument logs")
- .startsWith("Starting ")
- .contains(this.getClass().getSimpleName());
- assertThat(firstLog.getAttributes().asMap())
- .as("Should capture code attributes")
- .containsEntry(
- SemanticAttributes.CODE_NAMESPACE, "org.springframework.boot.StartupInfoLogger");
- }
- }
|