Skip to content

Commit

Permalink
Provide auto configuration for OpenTelemetry Logs
Browse files Browse the repository at this point in the history
  • Loading branch information
making authored and mhalbritter committed Jun 27, 2024
1 parent 895fbd7 commit 2d6f248
Show file tree
Hide file tree
Showing 12 changed files with 896 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2012-2024 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.boot.actuate.autoconfigure.logs;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.sdk.logs.LogRecordProcessor;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;
import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor;
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
import io.opentelemetry.sdk.resources.Resource;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;

/**
* {@link EnableAutoConfiguration Auto-configuration} for OpenTelemetry Logs.
*
* @author Toshiaki Maki
* @since 3.4.0
*/
@AutoConfiguration("openTelemetryLogsAutoConfiguration")
@ConditionalOnClass({ SdkLoggerProvider.class, OpenTelemetry.class })
public class OpenTelemetryAutoConfiguration {

@Bean
@ConditionalOnMissingBean
public BatchLogRecordProcessor batchLogRecordProcessor(ObjectProvider<LogRecordExporter> logRecordExporters) {
return BatchLogRecordProcessor.builder(LogRecordExporter.composite(logRecordExporters.orderedStream().toList()))
.build();
}

@Bean
@ConditionalOnMissingBean
public SdkLoggerProvider otelSdkLoggerProvider(Resource resource,
ObjectProvider<LogRecordProcessor> logRecordProcessors,
ObjectProvider<SdkLoggerProviderBuilderCustomizer> customizers) {
SdkLoggerProviderBuilder builder = SdkLoggerProvider.builder().setResource(resource);
logRecordProcessors.orderedStream().forEach(builder::addLogRecordProcessor);
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
return builder.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2012-2024 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.boot.actuate.autoconfigure.logs;

import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder;

/**
* Callback interface that can be used to customize the {@link SdkLoggerProviderBuilder}
* that is used to create the auto-configured {@link SdkLoggerProvider}.
*
* @author Toshiaki Maki
* @since 3.4.0
*/
@FunctionalInterface
public interface SdkLoggerProviderBuilderCustomizer {

/**
* Customize the given {@code builder}.
* @param builder the builder to customize
*/
void customize(SdkLoggerProviderBuilder builder);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2012-2024 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.boot.actuate.autoconfigure.logs.otlp;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;

/**
* {@link EnableAutoConfiguration Auto-configuration} for OTLP Logs.
*
* @author Toshiaki Maki
* @since 3.4.0
*/
@AutoConfiguration
@ConditionalOnClass({ SdkLoggerProvider.class, OpenTelemetry.class, OtlpHttpLogRecordExporter.class })
@EnableConfigurationProperties(OtlpProperties.class)
@Import({ OtlpLogsConfigurations.ConnectionDetails.class, OtlpLogsConfigurations.Exporters.class })
public class OtlpLogsAutoConfiguration {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright 2012-2024 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.boot.actuate.autoconfigure.logs.otlp;

import java.util.Locale;

import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* Configurations imported by {@link OtlpLogsAutoConfiguration}.
*
* @author Toshiaki Maki
* @since 3.4.0
*/
public class OtlpLogsConfigurations {

@Configuration(proxyBeanMethods = false)
static class ConnectionDetails {

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "management.otlp.logs", name = "endpoint")
OtlpLogsConnectionDetails otlpLogsConnectionDetails(OtlpProperties properties) {
return new PropertiesOtlpLogsConnectionDetails(properties);
}

/**
* Adapts {@link OtlpProperties} to {@link OtlpLogsConnectionDetails}.
*/
static class PropertiesOtlpLogsConnectionDetails implements OtlpLogsConnectionDetails {

private final OtlpProperties properties;

PropertiesOtlpLogsConnectionDetails(OtlpProperties properties) {
this.properties = properties;
}

@Override
public String getUrl() {
return this.properties.getEndpoint();
}

}

}

@Configuration(proxyBeanMethods = false)
static class Exporters {

@ConditionalOnMissingBean(value = OtlpHttpLogRecordExporter.class,
type = "io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter")
@ConditionalOnBean(OtlpLogsConnectionDetails.class)
@Bean
OtlpHttpLogRecordExporter otlpHttpLogRecordExporter(OtlpProperties properties,
OtlpLogsConnectionDetails connectionDetails) {
OtlpHttpLogRecordExporterBuilder builder = OtlpHttpLogRecordExporter.builder()
.setEndpoint(connectionDetails.getUrl())
.setCompression(properties.getCompression().name().toLowerCase(Locale.US))
.setTimeout(properties.getTimeout());
properties.getHeaders().forEach(builder::addHeader);
return builder.build();
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2012-2024 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.boot.actuate.autoconfigure.logs.otlp;

import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;

/**
* Details required to establish a connection to an OpenTelemetry logs service.
*
* @author Toshiaki Maki
* @since 3.4.0
*/
public interface OtlpLogsConnectionDetails extends ConnectionDetails {

/**
* Address to where logs will be published.
* @return the address to where logs will be published
*/
String getUrl();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright 2012-2024 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.boot.actuate.autoconfigure.logs.otlp;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* Configuration properties for exporting logs using OTLP.
*
* @author Jonatan Ivanov
* @since 3.4.0
*/
@ConfigurationProperties("management.otlp.logs")
public class OtlpProperties {

/**
* URL to the OTel collector's HTTP API.
*/
private String endpoint;

/**
* Call timeout for the OTel Collector to process an exported batch of data. This
* timeout spans the entire call: resolving DNS, connecting, writing the request body,
* server processing, and reading the response body. If the call requires redirects or
* retries all must complete within one timeout period.
*/
private Duration timeout = Duration.ofSeconds(10);

/**
* Method used to compress the payload.
*/
private Compression compression = Compression.NONE;

/**
* Custom HTTP headers you want to pass to the collector, for example auth headers.
*/
private Map<String, String> headers = new HashMap<>();

public String getEndpoint() {
return this.endpoint;
}

public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}

public Duration getTimeout() {
return this.timeout;
}

public void setTimeout(Duration timeout) {
this.timeout = timeout;
}

public Compression getCompression() {
return this.compression;
}

public void setCompression(Compression compression) {
this.compression = compression;
}

public Map<String, String> getHeaders() {
return this.headers;
}

public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}

public enum Compression {

/**
* Gzip compression.
*/
GZIP,

/**
* No compression.
*/
NONE

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2012-2023 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.
*/

/**
* Auto-configuration for OpenTelemetry logs with OTLP.
*/
package org.springframework.boot.actuate.autoconfigure.logs.otlp;
Loading

0 comments on commit 2d6f248

Please sign in to comment.