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 b017cebc2b Support related metrics friendly filters
b017cebc2b is described below

commit b017cebc2b4f29025fe1e527d60668fddac031e7
Author: Logic <[email protected]>
AuthorDate: Tue Jun 9 21:43:19 2026 +0800

    Support related metrics friendly filters
---
 .../impl/OtlpIngestionWorkspaceServiceImpl.java    |  5 +-
 .../OtlpIngestionWorkspaceServiceImplTest.java     | 55 ++++++++++++++++++++++
 2 files changed, 58 insertions(+), 2 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 5996245fe1..066e94eb2c 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
@@ -897,12 +897,13 @@ public class OtlpIngestionWorkspaceServiceImpl implements 
OtlpIngestionWorkspace
             return List.of();
         }
         List<OtlpRelatedMetricsDto.ResourceMatcher> matchers = new 
ArrayList<>();
-        for (String rawClause : normalized.split("(?i)\\s+and\\s+|\\s*,\\s*")) 
{
+        for (String rawClause : splitMetricsFilterClauses(normalized)) {
             String clause = trimToNull(rawClause);
             if (!StringUtils.hasText(clause)) {
                 continue;
             }
-            Matcher matcher = METRICS_FILTER_MATCHER.matcher(clause);
+            String parsedMatcher = parseMetricsFriendlyFilterMatcher(clause, 
Set.of());
+            Matcher matcher = 
METRICS_FILTER_MATCHER.matcher(StringUtils.hasText(parsedMatcher) ? 
parsedMatcher : clause);
             if (!matcher.matches()) {
                 continue;
             }
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 b7eeb2be2b..cbd0832a79 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
@@ -1070,6 +1070,61 @@ class OtlpIngestionWorkspaceServiceImplTest {
         assertEquals(related.getCandidates().size(), 
related.getCandidateCount());
     }
 
+    @Test
+    void relatedMetricsParsesFriendlyResourceFilterOperators() {
+        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());
+
+        OtlpRelatedMetricsDto related = 
otlpIngestionWorkspaceService.getRelatedMetrics(
+                42L,
+                "service",
+                1_000L,
+                2_000L,
+                "checkout",
+                "commerce",
+                "prod",
+                "k8s.pod.name IN ('checkout-7d9', \"checkout-8f1\") and 
host.name CONTAINS node "
+                        + "and cloud.region NOT IN ('us-west-1', 'us-west-2') 
and service.instance.id EXISTS",
+                null,
+                "8"
+        );
+
+        assertEquals("k8s_pod_name", 
related.getResourceMatchers().get(0).getLabel());
+        assertEquals("=~", related.getResourceMatchers().get(0).getOperator());
+        assertEquals("^(?:checkout-7d9|checkout-8f1)$", 
related.getResourceMatchers().get(0).getValue());
+        assertTrue(related.getResourceMatchers().stream().anyMatch(matcher ->
+                "host_name".equals(matcher.getLabel())
+                        && "=~".equals(matcher.getOperator())
+                        && ".*node.*".equals(matcher.getValue())));
+        assertTrue(related.getResourceMatchers().stream().anyMatch(matcher ->
+                "cloud_region".equals(matcher.getLabel())
+                        && "!~".equals(matcher.getOperator())
+                        && 
"^(?:us-west-1|us-west-2)$".equals(matcher.getValue())));
+        assertTrue(related.getResourceMatchers().stream().anyMatch(matcher ->
+                "service_instance_id".equals(matcher.getLabel())
+                        && "=~".equals(matcher.getOperator())
+                        && ".+".equals(matcher.getValue())));
+        assertTrue(related.getCandidates().stream().anyMatch(candidate ->
+                "container.cpu.usage".equals(candidate.getQuery())
+                        && 
candidate.getMatchedLabels().contains("k8s_pod_name")));
+        assertTrue(related.getCandidates().stream().anyMatch(candidate ->
+                "system.cpu.utilization".equals(candidate.getQuery())
+                        && 
candidate.getMatchedLabels().contains("host_name")));
+    }
+
     @Test
     void relatedMetricsReturnsOperationScopedServiceCandidates() {
         observabilitySignalIntakeGateway.recordOtlpMetricIntake(


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to