@@ -2542,6 +2542,48 @@ describe('signal dashboards API client', () => {
25422542 } ) ) ;
25432543 } ) ;
25442544
2545+ it ( 'maps log attribute groups to log attribute-filter drilldowns with entity context' , async ( ) => {
2546+ const [ logPlan ] = buildSignalDashboardExecutionPlans ( {
2547+ dashboardKey : 'log-attribute-breakouts' ,
2548+ title : 'Log attribute breakouts' ,
2549+ description : 'Grouped log panels' ,
2550+ tags : 'logs' ,
2551+ layout : '[]' ,
2552+ widgets : JSON . stringify ( [
2553+ {
2554+ id : 'log-route-breakout' ,
2555+ signal : 'logs' ,
2556+ title : 'Logs by route' ,
2557+ visualization : 'list' ,
2558+ route : '/log/manage?view=list&serviceName=checkout&serviceNamespace=payments&entityId=4200&entityType=service&entityName=Checkout+API&source=otlp&collector=collector-a&template=spring-boot&groupBy=attribute:http.route&groupLimit=8'
2559+ }
2560+ ] )
2561+ } ) ;
2562+
2563+ const logResult = await executeSignalDashboardPanelPlan ( logPlan , async url => {
2564+ expect ( url ) . toBe ( '/logs/stats/group-by?entityId=4200&entityType=service&serviceName=checkout&serviceNamespace=payments&groupBy=attribute%3Ahttp.route&limit=8' ) ;
2565+ return {
2566+ groupBy : 'attribute:http.route' ,
2567+ groups : [ {
2568+ value : 'POST /checkout' ,
2569+ count : 9 ,
2570+ errorCount : 3
2571+ } ]
2572+ } ;
2573+ } ) ;
2574+ const logRenderer = buildSignalDashboardPanelRuntimeRenderDescriptor ( logPlan , logResult ) ;
2575+
2576+ expect ( logRenderer . rows [ 0 ] ) . toEqual ( expect . objectContaining ( {
2577+ key : 'log-route-breakout:group:0' ,
2578+ title : 'POST /checkout' ,
2579+ copy : '9 logs · 3 errors' ,
2580+ meta : 'attribute:http.route' ,
2581+ relatedSignal : 'logs' ,
2582+ relatedHandoffHref : '/log/manage?serviceName=checkout&serviceNamespace=payments&entityId=4200&entityType=service&entityName=Checkout+API&source=otlp&collector=collector-a&template=spring-boot&view=list&attributeFilter=http.route%3APOST+%2Fcheckout'
2583+ } ) ) ;
2584+ expect ( logRenderer . rows [ 0 ] ?. relatedHandoffHref ) . not . toContain ( 'attributeFilter=http.route%3D' ) ;
2585+ } ) ;
2586+
25452587 it ( 'unwraps backend message envelopes for group-by dashboard panels before rendering' , async ( ) => {
25462588 const [ logPlan , tracePlan ] = buildSignalDashboardExecutionPlans ( {
25472589 dashboardKey : 'wrapped-breakouts' ,
0 commit comments