From 7fac4850491ba1edcb5003fba04ce839f64980b9 Mon Sep 17 00:00:00 2001 From: Nawaz Dhandala Date: Wed, 25 Mar 2026 22:54:52 +0000 Subject: [PATCH] feat: add Log Stream and Trace List components to dashboard with configuration options --- .../Components/DashboardBaseComponent.tsx | 20 ++ .../DashboardLogStreamComponent.tsx | 249 +++++++++++++++ .../DashboardTraceListComponent.tsx | 294 ++++++++++++++++++ .../Components/Dashboard/DashboardView.tsx | 12 + .../Dashboard/Toolbar/DashboardToolbar.tsx | 18 ++ .../Types/Dashboard/DashboardComponentType.ts | 2 + .../DashboardLogStreamComponent.ts | 14 + .../DashboardTraceListComponent.ts | 13 + .../Components/DashboardLogStreamComponent.ts | 81 +++++ .../Components/DashboardTraceListComponent.ts | 69 ++++ Common/Utils/Dashboard/Components/Index.ts | 14 + 11 files changed, 786 insertions(+) create mode 100644 App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardLogStreamComponent.tsx create mode 100644 App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardTraceListComponent.tsx create mode 100644 Common/Types/Dashboard/DashboardComponents/DashboardLogStreamComponent.ts create mode 100644 Common/Types/Dashboard/DashboardComponents/DashboardTraceListComponent.ts create mode 100644 Common/Utils/Dashboard/Components/DashboardLogStreamComponent.ts create mode 100644 Common/Utils/Dashboard/Components/DashboardTraceListComponent.ts diff --git a/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardBaseComponent.tsx b/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardBaseComponent.tsx index 7559725d19..263a5f1b1f 100644 --- a/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardBaseComponent.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardBaseComponent.tsx @@ -4,12 +4,16 @@ import DashboardChartComponentType from "Common/Types/Dashboard/DashboardCompone import DashboardValueComponentType from "Common/Types/Dashboard/DashboardComponents/DashboardValueComponent"; import DashboardTableComponentType from "Common/Types/Dashboard/DashboardComponents/DashboardTableComponent"; import DashboardGaugeComponentType from "Common/Types/Dashboard/DashboardComponents/DashboardGaugeComponent"; +import DashboardLogStreamComponentType from "Common/Types/Dashboard/DashboardComponents/DashboardLogStreamComponent"; +import DashboardTraceListComponentType from "Common/Types/Dashboard/DashboardComponents/DashboardTraceListComponent"; import DashboardBaseComponent from "Common/Types/Dashboard/DashboardComponents/DashboardBaseComponent"; import DashboardChartComponent from "./DashboardChartComponent"; import DashboardValueComponent from "./DashboardValueComponent"; import DashboardTextComponent from "./DashboardTextComponent"; import DashboardTableComponent from "./DashboardTableComponent"; import DashboardGaugeComponent from "./DashboardGaugeComponent"; +import DashboardLogStreamComponent from "./DashboardLogStreamComponent"; +import DashboardTraceListComponent from "./DashboardTraceListComponent"; import DefaultDashboardSize, { GetDashboardComponentHeightInDashboardUnits, GetDashboardComponentWidthInDashboardUnits, @@ -439,6 +443,22 @@ const DashboardBaseComponentElement: FunctionComponent = ( component={component as DashboardGaugeComponentType} /> )} + {component.componentType === DashboardComponentType.LogStream && ( + + )} + {component.componentType === DashboardComponentType.TraceList && ( + + )} {getResizeWidthElement()} {getResizeHeightElement()} diff --git a/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardLogStreamComponent.tsx b/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardLogStreamComponent.tsx new file mode 100644 index 0000000000..7d4a7f46fb --- /dev/null +++ b/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardLogStreamComponent.tsx @@ -0,0 +1,249 @@ +import React, { FunctionComponent, ReactElement, useEffect } from "react"; +import DashboardLogStreamComponent from "Common/Types/Dashboard/DashboardComponents/DashboardLogStreamComponent"; +import { DashboardBaseComponentProps } from "./DashboardBaseComponent"; +import { PromiseVoidFunction } from "Common/Types/FunctionTypes"; +import AnalyticsModelAPI, { + ListResult, +} from "Common/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI"; +import Log from "Common/Models/AnalyticsModels/Log"; +import API from "Common/UI/Utils/API/API"; +import Icon from "Common/UI/Components/Icon/Icon"; +import IconProp from "Common/Types/Icon/IconProp"; +import { RangeStartAndEndDateTimeUtil } from "Common/Types/Time/RangeStartAndEndDateTime"; +import InBetween from "Common/Types/BaseDatabase/InBetween"; +import SortOrder from "Common/Types/BaseDatabase/SortOrder"; +import OneUptimeDate from "Common/Types/Date"; +import Query from "Common/Types/BaseDatabase/Query"; + +export interface ComponentProps extends DashboardBaseComponentProps { + component: DashboardLogStreamComponent; +} + +type SeverityColor = { + dot: string; + text: string; + bg: string; +}; + +const getSeverityColor: (severity: string) => SeverityColor = ( + severity: string, +): SeverityColor => { + const lower: string = severity.toLowerCase(); + if (lower === "fatal") { + return { dot: "bg-purple-500", text: "text-purple-700", bg: "bg-purple-50" }; + } + if (lower === "error") { + return { dot: "bg-red-500", text: "text-red-700", bg: "bg-red-50" }; + } + if (lower === "warning") { + return { dot: "bg-yellow-500", text: "text-yellow-700", bg: "bg-yellow-50" }; + } + if (lower === "information") { + return { dot: "bg-blue-500", text: "text-blue-700", bg: "bg-blue-50" }; + } + if (lower === "debug") { + return { dot: "bg-gray-400", text: "text-gray-600", bg: "bg-gray-50" }; + } + if (lower === "trace") { + return { dot: "bg-gray-300", text: "text-gray-500", bg: "bg-gray-50" }; + } + return { dot: "bg-gray-300", text: "text-gray-500", bg: "bg-gray-50" }; +}; + +const DashboardLogStreamComponentElement: FunctionComponent = ( + props: ComponentProps, +): ReactElement => { + const [logs, setLogs] = React.useState>([]); + const [error, setError] = React.useState(null); + const [isLoading, setIsLoading] = React.useState(true); + + const maxRows: number = props.component.arguments.maxRows || 50; + + const fetchLogs: PromiseVoidFunction = async (): Promise => { + setIsLoading(true); + + const startAndEndDate: InBetween = + RangeStartAndEndDateTimeUtil.getStartAndEndDate( + props.dashboardStartAndEndDate, + ); + + if (!startAndEndDate.startValue || !startAndEndDate.endValue) { + setIsLoading(false); + setError("Please select a valid start and end date."); + return; + } + + try { + const query: Query = { + time: new InBetween( + startAndEndDate.startValue, + startAndEndDate.endValue, + ), + } as Query; + + // Add severity filter if set + if ( + props.component.arguments.severityFilter && + props.component.arguments.severityFilter !== "" + ) { + (query as Record)["severityText"] = + props.component.arguments.severityFilter; + } + + // Add body contains filter if set + if ( + props.component.arguments.bodyContains && + props.component.arguments.bodyContains.trim() !== "" + ) { + (query as Record)["body"] = + props.component.arguments.bodyContains.trim(); + } + + const listResult: ListResult = + await AnalyticsModelAPI.getList({ + modelType: Log, + query: query, + limit: maxRows, + skip: 0, + select: { + time: true, + severityText: true, + body: true, + serviceId: true, + traceId: true, + spanId: true, + }, + sort: { + time: SortOrder.Descending, + }, + requestOptions: {}, + }); + + setLogs(listResult.data); + setError(""); + } catch (err: unknown) { + setError(API.getFriendlyErrorMessage(err as Error)); + } + + setIsLoading(false); + }; + + useEffect(() => { + fetchLogs(); + }, [props.dashboardStartAndEndDate, props.refreshTick]); + + useEffect(() => { + fetchLogs(); + }, [ + props.component.arguments.severityFilter, + props.component.arguments.bodyContains, + props.component.arguments.maxRows, + ]); + + if (isLoading) { + return ( +
+
+
+ {Array.from({ length: 6 }).map((_: unknown, i: number) => { + return ( +
+
+
+
+
+ ); + })} +
+
+ ); + } + + if (error) { + return ( +
+
+
+ +
+
+

{error}

+
+ ); + } + + return ( +
+ {props.component.arguments.title && ( +
+ + {props.component.arguments.title} + + + {logs.length} entries + +
+ )} +
+
+ {logs.map((log: Log, index: number) => { + const severity: string = + (log.severityText as string) || "Unspecified"; + const colors: SeverityColor = getSeverityColor(severity); + const body: string = (log.body as string) || ""; + const time: Date | undefined = log.time + ? OneUptimeDate.fromString(log.time as string) + : undefined; + + return ( +
+
+
+ + {severity.substring(0, 4).toUpperCase()} + +
+ {time && ( + + {OneUptimeDate.getDateAsLocalFormattedString(time, true)} + + )} + + {body} + +
+ ); + })} + {logs.length === 0 && ( +
+ No logs found +
+ )} +
+
+
+ ); +}; + +export default DashboardLogStreamComponentElement; diff --git a/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardTraceListComponent.tsx b/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardTraceListComponent.tsx new file mode 100644 index 0000000000..6bfb70b6fc --- /dev/null +++ b/App/FeatureSet/Dashboard/src/Components/Dashboard/Components/DashboardTraceListComponent.tsx @@ -0,0 +1,294 @@ +import React, { FunctionComponent, ReactElement, useEffect } from "react"; +import DashboardTraceListComponent from "Common/Types/Dashboard/DashboardComponents/DashboardTraceListComponent"; +import { DashboardBaseComponentProps } from "./DashboardBaseComponent"; +import { PromiseVoidFunction } from "Common/Types/FunctionTypes"; +import AnalyticsModelAPI, { + ListResult, +} from "Common/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI"; +import Span, { SpanStatus } from "Common/Models/AnalyticsModels/Span"; +import API from "Common/UI/Utils/API/API"; +import Icon from "Common/UI/Components/Icon/Icon"; +import IconProp from "Common/Types/Icon/IconProp"; +import { RangeStartAndEndDateTimeUtil } from "Common/Types/Time/RangeStartAndEndDateTime"; +import InBetween from "Common/Types/BaseDatabase/InBetween"; +import SortOrder from "Common/Types/BaseDatabase/SortOrder"; +import OneUptimeDate from "Common/Types/Date"; +import Query from "Common/Types/BaseDatabase/Query"; + +export interface ComponentProps extends DashboardBaseComponentProps { + component: DashboardTraceListComponent; +} + +type StatusStyle = { + label: string; + textClass: string; + bgClass: string; +}; + +const getStatusStyle: (statusCode: number) => StatusStyle = ( + statusCode: number, +): StatusStyle => { + if (statusCode === SpanStatus.Error) { + return { + label: "Error", + textClass: "text-red-700", + bgClass: "bg-red-50 border-red-100", + }; + } + if (statusCode === SpanStatus.Ok) { + return { + label: "Ok", + textClass: "text-green-700", + bgClass: "bg-green-50 border-green-100", + }; + } + return { + label: "Unset", + textClass: "text-gray-500", + bgClass: "bg-gray-50 border-gray-100", + }; +}; + +const formatDuration: (durationNano: number) => string = ( + durationNano: number, +): string => { + if (durationNano < 1000) { + return `${durationNano}ns`; + } + const durationMicro: number = durationNano / 1000; + if (durationMicro < 1000) { + return `${Math.round(durationMicro)}µs`; + } + const durationMs: number = durationMicro / 1000; + if (durationMs < 1000) { + return `${Math.round(durationMs * 10) / 10}ms`; + } + const durationS: number = durationMs / 1000; + return `${Math.round(durationS * 100) / 100}s`; +}; + +const DashboardTraceListComponentElement: FunctionComponent = ( + props: ComponentProps, +): ReactElement => { + const [spans, setSpans] = React.useState>([]); + const [error, setError] = React.useState(null); + const [isLoading, setIsLoading] = React.useState(true); + + const maxRows: number = props.component.arguments.maxRows || 50; + + const fetchTraces: PromiseVoidFunction = async (): Promise => { + setIsLoading(true); + + const startAndEndDate: InBetween = + RangeStartAndEndDateTimeUtil.getStartAndEndDate( + props.dashboardStartAndEndDate, + ); + + if (!startAndEndDate.startValue || !startAndEndDate.endValue) { + setIsLoading(false); + setError("Please select a valid start and end date."); + return; + } + + try { + const query: Query = { + startTime: new InBetween( + startAndEndDate.startValue, + startAndEndDate.endValue, + ), + } as Query; + + // Add status filter if set + if ( + props.component.arguments.statusFilter && + props.component.arguments.statusFilter !== "" + ) { + (query as Record)["statusCode"] = parseInt( + props.component.arguments.statusFilter, + ); + } + + const listResult: ListResult = + await AnalyticsModelAPI.getList({ + modelType: Span, + query: query, + limit: maxRows, + skip: 0, + select: { + startTime: true, + name: true, + statusCode: true, + durationUnixNano: true, + traceId: true, + spanId: true, + kind: true, + serviceId: true, + }, + sort: { + startTime: SortOrder.Descending, + }, + requestOptions: {}, + }); + + setSpans(listResult.data); + setError(""); + } catch (err: unknown) { + setError(API.getFriendlyErrorMessage(err as Error)); + } + + setIsLoading(false); + }; + + useEffect(() => { + fetchTraces(); + }, [props.dashboardStartAndEndDate, props.refreshTick]); + + useEffect(() => { + fetchTraces(); + }, [ + props.component.arguments.statusFilter, + props.component.arguments.maxRows, + ]); + + if (isLoading) { + return ( +
+
+
+
+
+
+
+
+ {Array.from({ length: 5 }).map((_: unknown, i: number) => { + return ( +
+
+
+
+
+ ); + })} +
+
+ ); + } + + if (error) { + return ( +
+
+
+ +
+
+

{error}

+
+ ); + } + + return ( +
+ {props.component.arguments.title && ( +
+ + {props.component.arguments.title} + + + {spans.length} traces + +
+ )} +
+ + + + + + + + + + + {spans.map((span: Span, index: number) => { + const statusCode: number = + (span.statusCode as number) || SpanStatus.Unset; + const statusStyle: StatusStyle = getStatusStyle(statusCode); + const durationNano: number = + (span.durationUnixNano as number) || 0; + const startTime: Date | undefined = span.startTime + ? OneUptimeDate.fromString(span.startTime as string) + : undefined; + + return ( + + + + + + + ); + })} + {spans.length === 0 && ( + + + + )} + +
+ Span Name + + Duration + + Status + + Time +
+ {(span.name as string) || "—"} + + {formatDuration(durationNano)} + + + {statusStyle.label} + + + {startTime + ? OneUptimeDate.getDateAsLocalFormattedString( + startTime, + true, + ) + : "—"} +
+ No traces found +
+
+
+ ); +}; + +export default DashboardTraceListComponentElement; diff --git a/App/FeatureSet/Dashboard/src/Components/Dashboard/DashboardView.tsx b/App/FeatureSet/Dashboard/src/Components/Dashboard/DashboardView.tsx index 273dd36258..1a40c9905f 100644 --- a/App/FeatureSet/Dashboard/src/Components/Dashboard/DashboardView.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Dashboard/DashboardView.tsx @@ -21,6 +21,8 @@ import DashboardValueComponentUtil from "Common/Utils/Dashboard/Components/Dashb import DashboardTextComponentUtil from "Common/Utils/Dashboard/Components/DashboardTextComponent"; import DashboardTableComponentUtil from "Common/Utils/Dashboard/Components/DashboardTableComponent"; import DashboardGaugeComponentUtil from "Common/Utils/Dashboard/Components/DashboardGaugeComponent"; +import DashboardLogStreamComponentUtil from "Common/Utils/Dashboard/Components/DashboardLogStreamComponent"; +import DashboardTraceListComponentUtil from "Common/Utils/Dashboard/Components/DashboardTraceListComponent"; import BadDataException from "Common/Types/Exception/BadDataException"; import ObjectID from "Common/Types/ObjectID"; import Dashboard from "Common/Models/DatabaseModels/Dashboard"; @@ -378,6 +380,16 @@ const DashboardViewer: FunctionComponent = ( newComponent = DashboardGaugeComponentUtil.getDefaultComponent(); } + if (componentType === DashboardComponentType.LogStream) { + newComponent = + DashboardLogStreamComponentUtil.getDefaultComponent(); + } + + if (componentType === DashboardComponentType.TraceList) { + newComponent = + DashboardTraceListComponentUtil.getDefaultComponent(); + } + if (!newComponent) { throw new BadDataException( `Unknown component type: ${componentType}`, diff --git a/App/FeatureSet/Dashboard/src/Components/Dashboard/Toolbar/DashboardToolbar.tsx b/App/FeatureSet/Dashboard/src/Components/Dashboard/Toolbar/DashboardToolbar.tsx index d5022f6912..444a81e443 100644 --- a/App/FeatureSet/Dashboard/src/Components/Dashboard/Toolbar/DashboardToolbar.tsx +++ b/App/FeatureSet/Dashboard/src/Components/Dashboard/Toolbar/DashboardToolbar.tsx @@ -135,6 +135,24 @@ const DashboardToolbar: FunctionComponent = ( props.onAddComponentClick(DashboardComponentType.Gauge); }} /> + { + props.onAddComponentClick( + DashboardComponentType.LogStream, + ); + }} + /> + { + props.onAddComponentClick( + DashboardComponentType.TraceList, + ); + }} + />
diff --git a/Common/Types/Dashboard/DashboardComponentType.ts b/Common/Types/Dashboard/DashboardComponentType.ts index d9705fdf39..ae2bb142f5 100644 --- a/Common/Types/Dashboard/DashboardComponentType.ts +++ b/Common/Types/Dashboard/DashboardComponentType.ts @@ -4,6 +4,8 @@ enum DashboardComponentType { Text = `Text`, Table = `Table`, Gauge = `Gauge`, + LogStream = `LogStream`, + TraceList = `TraceList`, } export default DashboardComponentType; diff --git a/Common/Types/Dashboard/DashboardComponents/DashboardLogStreamComponent.ts b/Common/Types/Dashboard/DashboardComponents/DashboardLogStreamComponent.ts new file mode 100644 index 0000000000..e2db6a499b --- /dev/null +++ b/Common/Types/Dashboard/DashboardComponents/DashboardLogStreamComponent.ts @@ -0,0 +1,14 @@ +import ObjectID from "../../ObjectID"; +import DashboardComponentType from "../DashboardComponentType"; +import BaseComponent from "./DashboardBaseComponent"; + +export default interface DashboardLogStreamComponent extends BaseComponent { + componentType: DashboardComponentType.LogStream; + componentId: ObjectID; + arguments: { + title?: string | undefined; + severityFilter?: string | undefined; + bodyContains?: string | undefined; + maxRows?: number | undefined; + }; +} diff --git a/Common/Types/Dashboard/DashboardComponents/DashboardTraceListComponent.ts b/Common/Types/Dashboard/DashboardComponents/DashboardTraceListComponent.ts new file mode 100644 index 0000000000..7765927862 --- /dev/null +++ b/Common/Types/Dashboard/DashboardComponents/DashboardTraceListComponent.ts @@ -0,0 +1,13 @@ +import ObjectID from "../../ObjectID"; +import DashboardComponentType from "../DashboardComponentType"; +import BaseComponent from "./DashboardBaseComponent"; + +export default interface DashboardTraceListComponent extends BaseComponent { + componentType: DashboardComponentType.TraceList; + componentId: ObjectID; + arguments: { + title?: string | undefined; + statusFilter?: string | undefined; + maxRows?: number | undefined; + }; +} diff --git a/Common/Utils/Dashboard/Components/DashboardLogStreamComponent.ts b/Common/Utils/Dashboard/Components/DashboardLogStreamComponent.ts new file mode 100644 index 0000000000..ab7128d030 --- /dev/null +++ b/Common/Utils/Dashboard/Components/DashboardLogStreamComponent.ts @@ -0,0 +1,81 @@ +import DashboardLogStreamComponent from "../../../Types/Dashboard/DashboardComponents/DashboardLogStreamComponent"; +import { ObjectType } from "../../../Types/JSON"; +import ObjectID from "../../../Types/ObjectID"; +import DashboardBaseComponentUtil from "./DashboardBaseComponent"; +import { + ComponentArgument, + ComponentInputType, +} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument"; +import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType"; + +export default class DashboardLogStreamComponentUtil extends DashboardBaseComponentUtil { + public static override getDefaultComponent(): DashboardLogStreamComponent { + return { + _type: ObjectType.DashboardComponent, + componentType: DashboardComponentType.LogStream, + widthInDashboardUnits: 6, + heightInDashboardUnits: 4, + topInDashboardUnits: 0, + leftInDashboardUnits: 0, + componentId: ObjectID.generate(), + minHeightInDashboardUnits: 3, + minWidthInDashboardUnits: 6, + arguments: { + maxRows: 50, + }, + }; + } + + public static override getComponentConfigArguments(): Array< + ComponentArgument + > { + const componentArguments: Array< + ComponentArgument + > = []; + + componentArguments.push({ + name: "Title", + description: "The title of the log stream widget", + required: false, + type: ComponentInputType.Text, + id: "title", + }); + + componentArguments.push({ + name: "Severity Filter", + description: "Filter logs by severity level", + required: false, + type: ComponentInputType.Dropdown, + id: "severityFilter", + dropdownOptions: [ + { label: "All", value: "" }, + { label: "Trace", value: "Trace" }, + { label: "Debug", value: "Debug" }, + { label: "Information", value: "Information" }, + { label: "Warning", value: "Warning" }, + { label: "Error", value: "Error" }, + { label: "Fatal", value: "Fatal" }, + ], + }); + + componentArguments.push({ + name: "Body Contains", + description: "Filter logs where the body contains this text", + required: false, + type: ComponentInputType.Text, + id: "bodyContains", + placeholder: "Search text...", + }); + + componentArguments.push({ + name: "Max Rows", + description: "Maximum number of log entries to display", + required: false, + type: ComponentInputType.Number, + id: "maxRows", + placeholder: "50", + }); + + return componentArguments; + } +} diff --git a/Common/Utils/Dashboard/Components/DashboardTraceListComponent.ts b/Common/Utils/Dashboard/Components/DashboardTraceListComponent.ts new file mode 100644 index 0000000000..adfe7c6c02 --- /dev/null +++ b/Common/Utils/Dashboard/Components/DashboardTraceListComponent.ts @@ -0,0 +1,69 @@ +import DashboardTraceListComponent from "../../../Types/Dashboard/DashboardComponents/DashboardTraceListComponent"; +import { ObjectType } from "../../../Types/JSON"; +import ObjectID from "../../../Types/ObjectID"; +import DashboardBaseComponentUtil from "./DashboardBaseComponent"; +import { + ComponentArgument, + ComponentInputType, +} from "../../../Types/Dashboard/DashboardComponents/ComponentArgument"; +import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentType"; + +export default class DashboardTraceListComponentUtil extends DashboardBaseComponentUtil { + public static override getDefaultComponent(): DashboardTraceListComponent { + return { + _type: ObjectType.DashboardComponent, + componentType: DashboardComponentType.TraceList, + widthInDashboardUnits: 6, + heightInDashboardUnits: 4, + topInDashboardUnits: 0, + leftInDashboardUnits: 0, + componentId: ObjectID.generate(), + minHeightInDashboardUnits: 3, + minWidthInDashboardUnits: 6, + arguments: { + maxRows: 50, + }, + }; + } + + public static override getComponentConfigArguments(): Array< + ComponentArgument + > { + const componentArguments: Array< + ComponentArgument + > = []; + + componentArguments.push({ + name: "Title", + description: "The title of the trace list widget", + required: false, + type: ComponentInputType.Text, + id: "title", + }); + + componentArguments.push({ + name: "Status Filter", + description: "Filter traces by status", + required: false, + type: ComponentInputType.Dropdown, + id: "statusFilter", + dropdownOptions: [ + { label: "All", value: "" }, + { label: "Ok", value: "1" }, + { label: "Error", value: "2" }, + { label: "Unset", value: "0" }, + ], + }); + + componentArguments.push({ + name: "Max Rows", + description: "Maximum number of traces to display", + required: false, + type: ComponentInputType.Number, + id: "maxRows", + placeholder: "50", + }); + + return componentArguments; + } +} diff --git a/Common/Utils/Dashboard/Components/Index.ts b/Common/Utils/Dashboard/Components/Index.ts index b10fd36c9a..91132cad10 100644 --- a/Common/Utils/Dashboard/Components/Index.ts +++ b/Common/Utils/Dashboard/Components/Index.ts @@ -4,8 +4,10 @@ import DashboardComponentType from "../../../Types/Dashboard/DashboardComponentT import BadDataException from "../../../Types/Exception/BadDataException"; import DashboardChartComponentUtil from "./DashboardChartComponent"; import DashboardGaugeComponentUtil from "./DashboardGaugeComponent"; +import DashboardLogStreamComponentUtil from "./DashboardLogStreamComponent"; import DashboardTableComponentUtil from "./DashboardTableComponent"; import DashboardTextComponentUtil from "./DashboardTextComponent"; +import DashboardTraceListComponentUtil from "./DashboardTraceListComponent"; import DashboardValueComponentUtil from "./DashboardValueComponent"; export default class DashboardComponentsUtil { @@ -42,6 +44,18 @@ export default class DashboardComponentsUtil { >; } + if (dashboardComponentType === DashboardComponentType.LogStream) { + return DashboardLogStreamComponentUtil.getComponentConfigArguments() as Array< + ComponentArgument + >; + } + + if (dashboardComponentType === DashboardComponentType.TraceList) { + return DashboardTraceListComponentUtil.getComponentConfigArguments() as Array< + ComponentArgument + >; + } + throw new BadDataException( `Unknown dashboard component type: ${dashboardComponentType}`, );