@mastra/playground-ui 68.0.0-alpha.1 → 68.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/dist/{DataCodeSection-CcPmJPTp.cjs → DataCodeSection-CFxXsQWH.cjs} +3 -3
  2. package/dist/DataCodeSection-CFxXsQWH.cjs.map +1 -0
  3. package/dist/{DataCodeSection-KJRyRD1Q.js → DataCodeSection-PY9XEg2C.js} +3 -3
  4. package/dist/DataCodeSection-PY9XEg2C.js.map +1 -0
  5. package/dist/{DataPanel-BwB1Oifd.cjs → DataPanel-Coc9h35I.cjs} +2 -2
  6. package/dist/{DataPanel-BwB1Oifd.cjs.map → DataPanel-Coc9h35I.cjs.map} +1 -1
  7. package/dist/{DataPanel-Bv4M17xO.js → DataPanel-IgB9D5PO.js} +2 -2
  8. package/dist/{DataPanel-Bv4M17xO.js.map → DataPanel-IgB9D5PO.js.map} +1 -1
  9. package/dist/{FilterBar-BO-vvvyq.js → FilterBar-BgW2dqRQ.js} +7 -7
  10. package/dist/FilterBar-BgW2dqRQ.js.map +1 -0
  11. package/dist/{FilterBar-Buw0tv51.cjs → FilterBar-CQl04O6t.cjs} +7 -7
  12. package/dist/FilterBar-CQl04O6t.cjs.map +1 -0
  13. package/dist/{MetricsTable-D-aZf3dk.cjs → MetricsTable-BSl81oNe.cjs} +44 -9
  14. package/dist/MetricsTable-BSl81oNe.cjs.map +1 -0
  15. package/dist/{MetricsTable-CRPeLHe1.js → MetricsTable-DID6LRoP.js} +44 -9
  16. package/dist/MetricsTable-DID6LRoP.js.map +1 -0
  17. package/dist/{ask-user-DdYz56qH.cjs → ask-user-C1p2PEYe.cjs} +2 -2
  18. package/dist/ask-user-C1p2PEYe.cjs.map +1 -0
  19. package/dist/{ask-user-B225wzWc.js → ask-user-DPznrqGO.js} +2 -2
  20. package/dist/ask-user-DPznrqGO.js.map +1 -0
  21. package/dist/chart-plot.css +5 -4
  22. package/dist/{combobox-CtCK0mNx.js → combobox-D21no8t5.js} +4 -4
  23. package/dist/{combobox-CtCK0mNx.js.map → combobox-D21no8t5.js.map} +1 -1
  24. package/dist/{combobox-CMx2ayFN.cjs → combobox-DIT_6xiG.cjs} +4 -4
  25. package/dist/combobox-DIT_6xiG.cjs.map +1 -0
  26. package/dist/{combobox-parts-ScKcYjMR.cjs → combobox-parts-C4phOq4t.cjs} +2 -2
  27. package/dist/combobox-parts-C4phOq4t.cjs.map +1 -0
  28. package/dist/{combobox-parts-C1CugUAU.js → combobox-parts-D90ir0Py.js} +3 -3
  29. package/dist/combobox-parts-D90ir0Py.js.map +1 -0
  30. package/dist/components/Combobox.cjs.js +2 -2
  31. package/dist/components/Combobox.es.js +2 -2
  32. package/dist/components/Command.cjs.js +1 -1
  33. package/dist/components/Command.cjs.js.map +1 -1
  34. package/dist/components/Command.es.js +1 -1
  35. package/dist/components/Command.es.js.map +1 -1
  36. package/dist/components/DataCodeSection.cjs.js +1 -1
  37. package/dist/components/DataCodeSection.es.js +1 -1
  38. package/dist/components/DataList.cjs.js +1 -1
  39. package/dist/components/DataList.es.js +1 -1
  40. package/dist/components/DataPanel.cjs.js +1 -1
  41. package/dist/components/DataPanel.es.js +1 -1
  42. package/dist/components/DateTimePicker.cjs.js +1 -1
  43. package/dist/components/DateTimePicker.cjs.js.map +1 -1
  44. package/dist/components/DateTimePicker.es.js +1 -1
  45. package/dist/components/DateTimePicker.es.js.map +1 -1
  46. package/dist/components/FilterBar.cjs.js +3 -3
  47. package/dist/components/FilterBar.es.js +3 -3
  48. package/dist/components/FormFieldBlocks.cjs.js +1 -1
  49. package/dist/components/FormFieldBlocks.cjs.js.map +1 -1
  50. package/dist/components/FormFieldBlocks.es.js +1 -1
  51. package/dist/components/FormFieldBlocks.es.js.map +1 -1
  52. package/dist/components/MetricsTable.cjs.js +1 -1
  53. package/dist/components/MetricsTable.es.js +1 -1
  54. package/dist/components/PropertyFilter.cjs.js +3 -3
  55. package/dist/components/PropertyFilter.cjs.js.map +1 -1
  56. package/dist/components/PropertyFilter.es.js +3 -3
  57. package/dist/components/PropertyFilter.es.js.map +1 -1
  58. package/dist/components/SavedViews.cjs.js +1 -1
  59. package/dist/components/SavedViews.es.js +1 -1
  60. package/dist/components/Sidebar.cjs.js +8 -8
  61. package/dist/components/Sidebar.cjs.js.map +1 -1
  62. package/dist/components/Sidebar.es.js +9 -9
  63. package/dist/components/Sidebar.es.js.map +1 -1
  64. package/dist/components/ai/ask-user.cjs.js +1 -1
  65. package/dist/components/ai/ask-user.es.js +1 -1
  66. package/dist/domains/chat/tools/badges/ask-user-badge.cjs.js +1 -1
  67. package/dist/domains/chat/tools/badges/ask-user-badge.es.js +1 -1
  68. package/dist/domains/dashboards/kinds/table/table-view.cjs.js +1 -1
  69. package/dist/domains/dashboards/kinds/table/table-view.es.js +1 -1
  70. package/dist/domains/dashboards/metrics-dashboard.cjs.js +1 -1
  71. package/dist/domains/dashboards/metrics-dashboard.cjs.js.map +1 -1
  72. package/dist/domains/dashboards/metrics-dashboard.es.js +1 -1
  73. package/dist/domains/dashboards/metrics-dashboard.es.js.map +1 -1
  74. package/dist/domains/datasets/components/save-as-dataset-item-dialog.cjs.js +1 -1
  75. package/dist/domains/datasets/components/save-as-dataset-item-dialog.es.js +1 -1
  76. package/dist/domains/logs/components/log-data-panel.cjs.js +1 -1
  77. package/dist/domains/logs/components/log-data-panel.es.js +1 -1
  78. package/dist/domains/logs/components/logs-saved-views.cjs.js +1 -1
  79. package/dist/domains/logs/components/logs-saved-views.es.js +1 -1
  80. package/dist/domains/logs/components/logs-toolbar.cjs.js +1 -1
  81. package/dist/domains/logs/components/logs-toolbar.es.js +1 -1
  82. package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js +2 -2
  83. package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js.map +1 -1
  84. package/dist/domains/metrics/components/breakdown/breakdown-table.es.js +2 -2
  85. package/dist/domains/metrics/components/breakdown/breakdown-table.es.js.map +1 -1
  86. package/dist/domains/metrics/components/metrics-time-range-chip.cjs.js +1 -1
  87. package/dist/domains/metrics/components/metrics-time-range-chip.es.js +1 -1
  88. package/dist/domains/observability/saved-views/observability-saved-views.cjs.js +1 -1
  89. package/dist/domains/observability/saved-views/observability-saved-views.es.js +1 -1
  90. package/dist/domains/observability/saved-views.cjs.js +1 -1
  91. package/dist/domains/observability/saved-views.es.js +1 -1
  92. package/dist/domains/observability.cjs.js +1 -1
  93. package/dist/domains/observability.es.js +1 -1
  94. package/dist/domains/scores/components/score-data-panel.cjs.js +1 -1
  95. package/dist/domains/scores/components/score-data-panel.es.js +1 -1
  96. package/dist/domains/scores/components/span-scoring.cjs.js +3 -3
  97. package/dist/domains/scores/components/span-scoring.cjs.js.map +1 -1
  98. package/dist/domains/scores/components/span-scoring.es.js +3 -3
  99. package/dist/domains/scores/components/span-scoring.es.js.map +1 -1
  100. package/dist/domains/skills/skill-simple-form.cjs.js +1 -1
  101. package/dist/domains/skills/skill-simple-form.cjs.js.map +1 -1
  102. package/dist/domains/skills/skill-simple-form.es.js +1 -1
  103. package/dist/domains/skills/skill-simple-form.es.js.map +1 -1
  104. package/dist/domains/spans/components/spans-explorer-body.cjs.js +1 -1
  105. package/dist/domains/spans/components/spans-explorer-body.es.js +1 -1
  106. package/dist/domains/spans/components/spans-filter-bar.cjs.js +3 -3
  107. package/dist/domains/spans/components/spans-filter-bar.cjs.js.map +1 -1
  108. package/dist/domains/spans/components/spans-filter-bar.es.js +3 -3
  109. package/dist/domains/spans/components/spans-filter-bar.es.js.map +1 -1
  110. package/dist/domains/spans/hooks/use-spans-filter-bar.cjs.js +1 -1
  111. package/dist/domains/spans/hooks/use-spans-filter-bar.es.js +1 -1
  112. package/dist/domains/threads/components/threads-explorer-body.cjs.js +1 -1
  113. package/dist/domains/threads/components/threads-explorer-body.es.js +1 -1
  114. package/dist/domains/threads/components/threads-filter-bar.cjs.js +3 -3
  115. package/dist/domains/threads/components/threads-filter-bar.cjs.js.map +1 -1
  116. package/dist/domains/threads/components/threads-filter-bar.es.js +3 -3
  117. package/dist/domains/threads/components/threads-filter-bar.es.js.map +1 -1
  118. package/dist/domains/threads/hooks/use-threads-filter-bar.cjs.js +1 -1
  119. package/dist/domains/threads/hooks/use-threads-filter-bar.es.js +1 -1
  120. package/dist/domains/traces/components/feedback-thread.cjs.js +1 -1
  121. package/dist/domains/traces/components/feedback-thread.cjs.js.map +1 -1
  122. package/dist/domains/traces/components/feedback-thread.es.js +1 -1
  123. package/dist/domains/traces/components/feedback-thread.es.js.map +1 -1
  124. package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
  125. package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
  126. package/dist/domains/traces/components/span-summary-description.cjs.js +1 -1
  127. package/dist/domains/traces/components/span-summary-description.es.js +1 -1
  128. package/dist/domains/traces/components/thread-trace/thread-trace-details.cjs.js +1 -1
  129. package/dist/domains/traces/components/thread-trace/thread-trace-details.es.js +1 -1
  130. package/dist/domains/traces/components/trace-columns-menu.cjs.js +3 -3
  131. package/dist/domains/traces/components/trace-columns-menu.cjs.js.map +1 -1
  132. package/dist/domains/traces/components/trace-columns-menu.es.js +3 -3
  133. package/dist/domains/traces/components/trace-columns-menu.es.js.map +1 -1
  134. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +2 -2
  135. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  136. package/dist/domains/traces/components/trace-data-panel-view.es.js +2 -2
  137. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  138. package/dist/domains/traces/components/trace-id-button.cjs.js +1 -1
  139. package/dist/domains/traces/components/trace-id-button.es.js +1 -1
  140. package/dist/domains/traces/components/trace-summary-description.cjs.js +1 -1
  141. package/dist/domains/traces/components/trace-summary-description.es.js +1 -1
  142. package/dist/domains/traces/components/trace-thread-panel.cjs.js +1 -1
  143. package/dist/domains/traces/components/trace-thread-panel.es.js +1 -1
  144. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js +3 -3
  145. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js.map +1 -1
  146. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js +3 -3
  147. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js.map +1 -1
  148. package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.cjs.js +1 -1
  149. package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.es.js +1 -1
  150. package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.cjs.js +1 -1
  151. package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.es.js +1 -1
  152. package/dist/domains/workflows/components/workflow-combobox.cjs.js +2 -2
  153. package/dist/domains/workflows/components/workflow-combobox.cjs.js.map +1 -1
  154. package/dist/domains/workflows/components/workflow-combobox.es.js +2 -2
  155. package/dist/domains/workflows/components/workflow-combobox.es.js.map +1 -1
  156. package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js +1 -1
  157. package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js.map +1 -1
  158. package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js +1 -1
  159. package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js.map +1 -1
  160. package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js +1 -1
  161. package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js.map +1 -1
  162. package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js +1 -1
  163. package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js.map +1 -1
  164. package/dist/{filter-bar-chip-B4sV4gDm.js → filter-bar-chip-CABeKrtf.js} +4 -4
  165. package/dist/{filter-bar-chip-B4sV4gDm.js.map → filter-bar-chip-CABeKrtf.js.map} +1 -1
  166. package/dist/{filter-bar-chip-CIEsWcEw.cjs → filter-bar-chip-Cg-UbIwP.cjs} +4 -4
  167. package/dist/{filter-bar-chip-CIEsWcEw.cjs.map → filter-bar-chip-Cg-UbIwP.cjs.map} +1 -1
  168. package/dist/{filter-bar-time-range-DvuaFnkI.cjs → filter-bar-time-range-BA-pXMlo.cjs} +2 -2
  169. package/dist/{filter-bar-time-range-DvuaFnkI.cjs.map → filter-bar-time-range-BA-pXMlo.cjs.map} +1 -1
  170. package/dist/{filter-bar-time-range-CXQMBgpz.js → filter-bar-time-range-mg9JeYue.js} +2 -2
  171. package/dist/{filter-bar-time-range-CXQMBgpz.js.map → filter-bar-time-range-mg9JeYue.js.map} +1 -1
  172. package/dist/layout/tabbed-container.cjs.js +1 -1
  173. package/dist/layout/tabbed-container.es.js +1 -1
  174. package/dist/{observability-saved-views-BBam8Fr5.js → observability-saved-views-CjKTEp1V.js} +3 -3
  175. package/dist/observability-saved-views-CjKTEp1V.js.map +1 -0
  176. package/dist/{observability-saved-views-BAzxxoAr.cjs → observability-saved-views-Daizz4tU.cjs} +3 -3
  177. package/dist/observability-saved-views-Daizz4tU.cjs.map +1 -0
  178. package/dist/primitives/chart-plot.cjs.js +8 -6
  179. package/dist/primitives/chart-plot.cjs.js.map +1 -1
  180. package/dist/primitives/chart-plot.es.js +8 -6
  181. package/dist/primitives/chart-plot.es.js.map +1 -1
  182. package/dist/primitives/control-icon.cjs.js.map +1 -1
  183. package/dist/primitives/control-icon.es.js.map +1 -1
  184. package/dist/{property-filter-applied-p3dTTDdb.js → property-filter-applied--U5EZdaA.js} +2 -2
  185. package/dist/property-filter-applied--U5EZdaA.js.map +1 -0
  186. package/dist/{property-filter-applied-BCeRLcXb.cjs → property-filter-applied-BkkIObRq.cjs} +2 -2
  187. package/dist/property-filter-applied-BkkIObRq.cjs.map +1 -0
  188. package/dist/src/ds/components/MetricsTable/metrics-table-rows.d.ts +10 -3
  189. package/dist/src/ds/components/MetricsTable/metrics-table.d.ts +1 -1
  190. package/dist/style.css +14 -1
  191. package/dist/{tabbed-container-DQU7pVio.cjs → tabbed-container-B4lCBgRP.cjs} +2 -2
  192. package/dist/{tabbed-container-DQU7pVio.cjs.map → tabbed-container-B4lCBgRP.cjs.map} +1 -1
  193. package/dist/{tabbed-container-5j6dhoRX.js → tabbed-container-DI1GI1Qv.js} +2 -2
  194. package/dist/{tabbed-container-5j6dhoRX.js.map → tabbed-container-DI1GI1Qv.js.map} +1 -1
  195. package/oxlint/index.js +90 -0
  196. package/package.json +8 -8
  197. package/theme.css +4 -3
  198. package/dist/DataCodeSection-CcPmJPTp.cjs.map +0 -1
  199. package/dist/DataCodeSection-KJRyRD1Q.js.map +0 -1
  200. package/dist/FilterBar-BO-vvvyq.js.map +0 -1
  201. package/dist/FilterBar-Buw0tv51.cjs.map +0 -1
  202. package/dist/MetricsTable-CRPeLHe1.js.map +0 -1
  203. package/dist/MetricsTable-D-aZf3dk.cjs.map +0 -1
  204. package/dist/ask-user-B225wzWc.js.map +0 -1
  205. package/dist/ask-user-DdYz56qH.cjs.map +0 -1
  206. package/dist/combobox-CMx2ayFN.cjs.map +0 -1
  207. package/dist/combobox-parts-C1CugUAU.js.map +0 -1
  208. package/dist/combobox-parts-ScKcYjMR.cjs.map +0 -1
  209. package/dist/observability-saved-views-BAzxxoAr.cjs.map +0 -1
  210. package/dist/observability-saved-views-BBam8Fr5.js.map +0 -1
  211. package/dist/property-filter-applied-BCeRLcXb.cjs.map +0 -1
  212. package/dist/property-filter-applied-p3dTTDdb.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_ask_user = require("../../ask-user-DdYz56qH.cjs");
2
+ const require_ask_user = require("../../ask-user-C1p2PEYe.cjs");
3
3
  exports.AskUser = require_ask_user.AskUser;
4
4
  exports.AskUserBody = require_ask_user.AskUserBody;
5
5
  exports.AskUserContainer = require_ask_user.AskUserContainer;
@@ -1 +1 @@
1
- export { t as AskUser, c as AskUserBody, c as Body, l as AskUserContainer, r as AskUserCustomAnswer, r as CustomAnswer, u as AskUserLabel, i as AskUserOptionItem, i as Option, d as AskUserOptionRow, a as AskUserOptions, a as Options, f as AskUserOutput, f as Output, p as AskUserPending, p as Pending, m as AskUserQuestion, m as Question, n as AskUserRoot, n as Root, o as AskUserSubmit, o as Submit, s as AskUserTextAnswer, s as TextAnswer } from "../../ask-user-B225wzWc.js";
1
+ export { t as AskUser, c as AskUserBody, c as Body, l as AskUserContainer, r as AskUserCustomAnswer, r as CustomAnswer, u as AskUserLabel, i as AskUserOptionItem, i as Option, d as AskUserOptionRow, a as AskUserOptions, a as Options, f as AskUserOutput, f as Output, p as AskUserPending, p as Pending, m as AskUserQuestion, m as Question, n as AskUserRoot, n as Root, o as AskUserSubmit, o as Submit, s as AskUserTextAnswer, s as TextAnswer } from "../../ask-user-DPznrqGO.js";
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_domains_chat_context_tool_call_context = require("../../context/tool-call-context.cjs.js");
3
- const require_ask_user = require("../../../../ask-user-DdYz56qH.cjs");
3
+ const require_ask_user = require("../../../../ask-user-C1p2PEYe.cjs");
4
4
  let react_jsx_runtime = require("react/jsx-runtime");
5
5
  // src/domains/chat/tools/badges/ask-user-badge.tsx
6
6
  var AskUserBadge = ({ toolCallId, suspendPayload, result }) => {
@@ -1,5 +1,5 @@
1
1
  import { useToolCall } from "../../context/tool-call-context.es.js";
2
- import { t as AskUser } from "../../../../ask-user-B225wzWc.js";
2
+ import { t as AskUser } from "../../../../ask-user-DPznrqGO.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  // src/domains/chat/tools/badges/ask-user-badge.tsx
5
5
  var AskUserBadge = ({ toolCallId, suspendPayload, result }) => {
@@ -9,7 +9,7 @@ const require_domains_dashboards_lib_table = require("../../lib/table.cjs.js");
9
9
  const require_domains_dashboards_hooks_use_widget_views = require("../../hooks/use-widget-views.cjs.js");
10
10
  const require_domains_dashboards_kinds_table_table_frame = require("./table-frame.cjs.js");
11
11
  const require_domains_dashboards_kinds_table_table_columns = require("./table-columns.cjs.js");
12
- const require_MetricsTable = require("../../../../MetricsTable-D-aZf3dk.cjs");
12
+ const require_MetricsTable = require("../../../../MetricsTable-BSl81oNe.cjs");
13
13
  let react = require("react");
14
14
  let react_jsx_runtime = require("react/jsx-runtime");
15
15
  // src/domains/dashboards/kinds/table/table-view.tsx
@@ -8,7 +8,7 @@ import { isValueColumn, parseColumns, rowDrilldown, rowQueries, tableContent, va
8
8
  import { useDrilldown } from "../../hooks/use-widget-views.es.js";
9
9
  import { TableFrame } from "./table-frame.es.js";
10
10
  import { tableColumn } from "./table-columns.es.js";
11
- import { t as MetricsTable } from "../../../../MetricsTable-CRPeLHe1.js";
11
+ import { t as MetricsTable } from "../../../../MetricsTable-DID6LRoP.js";
12
12
  import { useState } from "react";
13
13
  import { jsx, jsxs } from "react/jsx-runtime";
14
14
  // src/domains/dashboards/kinds/table/table-view.tsx
@@ -460,7 +460,7 @@ var tableOptions = (groupBy, name, emptyMessage, extra = {}) => ({
460
460
  column: "count",
461
461
  direction: "desc"
462
462
  },
463
- pageSize: 13,
463
+ pageSize: 10,
464
464
  emptyMessage,
465
465
  ariaLabel: `${name} breakdown`,
466
466
  ...extra
@@ -1 +1 @@
1
- {"version":3,"file":"metrics-dashboard.cjs.js","names":[],"sources":["../../../src/domains/dashboards/metrics-dashboard.ts"],"sourcesContent":["import type {\n DashboardColumn,\n DashboardDefinition,\n DashboardDrilldownTarget,\n DashboardQuery,\n DashboardWidget,\n DashboardWidgetView,\n} from '@mastra/client-js';\n\nconst INPUT = 'mastra_model_total_input_tokens';\nconst OUTPUT = 'mastra_model_total_output_tokens';\nconst CACHE_READ = 'mastra_model_input_cache_read_tokens';\nconst AGENT_DURATION = 'mastra_agent_duration_ms';\n\nconst sumSeries = (id: string, name: string): DashboardQuery => ({\n id,\n source: 'metrics',\n request: 'timeSeries',\n name: [name],\n aggregation: 'sum',\n});\n\nconst agentRunsByStatus: DashboardQuery = {\n id: 'runs',\n source: 'metrics',\n request: 'timeSeries',\n name: [AGENT_DURATION],\n aggregation: 'count',\n groupBy: ['status'],\n};\n\n// Runs report status `ok` or `error` (observability/mastra auto-extract); the card also counts `failed`.\nconst FAILED = ['error', 'failed'];\nconst completedRuns = { query: 'runs', notGroups: FAILED };\nconst failedRuns = { query: 'runs', groups: FAILED };\nconst agentRunsTraces: DashboardDrilldownTarget = {\n page: 'traces',\n filters: [{ fieldId: 'rootEntityType', value: 'agent' }],\n};\n\nconst tokenUsageWidget: DashboardWidget = {\n id: 'token-usage',\n span: 6,\n kind: 'timeseries',\n title: 'Token usage',\n drilldown: { action: { page: 'traces' }, click: { page: 'traces' } },\n views: [\n {\n label: 'Token usage',\n description: 'Input, cache reads and output.',\n queries: [sumSeries('input', INPUT), sumSeries('output', OUTPUT), sumSeries('cacheRead', CACHE_READ)],\n options: {\n chart: 'stackedBar',\n format: 'count',\n xLabels: 'edges',\n series: [\n {\n dataKey: 'input',\n label: 'Input',\n color: 'green',\n value: { max: [{ minus: [{ query: 'input' }, { query: 'cacheRead' }] }, { const: 0 }] },\n },\n { dataKey: 'cacheRead', label: 'Cache read', color: 'violet', value: { query: 'cacheRead' } },\n { dataKey: 'output', label: 'Output', color: 'sky', value: { query: 'output' } },\n ],\n total: { value: 'total' },\n emptyMessage: 'No model calls in this range.',\n },\n },\n {\n label: 'Model cost',\n description: 'Estimated model spend.',\n // Cache reads aren't charted here, but fetching them keeps their answer, so going back to\n // Token usage sends nothing, as the card's one request for both views does.\n queries: [sumSeries('input', INPUT), sumSeries('output', OUTPUT), sumSeries('cacheRead', CACHE_READ)],\n options: {\n chart: 'stackedBar',\n format: 'usd',\n xLabels: 'edges',\n series: [\n {\n dataKey: 'cost',\n label: 'Cost',\n color: 'green',\n value: {\n sum: [\n { query: 'input', field: 'estimatedCost' },\n { query: 'output', field: 'estimatedCost' },\n ],\n },\n },\n ],\n total: { value: 'total' },\n emptyMessage: 'No model calls in this range.',\n },\n },\n ],\n};\n\nconst failedAgentRuns = [\n { fieldId: 'rootEntityType', value: 'agent' },\n { fieldId: 'status', value: 'error' },\n];\n\n/** Agent runs, with Failure rate in its title menu, as the Agent runs card. */\nconst agentRunsWidget: DashboardWidget = {\n id: 'agent-runs',\n span: 6,\n kind: 'timeseries',\n title: 'Agent runs',\n views: [\n {\n label: 'Agent runs',\n description: 'Completed and failed runs.',\n drilldown: { click: agentRunsTraces },\n queries: [agentRunsByStatus],\n options: {\n chart: 'stackedBar',\n format: 'count',\n axis: false,\n xLabels: 'edges',\n series: [\n { dataKey: 'completed', label: 'Completed', color: 'green', value: completedRuns },\n { dataKey: 'failed', label: 'Failed', color: 'error', value: failedRuns },\n ],\n total: { value: 'total' },\n emptyMessage: 'No agent runs in this range.',\n },\n },\n {\n label: 'Failure rate',\n description: 'Share of agent runs that failed.',\n drilldown: {\n action: { page: 'logs', filters: failedAgentRuns },\n click: { page: 'traces', filters: failedAgentRuns },\n },\n queries: [agentRunsByStatus],\n options: {\n chart: 'line',\n format: 'percent',\n xLabels: 'edges',\n flatYDomain: [0, 1],\n series: [\n {\n dataKey: 'failureRate',\n label: 'Failed runs',\n color: 'error',\n value: {\n coalesce: [{ ratio: { of: failedRuns, over: { sum: [completedRuns, failedRuns] } } }, { const: 0 }],\n },\n },\n ],\n total: {\n value: {\n coalesce: [{ ratio: { of: failedRuns, over: { sum: [completedRuns, failedRuns] } } }, { const: 0 }],\n },\n },\n emptyWhenZero: { sum: [completedRuns, failedRuns] },\n emptyMessage: 'No agent runs in this range.',\n },\n },\n ],\n};\n\nconst latencyView = (label: string, metric: string, rootEntityType: string, noun: string): DashboardWidgetView => ({\n label,\n queries: [\n {\n id: 'latency',\n source: 'metrics',\n request: 'percentiles',\n name: metric,\n percentiles: [0.5, 0.95, 0.99],\n } satisfies DashboardQuery,\n ],\n drilldown: { action: { page: 'traces', filters: [{ fieldId: 'rootEntityType', value: rootEntityType }] } },\n options: {\n chart: 'line',\n format: 'duration',\n buckets: 'api',\n xLabels: 'edges',\n series: [\n { dataKey: 'p50', label: 'P50', color: 'sky', value: { query: 'latency', percentile: 0.5 }, round: true },\n {\n dataKey: 'p95',\n label: 'P95',\n color: 'green',\n emphasis: true,\n value: { query: 'latency', percentile: 0.95 },\n round: true,\n },\n { dataKey: 'p99', label: 'P99', color: 'violet', value: { query: 'latency', percentile: 0.99 }, round: true },\n ],\n total: { value: { peak: 'p95' } },\n emptyMessage: `No ${noun} in this range.`,\n },\n});\n\nconst latencyWidget: DashboardWidget = {\n id: 'latency',\n span: 6,\n kind: 'timeseries',\n title: 'Latency',\n description: 'Duration percentiles.',\n drilldown: { click: { page: 'traces' } },\n views: [\n latencyView('Agent latency', 'mastra_agent_duration_ms', 'agent', 'agent runs'),\n latencyView('Workflow latency', 'mastra_workflow_duration_ms', 'workflow_run', 'workflow runs'),\n latencyView('Tool latency', 'mastra_tool_duration_ms', 'tool', 'tool calls'),\n ],\n};\n\nconst DISTINCT_IDS = [\n ['countDistinct.resourceId', 'resources', 'Resources', 'sky'],\n ['countDistinct.threadId', 'threads', 'Threads', 'green'],\n ['countDistinct.userId', 'users', 'Users', 'violet'],\n ['countDistinct.sessionId', 'sessions', 'Sessions', 'teal'],\n] as const;\nconst distinctMeasures = DISTINCT_IDS.map(([measure]) => measure);\n\nconst distinctIdsWidget: DashboardWidget = {\n id: 'distinct-ids',\n span: 6,\n kind: 'timeseries',\n title: 'Resources and threads',\n description: 'Unique ids on traces; users and sessions only when set.',\n drilldown: { click: { page: 'traces' } },\n views: [\n {\n queries: [\n { id: 'buckets', source: 'traceAggregate', measures: distinctMeasures, limit: 10 },\n { id: 'totals', source: 'traceAggregate', measures: distinctMeasures },\n ],\n options: {\n chart: 'line',\n format: 'count',\n xLabels: 'edges',\n totals: ['totals'],\n hideEmpty: true,\n emphasizeFirst: true,\n series: DISTINCT_IDS.map(([measure, dataKey, label, color]) => ({\n dataKey,\n label,\n color,\n value: { query: 'buckets', measure },\n rangeTotal: { query: 'totals', measure },\n })),\n emptyMessage: 'No traces in this range set a resource, thread, user or session id.',\n },\n },\n ],\n};\n\nconst USAGE = [INPUT, OUTPUT];\nconst TRACE_LIMIT = 1000;\nconst SPAN_LIMIT = 500;\ntype TraceMeasure = NonNullable<Extract<DashboardQuery, { source: 'traceAggregate' }>['measures']>[number];\ntype SpanMeasure = NonNullable<Extract<DashboardQuery, { source: 'spanAggregate' }>['measures']>[number];\nconst ERRORS: TraceMeasure[] = ['count', 'errorRate', 'duration.p95'];\n/** Traces with a thread. */\nconst hasThread = { op: 'exists', path: 'threadId' } as const;\n\nconst usageTotals = (groupBy: string[], filters?: Record<string, string>): DashboardQuery => ({\n id: 'usage',\n source: 'metrics',\n request: 'breakdown',\n name: USAGE,\n groupBy,\n aggregation: 'sum',\n orderDirection: 'DESC',\n limit: 1000,\n ...(filters ? { filters } : {}),\n compare: 'previousWindow',\n});\n\nconst TRACE_DESCRIPTION = 'A trace is one end-to-end request, with every step it took.';\nconst SPAN_DESCRIPTION =\n 'A span is one step inside a trace, such as a tool call or a model call. One trace can have many.';\n\nconst nameColumn = (label: string, options: Record<string, unknown> = {}): DashboardColumn => ({\n id: 'name',\n label,\n options: { type: 'name', width: 'minmax(12rem,3fr)', ...options },\n});\nconst projectColumn: DashboardColumn = {\n id: 'project',\n label: 'Project',\n scope: 'org',\n options: { type: 'dimension', dimension: 'projectId', as: 'project', width: 'minmax(8rem,2fr)' },\n};\nconst errorColumns: DashboardColumn[] = [\n {\n id: 'errorRate',\n label: 'Errors',\n options: { type: 'value', value: { query: 'figures', measure: 'errorRate' }, format: 'percent', better: 'lower' },\n },\n {\n id: 'p95',\n label: 'P95 latency',\n options: {\n type: 'value',\n value: { query: 'figures', measure: 'duration.p95' },\n format: 'duration',\n better: 'lower',\n },\n },\n];\nconst usageColumns: DashboardColumn[] = [\n {\n id: 'tokens',\n label: 'Tokens',\n options: {\n type: 'value',\n value: { query: 'usage', field: 'value' },\n format: 'count',\n missing: 0,\n additive: true,\n better: 'lower',\n },\n },\n {\n id: 'cost',\n label: 'Cost',\n options: {\n type: 'value',\n value: { query: 'usage', field: 'estimatedCost' },\n format: 'usd',\n additive: true,\n better: 'lower',\n unpricedWhen: 'tokens',\n },\n },\n];\nconst countColumn = (count: { label: string; value: Record<string, unknown>; spans: boolean }): DashboardColumn => ({\n id: 'count',\n label: count.label,\n options: {\n type: 'value',\n value: count.value,\n format: 'count',\n emphasis: true,\n missing: 0,\n additive: true,\n better: 'higher',\n description: count.spans ? SPAN_DESCRIPTION : TRACE_DESCRIPTION,\n },\n});\nconst changeColumn: DashboardColumn = { id: 'change', label: '% Change', options: { type: 'change' } };\nconst TRACES = { label: 'Traces', value: { query: 'figures', measure: 'count' }, spans: false };\n\nconst tableOptions = (groupBy: string[], name: string, emptyMessage: string, extra: Record<string, unknown> = {}) => ({\n groupBy,\n defaultSort: { column: 'count', direction: 'desc' },\n pageSize: 13,\n emptyMessage,\n ariaLabel: `${name} breakdown`,\n ...extra,\n});\n\n/** Row clicks open traces in the row's project, plus the row's own name as `field`. */\nconst drill = (scope: 'org' | 'project', name: string, field: string, extra: Record<string, unknown> = {}) => ({\n rowDrilldown: { fields: { ...(scope === 'org' ? { projectId: 'projectId' } : {}), [name]: field }, ...extra },\n});\n\nconst scoped = (scope: 'org' | 'project', dimension: string) =>\n scope === 'org' ? ['projectId', dimension] : [dimension];\n\nconst ENTITIES = {\n Agents: { name: 'Agent', icon: 'agent', spanTypes: ['agent_run'] },\n Workflows: { name: 'Workflow', icon: 'workflow', spanTypes: ['workflow_run'] },\n Tools: { name: 'Tool', icon: 'tool', spanTypes: ['tool_call', 'mcp_tool_call'] },\n} as const;\n\n/** An entity's figures; agents and workflows count the traces they ran in, tools every call. */\nconst spanMeasures = (traces: boolean): SpanMeasure[] => [\n 'count',\n ...(traces ? (['countDistinct.traceId'] as const) : []),\n 'errorCount',\n 'errorRate',\n 'duration.p95',\n];\n\nconst entityView = (\n scope: 'org' | 'project',\n label: keyof typeof ENTITIES,\n description: string,\n emptyMessage: string,\n): DashboardWidgetView => {\n const { name, icon, spanTypes } = ENTITIES[label];\n const groupBy = scoped(scope, 'entityName');\n const usage = label === 'Agents';\n const traces = label !== 'Tools';\n return {\n label: `Breakdown by ${name.toLowerCase()}`,\n scope,\n description,\n queries: [\n {\n id: 'figures',\n source: 'spanAggregate',\n where:\n spanTypes.length === 1\n ? { op: 'eq', left: { path: 'spanType' }, right: { literal: spanTypes[0] } }\n : { op: 'in', value: { path: 'spanType' }, set: [...spanTypes] },\n groupBy,\n measures: spanMeasures(traces),\n limit: SPAN_LIMIT,\n compare: 'previousWindow',\n },\n ...(usage ? [usageTotals(groupBy, { entityType: 'agent' })] : []),\n ],\n columns: [\n nameColumn(name, { mark: { icon } }),\n projectColumn,\n ...errorColumns,\n ...(usage ? usageColumns : []),\n countColumn(\n traces\n ? { label: 'Traces', value: { query: 'figures', measure: 'countDistinct.traceId' }, spans: false }\n : { label: 'Spans', value: { query: 'figures', measure: 'count' }, spans: true },\n ),\n changeColumn,\n ],\n options: tableOptions(\n groupBy,\n name,\n emptyMessage,\n drill(scope, 'entityName', 'entityName', { spanTypes, keepEmpty: true }),\n ),\n };\n};\n\nconst traceColumns = (\n name: string,\n options: Record<string, unknown> = {},\n extra: DashboardColumn[] = [],\n): DashboardColumn[] => [\n nameColumn(name, options),\n projectColumn,\n ...extra,\n ...errorColumns,\n ...usageColumns,\n countColumn(TRACES),\n changeColumn,\n];\n\nconst environmentsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'environment');\n return {\n label: 'Breakdown by environment',\n scope,\n description: 'Traces, errors, latency and spend per environment.',\n queries: [\n {\n id: 'figures',\n source: 'traceAggregate',\n groupBy,\n measures: ERRORS,\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n },\n usageTotals(groupBy),\n ],\n columns: traceColumns('Environment', { unnamed: 'No environment' }),\n options: tableOptions(\n groupBy,\n 'Environment',\n 'No traces in this range.',\n drill(scope, 'environment', 'environment'),\n ),\n };\n};\n\nconst threadsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'threadId');\n const threads: DashboardQuery = {\n id: 'figures',\n source: 'traceAggregate',\n where: hasThread,\n groupBy: scope === 'org' ? ['projectId', 'threadId'] : ['resourceId', 'threadId'],\n measures: ERRORS,\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n };\n // Org-wide the second dimension is the project, so a third request names each thread's resource.\n const resources: DashboardQuery = {\n id: 'resources',\n source: 'traceAggregate',\n where: hasThread,\n groupBy: ['resourceId', 'threadId'],\n measures: ['count'],\n limit: TRACE_LIMIT,\n };\n const resourceColumn: DashboardColumn = {\n id: 'resource',\n label: 'Resource',\n options: {\n type: 'dimension',\n dimension: 'resourceId',\n query: scope === 'org' ? 'resources' : 'figures',\n joinOn: 'threadId',\n width: 'minmax(6rem,1fr)',\n },\n };\n return {\n label: 'Breakdown by thread',\n scope,\n description: 'Traces, errors, latency and spend per thread.',\n queries: [threads, usageTotals(groupBy), ...(scope === 'org' ? [resources] : [])],\n columns: traceColumns('Thread', {}, [resourceColumn]),\n options: tableOptions(groupBy, 'Thread', 'No traces with a thread in this range.', {\n hideUnnamed: true,\n dropped: false,\n ...drill(scope, 'threadId', 'threadId', { keepEmpty: true }),\n }),\n };\n};\n\nconst modelsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'provider').concat('model');\n return {\n label: 'Breakdown by model',\n scope,\n description: 'Model calls, tokens and spend per model.',\n queries: [\n {\n id: 'calls',\n source: 'metrics',\n request: 'breakdown',\n name: [INPUT],\n groupBy,\n aggregation: 'count',\n orderDirection: 'DESC',\n limit: 1000,\n compare: 'previousWindow',\n },\n usageTotals(groupBy),\n ],\n columns: [\n nameColumn('Model', { unnamed: 'Unknown model', mark: { providerDimension: 'provider' } }),\n projectColumn,\n ...usageColumns,\n countColumn({ label: 'Spans', value: { query: 'calls', field: 'value' }, spans: true }),\n changeColumn,\n ],\n options: tableOptions(groupBy, 'Model', 'No model usage in this range.', drill(scope, 'model', 'model')),\n };\n};\n\nconst scopedViews = (scope: 'org' | 'project'): DashboardWidgetView[] => [\n entityView(\n scope,\n 'Agents',\n 'Traces each agent ran in, nested runs included, with errors, latency and spend.',\n 'No agent runs in this range.',\n ),\n entityView(\n scope,\n 'Workflows',\n 'Traces each workflow ran in, nested runs included, with errors and latency.',\n 'No workflow runs in this range.',\n ),\n entityView(\n scope,\n 'Tools',\n 'Every tool call, MCP tools included, with errors and latency.',\n 'No tool calls in this range.',\n ),\n modelsView(scope),\n threadsView(scope),\n environmentsView(scope),\n];\n\nconst breakdownWidget: DashboardWidget = {\n id: 'breakdown',\n span: 12,\n kind: 'table',\n title: 'Breakdown',\n drilldown: { click: { page: 'traces' } },\n views: [\n {\n label: 'Breakdown by project',\n scope: 'org',\n description: 'Traces, errors, latency and spend per project.',\n queries: [\n {\n id: 'figures',\n source: 'traceAggregate',\n groupBy: ['projectId'],\n measures: [...ERRORS, 'countDistinct.resourceId', 'countDistinct.threadId'],\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n },\n usageTotals(['projectId']),\n ],\n columns: [\n nameColumn('Project', { as: 'project' }),\n ...errorColumns,\n ...usageColumns,\n countColumn(TRACES),\n changeColumn,\n ],\n options: tableOptions(['projectId'], 'Project', 'No traces in this range.', {\n openWhen: { minRows: 2 },\n rowDrilldown: { fields: { projectId: 'projectId' } },\n }),\n },\n ...scopedViews('org'),\n ...scopedViews('project'),\n ],\n};\n\n/** Freezes a value and everything it holds, so a shared definition can't be edited in place. */\nfunction deepFreeze<T>(value: T): T {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n for (const child of Object.values(value)) deepFreeze(child);\n Object.freeze(value);\n }\n return value;\n}\n\n/**\n * The Metrics page as a dashboard: four charts in two rows (usage and health first), then the\n * breakdown of who caused them. Org and project pages share it; scope-tagged parts pick per page.\n * It is frozen: copy it (`structuredClone(METRICS_DASHBOARD)`) before customising.\n */\nexport const METRICS_DASHBOARD: DashboardDefinition = deepFreeze({\n schemaVersion: 1,\n rows: [\n { widgets: [tokenUsageWidget, agentRunsWidget] },\n { widgets: [latencyWidget, distinctIdsWidget] },\n { widgets: [breakdownWidget] },\n ],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"metrics-dashboard.cjs.js","names":[],"sources":["../../../src/domains/dashboards/metrics-dashboard.ts"],"sourcesContent":["import type {\n DashboardColumn,\n DashboardDefinition,\n DashboardDrilldownTarget,\n DashboardQuery,\n DashboardWidget,\n DashboardWidgetView,\n} from '@mastra/client-js';\n\nconst INPUT = 'mastra_model_total_input_tokens';\nconst OUTPUT = 'mastra_model_total_output_tokens';\nconst CACHE_READ = 'mastra_model_input_cache_read_tokens';\nconst AGENT_DURATION = 'mastra_agent_duration_ms';\n\nconst sumSeries = (id: string, name: string): DashboardQuery => ({\n id,\n source: 'metrics',\n request: 'timeSeries',\n name: [name],\n aggregation: 'sum',\n});\n\nconst agentRunsByStatus: DashboardQuery = {\n id: 'runs',\n source: 'metrics',\n request: 'timeSeries',\n name: [AGENT_DURATION],\n aggregation: 'count',\n groupBy: ['status'],\n};\n\n// Runs report status `ok` or `error` (observability/mastra auto-extract); the card also counts `failed`.\nconst FAILED = ['error', 'failed'];\nconst completedRuns = { query: 'runs', notGroups: FAILED };\nconst failedRuns = { query: 'runs', groups: FAILED };\nconst agentRunsTraces: DashboardDrilldownTarget = {\n page: 'traces',\n filters: [{ fieldId: 'rootEntityType', value: 'agent' }],\n};\n\nconst tokenUsageWidget: DashboardWidget = {\n id: 'token-usage',\n span: 6,\n kind: 'timeseries',\n title: 'Token usage',\n drilldown: { action: { page: 'traces' }, click: { page: 'traces' } },\n views: [\n {\n label: 'Token usage',\n description: 'Input, cache reads and output.',\n queries: [sumSeries('input', INPUT), sumSeries('output', OUTPUT), sumSeries('cacheRead', CACHE_READ)],\n options: {\n chart: 'stackedBar',\n format: 'count',\n xLabels: 'edges',\n series: [\n {\n dataKey: 'input',\n label: 'Input',\n color: 'green',\n value: { max: [{ minus: [{ query: 'input' }, { query: 'cacheRead' }] }, { const: 0 }] },\n },\n { dataKey: 'cacheRead', label: 'Cache read', color: 'violet', value: { query: 'cacheRead' } },\n { dataKey: 'output', label: 'Output', color: 'sky', value: { query: 'output' } },\n ],\n total: { value: 'total' },\n emptyMessage: 'No model calls in this range.',\n },\n },\n {\n label: 'Model cost',\n description: 'Estimated model spend.',\n // Cache reads aren't charted here, but fetching them keeps their answer, so going back to\n // Token usage sends nothing, as the card's one request for both views does.\n queries: [sumSeries('input', INPUT), sumSeries('output', OUTPUT), sumSeries('cacheRead', CACHE_READ)],\n options: {\n chart: 'stackedBar',\n format: 'usd',\n xLabels: 'edges',\n series: [\n {\n dataKey: 'cost',\n label: 'Cost',\n color: 'green',\n value: {\n sum: [\n { query: 'input', field: 'estimatedCost' },\n { query: 'output', field: 'estimatedCost' },\n ],\n },\n },\n ],\n total: { value: 'total' },\n emptyMessage: 'No model calls in this range.',\n },\n },\n ],\n};\n\nconst failedAgentRuns = [\n { fieldId: 'rootEntityType', value: 'agent' },\n { fieldId: 'status', value: 'error' },\n];\n\n/** Agent runs, with Failure rate in its title menu, as the Agent runs card. */\nconst agentRunsWidget: DashboardWidget = {\n id: 'agent-runs',\n span: 6,\n kind: 'timeseries',\n title: 'Agent runs',\n views: [\n {\n label: 'Agent runs',\n description: 'Completed and failed runs.',\n drilldown: { click: agentRunsTraces },\n queries: [agentRunsByStatus],\n options: {\n chart: 'stackedBar',\n format: 'count',\n axis: false,\n xLabels: 'edges',\n series: [\n { dataKey: 'completed', label: 'Completed', color: 'green', value: completedRuns },\n { dataKey: 'failed', label: 'Failed', color: 'error', value: failedRuns },\n ],\n total: { value: 'total' },\n emptyMessage: 'No agent runs in this range.',\n },\n },\n {\n label: 'Failure rate',\n description: 'Share of agent runs that failed.',\n drilldown: {\n action: { page: 'logs', filters: failedAgentRuns },\n click: { page: 'traces', filters: failedAgentRuns },\n },\n queries: [agentRunsByStatus],\n options: {\n chart: 'line',\n format: 'percent',\n xLabels: 'edges',\n flatYDomain: [0, 1],\n series: [\n {\n dataKey: 'failureRate',\n label: 'Failed runs',\n color: 'error',\n value: {\n coalesce: [{ ratio: { of: failedRuns, over: { sum: [completedRuns, failedRuns] } } }, { const: 0 }],\n },\n },\n ],\n total: {\n value: {\n coalesce: [{ ratio: { of: failedRuns, over: { sum: [completedRuns, failedRuns] } } }, { const: 0 }],\n },\n },\n emptyWhenZero: { sum: [completedRuns, failedRuns] },\n emptyMessage: 'No agent runs in this range.',\n },\n },\n ],\n};\n\nconst latencyView = (label: string, metric: string, rootEntityType: string, noun: string): DashboardWidgetView => ({\n label,\n queries: [\n {\n id: 'latency',\n source: 'metrics',\n request: 'percentiles',\n name: metric,\n percentiles: [0.5, 0.95, 0.99],\n } satisfies DashboardQuery,\n ],\n drilldown: { action: { page: 'traces', filters: [{ fieldId: 'rootEntityType', value: rootEntityType }] } },\n options: {\n chart: 'line',\n format: 'duration',\n buckets: 'api',\n xLabels: 'edges',\n series: [\n { dataKey: 'p50', label: 'P50', color: 'sky', value: { query: 'latency', percentile: 0.5 }, round: true },\n {\n dataKey: 'p95',\n label: 'P95',\n color: 'green',\n emphasis: true,\n value: { query: 'latency', percentile: 0.95 },\n round: true,\n },\n { dataKey: 'p99', label: 'P99', color: 'violet', value: { query: 'latency', percentile: 0.99 }, round: true },\n ],\n total: { value: { peak: 'p95' } },\n emptyMessage: `No ${noun} in this range.`,\n },\n});\n\nconst latencyWidget: DashboardWidget = {\n id: 'latency',\n span: 6,\n kind: 'timeseries',\n title: 'Latency',\n description: 'Duration percentiles.',\n drilldown: { click: { page: 'traces' } },\n views: [\n latencyView('Agent latency', 'mastra_agent_duration_ms', 'agent', 'agent runs'),\n latencyView('Workflow latency', 'mastra_workflow_duration_ms', 'workflow_run', 'workflow runs'),\n latencyView('Tool latency', 'mastra_tool_duration_ms', 'tool', 'tool calls'),\n ],\n};\n\nconst DISTINCT_IDS = [\n ['countDistinct.resourceId', 'resources', 'Resources', 'sky'],\n ['countDistinct.threadId', 'threads', 'Threads', 'green'],\n ['countDistinct.userId', 'users', 'Users', 'violet'],\n ['countDistinct.sessionId', 'sessions', 'Sessions', 'teal'],\n] as const;\nconst distinctMeasures = DISTINCT_IDS.map(([measure]) => measure);\n\nconst distinctIdsWidget: DashboardWidget = {\n id: 'distinct-ids',\n span: 6,\n kind: 'timeseries',\n title: 'Resources and threads',\n description: 'Unique ids on traces; users and sessions only when set.',\n drilldown: { click: { page: 'traces' } },\n views: [\n {\n queries: [\n { id: 'buckets', source: 'traceAggregate', measures: distinctMeasures, limit: 10 },\n { id: 'totals', source: 'traceAggregate', measures: distinctMeasures },\n ],\n options: {\n chart: 'line',\n format: 'count',\n xLabels: 'edges',\n totals: ['totals'],\n hideEmpty: true,\n emphasizeFirst: true,\n series: DISTINCT_IDS.map(([measure, dataKey, label, color]) => ({\n dataKey,\n label,\n color,\n value: { query: 'buckets', measure },\n rangeTotal: { query: 'totals', measure },\n })),\n emptyMessage: 'No traces in this range set a resource, thread, user or session id.',\n },\n },\n ],\n};\n\nconst USAGE = [INPUT, OUTPUT];\nconst TRACE_LIMIT = 1000;\nconst SPAN_LIMIT = 500;\ntype TraceMeasure = NonNullable<Extract<DashboardQuery, { source: 'traceAggregate' }>['measures']>[number];\ntype SpanMeasure = NonNullable<Extract<DashboardQuery, { source: 'spanAggregate' }>['measures']>[number];\nconst ERRORS: TraceMeasure[] = ['count', 'errorRate', 'duration.p95'];\n/** Traces with a thread. */\nconst hasThread = { op: 'exists', path: 'threadId' } as const;\n\nconst usageTotals = (groupBy: string[], filters?: Record<string, string>): DashboardQuery => ({\n id: 'usage',\n source: 'metrics',\n request: 'breakdown',\n name: USAGE,\n groupBy,\n aggregation: 'sum',\n orderDirection: 'DESC',\n limit: 1000,\n ...(filters ? { filters } : {}),\n compare: 'previousWindow',\n});\n\nconst TRACE_DESCRIPTION = 'A trace is one end-to-end request, with every step it took.';\nconst SPAN_DESCRIPTION =\n 'A span is one step inside a trace, such as a tool call or a model call. One trace can have many.';\n\nconst nameColumn = (label: string, options: Record<string, unknown> = {}): DashboardColumn => ({\n id: 'name',\n label,\n options: { type: 'name', width: 'minmax(12rem,3fr)', ...options },\n});\nconst projectColumn: DashboardColumn = {\n id: 'project',\n label: 'Project',\n scope: 'org',\n options: { type: 'dimension', dimension: 'projectId', as: 'project', width: 'minmax(8rem,2fr)' },\n};\nconst errorColumns: DashboardColumn[] = [\n {\n id: 'errorRate',\n label: 'Errors',\n options: { type: 'value', value: { query: 'figures', measure: 'errorRate' }, format: 'percent', better: 'lower' },\n },\n {\n id: 'p95',\n label: 'P95 latency',\n options: {\n type: 'value',\n value: { query: 'figures', measure: 'duration.p95' },\n format: 'duration',\n better: 'lower',\n },\n },\n];\nconst usageColumns: DashboardColumn[] = [\n {\n id: 'tokens',\n label: 'Tokens',\n options: {\n type: 'value',\n value: { query: 'usage', field: 'value' },\n format: 'count',\n missing: 0,\n additive: true,\n better: 'lower',\n },\n },\n {\n id: 'cost',\n label: 'Cost',\n options: {\n type: 'value',\n value: { query: 'usage', field: 'estimatedCost' },\n format: 'usd',\n additive: true,\n better: 'lower',\n unpricedWhen: 'tokens',\n },\n },\n];\nconst countColumn = (count: { label: string; value: Record<string, unknown>; spans: boolean }): DashboardColumn => ({\n id: 'count',\n label: count.label,\n options: {\n type: 'value',\n value: count.value,\n format: 'count',\n emphasis: true,\n missing: 0,\n additive: true,\n better: 'higher',\n description: count.spans ? SPAN_DESCRIPTION : TRACE_DESCRIPTION,\n },\n});\nconst changeColumn: DashboardColumn = { id: 'change', label: '% Change', options: { type: 'change' } };\nconst TRACES = { label: 'Traces', value: { query: 'figures', measure: 'count' }, spans: false };\n\nconst tableOptions = (groupBy: string[], name: string, emptyMessage: string, extra: Record<string, unknown> = {}) => ({\n groupBy,\n defaultSort: { column: 'count', direction: 'desc' },\n pageSize: 10,\n emptyMessage,\n ariaLabel: `${name} breakdown`,\n ...extra,\n});\n\n/** Row clicks open traces in the row's project, plus the row's own name as `field`. */\nconst drill = (scope: 'org' | 'project', name: string, field: string, extra: Record<string, unknown> = {}) => ({\n rowDrilldown: { fields: { ...(scope === 'org' ? { projectId: 'projectId' } : {}), [name]: field }, ...extra },\n});\n\nconst scoped = (scope: 'org' | 'project', dimension: string) =>\n scope === 'org' ? ['projectId', dimension] : [dimension];\n\nconst ENTITIES = {\n Agents: { name: 'Agent', icon: 'agent', spanTypes: ['agent_run'] },\n Workflows: { name: 'Workflow', icon: 'workflow', spanTypes: ['workflow_run'] },\n Tools: { name: 'Tool', icon: 'tool', spanTypes: ['tool_call', 'mcp_tool_call'] },\n} as const;\n\n/** An entity's figures; agents and workflows count the traces they ran in, tools every call. */\nconst spanMeasures = (traces: boolean): SpanMeasure[] => [\n 'count',\n ...(traces ? (['countDistinct.traceId'] as const) : []),\n 'errorCount',\n 'errorRate',\n 'duration.p95',\n];\n\nconst entityView = (\n scope: 'org' | 'project',\n label: keyof typeof ENTITIES,\n description: string,\n emptyMessage: string,\n): DashboardWidgetView => {\n const { name, icon, spanTypes } = ENTITIES[label];\n const groupBy = scoped(scope, 'entityName');\n const usage = label === 'Agents';\n const traces = label !== 'Tools';\n return {\n label: `Breakdown by ${name.toLowerCase()}`,\n scope,\n description,\n queries: [\n {\n id: 'figures',\n source: 'spanAggregate',\n where:\n spanTypes.length === 1\n ? { op: 'eq', left: { path: 'spanType' }, right: { literal: spanTypes[0] } }\n : { op: 'in', value: { path: 'spanType' }, set: [...spanTypes] },\n groupBy,\n measures: spanMeasures(traces),\n limit: SPAN_LIMIT,\n compare: 'previousWindow',\n },\n ...(usage ? [usageTotals(groupBy, { entityType: 'agent' })] : []),\n ],\n columns: [\n nameColumn(name, { mark: { icon } }),\n projectColumn,\n ...errorColumns,\n ...(usage ? usageColumns : []),\n countColumn(\n traces\n ? { label: 'Traces', value: { query: 'figures', measure: 'countDistinct.traceId' }, spans: false }\n : { label: 'Spans', value: { query: 'figures', measure: 'count' }, spans: true },\n ),\n changeColumn,\n ],\n options: tableOptions(\n groupBy,\n name,\n emptyMessage,\n drill(scope, 'entityName', 'entityName', { spanTypes, keepEmpty: true }),\n ),\n };\n};\n\nconst traceColumns = (\n name: string,\n options: Record<string, unknown> = {},\n extra: DashboardColumn[] = [],\n): DashboardColumn[] => [\n nameColumn(name, options),\n projectColumn,\n ...extra,\n ...errorColumns,\n ...usageColumns,\n countColumn(TRACES),\n changeColumn,\n];\n\nconst environmentsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'environment');\n return {\n label: 'Breakdown by environment',\n scope,\n description: 'Traces, errors, latency and spend per environment.',\n queries: [\n {\n id: 'figures',\n source: 'traceAggregate',\n groupBy,\n measures: ERRORS,\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n },\n usageTotals(groupBy),\n ],\n columns: traceColumns('Environment', { unnamed: 'No environment' }),\n options: tableOptions(\n groupBy,\n 'Environment',\n 'No traces in this range.',\n drill(scope, 'environment', 'environment'),\n ),\n };\n};\n\nconst threadsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'threadId');\n const threads: DashboardQuery = {\n id: 'figures',\n source: 'traceAggregate',\n where: hasThread,\n groupBy: scope === 'org' ? ['projectId', 'threadId'] : ['resourceId', 'threadId'],\n measures: ERRORS,\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n };\n // Org-wide the second dimension is the project, so a third request names each thread's resource.\n const resources: DashboardQuery = {\n id: 'resources',\n source: 'traceAggregate',\n where: hasThread,\n groupBy: ['resourceId', 'threadId'],\n measures: ['count'],\n limit: TRACE_LIMIT,\n };\n const resourceColumn: DashboardColumn = {\n id: 'resource',\n label: 'Resource',\n options: {\n type: 'dimension',\n dimension: 'resourceId',\n query: scope === 'org' ? 'resources' : 'figures',\n joinOn: 'threadId',\n width: 'minmax(6rem,1fr)',\n },\n };\n return {\n label: 'Breakdown by thread',\n scope,\n description: 'Traces, errors, latency and spend per thread.',\n queries: [threads, usageTotals(groupBy), ...(scope === 'org' ? [resources] : [])],\n columns: traceColumns('Thread', {}, [resourceColumn]),\n options: tableOptions(groupBy, 'Thread', 'No traces with a thread in this range.', {\n hideUnnamed: true,\n dropped: false,\n ...drill(scope, 'threadId', 'threadId', { keepEmpty: true }),\n }),\n };\n};\n\nconst modelsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'provider').concat('model');\n return {\n label: 'Breakdown by model',\n scope,\n description: 'Model calls, tokens and spend per model.',\n queries: [\n {\n id: 'calls',\n source: 'metrics',\n request: 'breakdown',\n name: [INPUT],\n groupBy,\n aggregation: 'count',\n orderDirection: 'DESC',\n limit: 1000,\n compare: 'previousWindow',\n },\n usageTotals(groupBy),\n ],\n columns: [\n nameColumn('Model', { unnamed: 'Unknown model', mark: { providerDimension: 'provider' } }),\n projectColumn,\n ...usageColumns,\n countColumn({ label: 'Spans', value: { query: 'calls', field: 'value' }, spans: true }),\n changeColumn,\n ],\n options: tableOptions(groupBy, 'Model', 'No model usage in this range.', drill(scope, 'model', 'model')),\n };\n};\n\nconst scopedViews = (scope: 'org' | 'project'): DashboardWidgetView[] => [\n entityView(\n scope,\n 'Agents',\n 'Traces each agent ran in, nested runs included, with errors, latency and spend.',\n 'No agent runs in this range.',\n ),\n entityView(\n scope,\n 'Workflows',\n 'Traces each workflow ran in, nested runs included, with errors and latency.',\n 'No workflow runs in this range.',\n ),\n entityView(\n scope,\n 'Tools',\n 'Every tool call, MCP tools included, with errors and latency.',\n 'No tool calls in this range.',\n ),\n modelsView(scope),\n threadsView(scope),\n environmentsView(scope),\n];\n\nconst breakdownWidget: DashboardWidget = {\n id: 'breakdown',\n span: 12,\n kind: 'table',\n title: 'Breakdown',\n drilldown: { click: { page: 'traces' } },\n views: [\n {\n label: 'Breakdown by project',\n scope: 'org',\n description: 'Traces, errors, latency and spend per project.',\n queries: [\n {\n id: 'figures',\n source: 'traceAggregate',\n groupBy: ['projectId'],\n measures: [...ERRORS, 'countDistinct.resourceId', 'countDistinct.threadId'],\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n },\n usageTotals(['projectId']),\n ],\n columns: [\n nameColumn('Project', { as: 'project' }),\n ...errorColumns,\n ...usageColumns,\n countColumn(TRACES),\n changeColumn,\n ],\n options: tableOptions(['projectId'], 'Project', 'No traces in this range.', {\n openWhen: { minRows: 2 },\n rowDrilldown: { fields: { projectId: 'projectId' } },\n }),\n },\n ...scopedViews('org'),\n ...scopedViews('project'),\n ],\n};\n\n/** Freezes a value and everything it holds, so a shared definition can't be edited in place. */\nfunction deepFreeze<T>(value: T): T {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n for (const child of Object.values(value)) deepFreeze(child);\n Object.freeze(value);\n }\n return value;\n}\n\n/**\n * The Metrics page as a dashboard: four charts in two rows (usage and health first), then the\n * breakdown of who caused them. Org and project pages share it; scope-tagged parts pick per page.\n * It is frozen: copy it (`structuredClone(METRICS_DASHBOARD)`) before customising.\n */\nexport const METRICS_DASHBOARD: DashboardDefinition = deepFreeze({\n schemaVersion: 1,\n rows: [\n { widgets: [tokenUsageWidget, agentRunsWidget] },\n { widgets: [latencyWidget, distinctIdsWidget] },\n { widgets: [breakdownWidget] },\n ],\n});\n"],"mappings":"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"}
@@ -459,7 +459,7 @@ var tableOptions = (groupBy, name, emptyMessage, extra = {}) => ({
459
459
  column: "count",
460
460
  direction: "desc"
461
461
  },
462
- pageSize: 13,
462
+ pageSize: 10,
463
463
  emptyMessage,
464
464
  ariaLabel: `${name} breakdown`,
465
465
  ...extra
@@ -1 +1 @@
1
- {"version":3,"file":"metrics-dashboard.es.js","names":[],"sources":["../../../src/domains/dashboards/metrics-dashboard.ts"],"sourcesContent":["import type {\n DashboardColumn,\n DashboardDefinition,\n DashboardDrilldownTarget,\n DashboardQuery,\n DashboardWidget,\n DashboardWidgetView,\n} from '@mastra/client-js';\n\nconst INPUT = 'mastra_model_total_input_tokens';\nconst OUTPUT = 'mastra_model_total_output_tokens';\nconst CACHE_READ = 'mastra_model_input_cache_read_tokens';\nconst AGENT_DURATION = 'mastra_agent_duration_ms';\n\nconst sumSeries = (id: string, name: string): DashboardQuery => ({\n id,\n source: 'metrics',\n request: 'timeSeries',\n name: [name],\n aggregation: 'sum',\n});\n\nconst agentRunsByStatus: DashboardQuery = {\n id: 'runs',\n source: 'metrics',\n request: 'timeSeries',\n name: [AGENT_DURATION],\n aggregation: 'count',\n groupBy: ['status'],\n};\n\n// Runs report status `ok` or `error` (observability/mastra auto-extract); the card also counts `failed`.\nconst FAILED = ['error', 'failed'];\nconst completedRuns = { query: 'runs', notGroups: FAILED };\nconst failedRuns = { query: 'runs', groups: FAILED };\nconst agentRunsTraces: DashboardDrilldownTarget = {\n page: 'traces',\n filters: [{ fieldId: 'rootEntityType', value: 'agent' }],\n};\n\nconst tokenUsageWidget: DashboardWidget = {\n id: 'token-usage',\n span: 6,\n kind: 'timeseries',\n title: 'Token usage',\n drilldown: { action: { page: 'traces' }, click: { page: 'traces' } },\n views: [\n {\n label: 'Token usage',\n description: 'Input, cache reads and output.',\n queries: [sumSeries('input', INPUT), sumSeries('output', OUTPUT), sumSeries('cacheRead', CACHE_READ)],\n options: {\n chart: 'stackedBar',\n format: 'count',\n xLabels: 'edges',\n series: [\n {\n dataKey: 'input',\n label: 'Input',\n color: 'green',\n value: { max: [{ minus: [{ query: 'input' }, { query: 'cacheRead' }] }, { const: 0 }] },\n },\n { dataKey: 'cacheRead', label: 'Cache read', color: 'violet', value: { query: 'cacheRead' } },\n { dataKey: 'output', label: 'Output', color: 'sky', value: { query: 'output' } },\n ],\n total: { value: 'total' },\n emptyMessage: 'No model calls in this range.',\n },\n },\n {\n label: 'Model cost',\n description: 'Estimated model spend.',\n // Cache reads aren't charted here, but fetching them keeps their answer, so going back to\n // Token usage sends nothing, as the card's one request for both views does.\n queries: [sumSeries('input', INPUT), sumSeries('output', OUTPUT), sumSeries('cacheRead', CACHE_READ)],\n options: {\n chart: 'stackedBar',\n format: 'usd',\n xLabels: 'edges',\n series: [\n {\n dataKey: 'cost',\n label: 'Cost',\n color: 'green',\n value: {\n sum: [\n { query: 'input', field: 'estimatedCost' },\n { query: 'output', field: 'estimatedCost' },\n ],\n },\n },\n ],\n total: { value: 'total' },\n emptyMessage: 'No model calls in this range.',\n },\n },\n ],\n};\n\nconst failedAgentRuns = [\n { fieldId: 'rootEntityType', value: 'agent' },\n { fieldId: 'status', value: 'error' },\n];\n\n/** Agent runs, with Failure rate in its title menu, as the Agent runs card. */\nconst agentRunsWidget: DashboardWidget = {\n id: 'agent-runs',\n span: 6,\n kind: 'timeseries',\n title: 'Agent runs',\n views: [\n {\n label: 'Agent runs',\n description: 'Completed and failed runs.',\n drilldown: { click: agentRunsTraces },\n queries: [agentRunsByStatus],\n options: {\n chart: 'stackedBar',\n format: 'count',\n axis: false,\n xLabels: 'edges',\n series: [\n { dataKey: 'completed', label: 'Completed', color: 'green', value: completedRuns },\n { dataKey: 'failed', label: 'Failed', color: 'error', value: failedRuns },\n ],\n total: { value: 'total' },\n emptyMessage: 'No agent runs in this range.',\n },\n },\n {\n label: 'Failure rate',\n description: 'Share of agent runs that failed.',\n drilldown: {\n action: { page: 'logs', filters: failedAgentRuns },\n click: { page: 'traces', filters: failedAgentRuns },\n },\n queries: [agentRunsByStatus],\n options: {\n chart: 'line',\n format: 'percent',\n xLabels: 'edges',\n flatYDomain: [0, 1],\n series: [\n {\n dataKey: 'failureRate',\n label: 'Failed runs',\n color: 'error',\n value: {\n coalesce: [{ ratio: { of: failedRuns, over: { sum: [completedRuns, failedRuns] } } }, { const: 0 }],\n },\n },\n ],\n total: {\n value: {\n coalesce: [{ ratio: { of: failedRuns, over: { sum: [completedRuns, failedRuns] } } }, { const: 0 }],\n },\n },\n emptyWhenZero: { sum: [completedRuns, failedRuns] },\n emptyMessage: 'No agent runs in this range.',\n },\n },\n ],\n};\n\nconst latencyView = (label: string, metric: string, rootEntityType: string, noun: string): DashboardWidgetView => ({\n label,\n queries: [\n {\n id: 'latency',\n source: 'metrics',\n request: 'percentiles',\n name: metric,\n percentiles: [0.5, 0.95, 0.99],\n } satisfies DashboardQuery,\n ],\n drilldown: { action: { page: 'traces', filters: [{ fieldId: 'rootEntityType', value: rootEntityType }] } },\n options: {\n chart: 'line',\n format: 'duration',\n buckets: 'api',\n xLabels: 'edges',\n series: [\n { dataKey: 'p50', label: 'P50', color: 'sky', value: { query: 'latency', percentile: 0.5 }, round: true },\n {\n dataKey: 'p95',\n label: 'P95',\n color: 'green',\n emphasis: true,\n value: { query: 'latency', percentile: 0.95 },\n round: true,\n },\n { dataKey: 'p99', label: 'P99', color: 'violet', value: { query: 'latency', percentile: 0.99 }, round: true },\n ],\n total: { value: { peak: 'p95' } },\n emptyMessage: `No ${noun} in this range.`,\n },\n});\n\nconst latencyWidget: DashboardWidget = {\n id: 'latency',\n span: 6,\n kind: 'timeseries',\n title: 'Latency',\n description: 'Duration percentiles.',\n drilldown: { click: { page: 'traces' } },\n views: [\n latencyView('Agent latency', 'mastra_agent_duration_ms', 'agent', 'agent runs'),\n latencyView('Workflow latency', 'mastra_workflow_duration_ms', 'workflow_run', 'workflow runs'),\n latencyView('Tool latency', 'mastra_tool_duration_ms', 'tool', 'tool calls'),\n ],\n};\n\nconst DISTINCT_IDS = [\n ['countDistinct.resourceId', 'resources', 'Resources', 'sky'],\n ['countDistinct.threadId', 'threads', 'Threads', 'green'],\n ['countDistinct.userId', 'users', 'Users', 'violet'],\n ['countDistinct.sessionId', 'sessions', 'Sessions', 'teal'],\n] as const;\nconst distinctMeasures = DISTINCT_IDS.map(([measure]) => measure);\n\nconst distinctIdsWidget: DashboardWidget = {\n id: 'distinct-ids',\n span: 6,\n kind: 'timeseries',\n title: 'Resources and threads',\n description: 'Unique ids on traces; users and sessions only when set.',\n drilldown: { click: { page: 'traces' } },\n views: [\n {\n queries: [\n { id: 'buckets', source: 'traceAggregate', measures: distinctMeasures, limit: 10 },\n { id: 'totals', source: 'traceAggregate', measures: distinctMeasures },\n ],\n options: {\n chart: 'line',\n format: 'count',\n xLabels: 'edges',\n totals: ['totals'],\n hideEmpty: true,\n emphasizeFirst: true,\n series: DISTINCT_IDS.map(([measure, dataKey, label, color]) => ({\n dataKey,\n label,\n color,\n value: { query: 'buckets', measure },\n rangeTotal: { query: 'totals', measure },\n })),\n emptyMessage: 'No traces in this range set a resource, thread, user or session id.',\n },\n },\n ],\n};\n\nconst USAGE = [INPUT, OUTPUT];\nconst TRACE_LIMIT = 1000;\nconst SPAN_LIMIT = 500;\ntype TraceMeasure = NonNullable<Extract<DashboardQuery, { source: 'traceAggregate' }>['measures']>[number];\ntype SpanMeasure = NonNullable<Extract<DashboardQuery, { source: 'spanAggregate' }>['measures']>[number];\nconst ERRORS: TraceMeasure[] = ['count', 'errorRate', 'duration.p95'];\n/** Traces with a thread. */\nconst hasThread = { op: 'exists', path: 'threadId' } as const;\n\nconst usageTotals = (groupBy: string[], filters?: Record<string, string>): DashboardQuery => ({\n id: 'usage',\n source: 'metrics',\n request: 'breakdown',\n name: USAGE,\n groupBy,\n aggregation: 'sum',\n orderDirection: 'DESC',\n limit: 1000,\n ...(filters ? { filters } : {}),\n compare: 'previousWindow',\n});\n\nconst TRACE_DESCRIPTION = 'A trace is one end-to-end request, with every step it took.';\nconst SPAN_DESCRIPTION =\n 'A span is one step inside a trace, such as a tool call or a model call. One trace can have many.';\n\nconst nameColumn = (label: string, options: Record<string, unknown> = {}): DashboardColumn => ({\n id: 'name',\n label,\n options: { type: 'name', width: 'minmax(12rem,3fr)', ...options },\n});\nconst projectColumn: DashboardColumn = {\n id: 'project',\n label: 'Project',\n scope: 'org',\n options: { type: 'dimension', dimension: 'projectId', as: 'project', width: 'minmax(8rem,2fr)' },\n};\nconst errorColumns: DashboardColumn[] = [\n {\n id: 'errorRate',\n label: 'Errors',\n options: { type: 'value', value: { query: 'figures', measure: 'errorRate' }, format: 'percent', better: 'lower' },\n },\n {\n id: 'p95',\n label: 'P95 latency',\n options: {\n type: 'value',\n value: { query: 'figures', measure: 'duration.p95' },\n format: 'duration',\n better: 'lower',\n },\n },\n];\nconst usageColumns: DashboardColumn[] = [\n {\n id: 'tokens',\n label: 'Tokens',\n options: {\n type: 'value',\n value: { query: 'usage', field: 'value' },\n format: 'count',\n missing: 0,\n additive: true,\n better: 'lower',\n },\n },\n {\n id: 'cost',\n label: 'Cost',\n options: {\n type: 'value',\n value: { query: 'usage', field: 'estimatedCost' },\n format: 'usd',\n additive: true,\n better: 'lower',\n unpricedWhen: 'tokens',\n },\n },\n];\nconst countColumn = (count: { label: string; value: Record<string, unknown>; spans: boolean }): DashboardColumn => ({\n id: 'count',\n label: count.label,\n options: {\n type: 'value',\n value: count.value,\n format: 'count',\n emphasis: true,\n missing: 0,\n additive: true,\n better: 'higher',\n description: count.spans ? SPAN_DESCRIPTION : TRACE_DESCRIPTION,\n },\n});\nconst changeColumn: DashboardColumn = { id: 'change', label: '% Change', options: { type: 'change' } };\nconst TRACES = { label: 'Traces', value: { query: 'figures', measure: 'count' }, spans: false };\n\nconst tableOptions = (groupBy: string[], name: string, emptyMessage: string, extra: Record<string, unknown> = {}) => ({\n groupBy,\n defaultSort: { column: 'count', direction: 'desc' },\n pageSize: 13,\n emptyMessage,\n ariaLabel: `${name} breakdown`,\n ...extra,\n});\n\n/** Row clicks open traces in the row's project, plus the row's own name as `field`. */\nconst drill = (scope: 'org' | 'project', name: string, field: string, extra: Record<string, unknown> = {}) => ({\n rowDrilldown: { fields: { ...(scope === 'org' ? { projectId: 'projectId' } : {}), [name]: field }, ...extra },\n});\n\nconst scoped = (scope: 'org' | 'project', dimension: string) =>\n scope === 'org' ? ['projectId', dimension] : [dimension];\n\nconst ENTITIES = {\n Agents: { name: 'Agent', icon: 'agent', spanTypes: ['agent_run'] },\n Workflows: { name: 'Workflow', icon: 'workflow', spanTypes: ['workflow_run'] },\n Tools: { name: 'Tool', icon: 'tool', spanTypes: ['tool_call', 'mcp_tool_call'] },\n} as const;\n\n/** An entity's figures; agents and workflows count the traces they ran in, tools every call. */\nconst spanMeasures = (traces: boolean): SpanMeasure[] => [\n 'count',\n ...(traces ? (['countDistinct.traceId'] as const) : []),\n 'errorCount',\n 'errorRate',\n 'duration.p95',\n];\n\nconst entityView = (\n scope: 'org' | 'project',\n label: keyof typeof ENTITIES,\n description: string,\n emptyMessage: string,\n): DashboardWidgetView => {\n const { name, icon, spanTypes } = ENTITIES[label];\n const groupBy = scoped(scope, 'entityName');\n const usage = label === 'Agents';\n const traces = label !== 'Tools';\n return {\n label: `Breakdown by ${name.toLowerCase()}`,\n scope,\n description,\n queries: [\n {\n id: 'figures',\n source: 'spanAggregate',\n where:\n spanTypes.length === 1\n ? { op: 'eq', left: { path: 'spanType' }, right: { literal: spanTypes[0] } }\n : { op: 'in', value: { path: 'spanType' }, set: [...spanTypes] },\n groupBy,\n measures: spanMeasures(traces),\n limit: SPAN_LIMIT,\n compare: 'previousWindow',\n },\n ...(usage ? [usageTotals(groupBy, { entityType: 'agent' })] : []),\n ],\n columns: [\n nameColumn(name, { mark: { icon } }),\n projectColumn,\n ...errorColumns,\n ...(usage ? usageColumns : []),\n countColumn(\n traces\n ? { label: 'Traces', value: { query: 'figures', measure: 'countDistinct.traceId' }, spans: false }\n : { label: 'Spans', value: { query: 'figures', measure: 'count' }, spans: true },\n ),\n changeColumn,\n ],\n options: tableOptions(\n groupBy,\n name,\n emptyMessage,\n drill(scope, 'entityName', 'entityName', { spanTypes, keepEmpty: true }),\n ),\n };\n};\n\nconst traceColumns = (\n name: string,\n options: Record<string, unknown> = {},\n extra: DashboardColumn[] = [],\n): DashboardColumn[] => [\n nameColumn(name, options),\n projectColumn,\n ...extra,\n ...errorColumns,\n ...usageColumns,\n countColumn(TRACES),\n changeColumn,\n];\n\nconst environmentsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'environment');\n return {\n label: 'Breakdown by environment',\n scope,\n description: 'Traces, errors, latency and spend per environment.',\n queries: [\n {\n id: 'figures',\n source: 'traceAggregate',\n groupBy,\n measures: ERRORS,\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n },\n usageTotals(groupBy),\n ],\n columns: traceColumns('Environment', { unnamed: 'No environment' }),\n options: tableOptions(\n groupBy,\n 'Environment',\n 'No traces in this range.',\n drill(scope, 'environment', 'environment'),\n ),\n };\n};\n\nconst threadsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'threadId');\n const threads: DashboardQuery = {\n id: 'figures',\n source: 'traceAggregate',\n where: hasThread,\n groupBy: scope === 'org' ? ['projectId', 'threadId'] : ['resourceId', 'threadId'],\n measures: ERRORS,\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n };\n // Org-wide the second dimension is the project, so a third request names each thread's resource.\n const resources: DashboardQuery = {\n id: 'resources',\n source: 'traceAggregate',\n where: hasThread,\n groupBy: ['resourceId', 'threadId'],\n measures: ['count'],\n limit: TRACE_LIMIT,\n };\n const resourceColumn: DashboardColumn = {\n id: 'resource',\n label: 'Resource',\n options: {\n type: 'dimension',\n dimension: 'resourceId',\n query: scope === 'org' ? 'resources' : 'figures',\n joinOn: 'threadId',\n width: 'minmax(6rem,1fr)',\n },\n };\n return {\n label: 'Breakdown by thread',\n scope,\n description: 'Traces, errors, latency and spend per thread.',\n queries: [threads, usageTotals(groupBy), ...(scope === 'org' ? [resources] : [])],\n columns: traceColumns('Thread', {}, [resourceColumn]),\n options: tableOptions(groupBy, 'Thread', 'No traces with a thread in this range.', {\n hideUnnamed: true,\n dropped: false,\n ...drill(scope, 'threadId', 'threadId', { keepEmpty: true }),\n }),\n };\n};\n\nconst modelsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'provider').concat('model');\n return {\n label: 'Breakdown by model',\n scope,\n description: 'Model calls, tokens and spend per model.',\n queries: [\n {\n id: 'calls',\n source: 'metrics',\n request: 'breakdown',\n name: [INPUT],\n groupBy,\n aggregation: 'count',\n orderDirection: 'DESC',\n limit: 1000,\n compare: 'previousWindow',\n },\n usageTotals(groupBy),\n ],\n columns: [\n nameColumn('Model', { unnamed: 'Unknown model', mark: { providerDimension: 'provider' } }),\n projectColumn,\n ...usageColumns,\n countColumn({ label: 'Spans', value: { query: 'calls', field: 'value' }, spans: true }),\n changeColumn,\n ],\n options: tableOptions(groupBy, 'Model', 'No model usage in this range.', drill(scope, 'model', 'model')),\n };\n};\n\nconst scopedViews = (scope: 'org' | 'project'): DashboardWidgetView[] => [\n entityView(\n scope,\n 'Agents',\n 'Traces each agent ran in, nested runs included, with errors, latency and spend.',\n 'No agent runs in this range.',\n ),\n entityView(\n scope,\n 'Workflows',\n 'Traces each workflow ran in, nested runs included, with errors and latency.',\n 'No workflow runs in this range.',\n ),\n entityView(\n scope,\n 'Tools',\n 'Every tool call, MCP tools included, with errors and latency.',\n 'No tool calls in this range.',\n ),\n modelsView(scope),\n threadsView(scope),\n environmentsView(scope),\n];\n\nconst breakdownWidget: DashboardWidget = {\n id: 'breakdown',\n span: 12,\n kind: 'table',\n title: 'Breakdown',\n drilldown: { click: { page: 'traces' } },\n views: [\n {\n label: 'Breakdown by project',\n scope: 'org',\n description: 'Traces, errors, latency and spend per project.',\n queries: [\n {\n id: 'figures',\n source: 'traceAggregate',\n groupBy: ['projectId'],\n measures: [...ERRORS, 'countDistinct.resourceId', 'countDistinct.threadId'],\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n },\n usageTotals(['projectId']),\n ],\n columns: [\n nameColumn('Project', { as: 'project' }),\n ...errorColumns,\n ...usageColumns,\n countColumn(TRACES),\n changeColumn,\n ],\n options: tableOptions(['projectId'], 'Project', 'No traces in this range.', {\n openWhen: { minRows: 2 },\n rowDrilldown: { fields: { projectId: 'projectId' } },\n }),\n },\n ...scopedViews('org'),\n ...scopedViews('project'),\n ],\n};\n\n/** Freezes a value and everything it holds, so a shared definition can't be edited in place. */\nfunction deepFreeze<T>(value: T): T {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n for (const child of Object.values(value)) deepFreeze(child);\n Object.freeze(value);\n }\n return value;\n}\n\n/**\n * The Metrics page as a dashboard: four charts in two rows (usage and health first), then the\n * breakdown of who caused them. Org and project pages share it; scope-tagged parts pick per page.\n * It is frozen: copy it (`structuredClone(METRICS_DASHBOARD)`) before customising.\n */\nexport const METRICS_DASHBOARD: DashboardDefinition = deepFreeze({\n schemaVersion: 1,\n rows: [\n { widgets: [tokenUsageWidget, agentRunsWidget] },\n { widgets: [latencyWidget, distinctIdsWidget] },\n { widgets: [breakdownWidget] },\n ],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"metrics-dashboard.es.js","names":[],"sources":["../../../src/domains/dashboards/metrics-dashboard.ts"],"sourcesContent":["import type {\n DashboardColumn,\n DashboardDefinition,\n DashboardDrilldownTarget,\n DashboardQuery,\n DashboardWidget,\n DashboardWidgetView,\n} from '@mastra/client-js';\n\nconst INPUT = 'mastra_model_total_input_tokens';\nconst OUTPUT = 'mastra_model_total_output_tokens';\nconst CACHE_READ = 'mastra_model_input_cache_read_tokens';\nconst AGENT_DURATION = 'mastra_agent_duration_ms';\n\nconst sumSeries = (id: string, name: string): DashboardQuery => ({\n id,\n source: 'metrics',\n request: 'timeSeries',\n name: [name],\n aggregation: 'sum',\n});\n\nconst agentRunsByStatus: DashboardQuery = {\n id: 'runs',\n source: 'metrics',\n request: 'timeSeries',\n name: [AGENT_DURATION],\n aggregation: 'count',\n groupBy: ['status'],\n};\n\n// Runs report status `ok` or `error` (observability/mastra auto-extract); the card also counts `failed`.\nconst FAILED = ['error', 'failed'];\nconst completedRuns = { query: 'runs', notGroups: FAILED };\nconst failedRuns = { query: 'runs', groups: FAILED };\nconst agentRunsTraces: DashboardDrilldownTarget = {\n page: 'traces',\n filters: [{ fieldId: 'rootEntityType', value: 'agent' }],\n};\n\nconst tokenUsageWidget: DashboardWidget = {\n id: 'token-usage',\n span: 6,\n kind: 'timeseries',\n title: 'Token usage',\n drilldown: { action: { page: 'traces' }, click: { page: 'traces' } },\n views: [\n {\n label: 'Token usage',\n description: 'Input, cache reads and output.',\n queries: [sumSeries('input', INPUT), sumSeries('output', OUTPUT), sumSeries('cacheRead', CACHE_READ)],\n options: {\n chart: 'stackedBar',\n format: 'count',\n xLabels: 'edges',\n series: [\n {\n dataKey: 'input',\n label: 'Input',\n color: 'green',\n value: { max: [{ minus: [{ query: 'input' }, { query: 'cacheRead' }] }, { const: 0 }] },\n },\n { dataKey: 'cacheRead', label: 'Cache read', color: 'violet', value: { query: 'cacheRead' } },\n { dataKey: 'output', label: 'Output', color: 'sky', value: { query: 'output' } },\n ],\n total: { value: 'total' },\n emptyMessage: 'No model calls in this range.',\n },\n },\n {\n label: 'Model cost',\n description: 'Estimated model spend.',\n // Cache reads aren't charted here, but fetching them keeps their answer, so going back to\n // Token usage sends nothing, as the card's one request for both views does.\n queries: [sumSeries('input', INPUT), sumSeries('output', OUTPUT), sumSeries('cacheRead', CACHE_READ)],\n options: {\n chart: 'stackedBar',\n format: 'usd',\n xLabels: 'edges',\n series: [\n {\n dataKey: 'cost',\n label: 'Cost',\n color: 'green',\n value: {\n sum: [\n { query: 'input', field: 'estimatedCost' },\n { query: 'output', field: 'estimatedCost' },\n ],\n },\n },\n ],\n total: { value: 'total' },\n emptyMessage: 'No model calls in this range.',\n },\n },\n ],\n};\n\nconst failedAgentRuns = [\n { fieldId: 'rootEntityType', value: 'agent' },\n { fieldId: 'status', value: 'error' },\n];\n\n/** Agent runs, with Failure rate in its title menu, as the Agent runs card. */\nconst agentRunsWidget: DashboardWidget = {\n id: 'agent-runs',\n span: 6,\n kind: 'timeseries',\n title: 'Agent runs',\n views: [\n {\n label: 'Agent runs',\n description: 'Completed and failed runs.',\n drilldown: { click: agentRunsTraces },\n queries: [agentRunsByStatus],\n options: {\n chart: 'stackedBar',\n format: 'count',\n axis: false,\n xLabels: 'edges',\n series: [\n { dataKey: 'completed', label: 'Completed', color: 'green', value: completedRuns },\n { dataKey: 'failed', label: 'Failed', color: 'error', value: failedRuns },\n ],\n total: { value: 'total' },\n emptyMessage: 'No agent runs in this range.',\n },\n },\n {\n label: 'Failure rate',\n description: 'Share of agent runs that failed.',\n drilldown: {\n action: { page: 'logs', filters: failedAgentRuns },\n click: { page: 'traces', filters: failedAgentRuns },\n },\n queries: [agentRunsByStatus],\n options: {\n chart: 'line',\n format: 'percent',\n xLabels: 'edges',\n flatYDomain: [0, 1],\n series: [\n {\n dataKey: 'failureRate',\n label: 'Failed runs',\n color: 'error',\n value: {\n coalesce: [{ ratio: { of: failedRuns, over: { sum: [completedRuns, failedRuns] } } }, { const: 0 }],\n },\n },\n ],\n total: {\n value: {\n coalesce: [{ ratio: { of: failedRuns, over: { sum: [completedRuns, failedRuns] } } }, { const: 0 }],\n },\n },\n emptyWhenZero: { sum: [completedRuns, failedRuns] },\n emptyMessage: 'No agent runs in this range.',\n },\n },\n ],\n};\n\nconst latencyView = (label: string, metric: string, rootEntityType: string, noun: string): DashboardWidgetView => ({\n label,\n queries: [\n {\n id: 'latency',\n source: 'metrics',\n request: 'percentiles',\n name: metric,\n percentiles: [0.5, 0.95, 0.99],\n } satisfies DashboardQuery,\n ],\n drilldown: { action: { page: 'traces', filters: [{ fieldId: 'rootEntityType', value: rootEntityType }] } },\n options: {\n chart: 'line',\n format: 'duration',\n buckets: 'api',\n xLabels: 'edges',\n series: [\n { dataKey: 'p50', label: 'P50', color: 'sky', value: { query: 'latency', percentile: 0.5 }, round: true },\n {\n dataKey: 'p95',\n label: 'P95',\n color: 'green',\n emphasis: true,\n value: { query: 'latency', percentile: 0.95 },\n round: true,\n },\n { dataKey: 'p99', label: 'P99', color: 'violet', value: { query: 'latency', percentile: 0.99 }, round: true },\n ],\n total: { value: { peak: 'p95' } },\n emptyMessage: `No ${noun} in this range.`,\n },\n});\n\nconst latencyWidget: DashboardWidget = {\n id: 'latency',\n span: 6,\n kind: 'timeseries',\n title: 'Latency',\n description: 'Duration percentiles.',\n drilldown: { click: { page: 'traces' } },\n views: [\n latencyView('Agent latency', 'mastra_agent_duration_ms', 'agent', 'agent runs'),\n latencyView('Workflow latency', 'mastra_workflow_duration_ms', 'workflow_run', 'workflow runs'),\n latencyView('Tool latency', 'mastra_tool_duration_ms', 'tool', 'tool calls'),\n ],\n};\n\nconst DISTINCT_IDS = [\n ['countDistinct.resourceId', 'resources', 'Resources', 'sky'],\n ['countDistinct.threadId', 'threads', 'Threads', 'green'],\n ['countDistinct.userId', 'users', 'Users', 'violet'],\n ['countDistinct.sessionId', 'sessions', 'Sessions', 'teal'],\n] as const;\nconst distinctMeasures = DISTINCT_IDS.map(([measure]) => measure);\n\nconst distinctIdsWidget: DashboardWidget = {\n id: 'distinct-ids',\n span: 6,\n kind: 'timeseries',\n title: 'Resources and threads',\n description: 'Unique ids on traces; users and sessions only when set.',\n drilldown: { click: { page: 'traces' } },\n views: [\n {\n queries: [\n { id: 'buckets', source: 'traceAggregate', measures: distinctMeasures, limit: 10 },\n { id: 'totals', source: 'traceAggregate', measures: distinctMeasures },\n ],\n options: {\n chart: 'line',\n format: 'count',\n xLabels: 'edges',\n totals: ['totals'],\n hideEmpty: true,\n emphasizeFirst: true,\n series: DISTINCT_IDS.map(([measure, dataKey, label, color]) => ({\n dataKey,\n label,\n color,\n value: { query: 'buckets', measure },\n rangeTotal: { query: 'totals', measure },\n })),\n emptyMessage: 'No traces in this range set a resource, thread, user or session id.',\n },\n },\n ],\n};\n\nconst USAGE = [INPUT, OUTPUT];\nconst TRACE_LIMIT = 1000;\nconst SPAN_LIMIT = 500;\ntype TraceMeasure = NonNullable<Extract<DashboardQuery, { source: 'traceAggregate' }>['measures']>[number];\ntype SpanMeasure = NonNullable<Extract<DashboardQuery, { source: 'spanAggregate' }>['measures']>[number];\nconst ERRORS: TraceMeasure[] = ['count', 'errorRate', 'duration.p95'];\n/** Traces with a thread. */\nconst hasThread = { op: 'exists', path: 'threadId' } as const;\n\nconst usageTotals = (groupBy: string[], filters?: Record<string, string>): DashboardQuery => ({\n id: 'usage',\n source: 'metrics',\n request: 'breakdown',\n name: USAGE,\n groupBy,\n aggregation: 'sum',\n orderDirection: 'DESC',\n limit: 1000,\n ...(filters ? { filters } : {}),\n compare: 'previousWindow',\n});\n\nconst TRACE_DESCRIPTION = 'A trace is one end-to-end request, with every step it took.';\nconst SPAN_DESCRIPTION =\n 'A span is one step inside a trace, such as a tool call or a model call. One trace can have many.';\n\nconst nameColumn = (label: string, options: Record<string, unknown> = {}): DashboardColumn => ({\n id: 'name',\n label,\n options: { type: 'name', width: 'minmax(12rem,3fr)', ...options },\n});\nconst projectColumn: DashboardColumn = {\n id: 'project',\n label: 'Project',\n scope: 'org',\n options: { type: 'dimension', dimension: 'projectId', as: 'project', width: 'minmax(8rem,2fr)' },\n};\nconst errorColumns: DashboardColumn[] = [\n {\n id: 'errorRate',\n label: 'Errors',\n options: { type: 'value', value: { query: 'figures', measure: 'errorRate' }, format: 'percent', better: 'lower' },\n },\n {\n id: 'p95',\n label: 'P95 latency',\n options: {\n type: 'value',\n value: { query: 'figures', measure: 'duration.p95' },\n format: 'duration',\n better: 'lower',\n },\n },\n];\nconst usageColumns: DashboardColumn[] = [\n {\n id: 'tokens',\n label: 'Tokens',\n options: {\n type: 'value',\n value: { query: 'usage', field: 'value' },\n format: 'count',\n missing: 0,\n additive: true,\n better: 'lower',\n },\n },\n {\n id: 'cost',\n label: 'Cost',\n options: {\n type: 'value',\n value: { query: 'usage', field: 'estimatedCost' },\n format: 'usd',\n additive: true,\n better: 'lower',\n unpricedWhen: 'tokens',\n },\n },\n];\nconst countColumn = (count: { label: string; value: Record<string, unknown>; spans: boolean }): DashboardColumn => ({\n id: 'count',\n label: count.label,\n options: {\n type: 'value',\n value: count.value,\n format: 'count',\n emphasis: true,\n missing: 0,\n additive: true,\n better: 'higher',\n description: count.spans ? SPAN_DESCRIPTION : TRACE_DESCRIPTION,\n },\n});\nconst changeColumn: DashboardColumn = { id: 'change', label: '% Change', options: { type: 'change' } };\nconst TRACES = { label: 'Traces', value: { query: 'figures', measure: 'count' }, spans: false };\n\nconst tableOptions = (groupBy: string[], name: string, emptyMessage: string, extra: Record<string, unknown> = {}) => ({\n groupBy,\n defaultSort: { column: 'count', direction: 'desc' },\n pageSize: 10,\n emptyMessage,\n ariaLabel: `${name} breakdown`,\n ...extra,\n});\n\n/** Row clicks open traces in the row's project, plus the row's own name as `field`. */\nconst drill = (scope: 'org' | 'project', name: string, field: string, extra: Record<string, unknown> = {}) => ({\n rowDrilldown: { fields: { ...(scope === 'org' ? { projectId: 'projectId' } : {}), [name]: field }, ...extra },\n});\n\nconst scoped = (scope: 'org' | 'project', dimension: string) =>\n scope === 'org' ? ['projectId', dimension] : [dimension];\n\nconst ENTITIES = {\n Agents: { name: 'Agent', icon: 'agent', spanTypes: ['agent_run'] },\n Workflows: { name: 'Workflow', icon: 'workflow', spanTypes: ['workflow_run'] },\n Tools: { name: 'Tool', icon: 'tool', spanTypes: ['tool_call', 'mcp_tool_call'] },\n} as const;\n\n/** An entity's figures; agents and workflows count the traces they ran in, tools every call. */\nconst spanMeasures = (traces: boolean): SpanMeasure[] => [\n 'count',\n ...(traces ? (['countDistinct.traceId'] as const) : []),\n 'errorCount',\n 'errorRate',\n 'duration.p95',\n];\n\nconst entityView = (\n scope: 'org' | 'project',\n label: keyof typeof ENTITIES,\n description: string,\n emptyMessage: string,\n): DashboardWidgetView => {\n const { name, icon, spanTypes } = ENTITIES[label];\n const groupBy = scoped(scope, 'entityName');\n const usage = label === 'Agents';\n const traces = label !== 'Tools';\n return {\n label: `Breakdown by ${name.toLowerCase()}`,\n scope,\n description,\n queries: [\n {\n id: 'figures',\n source: 'spanAggregate',\n where:\n spanTypes.length === 1\n ? { op: 'eq', left: { path: 'spanType' }, right: { literal: spanTypes[0] } }\n : { op: 'in', value: { path: 'spanType' }, set: [...spanTypes] },\n groupBy,\n measures: spanMeasures(traces),\n limit: SPAN_LIMIT,\n compare: 'previousWindow',\n },\n ...(usage ? [usageTotals(groupBy, { entityType: 'agent' })] : []),\n ],\n columns: [\n nameColumn(name, { mark: { icon } }),\n projectColumn,\n ...errorColumns,\n ...(usage ? usageColumns : []),\n countColumn(\n traces\n ? { label: 'Traces', value: { query: 'figures', measure: 'countDistinct.traceId' }, spans: false }\n : { label: 'Spans', value: { query: 'figures', measure: 'count' }, spans: true },\n ),\n changeColumn,\n ],\n options: tableOptions(\n groupBy,\n name,\n emptyMessage,\n drill(scope, 'entityName', 'entityName', { spanTypes, keepEmpty: true }),\n ),\n };\n};\n\nconst traceColumns = (\n name: string,\n options: Record<string, unknown> = {},\n extra: DashboardColumn[] = [],\n): DashboardColumn[] => [\n nameColumn(name, options),\n projectColumn,\n ...extra,\n ...errorColumns,\n ...usageColumns,\n countColumn(TRACES),\n changeColumn,\n];\n\nconst environmentsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'environment');\n return {\n label: 'Breakdown by environment',\n scope,\n description: 'Traces, errors, latency and spend per environment.',\n queries: [\n {\n id: 'figures',\n source: 'traceAggregate',\n groupBy,\n measures: ERRORS,\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n },\n usageTotals(groupBy),\n ],\n columns: traceColumns('Environment', { unnamed: 'No environment' }),\n options: tableOptions(\n groupBy,\n 'Environment',\n 'No traces in this range.',\n drill(scope, 'environment', 'environment'),\n ),\n };\n};\n\nconst threadsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'threadId');\n const threads: DashboardQuery = {\n id: 'figures',\n source: 'traceAggregate',\n where: hasThread,\n groupBy: scope === 'org' ? ['projectId', 'threadId'] : ['resourceId', 'threadId'],\n measures: ERRORS,\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n };\n // Org-wide the second dimension is the project, so a third request names each thread's resource.\n const resources: DashboardQuery = {\n id: 'resources',\n source: 'traceAggregate',\n where: hasThread,\n groupBy: ['resourceId', 'threadId'],\n measures: ['count'],\n limit: TRACE_LIMIT,\n };\n const resourceColumn: DashboardColumn = {\n id: 'resource',\n label: 'Resource',\n options: {\n type: 'dimension',\n dimension: 'resourceId',\n query: scope === 'org' ? 'resources' : 'figures',\n joinOn: 'threadId',\n width: 'minmax(6rem,1fr)',\n },\n };\n return {\n label: 'Breakdown by thread',\n scope,\n description: 'Traces, errors, latency and spend per thread.',\n queries: [threads, usageTotals(groupBy), ...(scope === 'org' ? [resources] : [])],\n columns: traceColumns('Thread', {}, [resourceColumn]),\n options: tableOptions(groupBy, 'Thread', 'No traces with a thread in this range.', {\n hideUnnamed: true,\n dropped: false,\n ...drill(scope, 'threadId', 'threadId', { keepEmpty: true }),\n }),\n };\n};\n\nconst modelsView = (scope: 'org' | 'project'): DashboardWidgetView => {\n const groupBy = scoped(scope, 'provider').concat('model');\n return {\n label: 'Breakdown by model',\n scope,\n description: 'Model calls, tokens and spend per model.',\n queries: [\n {\n id: 'calls',\n source: 'metrics',\n request: 'breakdown',\n name: [INPUT],\n groupBy,\n aggregation: 'count',\n orderDirection: 'DESC',\n limit: 1000,\n compare: 'previousWindow',\n },\n usageTotals(groupBy),\n ],\n columns: [\n nameColumn('Model', { unnamed: 'Unknown model', mark: { providerDimension: 'provider' } }),\n projectColumn,\n ...usageColumns,\n countColumn({ label: 'Spans', value: { query: 'calls', field: 'value' }, spans: true }),\n changeColumn,\n ],\n options: tableOptions(groupBy, 'Model', 'No model usage in this range.', drill(scope, 'model', 'model')),\n };\n};\n\nconst scopedViews = (scope: 'org' | 'project'): DashboardWidgetView[] => [\n entityView(\n scope,\n 'Agents',\n 'Traces each agent ran in, nested runs included, with errors, latency and spend.',\n 'No agent runs in this range.',\n ),\n entityView(\n scope,\n 'Workflows',\n 'Traces each workflow ran in, nested runs included, with errors and latency.',\n 'No workflow runs in this range.',\n ),\n entityView(\n scope,\n 'Tools',\n 'Every tool call, MCP tools included, with errors and latency.',\n 'No tool calls in this range.',\n ),\n modelsView(scope),\n threadsView(scope),\n environmentsView(scope),\n];\n\nconst breakdownWidget: DashboardWidget = {\n id: 'breakdown',\n span: 12,\n kind: 'table',\n title: 'Breakdown',\n drilldown: { click: { page: 'traces' } },\n views: [\n {\n label: 'Breakdown by project',\n scope: 'org',\n description: 'Traces, errors, latency and spend per project.',\n queries: [\n {\n id: 'figures',\n source: 'traceAggregate',\n groupBy: ['projectId'],\n measures: [...ERRORS, 'countDistinct.resourceId', 'countDistinct.threadId'],\n limit: TRACE_LIMIT,\n compare: 'previousWindow',\n },\n usageTotals(['projectId']),\n ],\n columns: [\n nameColumn('Project', { as: 'project' }),\n ...errorColumns,\n ...usageColumns,\n countColumn(TRACES),\n changeColumn,\n ],\n options: tableOptions(['projectId'], 'Project', 'No traces in this range.', {\n openWhen: { minRows: 2 },\n rowDrilldown: { fields: { projectId: 'projectId' } },\n }),\n },\n ...scopedViews('org'),\n ...scopedViews('project'),\n ],\n};\n\n/** Freezes a value and everything it holds, so a shared definition can't be edited in place. */\nfunction deepFreeze<T>(value: T): T {\n if (value && typeof value === 'object' && !Object.isFrozen(value)) {\n for (const child of Object.values(value)) deepFreeze(child);\n Object.freeze(value);\n }\n return value;\n}\n\n/**\n * The Metrics page as a dashboard: four charts in two rows (usage and health first), then the\n * breakdown of who caused them. Org and project pages share it; scope-tagged parts pick per page.\n * It is frozen: copy it (`structuredClone(METRICS_DASHBOARD)`) before customising.\n */\nexport const METRICS_DASHBOARD: DashboardDefinition = deepFreeze({\n schemaVersion: 1,\n rows: [\n { widgets: [tokenUsageWidget, agentRunsWidget] },\n { widgets: [latencyWidget, distinctIdsWidget] },\n { widgets: [breakdownWidget] },\n ],\n});\n"],"mappings":"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"}
@@ -6,7 +6,7 @@ const require_select = require("../../../select-Dg8L5ROX.cjs");
6
6
  const require_Txt = require("../../../Txt-BnoSqxKE.cjs");
7
7
  const require_toast_api = require("../../../toast-api-qtkOucy2.cjs");
8
8
  const require_CodeEditor = require("../../../CodeEditor-CLzs0yVc.cjs");
9
- const require_DataPanel = require("../../../DataPanel-BwB1Oifd.cjs");
9
+ const require_DataPanel = require("../../../DataPanel-Coc9h35I.cjs");
10
10
  const require_components_Field = require("../../../components/Field.cjs.js");
11
11
  const require_components_Form = require("../../../components/Form.cjs.js");
12
12
  let react = require("react");
@@ -5,7 +5,7 @@ import { i as SelectItem, n as SelectContent, o as SelectTrigger, s as SelectVal
5
5
  import { t as Txt } from "../../../Txt-BM6TVV_c.js";
6
6
  import { t as toast } from "../../../toast-api-D_rrRhNG.js";
7
7
  import { t as CodeEditor } from "../../../CodeEditor-COnz9c6B.js";
8
- import { t as DataPanel } from "../../../DataPanel-Bv4M17xO.js";
8
+ import { t as DataPanel } from "../../../DataPanel-IgB9D5PO.js";
9
9
  import { Field, FieldLabel } from "../../../components/Field.es.js";
10
10
  import { Form } from "../../../components/Form.es.js";
11
11
  import { useEffect, useRef, useState } from "react";
@@ -4,7 +4,7 @@ const require_Button = require("../../../Button-DLcMcuUL.cjs");
4
4
  const require_Txt = require("../../../Txt-BnoSqxKE.cjs");
5
5
  const require_copy_button = require("../../../copy-button-DJAQ6_3o.cjs");
6
6
  const require_buttons_group = require("../../../buttons-group-Dc6R7YSs.cjs");
7
- const require_DataPanel = require("../../../DataPanel-BwB1Oifd.cjs");
7
+ const require_DataPanel = require("../../../DataPanel-Coc9h35I.cjs");
8
8
  const require_DataKeysAndValues = require("../../../DataKeysAndValues-DsH6AbAo.cjs");
9
9
  let react = require("react");
10
10
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -3,7 +3,7 @@ import { t as Button } from "../../../Button-CLXTbAY8.js";
3
3
  import { t as Txt } from "../../../Txt-BM6TVV_c.js";
4
4
  import { t as CopyButton } from "../../../copy-button-BXrbevLn.js";
5
5
  import { t as ButtonsGroup } from "../../../buttons-group-DkFlnMiL.js";
6
- import { t as DataPanel } from "../../../DataPanel-Bv4M17xO.js";
6
+ import { t as DataPanel } from "../../../DataPanel-IgB9D5PO.js";
7
7
  import { t as DataKeysAndValues } from "../../../DataKeysAndValues-PwOmGxyp.js";
8
8
  import { Fragment } from "react";
9
9
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_observability_saved_views = require("../../../observability-saved-views-BAzxxoAr.cjs");
2
+ const require_observability_saved_views = require("../../../observability-saved-views-Daizz4tU.cjs");
3
3
  let react_jsx_runtime = require("react/jsx-runtime");
4
4
  // src/domains/logs/components/logs-saved-views.tsx
5
5
  /** Saved views of the logs page, placed by the host next to `LogsToolbar`. Renders nothing without a `SavedViewsProvider`. */
@@ -1,4 +1,4 @@
1
- import { t as ObservabilitySavedViews } from "../../../observability-saved-views-BBam8Fr5.js";
1
+ import { t as ObservabilitySavedViews } from "../../../observability-saved-views-CjKTEp1V.js";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  // src/domains/logs/components/logs-saved-views.tsx
4
4
  /** Saved views of the logs page, placed by the host next to `LogsToolbar`. Renders nothing without a `SavedViewsProvider`. */
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_utils = require("../../../utils-uDc1ofX1.cjs");
3
- const require_property_filter_applied = require("../../../property-filter-applied-BCeRLcXb.cjs");
3
+ const require_property_filter_applied = require("../../../property-filter-applied-BkkIObRq.cjs");
4
4
  let react_jsx_runtime = require("react/jsx-runtime");
5
5
  // src/domains/logs/components/logs-toolbar.tsx
6
6
  function LogsToolbar({ onClear, onRemoveAll, onSave, onRemoveSaved, isLoading, filterFields, filterTokens, onFilterTokensChange, autoFocusFilterFieldId }) {
@@ -1,5 +1,5 @@
1
1
  import { t as cn } from "../../../utils-DQx8TpNT.js";
2
- import { r as PropertyFilterActions, t as PropertyFilterApplied } from "../../../property-filter-applied-p3dTTDdb.js";
2
+ import { r as PropertyFilterActions, t as PropertyFilterApplied } from "../../../property-filter-applied--U5EZdaA.js";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  // src/domains/logs/components/logs-toolbar.tsx
5
5
  function LogsToolbar({ onClear, onRemoveAll, onSave, onRemoveSaved, isLoading, filterFields, filterTokens, onFilterTokensChange, autoFocusFilterFieldId }) {
@@ -9,7 +9,7 @@ const require_domains_metrics_components_breakdown_breakdown_change_description
9
9
  const require_domains_metrics_components_breakdown_breakdown_figure = require("./breakdown-figure.cjs.js");
10
10
  const require_domains_metrics_components_breakdown_breakdown_text = require("./breakdown-text.cjs.js");
11
11
  const require_domains_metrics_hooks_use_metrics_scope = require("../../hooks/use-metrics-scope.cjs.js");
12
- const require_MetricsTable = require("../../../../MetricsTable-D-aZf3dk.cjs");
12
+ const require_MetricsTable = require("../../../../MetricsTable-BSl81oNe.cjs");
13
13
  const require_domains_metrics_components_breakdown_breakdown_change_cell = require("./breakdown-change-cell.cjs.js");
14
14
  const require_domains_metrics_components_breakdown_breakdown_cost_cell = require("./breakdown-cost-cell.cjs.js");
15
15
  const require_domains_metrics_components_breakdown_breakdown_frame = require("./breakdown-frame.cjs.js");
@@ -17,7 +17,7 @@ const require_domains_metrics_components_breakdown_breakdown_row_name = require(
17
17
  let react = require("react");
18
18
  let react_jsx_runtime = require("react/jsx-runtime");
19
19
  // src/domains/metrics/components/breakdown/breakdown-table.tsx
20
- var PAGE_SIZE = 13;
20
+ var PAGE_SIZE = 10;
21
21
  /** Busiest first; where a third click on a column's header returns to. */
22
22
  var DEFAULT_SORT = {
23
23
  column: "count",
@@ -1 +1 @@
1
- {"version":3,"file":"breakdown-table.cjs.js","names":["useMetricsScope","useState","isChangeMetric","BreakdownFrame","ChartCardError","hasErrors","showsProject","buildBreakdownRows","threadResources","previousFigures","tableRows","volumeLabel","rowChange","BreakdownRowName","BreakdownText","BreakdownFigure","formatPercent","formatDuration","formatCount","BreakdownCostCell","countDescription","BreakdownChangeDescription","comparedLabel","BreakdownChangeCell","ChartArea","MetricsTable","drilldownFor","Txt"],"sources":["../../../../../src/domains/metrics/components/breakdown/breakdown-table.tsx"],"sourcesContent":["import type { AggregateTracesResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useState } from 'react';\nimport { useMetricsScope } from '../../hooks/use-metrics-scope';\nimport type { useMetricsUsageTotals } from '../../hooks/use-metrics-usage-totals';\nimport { buildBreakdownRows, hasErrors, previousFigures, rowChange, threadResources } from '../../lib/breakdown';\nimport type { BreakdownRow, BreakdownTab, ChangeMetric } from '../../lib/breakdown';\nimport {\n DASH,\n comparedLabel,\n countDescription,\n drilldownFor,\n isChangeMetric,\n showsProject,\n tableRows,\n volumeLabel,\n} from '../../lib/breakdown-table';\nimport { formatCount, formatDuration, formatPercent } from '../../lib/chart-format';\nimport { ChartArea } from '../chart-area';\nimport { ChartCardError } from '../chart-card-error';\nimport { BreakdownChangeCell } from './breakdown-change-cell';\nimport { BreakdownChangeDescription } from './breakdown-change-description';\nimport { BreakdownCostCell } from './breakdown-cost-cell';\nimport { BreakdownFigure } from './breakdown-figure';\nimport { BreakdownFrame } from './breakdown-frame';\nimport type { BreakdownFrameProps } from './breakdown-frame';\nimport { BreakdownRowName } from './breakdown-row-name';\nimport { BreakdownText } from './breakdown-text';\nimport { MetricsTable } from '@/ds/components/MetricsTable';\nimport type { MetricsTableColumn, MetricsTableSort } from '@/ds/components/MetricsTable';\nimport { Txt } from '@/ds/components/Txt';\n\ntype UsageTotals = ReturnType<typeof useMetricsUsageTotals>;\n\nconst PAGE_SIZE = 13;\n\n/** Busiest first; where a third click on a column's header returns to. */\nconst DEFAULT_SORT: MetricsTableSort = { column: 'count', direction: 'desc' };\n\n/** The first column's header: what each row is. */\nconst NAME_HEADER: Record<BreakdownTab, string> = {\n projects: 'Project',\n agents: 'Agent',\n workflows: 'Workflow',\n tools: 'Tool',\n models: 'Model',\n threads: 'Thread',\n environments: 'Environment',\n};\n\nconst EMPTY: Record<BreakdownTab, string> = {\n projects: 'No traces in this range.',\n agents: 'No agent runs in this range.',\n workflows: 'No workflow runs in this range.',\n tools: 'No tool calls in this range.',\n models: 'No model usage in this range.',\n threads: 'No traces with a thread in this range.',\n environments: 'No traces in this range.',\n};\n\nexport type BreakdownTableProps = BreakdownFrameProps & {\n tab: BreakdownTab;\n groupBy: string[];\n window: { start: Date; end: Date };\n aggregate?: UseQueryResult<AggregateTracesResponse>;\n /** Tokens and cost per row. */\n totals?: UsageTotals;\n /** Model spans per row (Models tab). */\n spans?: UsageTotals;\n /** Rows naming each thread's resource (Threads tab). */\n resources?: UseQueryResult<AggregateTracesResponse>;\n previousAggregate?: UseQueryResult<AggregateTracesResponse>;\n previousUsage?: UsageTotals;\n previousSpans?: UsageTotals;\n /** The server's row cap, named when it truncates. */\n limit: number;\n};\n\n/** One tab's sortable table, with % Change against the previous window. */\nexport function BreakdownTable({\n tab,\n groupBy,\n window,\n aggregate,\n totals,\n spans,\n resources,\n previousAggregate,\n previousUsage,\n previousSpans,\n limit,\n ...frame\n}: BreakdownTableProps) {\n const scope = useMetricsScope();\n const [sort, setSort] = useState<MetricsTableSort>(DEFAULT_SORT);\n const [metric, setMetric] = useState<ChangeMetric>('count');\n const onSortChange = (next = DEFAULT_SORT) => {\n setSort(next);\n if (isChangeMetric(next.column)) setMetric(next.column);\n };\n\n const current = [aggregate, totals, spans].filter(q => q !== undefined);\n if (current.some(q => q.isError)) {\n return (\n <BreakdownFrame {...frame} tab={tab}>\n <ChartCardError onRetry={() => current.forEach(q => q.isError && void q.refetch())} />\n </BreakdownFrame>\n );\n }\n\n const isLoading = current.some(q => q.isLoading);\n const errors = hasErrors(tab);\n const usage = totals !== undefined;\n const project = showsProject(tab, frame.byProject);\n const truncated = aggregate?.data?.truncated === true;\n const built = isLoading\n ? []\n : buildBreakdownRows({\n tab,\n groupBy,\n aggregateRows: aggregate?.data?.rows,\n usageGroups: totals?.data?.groups,\n spanGroups: spans?.data?.groups,\n // The resource is a nicety: the table doesn't wait for it, and shows a dash without it.\n resources: resources?.data ? threadResources(resources.data.rows) : undefined,\n });\n // The previous window never holds the table up: until it answers, or if it fails, Change shows a dash.\n const previousSettled = [previousAggregate, previousUsage, previousSpans].every(\n q => !q || (!q.isLoading && !q.isError),\n );\n const previous =\n previousSettled && !isLoading\n ? previousFigures({\n tab,\n groupBy,\n aggregateRows: previousAggregate?.data?.rows,\n usageGroups: previousUsage?.data?.groups,\n spanGroups: previousSpans?.data?.groups,\n })\n : undefined;\n const rows = tableRows({ tab, built, previous, truncated, groupBy, usage });\n const volume = volumeLabel(tab);\n\n const changeOf = (row: BreakdownRow) => (previous ? rowChange(row, previous.get(row.key), metric) : undefined);\n const projectName = (row: BreakdownRow) => {\n if (!row.projectId) return DASH;\n return scope.projectLabel?.(row.projectId) ?? row.projectId;\n };\n\n const nameColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'name',\n header: NAME_HEADER[tab],\n width: 'minmax(12rem,3fr)',\n cell: row => <BreakdownRowName tab={tab} row={row} />,\n };\n const projectColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'project',\n header: 'Project',\n width: 'minmax(8rem,2fr)',\n cell: row => <BreakdownText text={projectName(row)} />,\n };\n const resourceColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'resource',\n header: 'Resource',\n width: 'minmax(6rem,1fr)',\n cell: row => <BreakdownText text={row.resource ?? DASH} />,\n };\n const errorColumns: MetricsTableColumn<BreakdownRow>[] = [\n {\n id: 'errorRate',\n header: 'Errors',\n align: 'end',\n sortValue: row => row.errorRate,\n cell: row => (\n <BreakdownFigure muted>{row.errorRate === undefined ? DASH : formatPercent(row.errorRate)}</BreakdownFigure>\n ),\n },\n {\n id: 'p95',\n header: 'P95 latency',\n align: 'end',\n sortValue: row => row.p95,\n cell: row => <BreakdownFigure muted>{row.p95 === undefined ? DASH : formatDuration(row.p95)}</BreakdownFigure>,\n },\n ];\n const usageColumns: MetricsTableColumn<BreakdownRow>[] = [\n {\n id: 'tokens',\n header: 'Tokens',\n align: 'end',\n sortValue: row => row.tokens,\n cell: row => <BreakdownFigure muted>{row.tokens === undefined ? DASH : formatCount(row.tokens)}</BreakdownFigure>,\n },\n {\n id: 'cost',\n header: 'Cost',\n align: 'end',\n sortValue: row => row.cost,\n cell: row => (\n <BreakdownFigure muted>\n <BreakdownCostCell row={row} />\n </BreakdownFigure>\n ),\n },\n ];\n const countColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'count',\n header: volume,\n align: 'end',\n description: countDescription(tab),\n sortValue: row => row.count,\n cell: row => <BreakdownFigure>{formatCount(row.count)}</BreakdownFigure>,\n };\n const changeColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'change',\n header: '% Change',\n align: 'end',\n description: <BreakdownChangeDescription window={window} label={comparedLabel(tab, metric)} />,\n // Sorted by the change shown: biggest rise first, biggest fall first the other way. New rows\n // have no change to rank, so they sort last.\n sortValue: row => changeOf(row)?.change,\n cell: row => (\n <BreakdownFigure>\n <BreakdownChangeCell change={changeOf(row)} metric={metric} />\n </BreakdownFigure>\n ),\n };\n const columns = [\n nameColumn,\n ...(project ? [projectColumn] : []),\n ...(tab === 'threads' ? [resourceColumn] : []),\n ...(errors ? errorColumns : []),\n ...(usage ? usageColumns : []),\n countColumn,\n changeColumn,\n ];\n\n return (\n <BreakdownFrame {...frame} tab={tab} isUpdating={aggregate?.isPlaceholderData}>\n <ChartArea>\n <MetricsTable\n key={tab}\n aria-label={`${NAME_HEADER[tab]} breakdown`}\n columns={columns}\n rows={rows}\n getRowKey={row => row.key}\n sort={sort}\n defaultSort={DEFAULT_SORT}\n onSortChange={onSortChange}\n onRowClick={frame.onRowClick && (row => frame.onRowClick?.(drilldownFor(tab, row)))}\n pageSize={PAGE_SIZE}\n isLoading={isLoading}\n empty={EMPTY[tab]}\n />\n {!isLoading && truncated && (\n <Txt variant=\"caption\" tone=\"muted\" className=\"pt-2\">\n Showing the {formatCount(limit)} busiest; sorting covers only these.\n </Txt>\n )}\n </ChartArea>\n </BreakdownFrame>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"breakdown-table.cjs.js","names":["useMetricsScope","useState","isChangeMetric","BreakdownFrame","ChartCardError","hasErrors","showsProject","buildBreakdownRows","threadResources","previousFigures","tableRows","volumeLabel","rowChange","BreakdownRowName","BreakdownText","BreakdownFigure","formatPercent","formatDuration","formatCount","BreakdownCostCell","countDescription","BreakdownChangeDescription","comparedLabel","BreakdownChangeCell","ChartArea","MetricsTable","drilldownFor","Txt"],"sources":["../../../../../src/domains/metrics/components/breakdown/breakdown-table.tsx"],"sourcesContent":["import type { AggregateTracesResponse } from '@mastra/client-js';\nimport type { UseQueryResult } from '@tanstack/react-query';\nimport { useState } from 'react';\nimport { useMetricsScope } from '../../hooks/use-metrics-scope';\nimport type { useMetricsUsageTotals } from '../../hooks/use-metrics-usage-totals';\nimport { buildBreakdownRows, hasErrors, previousFigures, rowChange, threadResources } from '../../lib/breakdown';\nimport type { BreakdownRow, BreakdownTab, ChangeMetric } from '../../lib/breakdown';\nimport {\n DASH,\n comparedLabel,\n countDescription,\n drilldownFor,\n isChangeMetric,\n showsProject,\n tableRows,\n volumeLabel,\n} from '../../lib/breakdown-table';\nimport { formatCount, formatDuration, formatPercent } from '../../lib/chart-format';\nimport { ChartArea } from '../chart-area';\nimport { ChartCardError } from '../chart-card-error';\nimport { BreakdownChangeCell } from './breakdown-change-cell';\nimport { BreakdownChangeDescription } from './breakdown-change-description';\nimport { BreakdownCostCell } from './breakdown-cost-cell';\nimport { BreakdownFigure } from './breakdown-figure';\nimport { BreakdownFrame } from './breakdown-frame';\nimport type { BreakdownFrameProps } from './breakdown-frame';\nimport { BreakdownRowName } from './breakdown-row-name';\nimport { BreakdownText } from './breakdown-text';\nimport { MetricsTable } from '@/ds/components/MetricsTable';\nimport type { MetricsTableColumn, MetricsTableSort } from '@/ds/components/MetricsTable';\nimport { Txt } from '@/ds/components/Txt';\n\ntype UsageTotals = ReturnType<typeof useMetricsUsageTotals>;\n\nconst PAGE_SIZE = 10;\n\n/** Busiest first; where a third click on a column's header returns to. */\nconst DEFAULT_SORT: MetricsTableSort = { column: 'count', direction: 'desc' };\n\n/** The first column's header: what each row is. */\nconst NAME_HEADER: Record<BreakdownTab, string> = {\n projects: 'Project',\n agents: 'Agent',\n workflows: 'Workflow',\n tools: 'Tool',\n models: 'Model',\n threads: 'Thread',\n environments: 'Environment',\n};\n\nconst EMPTY: Record<BreakdownTab, string> = {\n projects: 'No traces in this range.',\n agents: 'No agent runs in this range.',\n workflows: 'No workflow runs in this range.',\n tools: 'No tool calls in this range.',\n models: 'No model usage in this range.',\n threads: 'No traces with a thread in this range.',\n environments: 'No traces in this range.',\n};\n\nexport type BreakdownTableProps = BreakdownFrameProps & {\n tab: BreakdownTab;\n groupBy: string[];\n window: { start: Date; end: Date };\n aggregate?: UseQueryResult<AggregateTracesResponse>;\n /** Tokens and cost per row. */\n totals?: UsageTotals;\n /** Model spans per row (Models tab). */\n spans?: UsageTotals;\n /** Rows naming each thread's resource (Threads tab). */\n resources?: UseQueryResult<AggregateTracesResponse>;\n previousAggregate?: UseQueryResult<AggregateTracesResponse>;\n previousUsage?: UsageTotals;\n previousSpans?: UsageTotals;\n /** The server's row cap, named when it truncates. */\n limit: number;\n};\n\n/** One tab's sortable table, with % Change against the previous window. */\nexport function BreakdownTable({\n tab,\n groupBy,\n window,\n aggregate,\n totals,\n spans,\n resources,\n previousAggregate,\n previousUsage,\n previousSpans,\n limit,\n ...frame\n}: BreakdownTableProps) {\n const scope = useMetricsScope();\n const [sort, setSort] = useState<MetricsTableSort>(DEFAULT_SORT);\n const [metric, setMetric] = useState<ChangeMetric>('count');\n const onSortChange = (next = DEFAULT_SORT) => {\n setSort(next);\n if (isChangeMetric(next.column)) setMetric(next.column);\n };\n\n const current = [aggregate, totals, spans].filter(q => q !== undefined);\n if (current.some(q => q.isError)) {\n return (\n <BreakdownFrame {...frame} tab={tab}>\n <ChartCardError onRetry={() => current.forEach(q => q.isError && void q.refetch())} />\n </BreakdownFrame>\n );\n }\n\n const isLoading = current.some(q => q.isLoading);\n const errors = hasErrors(tab);\n const usage = totals !== undefined;\n const project = showsProject(tab, frame.byProject);\n const truncated = aggregate?.data?.truncated === true;\n const built = isLoading\n ? []\n : buildBreakdownRows({\n tab,\n groupBy,\n aggregateRows: aggregate?.data?.rows,\n usageGroups: totals?.data?.groups,\n spanGroups: spans?.data?.groups,\n // The resource is a nicety: the table doesn't wait for it, and shows a dash without it.\n resources: resources?.data ? threadResources(resources.data.rows) : undefined,\n });\n // The previous window never holds the table up: until it answers, or if it fails, Change shows a dash.\n const previousSettled = [previousAggregate, previousUsage, previousSpans].every(\n q => !q || (!q.isLoading && !q.isError),\n );\n const previous =\n previousSettled && !isLoading\n ? previousFigures({\n tab,\n groupBy,\n aggregateRows: previousAggregate?.data?.rows,\n usageGroups: previousUsage?.data?.groups,\n spanGroups: previousSpans?.data?.groups,\n })\n : undefined;\n const rows = tableRows({ tab, built, previous, truncated, groupBy, usage });\n const volume = volumeLabel(tab);\n\n const changeOf = (row: BreakdownRow) => (previous ? rowChange(row, previous.get(row.key), metric) : undefined);\n const projectName = (row: BreakdownRow) => {\n if (!row.projectId) return DASH;\n return scope.projectLabel?.(row.projectId) ?? row.projectId;\n };\n\n const nameColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'name',\n header: NAME_HEADER[tab],\n width: 'minmax(12rem,3fr)',\n cell: row => <BreakdownRowName tab={tab} row={row} />,\n };\n const projectColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'project',\n header: 'Project',\n width: 'minmax(8rem,2fr)',\n cell: row => <BreakdownText text={projectName(row)} />,\n };\n const resourceColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'resource',\n header: 'Resource',\n width: 'minmax(6rem,1fr)',\n cell: row => <BreakdownText text={row.resource ?? DASH} />,\n };\n const errorColumns: MetricsTableColumn<BreakdownRow>[] = [\n {\n id: 'errorRate',\n header: 'Errors',\n align: 'end',\n sortValue: row => row.errorRate,\n cell: row => (\n <BreakdownFigure muted>{row.errorRate === undefined ? DASH : formatPercent(row.errorRate)}</BreakdownFigure>\n ),\n },\n {\n id: 'p95',\n header: 'P95 latency',\n align: 'end',\n sortValue: row => row.p95,\n cell: row => <BreakdownFigure muted>{row.p95 === undefined ? DASH : formatDuration(row.p95)}</BreakdownFigure>,\n },\n ];\n const usageColumns: MetricsTableColumn<BreakdownRow>[] = [\n {\n id: 'tokens',\n header: 'Tokens',\n align: 'end',\n sortValue: row => row.tokens,\n cell: row => <BreakdownFigure muted>{row.tokens === undefined ? DASH : formatCount(row.tokens)}</BreakdownFigure>,\n },\n {\n id: 'cost',\n header: 'Cost',\n align: 'end',\n sortValue: row => row.cost,\n cell: row => (\n <BreakdownFigure muted>\n <BreakdownCostCell row={row} />\n </BreakdownFigure>\n ),\n },\n ];\n const countColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'count',\n header: volume,\n align: 'end',\n description: countDescription(tab),\n sortValue: row => row.count,\n cell: row => <BreakdownFigure>{formatCount(row.count)}</BreakdownFigure>,\n };\n const changeColumn: MetricsTableColumn<BreakdownRow> = {\n id: 'change',\n header: '% Change',\n align: 'end',\n description: <BreakdownChangeDescription window={window} label={comparedLabel(tab, metric)} />,\n // Sorted by the change shown: biggest rise first, biggest fall first the other way. New rows\n // have no change to rank, so they sort last.\n sortValue: row => changeOf(row)?.change,\n cell: row => (\n <BreakdownFigure>\n <BreakdownChangeCell change={changeOf(row)} metric={metric} />\n </BreakdownFigure>\n ),\n };\n const columns = [\n nameColumn,\n ...(project ? [projectColumn] : []),\n ...(tab === 'threads' ? [resourceColumn] : []),\n ...(errors ? errorColumns : []),\n ...(usage ? usageColumns : []),\n countColumn,\n changeColumn,\n ];\n\n return (\n <BreakdownFrame {...frame} tab={tab} isUpdating={aggregate?.isPlaceholderData}>\n <ChartArea>\n <MetricsTable\n key={tab}\n aria-label={`${NAME_HEADER[tab]} breakdown`}\n columns={columns}\n rows={rows}\n getRowKey={row => row.key}\n sort={sort}\n defaultSort={DEFAULT_SORT}\n onSortChange={onSortChange}\n onRowClick={frame.onRowClick && (row => frame.onRowClick?.(drilldownFor(tab, row)))}\n pageSize={PAGE_SIZE}\n isLoading={isLoading}\n empty={EMPTY[tab]}\n />\n {!isLoading && truncated && (\n <Txt variant=\"caption\" tone=\"muted\" className=\"pt-2\">\n Showing the {formatCount(limit)} busiest; sorting covers only these.\n </Txt>\n )}\n </ChartArea>\n </BreakdownFrame>\n );\n}\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ import { BreakdownChangeDescription } from "./breakdown-change-description.es.js
8
8
  import { BreakdownFigure } from "./breakdown-figure.es.js";
9
9
  import { BreakdownText } from "./breakdown-text.es.js";
10
10
  import { useMetricsScope } from "../../hooks/use-metrics-scope.es.js";
11
- import { t as MetricsTable } from "../../../../MetricsTable-CRPeLHe1.js";
11
+ import { t as MetricsTable } from "../../../../MetricsTable-DID6LRoP.js";
12
12
  import { BreakdownChangeCell } from "./breakdown-change-cell.es.js";
13
13
  import { BreakdownCostCell } from "./breakdown-cost-cell.es.js";
14
14
  import { BreakdownFrame } from "./breakdown-frame.es.js";
@@ -16,7 +16,7 @@ import { BreakdownRowName } from "./breakdown-row-name.es.js";
16
16
  import { useState } from "react";
17
17
  import { jsx, jsxs } from "react/jsx-runtime";
18
18
  // src/domains/metrics/components/breakdown/breakdown-table.tsx
19
- var PAGE_SIZE = 13;
19
+ var PAGE_SIZE = 10;
20
20
  /** Busiest first; where a third click on a column's header returns to. */
21
21
  var DEFAULT_SORT = {
22
22
  column: "count",