@kopai/ui 0.9.0 → 0.11.0

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.
package/dist/index.mjs CHANGED
@@ -34,16 +34,20 @@ function fetchForDataSource(client, dataSource, signal) {
34
34
  switch (dataSource.method) {
35
35
  case "searchTracesPage": return client.searchTracesPage(dataSource.params, { signal });
36
36
  case "searchLogsPage": return client.searchLogsPage(dataSource.params, { signal });
37
- case "searchMetricsPage": return client.searchMetricsPage(dataSource.params, { signal });
37
+ case "searchMetricsPage": {
38
+ const params = dataSource.params;
39
+ if (params.aggregate) return client.searchAggregatedMetrics({
40
+ ...params,
41
+ aggregate: params.aggregate
42
+ }, { signal });
43
+ return client.searchMetricsPage(params, { signal });
44
+ }
38
45
  case "getTrace": return client.getTrace(dataSource.params.traceId, { signal });
39
46
  case "discoverMetrics": return client.discoverMetrics({ signal });
40
47
  case "getServices": return client.getServices({ signal });
41
48
  case "getOperations": return client.getOperations(dataSource.params.serviceName, { signal });
42
49
  case "searchTraceSummariesPage": return client.searchTraceSummariesPage(dataSource.params, { signal });
43
- default: {
44
- const exhaustiveCheck = dataSource;
45
- throw new Error(`Unknown method: ${exhaustiveCheck.method}`);
46
- }
50
+ default: throw new Error(`Unknown method: ${dataSource.method}`);
47
51
  }
48
52
  }
49
53
  function useKopaiData(dataSource) {
@@ -5700,8 +5704,11 @@ function buildStatData(rows) {
5700
5704
  metricName
5701
5705
  };
5702
5706
  }
5703
- function MetricStat({ rows, isLoading = false, error, label, formatValue = defaultFormatValue$1, showTimestamp = false, trend, trendValue, className = "", showSparkline = false, sparklinePoints = 20, sparklineHeight = 40, thresholds, colorBackground, colorValue = false }) {
5704
- const { latestValue, unit, timestamp, dataPoints, metricName } = useMemo(() => buildStatData(rows), [rows]);
5707
+ function MetricStat({ rows, value: directValue, unit: directUnit, isLoading = false, error, label, formatValue = defaultFormatValue$1, showTimestamp = false, trend, trendValue, className = "", showSparkline = false, sparklinePoints = 20, sparklineHeight = 40, thresholds, colorBackground, colorValue = false }) {
5708
+ const statData = useMemo(() => buildStatData(rows), [rows]);
5709
+ const latestValue = directValue ?? statData.latestValue;
5710
+ const unit = directUnit ?? statData.unit;
5711
+ const { timestamp, dataPoints, metricName } = statData;
5705
5712
  const sparklineData = useMemo(() => {
5706
5713
  if (!showSparkline || dataPoints.length === 0) return [];
5707
5714
  return dataPoints.slice(-sparklinePoints).map((dp) => ({ value: dp.value }));
@@ -6586,6 +6593,13 @@ function OtelMetricHistogram(props) {
6586
6593
  }
6587
6594
  //#endregion
6588
6595
  //#region src/components/observability/renderers/OtelMetricStat.tsx
6596
+ const EMPTY_ROWS = [];
6597
+ const GROUPED_AGGREGATE_ERROR = /* @__PURE__ */ new Error("MetricStat cannot display grouped aggregates. Remove groupBy or use MetricTable.");
6598
+ function isAggregatedRequest(props) {
6599
+ const ds = props.element.dataSource;
6600
+ if (!ds || ds.method !== "searchMetricsPage" || !ds.params) return false;
6601
+ return !!ds.params.aggregate;
6602
+ }
6589
6603
  function OtelMetricStat(props) {
6590
6604
  if (!props.hasData) return /* @__PURE__ */ jsx("div", {
6591
6605
  style: {
@@ -6594,6 +6608,24 @@ function OtelMetricStat(props) {
6594
6608
  },
6595
6609
  children: "No data source"
6596
6610
  });
6611
+ if (isAggregatedRequest(props)) {
6612
+ const rows = props.data?.data ?? [];
6613
+ if (rows.length > 1) return /* @__PURE__ */ jsx(MetricStat, {
6614
+ rows: EMPTY_ROWS,
6615
+ error: GROUPED_AGGREGATE_ERROR,
6616
+ label: props.element.props.label ?? void 0,
6617
+ formatValue: formatOtelValue
6618
+ });
6619
+ return /* @__PURE__ */ jsx(MetricStat, {
6620
+ rows: EMPTY_ROWS,
6621
+ value: rows[0]?.value,
6622
+ isLoading: props.loading,
6623
+ error: props.error ?? void 0,
6624
+ label: props.element.props.label ?? void 0,
6625
+ showSparkline: false,
6626
+ formatValue: formatOtelValue
6627
+ });
6628
+ }
6597
6629
  const response = props.data;
6598
6630
  return /* @__PURE__ */ jsx(MetricStat, {
6599
6631
  rows: response?.data ?? [],
@@ -6645,6 +6677,54 @@ function OtelMetricTimeSeries(props) {
6645
6677
  }
6646
6678
  //#endregion
6647
6679
  //#region src/components/observability/renderers/OtelTraceDetail.tsx
6680
+ function isTraceSummariesSource(props) {
6681
+ return props.element.dataSource?.method === "searchTraceSummariesPage";
6682
+ }
6683
+ function TraceSummariesView({ data, loading, error }) {
6684
+ const [selectedTraceId, setSelectedTraceId] = useState(null);
6685
+ const client = useKopaiSDK();
6686
+ const response = data;
6687
+ const traces = useMemo(() => {
6688
+ const rows = response?.data;
6689
+ if (!Array.isArray(rows)) return [];
6690
+ return rows.map((row) => ({
6691
+ traceId: row.traceId,
6692
+ rootSpanName: row.rootSpanName,
6693
+ serviceName: row.rootServiceName,
6694
+ durationMs: parseInt(row.durationNs, 10) / 1e6,
6695
+ statusCode: row.errorCount > 0 ? "ERROR" : "OK",
6696
+ timestampMs: parseInt(row.startTimeNs, 10) / 1e6,
6697
+ spanCount: row.spanCount,
6698
+ services: row.services,
6699
+ errorCount: row.errorCount
6700
+ }));
6701
+ }, [response]);
6702
+ const { data: traceRows, isFetching: traceLoading, error: traceError } = useQuery({
6703
+ queryKey: [
6704
+ "kopai",
6705
+ "getTrace",
6706
+ selectedTraceId
6707
+ ],
6708
+ queryFn: ({ signal }) => client.getTrace(selectedTraceId, { signal }),
6709
+ enabled: !!selectedTraceId
6710
+ });
6711
+ const handleBack = useCallback(() => setSelectedTraceId(null), []);
6712
+ if (selectedTraceId) return /* @__PURE__ */ jsx(TraceDetail, {
6713
+ traceId: selectedTraceId,
6714
+ rows: traceRows ?? [],
6715
+ isLoading: traceLoading,
6716
+ error: traceError ?? void 0,
6717
+ onBack: handleBack
6718
+ });
6719
+ return /* @__PURE__ */ jsx(TraceSearch, {
6720
+ services: [],
6721
+ service: "",
6722
+ traces,
6723
+ isLoading: loading,
6724
+ error: error ?? void 0,
6725
+ onSelectTrace: setSelectedTraceId
6726
+ });
6727
+ }
6648
6728
  function OtelTraceDetail(props) {
6649
6729
  if (!props.hasData) return /* @__PURE__ */ jsx("div", {
6650
6730
  style: {
@@ -6653,7 +6733,13 @@ function OtelTraceDetail(props) {
6653
6733
  },
6654
6734
  children: "No data source"
6655
6735
  });
6656
- const rows = props.data?.data ?? [];
6736
+ if (isTraceSummariesSource(props)) return /* @__PURE__ */ jsx(TraceSummariesView, {
6737
+ data: props.data,
6738
+ loading: props.loading,
6739
+ error: props.error
6740
+ });
6741
+ const response = props.data;
6742
+ const rows = Array.isArray(response?.data) ? response.data : [];
6657
6743
  const traceId = rows[0]?.TraceId ?? "";
6658
6744
  return /* @__PURE__ */ jsx(TraceDetail, {
6659
6745
  rows,
@@ -7391,6 +7477,9 @@ const METRICS_TREE = {
7391
7477
  type: "Stack",
7392
7478
  children: [
7393
7479
  "heading",
7480
+ "ingestion-heading",
7481
+ "ingestion-grid",
7482
+ "discovery-heading",
7394
7483
  "description",
7395
7484
  "discovery-card"
7396
7485
  ],
@@ -7411,6 +7500,96 @@ const METRICS_TREE = {
7411
7500
  level: "h2"
7412
7501
  }
7413
7502
  },
7503
+ "ingestion-heading": {
7504
+ key: "ingestion-heading",
7505
+ type: "Heading",
7506
+ children: [],
7507
+ parentKey: "root",
7508
+ props: {
7509
+ text: "OTEL Ingestion",
7510
+ level: "h3"
7511
+ }
7512
+ },
7513
+ "ingestion-grid": {
7514
+ key: "ingestion-grid",
7515
+ type: "Grid",
7516
+ children: ["card-bytes", "card-requests"],
7517
+ parentKey: "root",
7518
+ props: {
7519
+ columns: 2,
7520
+ gap: "md"
7521
+ }
7522
+ },
7523
+ "card-bytes": {
7524
+ key: "card-bytes",
7525
+ type: "Card",
7526
+ children: ["stat-bytes"],
7527
+ parentKey: "ingestion-grid",
7528
+ props: {
7529
+ title: "Total Bytes Ingested",
7530
+ description: null,
7531
+ padding: null
7532
+ }
7533
+ },
7534
+ "stat-bytes": {
7535
+ key: "stat-bytes",
7536
+ type: "MetricStat",
7537
+ children: [],
7538
+ parentKey: "card-bytes",
7539
+ dataSource: {
7540
+ method: "searchMetricsPage",
7541
+ params: {
7542
+ metricType: "Sum",
7543
+ metricName: "kopai.ingestion.bytes",
7544
+ aggregate: "sum"
7545
+ },
7546
+ refetchIntervalMs: 1e4
7547
+ },
7548
+ props: {
7549
+ label: "Bytes",
7550
+ showSparkline: false
7551
+ }
7552
+ },
7553
+ "card-requests": {
7554
+ key: "card-requests",
7555
+ type: "Card",
7556
+ children: ["stat-requests"],
7557
+ parentKey: "ingestion-grid",
7558
+ props: {
7559
+ title: "Total Requests",
7560
+ description: null,
7561
+ padding: null
7562
+ }
7563
+ },
7564
+ "stat-requests": {
7565
+ key: "stat-requests",
7566
+ type: "MetricStat",
7567
+ children: [],
7568
+ parentKey: "card-requests",
7569
+ dataSource: {
7570
+ method: "searchMetricsPage",
7571
+ params: {
7572
+ metricType: "Sum",
7573
+ metricName: "kopai.ingestion.requests",
7574
+ aggregate: "sum"
7575
+ },
7576
+ refetchIntervalMs: 1e4
7577
+ },
7578
+ props: {
7579
+ label: "Requests",
7580
+ showSparkline: false
7581
+ }
7582
+ },
7583
+ "discovery-heading": {
7584
+ key: "discovery-heading",
7585
+ type: "Heading",
7586
+ children: [],
7587
+ parentKey: "root",
7588
+ props: {
7589
+ text: "Discovered Metrics",
7590
+ level: "h3"
7591
+ }
7592
+ },
7414
7593
  description: {
7415
7594
  key: "description",
7416
7595
  type: "Text",