Part of: #2696. Every integration dashboard task depends on this one, so it goes first.
Why
Each integration dashboard shows that technology's logs grouped by event type, so a person can pick one and look at the real logs behind it. Today nothing on a v12 dashboard can be clicked: no renderer in frontend/src/features/dashboard/components/ handles a click. Without that, the dashboards are pictures, not a way into the logs.
What to build
1. Click-through from every widget to the logs behind it.
Clicking a bar, a pie slice, a table row or a point on a line opens /log-explorer filtered to exactly the logs that mark counted:
dataType of the widget, plus the widget's own filters;
<dimension>=<clicked value> (for a line split by a field, the line's value; for a point on a time chart, that time bucket as the range);
- the dashboard's current time range.
The Log Explorer already opens from a link (frontend/src/features/log-explorer/pages/LogExplorerPage.tsx): every query parameter becomes a filter (?field=value, or ?field=a,b for "is one of"), and ?@timestamp=24h picks a preset range. Close these gaps:
- It only accepts preset ranges. Add absolute
from and to, so a click on an hourly bucket or a custom range carries over.
- One value becomes an "is" filter, which the store compares by type on nested fields (
log.*, origin.*, target.*). "Is one of" is compared as text (toString(...) IN (...) in the ClickHouse driver of github.com/threatwinds/go-sdk/store). Test a numeric nested value such as a Windows event ID; if "is" misses it, send single values as "is one of".
- Filters other than "is" and "is one of" (for example
not_in or exists) cannot travel as query parameters. Either extend the link format or pass the full filter list in navigation state, the way features/alerts/hooks/use-related-logs.ts already opens the Log Explorer.
- Widgets on the
alerts dataset should open the alerts view with the same filters instead of the Log Explorer.
- A number widget opens the Log Explorer with the widget's filters. A row of the "Latest logs" table opens that one log (filter on
id).
2. The value and count table.
The main widget of every integration dashboard is a table of a field's top values with their counts. It already renders when a shipped widget pairs spec.chart: category with config.__builder.chartType: table (WidgetRenderer picks the renderer from the chart type and the rows from the query). Make it a proper widget: readable column headers (the widget's label rather than log.eventCode), counts right-aligned with thousands separators, and every row clickable (item 1). The editor cannot build this shape today (specChartFor('table') always asks for raw records); add "Top values table" to the editor if it is cheap, otherwise keep it as a shipped-only shape.
3. "Open dashboard" from the integration.
In features/integrations/components/IntegrationDrawer.tsx, add a button that opens the integration's dashboard. Match on the dashboard name, or add an integration key to the dashboard definition (backend/modules/dashboards/repository/definition.go) so the link does not depend on a name. While there: the drawer's "View logs" button only appears for integrations marked configured, and only cloud pullers can ever be configured (configured in backend/modules/integrations/usecase/integration.go). Agent and syslog integrations therefore never show it. Show both buttons for every integration.
4. Fix the shipped Agents dashboard.
definitions/dashboards/agents-overview.yaml counts Windows logs with dataType: windows. Windows logs are wineventlog (agent config/const.go, catalog row WINDOWS_AGENT, every Windows rule), so its "Windows Events" number is always 0.
5. Optional: a "Device" dropdown on shipped dashboards.
Each integration dashboard would be more useful with a filter-bar dropdown on dataSource. Two things block it. The page saves dropdowns into dashboard.filters (DashboardPage.tsx), but the backend Dashboard has no such field (only config, see backend/modules/dashboards/domain/dashboard.go), so they are silently dropped on save. And the shipped YAML has no place to declare them. Keep the dropdowns in config (or add a column) and let DashboardDefinition declare them. Skip this item if it grows beyond a small change.
Conventions for all integration dashboards
- One file per integration, at the top of
definitions/dashboards/, named integration-<name>.yaml. The startup loader reads sub-folders, but the test that checks shipped files (TestEveryShippedDashboardDefinitionIsValid) only reads the top folder, so a file in a sub-folder would go unchecked.
name: must be unique across dashboards; each sub-issue gives it.
- Filter nested fields with
in, even for one value (text comparison, see item 1).
- Count is the only measure: no sums, averages or unique counts (
backend/modules/dashboards/domain/spec.go).
- Don't use the map widget for logs. It looks for top-level
lat/lon keys, and log records carry origin.geolocation.latitude, so it stays empty. Use a bar chart of origin.geolocation.country.
Done when
Part of: #2696. Every integration dashboard task depends on this one, so it goes first.
Why
Each integration dashboard shows that technology's logs grouped by event type, so a person can pick one and look at the real logs behind it. Today nothing on a v12 dashboard can be clicked: no renderer in
frontend/src/features/dashboard/components/handles a click. Without that, the dashboards are pictures, not a way into the logs.What to build
1. Click-through from every widget to the logs behind it.
Clicking a bar, a pie slice, a table row or a point on a line opens
/log-explorerfiltered to exactly the logs that mark counted:dataTypeof the widget, plus the widget's own filters;<dimension>=<clicked value>(for a line split by a field, the line's value; for a point on a time chart, that time bucket as the range);The Log Explorer already opens from a link (
frontend/src/features/log-explorer/pages/LogExplorerPage.tsx): every query parameter becomes a filter (?field=value, or?field=a,bfor "is one of"), and?@timestamp=24hpicks a preset range. Close these gaps:fromandto, so a click on an hourly bucket or a custom range carries over.log.*,origin.*,target.*). "Is one of" is compared as text (toString(...) IN (...)in the ClickHouse driver ofgithub.com/threatwinds/go-sdk/store). Test a numeric nested value such as a Windows event ID; if "is" misses it, send single values as "is one of".not_inorexists) cannot travel as query parameters. Either extend the link format or pass the full filter list in navigation state, the wayfeatures/alerts/hooks/use-related-logs.tsalready opens the Log Explorer.alertsdataset should open the alerts view with the same filters instead of the Log Explorer.id).2. The value and count table.
The main widget of every integration dashboard is a table of a field's top values with their counts. It already renders when a shipped widget pairs
spec.chart: categorywithconfig.__builder.chartType: table(WidgetRendererpicks the renderer from the chart type and the rows from the query). Make it a proper widget: readable column headers (the widget's label rather thanlog.eventCode), counts right-aligned with thousands separators, and every row clickable (item 1). The editor cannot build this shape today (specChartFor('table')always asks for raw records); add "Top values table" to the editor if it is cheap, otherwise keep it as a shipped-only shape.3. "Open dashboard" from the integration.
In
features/integrations/components/IntegrationDrawer.tsx, add a button that opens the integration's dashboard. Match on the dashboard name, or add anintegrationkey to the dashboard definition (backend/modules/dashboards/repository/definition.go) so the link does not depend on a name. While there: the drawer's "View logs" button only appears for integrations marked configured, and only cloud pullers can ever be configured (configuredinbackend/modules/integrations/usecase/integration.go). Agent and syslog integrations therefore never show it. Show both buttons for every integration.4. Fix the shipped Agents dashboard.
definitions/dashboards/agents-overview.yamlcounts Windows logs withdataType: windows. Windows logs arewineventlog(agentconfig/const.go, catalog rowWINDOWS_AGENT, every Windows rule), so its "Windows Events" number is always 0.5. Optional: a "Device" dropdown on shipped dashboards.
Each integration dashboard would be more useful with a filter-bar dropdown on
dataSource. Two things block it. The page saves dropdowns intodashboard.filters(DashboardPage.tsx), but the backendDashboardhas no such field (onlyconfig, seebackend/modules/dashboards/domain/dashboard.go), so they are silently dropped on save. And the shipped YAML has no place to declare them. Keep the dropdowns inconfig(or add a column) and letDashboardDefinitiondeclare them. Skip this item if it grows beyond a small change.Conventions for all integration dashboards
definitions/dashboards/, namedintegration-<name>.yaml. The startup loader reads sub-folders, but the test that checks shipped files (TestEveryShippedDashboardDefinitionIsValid) only reads the top folder, so a file in a sub-folder would go unchecked.name:must be unique across dashboards; each sub-issue gives it.in, even for one value (text comparison, see item 1).backend/modules/dashboards/domain/spec.go).lat/lonkeys, and log records carryorigin.geolocation.latitude, so it stays empty. Use a bar chart oforigin.geolocation.country.Done when
origin.user).