Skip to content

Commit 86ffb68

Browse files
committed
Merge pull request #40961 from making
* pr/40961: Polish "Provide auto configuration for OpenTelemetry Logs" Provide auto configuration for OpenTelemetry Logs Closes gh-40961
2 parents 895fbd7 + cfa0571 commit 86ffb68

File tree

12 files changed

+891
-0
lines changed

12 files changed

+891
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry;
18+
19+
import io.opentelemetry.api.OpenTelemetry;
20+
import io.opentelemetry.sdk.logs.LogRecordProcessor;
21+
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
22+
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
23+
import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor;
24+
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
25+
import io.opentelemetry.sdk.resources.Resource;
26+
27+
import org.springframework.beans.factory.ObjectProvider;
28+
import org.springframework.boot.autoconfigure.AutoConfiguration;
29+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
30+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
31+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
32+
import org.springframework.context.annotation.Bean;
33+
34+
/**
35+
* {@link EnableAutoConfiguration Auto-configuration} for OpenTelemetry logging.
36+
*
37+
* @author Toshiaki Maki
38+
* @since 3.4.0
39+
*/
40+
@AutoConfiguration
41+
@ConditionalOnClass({ SdkLoggerProvider.class, OpenTelemetry.class })
42+
public class OpenTelemetryLoggingAutoConfiguration {
43+
44+
@Bean
45+
@ConditionalOnMissingBean
46+
BatchLogRecordProcessor batchLogRecordProcessor(ObjectProvider<LogRecordExporter> logRecordExporters) {
47+
return BatchLogRecordProcessor.builder(LogRecordExporter.composite(logRecordExporters.orderedStream().toList()))
48+
.build();
49+
}
50+
51+
@Bean
52+
@ConditionalOnMissingBean
53+
SdkLoggerProvider otelSdkLoggerProvider(Resource resource, ObjectProvider<LogRecordProcessor> logRecordProcessors,
54+
ObjectProvider<SdkLoggerProviderBuilderCustomizer> customizers) {
55+
SdkLoggerProviderBuilder builder = SdkLoggerProvider.builder().setResource(resource);
56+
logRecordProcessors.orderedStream().forEach(builder::addLogRecordProcessor);
57+
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
58+
return builder.build();
59+
}
60+
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry;
18+
19+
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
20+
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
21+
22+
/**
23+
* Callback interface that can be used to customize the {@link SdkLoggerProviderBuilder}
24+
* that is used to create the auto-configured {@link SdkLoggerProvider}.
25+
*
26+
* @author Toshiaki Maki
27+
* @since 3.4.0
28+
*/
29+
@FunctionalInterface
30+
public interface SdkLoggerProviderBuilderCustomizer {
31+
32+
/**
33+
* Customize the given {@code builder}.
34+
* @param builder the builder to customize
35+
*/
36+
void customize(SdkLoggerProviderBuilder builder);
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
18+
19+
import io.opentelemetry.api.OpenTelemetry;
20+
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
21+
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
22+
23+
import org.springframework.boot.autoconfigure.AutoConfiguration;
24+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
26+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
27+
import org.springframework.context.annotation.Import;
28+
29+
/**
30+
* {@link EnableAutoConfiguration Auto-configuration} for OTLP logging.
31+
*
32+
* @author Toshiaki Maki
33+
* @since 3.4.0
34+
*/
35+
@AutoConfiguration
36+
@ConditionalOnClass({ SdkLoggerProvider.class, OpenTelemetry.class, OtlpHttpLogRecordExporter.class })
37+
@EnableConfigurationProperties(OtlpLoggingProperties.class)
38+
@Import({ OtlpLoggingConfigurations.ConnectionDetails.class, OtlpLoggingConfigurations.Exporters.class })
39+
public class OtlpLoggingAutoConfiguration {
40+
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
18+
19+
import java.util.Locale;
20+
21+
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
22+
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder;
23+
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
26+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
27+
import org.springframework.context.annotation.Bean;
28+
import org.springframework.context.annotation.Configuration;
29+
30+
/**
31+
* Configurations imported by {@link OtlpLoggingAutoConfiguration}.
32+
*
33+
* @author Toshiaki Maki
34+
*/
35+
final class OtlpLoggingConfigurations {
36+
37+
private OtlpLoggingConfigurations() {
38+
}
39+
40+
@Configuration(proxyBeanMethods = false)
41+
static class ConnectionDetails {
42+
43+
@Bean
44+
@ConditionalOnMissingBean
45+
@ConditionalOnProperty(prefix = "management.otlp.logging", name = "endpoint")
46+
OtlpLoggingConnectionDetails otlpLogsConnectionDetails(OtlpLoggingProperties properties) {
47+
return new PropertiesOtlpLoggingConnectionDetails(properties);
48+
}
49+
50+
/**
51+
* Adapts {@link OtlpLoggingProperties} to {@link OtlpLoggingConnectionDetails}.
52+
*/
53+
static class PropertiesOtlpLoggingConnectionDetails implements OtlpLoggingConnectionDetails {
54+
55+
private final OtlpLoggingProperties properties;
56+
57+
PropertiesOtlpLoggingConnectionDetails(OtlpLoggingProperties properties) {
58+
this.properties = properties;
59+
}
60+
61+
@Override
62+
public String getEndpoint() {
63+
return this.properties.getEndpoint();
64+
}
65+
66+
}
67+
68+
}
69+
70+
@Configuration(proxyBeanMethods = false)
71+
static class Exporters {
72+
73+
@ConditionalOnMissingBean(value = OtlpHttpLogRecordExporter.class,
74+
type = "io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter")
75+
@ConditionalOnBean(OtlpLoggingConnectionDetails.class)
76+
@Bean
77+
OtlpHttpLogRecordExporter otlpHttpLogRecordExporter(OtlpLoggingProperties properties,
78+
OtlpLoggingConnectionDetails connectionDetails) {
79+
OtlpHttpLogRecordExporterBuilder builder = OtlpHttpLogRecordExporter.builder()
80+
.setEndpoint(connectionDetails.getEndpoint())
81+
.setCompression(properties.getCompression().name().toLowerCase(Locale.US))
82+
.setTimeout(properties.getTimeout());
83+
properties.getHeaders().forEach(builder::addHeader);
84+
return builder.build();
85+
}
86+
87+
}
88+
89+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
18+
19+
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
20+
21+
/**
22+
* Details required to establish a connection to an OpenTelemetry logging service.
23+
*
24+
* @author Toshiaki Maki
25+
* @since 3.4.0
26+
*/
27+
public interface OtlpLoggingConnectionDetails extends ConnectionDetails {
28+
29+
/**
30+
* Address to where logs will be published.
31+
* @return the address to where logs will be published
32+
*/
33+
String getEndpoint();
34+
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;
18+
19+
import java.time.Duration;
20+
import java.util.HashMap;
21+
import java.util.Map;
22+
23+
import org.springframework.boot.context.properties.ConfigurationProperties;
24+
25+
/**
26+
* Configuration properties for exporting logs using OTLP.
27+
*
28+
* @author Jonatan Ivanov
29+
* @since 3.4.0
30+
*/
31+
@ConfigurationProperties("management.otlp.logging")
32+
public class OtlpLoggingProperties {
33+
34+
/**
35+
* URL to the OTel collector's HTTP API.
36+
*/
37+
private String endpoint;
38+
39+
/**
40+
* Call timeout for the OTel Collector to process an exported batch of data. This
41+
* timeout spans the entire call: resolving DNS, connecting, writing the request body,
42+
* server processing, and reading the response body. If the call requires redirects or
43+
* retries all must complete within one timeout period.
44+
*/
45+
private Duration timeout = Duration.ofSeconds(10);
46+
47+
/**
48+
* Method used to compress the payload.
49+
*/
50+
private Compression compression = Compression.NONE;
51+
52+
/**
53+
* Custom HTTP headers you want to pass to the collector, for example auth headers.
54+
*/
55+
private final Map<String, String> headers = new HashMap<>();
56+
57+
public String getEndpoint() {
58+
return this.endpoint;
59+
}
60+
61+
public void setEndpoint(String endpoint) {
62+
this.endpoint = endpoint;
63+
}
64+
65+
public Duration getTimeout() {
66+
return this.timeout;
67+
}
68+
69+
public void setTimeout(Duration timeout) {
70+
this.timeout = timeout;
71+
}
72+
73+
public Compression getCompression() {
74+
return this.compression;
75+
}
76+
77+
public void setCompression(Compression compression) {
78+
this.compression = compression;
79+
}
80+
81+
public Map<String, String> getHeaders() {
82+
return this.headers;
83+
}
84+
85+
public enum Compression {
86+
87+
/**
88+
* Gzip compression.
89+
*/
90+
GZIP,
91+
92+
/**
93+
* No compression.
94+
*/
95+
NONE
96+
97+
}
98+
99+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2012-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* Auto-configuration for OpenTelemetry logging with OTLP.
19+
*/
20+
package org.springframework.boot.actuate.autoconfigure.logging.opentelemetry.otlp;

0 commit comments

Comments
 (0)