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 5c8bc5914d Preserve entity context in live log streams
5c8bc5914d is described below
commit 5c8bc5914d823f021a4a959dc537bde032648d1b
Author: Logic <[email protected]>
AuthorDate: Tue Jun 9 20:18:53 2026 +0800
Preserve entity context in live log streams
---
.../observability/logs/sse/LogSseFilterCriteria.java | 10 +++++++++-
.../logs/controller/LogSseControllerTest.java | 6 ++++++
.../observability/logs/sse/LogSseFilterCriteriaTest.java | 10 ++++++++--
web-next/lib/log-manage/query-state.test.ts | 15 +++++++++++++--
web-next/lib/log-manage/query-state.ts | 1 +
5 files changed, 37 insertions(+), 5 deletions(-)
diff --git
a/hertzbeat-observability/src/main/java/org/apache/hertzbeat/observability/logs/sse/LogSseFilterCriteria.java
b/hertzbeat-observability/src/main/java/org/apache/hertzbeat/observability/logs/sse/LogSseFilterCriteria.java
index d904a136e2..20f245ecca 100644
---
a/hertzbeat-observability/src/main/java/org/apache/hertzbeat/observability/logs/sse/LogSseFilterCriteria.java
+++
b/hertzbeat-observability/src/main/java/org/apache/hertzbeat/observability/logs/sse/LogSseFilterCriteria.java
@@ -91,6 +91,12 @@ public class LogSseFilterCriteria {
@Schema(description = "OTel deployment.environment.name resource
attribute.", example = "prod", accessMode = READ_WRITE)
private String environment;
+ @Schema(description = "HertzBeat entity id resource attribute.", example =
"42", accessMode = READ_WRITE)
+ private String entityId;
+
+ @Schema(description = "HertzBeat entity type resource attribute.", example
= "service", accessMode = READ_WRITE)
+ private String entityType;
+
/**
* Workspace boundary captured from the authenticated request.
*/
@@ -158,7 +164,9 @@ public class LogSseFilterCriteria {
return matchesOptionalValue(resolveValue(log, "service.name",
"service_name"), serviceName)
&& matchesOptionalValue(resolveValue(log, "service.namespace",
"service_namespace"), serviceNamespace)
&& matchesOptionalValue(resolveValue(log,
- "deployment.environment.name",
"deployment_environment_name", "environment"), environment);
+ "deployment.environment.name",
"deployment_environment_name", "environment"), environment)
+ && matchesOptionalValue(resolveValue(log,
"hertzbeat.entity_id", "hertzbeat_entity_id"), entityId)
+ && matchesOptionalValue(resolveValue(log,
"hertzbeat.entity_type", "hertzbeat_entity_type"), entityType);
}
private boolean matchesOptionalValue(String actualValue, String
expectedValue) {
diff --git
a/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/logs/controller/LogSseControllerTest.java
b/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/logs/controller/LogSseControllerTest.java
index dfe0ef4361..d029918d38 100644
---
a/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/logs/controller/LogSseControllerTest.java
+++
b/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/logs/controller/LogSseControllerTest.java
@@ -101,6 +101,8 @@ class LogSseControllerTest {
String severityNumber = "17";
String traceId = "abcdef1234567890abcdef1234567890";
String spanId = "abcdef1234567890";
+ String entityId = "42";
+ String entityType = "service";
// When: A request is made with all filter parameters
mockMvc.perform(get("/api/logs/sse/subscribe")
@@ -108,6 +110,8 @@ class LogSseControllerTest {
.param("severityNumber", severityNumber)
.param("traceId", traceId)
.param("spanId", spanId)
+ .param("entityId", entityId)
+ .param("entityType", entityType)
.accept(MediaType.TEXT_EVENT_STREAM_VALUE))
.andExpect(status().isOk());
@@ -119,6 +123,8 @@ class LogSseControllerTest {
Assertions.assertEquals(capturedCriteria.getSeverityNumber(),
Integer.parseInt(severityNumber));
Assertions.assertEquals(capturedCriteria.getTraceId(), traceId);
Assertions.assertEquals(capturedCriteria.getSpanId(), spanId);
+ Assertions.assertEquals(capturedCriteria.getEntityId(), entityId);
+ Assertions.assertEquals(capturedCriteria.getEntityType(), entityType);
}
@Test
diff --git
a/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/logs/sse/LogSseFilterCriteriaTest.java
b/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/logs/sse/LogSseFilterCriteriaTest.java
index 84e4b89a24..e902fcb130 100644
---
a/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/logs/sse/LogSseFilterCriteriaTest.java
+++
b/hertzbeat-observability/src/test/java/org/apache/hertzbeat/observability/logs/sse/LogSseFilterCriteriaTest.java
@@ -165,7 +165,9 @@ class LogSseFilterCriteriaTest {
.resource(java.util.Map.of(
"service.name", "checkout",
"service.namespace", "payments",
- "deployment.environment.name", "prod"))
+ "deployment.environment.name", "prod",
+ "hertzbeat.entity_id", "42",
+ "hertzbeat.entity_type", "service"))
.build();
LogEntry paymentStagingLog = LogEntry.builder()
.severityText("INFO")
@@ -173,12 +175,16 @@ class LogSseFilterCriteriaTest {
.resource(java.util.Map.of(
"service.name", "payment",
"service.namespace", "payments",
- "deployment.environment.name", "staging"))
+ "deployment.environment.name", "staging",
+ "hertzbeat.entity_id", "43",
+ "hertzbeat.entity_type", "service"))
.build();
filterCriteria.setServiceName("checkout");
filterCriteria.setServiceNamespace("payments");
filterCriteria.setEnvironment("prod");
+ filterCriteria.setEntityId("42");
+ filterCriteria.setEntityType("service");
assertTrue(filterCriteria.matches(checkoutProdLog));
assertFalse(filterCriteria.matches(paymentStagingLog));
diff --git a/web-next/lib/log-manage/query-state.test.ts
b/web-next/lib/log-manage/query-state.test.ts
index 53f8f15bfd..7476664fa5 100644
--- a/web-next/lib/log-manage/query-state.test.ts
+++ b/web-next/lib/log-manage/query-state.test.ts
@@ -312,8 +312,19 @@ describe('log query state codec', () => {
expect(buildLogStreamUrl({ search: 'timeout', logContent: 'db down',
traceId: 'abc123', spanId: 'span456', severityNumber: '17', severityText:
'ERROR' })).toBe(
'/api/logs/sse/subscribe?logContent=db+down&traceId=abc123&spanId=span456&severityNumber=17&severityText=ERROR'
);
- expect(buildLogStreamUrl({ search: 'timeout', logContent: '', traceId: '',
spanId: '', severityNumber: '', severityText: 'ERROR' }, { serviceName:
'checkout', environment: 'prod' })).toBe(
-
'/api/logs/sse/subscribe?logContent=timeout&severityText=ERROR&serviceName=checkout&environment=prod'
+ expect(
+ buildLogStreamUrl(
+ { search: 'timeout', logContent: '', traceId: '', spanId: '',
severityNumber: '', severityText: 'ERROR' },
+ {
+ entityId: '42',
+ entityType: 'service',
+ serviceName: 'checkout',
+ serviceNamespace: 'payments',
+ environment: 'prod'
+ }
+ )
+ ).toBe(
+
'/api/logs/sse/subscribe?logContent=timeout&severityText=ERROR&entityId=42&entityType=service&serviceName=checkout&serviceNamespace=payments&environment=prod'
);
});
diff --git a/web-next/lib/log-manage/query-state.ts
b/web-next/lib/log-manage/query-state.ts
index 7cada879ca..f2bbf60ac7 100644
--- a/web-next/lib/log-manage/query-state.ts
+++ b/web-next/lib/log-manage/query-state.ts
@@ -443,6 +443,7 @@ export function buildLogStreamUrl(query: LogQueryState,
routeContext: SignalRout
const severityNumber = normalizeSeverityNumberParam(query.severityNumber);
if (severityNumber) params.set('severityNumber', severityNumber);
if (query.severityText.trim()) params.set('severityText',
query.severityText.trim());
+ appendLogEntityContextParams(params, routeContext);
appendLogQuickFilterContext(params, routeContext);
const qs = params.toString();
return qs ? `/api/logs/sse/subscribe?${qs}` : '/api/logs/sse/subscribe';
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]