-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OTLP metrics sender interface (#5691)
* Add capability for anyone to define their implementation of OTLP metrics sending * Fix formatting * Remove otlp proto from API and introduce Builder Keeps the API more generic without a dependency on API from the opentelemetry-proto-java project. Also adds a Builder to avoid the need for more public constructors that may change in the future. * Polish * Add docs --------- Co-authored-by: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com>
- Loading branch information
1 parent
2948805
commit f99efa6
Showing
8 changed files
with
299 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
docs/src/test/java/io/micrometer/docs/metrics/OtlpMeterRegistryCustomizationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright 2025 VMware, Inc. | ||
* | ||
* 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 io.micrometer.docs.metrics; | ||
|
||
import io.micrometer.common.lang.NonNullApi; | ||
import io.micrometer.core.ipc.http.OkHttpSender; | ||
import io.micrometer.registry.otlp.OtlpConfig; | ||
import io.micrometer.registry.otlp.OtlpHttpMetricsSender; | ||
import io.micrometer.registry.otlp.OtlpMeterRegistry; | ||
import io.micrometer.registry.otlp.OtlpMetricsSender; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.util.Map; | ||
|
||
class OtlpMeterRegistryCustomizationTest { | ||
|
||
@Test | ||
void customizeHttpSender() { | ||
// tag::customizeHttpSender[] | ||
OtlpConfig config = OtlpConfig.DEFAULT; | ||
OtlpHttpMetricsSender httpMetricsSender = new OtlpHttpMetricsSender(new OkHttpSender(), config); | ||
OtlpMeterRegistry meterRegistry = OtlpMeterRegistry.builder(config).metricsSender(httpMetricsSender).build(); | ||
// end::customizeHttpSender[] | ||
} | ||
|
||
@Test | ||
void customizeOtlpSender() { | ||
// tag::customGrpcSender[] | ||
OtlpConfig config = OtlpConfig.DEFAULT; | ||
OtlpMetricsSender metricsSender = new OtlpGrpcMetricsSender(); | ||
OtlpMeterRegistry meterRegistry = OtlpMeterRegistry.builder(config).metricsSender(metricsSender).build(); | ||
// end::customGrpcSender[] | ||
} | ||
|
||
@NonNullApi | ||
private static class OtlpGrpcMetricsSender implements OtlpMetricsSender { | ||
|
||
@Override | ||
public void send(byte[] metricsData, Map<String, String> headers) { | ||
} | ||
|
||
} | ||
|
||
} |
32 changes: 32 additions & 0 deletions
32
...ons/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/MetricsSender.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright 2025 VMware, Inc. | ||
* | ||
* 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 io.micrometer.registry.otlp; | ||
|
||
import java.util.Map; | ||
|
||
// intentionally not public while we incubate this concept | ||
// if we want to use this in other registries, it should move to micrometer-core and become public API | ||
interface MetricsSender { | ||
|
||
/** | ||
* Send encoded metrics data from a {@link io.micrometer.core.instrument.MeterRegistry | ||
* MeterRegistry}. | ||
* @param metricsData encoded batch of metrics | ||
* @param headers metadata to send as headers with the metrics data | ||
*/ | ||
void send(byte[] metricsData, Map<String, String> headers); | ||
|
||
} |
83 changes: 83 additions & 0 deletions
83
...ometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpHttpMetricsSender.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* | ||
* Copyright 2025 VMware, Inc. | ||
* | ||
* 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 io.micrometer.registry.otlp; | ||
|
||
import io.micrometer.common.util.internal.logging.InternalLogger; | ||
import io.micrometer.common.util.internal.logging.InternalLoggerFactory; | ||
import io.micrometer.core.ipc.http.HttpSender; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* An implementation of {@link OtlpMetricsSender} that uses an {@link HttpSender}. | ||
* | ||
* @since 1.15.0 | ||
*/ | ||
public class OtlpHttpMetricsSender implements OtlpMetricsSender { | ||
|
||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(OtlpHttpMetricsSender.class); | ||
|
||
private final HttpSender httpSender; | ||
|
||
private final OtlpConfig config; | ||
|
||
private final String userAgentHeader; | ||
|
||
public OtlpHttpMetricsSender(HttpSender httpSender, OtlpConfig config) { | ||
this.httpSender = httpSender; | ||
this.config = config; | ||
this.userAgentHeader = getUserAgentHeader(); | ||
} | ||
|
||
@Override | ||
public void send(byte[] metricsData, Map<String, String> headers) { | ||
HttpSender.Request.Builder httpRequest = this.httpSender.post(config.url()) | ||
.withHeader("User-Agent", userAgentHeader) | ||
.withContent("application/x-protobuf", metricsData); | ||
headers.forEach(httpRequest::withHeader); | ||
try { | ||
HttpSender.Response response = httpRequest.send(); | ||
if (!response.isSuccessful()) { | ||
logger.warn( | ||
"Failed to publish metrics (context: {}). Server responded with HTTP status code {} and body {}", | ||
getConfigurationContext(), response.code(), response.body()); | ||
} | ||
} | ||
catch (Throwable e) { | ||
logger.warn("Failed to publish metrics (context: {}) ", getConfigurationContext(), e); | ||
} | ||
} | ||
|
||
private String getUserAgentHeader() { | ||
String userAgent = "Micrometer-OTLP-Exporter-Java"; | ||
String version = getClass().getPackage().getImplementationVersion(); | ||
if (version != null) { | ||
userAgent += "/" + version; | ||
} | ||
return userAgent; | ||
} | ||
|
||
/** | ||
* Get the configuration context. | ||
* @return A message containing enough information for the log reader to figure out | ||
* what configuration details may have contributed to the failure. | ||
*/ | ||
private String getConfigurationContext() { | ||
// While other values may contribute to failures, these two are most common | ||
return "url=" + config.url() + ", resource-attributes=" + config.resourceAttributes(); | ||
} | ||
|
||
} |
Oops, something went wrong.