This is an automated email from the ASF dual-hosted git repository.
zqr10159 pushed a commit to branch 2.0.0
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/2.0.0 by this push:
new 03da23d1d5 Report actual related metric matchers
03da23d1d5 is described below
commit 03da23d1d5e61610e5b4059f186793661b43ba64
Author: Logic <[email protected]>
AuthorDate: Wed Jun 10 08:11:29 2026 +0800
Report actual related metric matchers
---
.../impl/OtlpIngestionWorkspaceServiceImpl.java | 41 +++++++++---
.../OtlpIngestionWorkspaceServiceImplTest.java | 76 ++++++++++++++++++++++
2 files changed, 109 insertions(+), 8 deletions(-)
diff --git
a/hertzbeat-observability/src/main/java/org/apache/hertzbeat/observability/ingestion/service/impl/OtlpIngestionWorkspaceServiceImpl.java
b/hertzbeat-observability/src/main/java/org/apache/hertzbeat/observability/ingestion/service/impl/OtlpIngestionWorkspaceServiceImpl.java
index 95d7cfffc9..99ba05223e 100644
---
a/hertzbeat-observability/src/main/java/org/apache/hertzbeat/observability/ingestion/service/impl/OtlpIngestionWorkspaceServiceImpl.java
+++
b/hertzbeat-observability/src/main/java/org/apache/hertzbeat/observability/ingestion/service/impl/OtlpIngestionWorkspaceServiceImpl.java
@@ -1042,10 +1042,10 @@ public class OtlpIngestionWorkspaceServiceImpl
implements OtlpIngestionWorkspace
String step = resolvePromqlStep(start, end, null);
List<OtlpRelatedMetricsDto.Candidate> available = new ArrayList<>();
for (OtlpRelatedMetricsDto.Candidate candidate : candidates) {
- for (String query :
buildRelatedMetricAvailabilityQueries(candidate)) {
+ for (RelatedMetricAvailabilityProbe probe :
buildRelatedMetricAvailabilityProbes(candidate)) {
MetricQueryRepository.PromqlRangeQueryResult result =
metricQueryRepository.queryPromqlRange(
RELATED_METRICS_REF_ID,
- query,
+ probe.query(),
start,
end,
step
@@ -1063,8 +1063,8 @@ public class OtlpIngestionWorkspaceServiceImpl implements
OtlpIngestionWorkspace
candidate.getSource(),
candidate.getFamily(),
"promql-series",
- candidate.getMatchedLabels(),
- candidate.getResourceMatch()
+ probe.matchedLabels(),
+ probe.resourceMatch()
));
break;
}
@@ -1076,7 +1076,7 @@ public class OtlpIngestionWorkspaceServiceImpl implements
OtlpIngestionWorkspace
return available;
}
- private List<String>
buildRelatedMetricAvailabilityQueries(OtlpRelatedMetricsDto.Candidate
candidate) {
+ private List<RelatedMetricAvailabilityProbe>
buildRelatedMetricAvailabilityProbes(OtlpRelatedMetricsDto.Candidate candidate)
{
if (candidate == null || !StringUtils.hasText(candidate.getQuery())) {
return List.of();
}
@@ -1095,11 +1095,21 @@ public class OtlpIngestionWorkspaceServiceImpl
implements OtlpIngestionWorkspace
LinkedHashMap<String, String> httpRouteMatch = new
LinkedHashMap<>(resourceMatch);
httpRouteMatch.remove("operation_name");
return List.of(
- buildRelatedMetricAvailabilityQuery(metricName,
operationNameMatch),
- buildRelatedMetricAvailabilityQuery(metricName,
httpRouteMatch)
+ buildRelatedMetricAvailabilityProbe(metricName, candidate,
operationNameMatch),
+ buildRelatedMetricAvailabilityProbe(metricName, candidate,
httpRouteMatch)
);
}
- return List.of(buildRelatedMetricAvailabilityQuery(metricName,
resourceMatch));
+ return List.of(buildRelatedMetricAvailabilityProbe(metricName,
candidate, resourceMatch));
+ }
+
+ private RelatedMetricAvailabilityProbe
buildRelatedMetricAvailabilityProbe(String metricName,
+
OtlpRelatedMetricsDto.Candidate candidate,
+
Map<String, String> resourceMatch) {
+ return new RelatedMetricAvailabilityProbe(
+ buildRelatedMetricAvailabilityQuery(metricName, resourceMatch),
+ matchedAvailabilityLabels(candidate, resourceMatch),
+ resourceMatch
+ );
}
private String buildRelatedMetricAvailabilityQuery(String metricName,
Map<String, String> resourceMatch) {
@@ -1118,6 +1128,16 @@ public class OtlpIngestionWorkspaceServiceImpl
implements OtlpIngestionWorkspace
return "sum by (__name__) ({" + String.join(", ", matchers) + "})";
}
+ private List<String>
matchedAvailabilityLabels(OtlpRelatedMetricsDto.Candidate candidate,
Map<String, String> resourceMatch) {
+ if (candidate == null ||
CollectionUtils.isEmpty(candidate.getMatchedLabels()) ||
CollectionUtils.isEmpty(resourceMatch)) {
+ return List.of();
+ }
+ Set<String> resourceLabels = resourceMatch.keySet();
+ return candidate.getMatchedLabels().stream()
+ .filter(resourceLabels::contains)
+ .toList();
+ }
+
private void addRelatedMetricCandidate(LinkedHashMap<String,
OtlpRelatedMetricsDto.Candidate> candidates,
String query,
String source,
@@ -2791,4 +2811,9 @@ public class OtlpIngestionWorkspaceServiceImpl implements
OtlpIngestionWorkspace
OtlpMetricsConsoleDto.Stats stats,
String errorMessage) {
}
+
+ private record RelatedMetricAvailabilityProbe(String query,
+ List<String> matchedLabels,
+ Map<String, String>
resourceMatch) {
+ }
}
diff --git
a/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/ingestion/service/impl/OtlpIngestionWorkspaceServiceImplTest.java
b/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/ingestion/service/impl/OtlpIngestionWorkspaceServiceImplTest.java
index 8f0c232bc6..ddaa9e1d8d 100644
---
a/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/ingestion/service/impl/OtlpIngestionWorkspaceServiceImplTest.java
+++
b/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/ingestion/service/impl/OtlpIngestionWorkspaceServiceImplTest.java
@@ -1168,6 +1168,82 @@ class OtlpIngestionWorkspaceServiceImplTest {
&& "POST
/checkout".equals(candidate.getResourceMatch().get("http_route"))));
}
+ @Test
+ void relatedMetricsReportsActualOperationAvailabilityMatcher() {
+ observabilitySignalIntakeGateway.recordOtlpMetricIntake(
+ Map.of(
+ "service.name", "checkout",
+ "service.namespace", "commerce",
+ "deployment.environment.name", "prod"
+ ),
+ 2_000L,
+ "http.server.duration",
+ "histogram",
+ "ms",
+ 14.0,
+ Map.of()
+ );
+
when(workspaceQueryGateway.findEntityById(42L)).thenReturn(java.util.Optional.empty());
+
when(workspaceQueryGateway.findIdentitiesByEntityId(42L)).thenReturn(List.of());
+ when(metricQueryRepository.hasPromqlExecutor()).thenReturn(true);
+ when(metricQueryRepository.queryPromqlRange(
+ anyString(),
+ anyString(),
+ anyLong(),
+ anyLong(),
+ anyString()
+ )).thenAnswer(invocation -> {
+ String refId = invocation.getArgument(0);
+ String query = invocation.getArgument(1);
+ if ("otlp-related-metrics-inventory".equals(refId)) {
+ return promqlSuccess(new
DatasourceQueryData("otlp-related-metrics-inventory", 200, null, List.of()));
+ }
+ if (query.contains("__name__=\"http_server_duration\"")
+ && query.contains("http_route=\"POST /checkout\"")
+ && !query.contains("operation_name=\"POST /checkout\"")) {
+ return promqlSuccess(new DatasourceQueryData(
+ "otlp-related-metrics",
+ 200,
+ null,
+ List.of(new DatasourceQueryData.SchemaData(
+ new DatasourceQueryData.MetricSchema(
+ List.of(
+ new
DatasourceQueryData.MetricField("__ts__", "time", null),
+ new
DatasourceQueryData.MetricField("__value__", "number", null)
+ ),
+ Map.of("__name__",
"http_server_duration"),
+ Map.of()
+ ),
+ Collections.singletonList(new Object[]
{2_000L, 14.0})
+ ))
+ ));
+ }
+ return promqlSuccess(new
DatasourceQueryData("otlp-related-metrics", 200, null, List.of()));
+ });
+
+ OtlpRelatedMetricsDto related =
otlpIngestionWorkspaceService.getRelatedMetrics(
+ 42L,
+ "service",
+ 1_000L,
+ 2_000L,
+ "checkout",
+ "commerce",
+ "prod",
+ null,
+ "POST /checkout",
+ "8"
+ );
+
+ assertFalse(related.getCandidates().isEmpty());
+ OtlpRelatedMetricsDto.Candidate candidate =
related.getCandidates().getFirst();
+ assertEquals("http_server_duration", candidate.getQuery());
+ assertEquals("promql-series", candidate.getReason());
+ assertTrue(candidate.getMatchedLabels().contains("http_route"));
+ assertFalse(candidate.getMatchedLabels().contains("operation_name"));
+ assertEquals("POST /checkout",
candidate.getResourceMatch().get("http_route"));
+
assertFalse(candidate.getResourceMatch().containsKey("operation_name"));
+ }
+
@Test
void relatedMetricsPrefersPromqlAvailableCandidatesWhenExecutorExists() {
observabilitySignalIntakeGateway.recordOtlpMetricIntake(
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]