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 9193e3bcfd Preserve metrics response operation handoffs
9193e3bcfd is described below
commit 9193e3bcfd8c34c3de6b10d423b84c6e8f1e1bce
Author: Logic <[email protected]>
AuthorDate: Wed Jun 10 09:28:57 2026 +0800
Preserve metrics response operation handoffs
---
web-next/lib/otlp-metrics/view-model.test.ts | 41 ++++++++++++++++++++++++++++
web-next/lib/otlp-metrics/view-model.ts | 7 ++++-
2 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/web-next/lib/otlp-metrics/view-model.test.ts
b/web-next/lib/otlp-metrics/view-model.test.ts
index 62d130848e..065b5a30db 100644
--- a/web-next/lib/otlp-metrics/view-model.test.ts
+++ b/web-next/lib/otlp-metrics/view-model.test.ts
@@ -1142,6 +1142,47 @@ describe('otlp metrics view model', () => {
expect(alertRulesHref.searchParams.get('alertQuery')).toContain('operationName=/inventory/{id}');
});
+ it('preserves backend-resolved metrics operation context in shared
handoffs', () => {
+ const result = buildMetricsHandoffLinks(
+ {
+ context: {
+ entityId: 7,
+ entityType: 'service',
+ entityName: 'Checkout API',
+ serviceName: 'checkout',
+ serviceNamespace: 'payments',
+ environment: 'prod',
+ operationName: 'POST /checkout',
+ start: 1000,
+ end: 2000
+ }
+ } as any,
+ {
+ query: 'http.server.duration',
+ filter: 'service.name="checkout"'
+ },
+ {
+ source: 'otlp'
+ }
+ );
+
+ const logParams = new URL(result.logsHref,
'https://example.com').searchParams;
+ expect(logParams.get('operationName')).toBe('POST /checkout');
+ expect(logParams.get('attributeFilter')).toBe('span.name="POST
/checkout"');
+
+ const traceParams = new URL(result.tracesHref,
'https://example.com').searchParams;
+ expect(traceParams.get('operationName')).toBe('POST /checkout');
+ expect(traceParams.get('serviceName')).toBe('checkout');
+ expect(traceParams.get('entityType')).toBe('service');
+
+ const alertRulesHref = new URL(result.alertRulesHref,
'https://example.com');
+ expect(alertRulesHref.searchParams.get('operationName')).toBe('POST
/checkout');
+
expect(alertRulesHref.searchParams.get('alertQuery')).toContain('operationName=POST
/checkout');
+
+ const dashboardHref = new URL(result.dashboardHref, 'https://example.com');
+
expect(dashboardHref.searchParams.get('panelQuery')).toContain('operationName=POST
/checkout');
+ });
+
it('adds an executable log attribute filter for operation-level metric
handoffs', () => {
const result = buildMetricsHandoffLinks(
{
diff --git a/web-next/lib/otlp-metrics/view-model.ts
b/web-next/lib/otlp-metrics/view-model.ts
index 17c44ce0c5..6172543882 100644
--- a/web-next/lib/otlp-metrics/view-model.ts
+++ b/web-next/lib/otlp-metrics/view-model.ts
@@ -992,7 +992,12 @@ export function buildMetricsHandoffLinks(
const end = query.end || (data.context?.end != null ?
String(data.context.end) : routeContext.end);
const traceId = firstText(selectedContext.traceId, query.traceId,
routeContext.traceId);
const spanId = firstText(selectedContext.spanId, query.spanId,
routeContext.spanId);
- const operationName = firstText(selectedContext.operationName,
query.operationName, routeContext.operationName);
+ const operationName = firstText(
+ selectedContext.operationName,
+ data.context?.operationName ?? undefined,
+ query.operationName,
+ routeContext.operationName
+ );
const signalContext: SignalRouteContext = {
...routeContext,
...query,
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]