diff --git a/esp/src/src-react/components/Logs.tsx b/esp/src/src-react/components/Logs.tsx index 675bfca7b9b..f67edfba0be 100644 --- a/esp/src/src-react/components/Logs.tsx +++ b/esp/src/src-react/components/Logs.tsx @@ -1,9 +1,10 @@ import * as React from "react"; import { CommandBar, ContextualMenuItemType, ICommandBarItemProps } from "@fluentui/react"; -import { GetLogsExRequest, LogaccessService, TargetAudience, LogType } from "@hpcc-js/comms"; +import { GetLogsExRequest, LogaccessService, LogType, TargetAudience, WsLogaccess } from "@hpcc-js/comms"; import { Level, scopedLogger } from "@hpcc-js/util"; import nlsHPCC from "src/nlsHPCC"; -import { logColor, wuidToDate, wuidToTime } from "src/Utility"; +import { logColor, removeAllExcept, wuidToDate, wuidToTime } from "src/Utility"; +import { useLogAccessInfo } from "../hooks/platform"; import { HolyGrail } from "../layouts/HolyGrail"; import { pushParams } from "../util/history"; import { FluentGrid, useCopyButtons, useFluentStoreState, FluentColumns } from "./controls/Grid"; @@ -92,6 +93,8 @@ const levelMap = (level) => { } }; +const columnOrder: string[] = [WsLogaccess.LogColumnType.timestamp, WsLogaccess.LogColumnType.message] + export const Logs: React.FunctionComponent = ({ wuid, filter = defaultFilter, @@ -109,9 +112,26 @@ export const Logs: React.FunctionComponent = ({ const now = React.useMemo(() => new Date(), []); + const { columns: logColumns } = useLogAccessInfo(); + // Grid --- const columns = React.useMemo((): FluentColumns => { - return { + // we've defined the columnOrder array above to ensure specific columns will + // appear on the left-most side of the grid, eg timestamps and log messages + const cols = logColumns?.sort((a, b) => { + const logTypeA = columnOrder.indexOf(a.LogType); + const logTypeB = columnOrder.indexOf(b.LogType); + + if (logTypeA >= 0) { + if (logTypeB >= 0) { return logTypeA - logTypeB; } + return -1; + } else if (logTypeB >= 0) { + return 1; + } else { + return 0; + } + }); + const retVal = { timestamp: { label: nlsHPCC.TimeStamp, width: 140, sortable: false, }, message: { label: nlsHPCC.Message, width: 600, sortable: false, }, components: { label: nlsHPCC.ContainerName, width: 150, sortable: false }, @@ -129,7 +149,10 @@ export const Logs: React.FunctionComponent = ({ logid: { label: nlsHPCC.Sequence, width: 70, sortable: false, }, threadid: { label: nlsHPCC.ThreadID, width: 60, sortable: false, }, }; - }, [wuid]); + const colTypes = cols?.map(c => c.LogType.toString()) ?? []; + removeAllExcept(retVal, colTypes); + return retVal; + }, [logColumns, wuid]); const copyButtons = useCopyButtons(columns, selection, "logaccess"); @@ -194,8 +217,10 @@ export const Logs: React.FunctionComponent = ({ delete retVal.jobId; } } + const colTypes = logColumns?.map(c => c.LogType.toString()) ?? []; + removeAllExcept(retVal, colTypes); return retVal; - }, [filter, wuid]); + }, [filter, logColumns, wuid]); return } diff --git a/esp/src/src-react/hooks/platform.ts b/esp/src/src-react/hooks/platform.ts index 66dac5d9487..e0b9ea69a1c 100644 --- a/esp/src/src-react/hooks/platform.ts +++ b/esp/src/src-react/hooks/platform.ts @@ -2,7 +2,7 @@ import * as React from "react"; import { Octokit } from "octokit"; import { useConst } from "@fluentui/react-hooks"; import { scopedLogger } from "@hpcc-js/util"; -import { Topology, WsTopology, WorkunitsServiceEx } from "@hpcc-js/comms"; +import { LogaccessService, Topology, WsLogaccess, WsTopology, WorkunitsServiceEx } from "@hpcc-js/comms"; import { getBuildInfo, BuildInfo, fetchModernMode } from "src/Session"; import { cmake_build_type, containerized, ModernMode } from "src/BuildInfo"; import { sessionKeyValStore, userKeyValStore } from "src/KeyValStore"; @@ -10,6 +10,8 @@ import { Palette } from "@hpcc-js/common"; const logger = scopedLogger("src-react/hooks/platform.ts"); +export const service = new LogaccessService({ baseUrl: "" }); + declare const dojoConfig; export function useBuildInfo(): [BuildInfo, { isContainer: boolean, currencyCode: string, opsCategory: string }] { @@ -205,4 +207,21 @@ export function useModernMode(): { }, [modernMode, sessionStore, userStore]); return { modernMode, setModernMode }; -} \ No newline at end of file +} + +export function useLogAccessInfo(): { + managerType: string; + columns: WsLogaccess.Column[] +} { + const [managerType, setManagerType] = React.useState(""); + const [columns, setColumns] = React.useState(); + + React.useEffect(() => { + service.GetLogAccessInfo({}).then(response => { + setManagerType(response.RemoteLogManagerType ?? ""); + setColumns(response?.Columns?.Column) + }); + }, []); + + return { managerType, columns }; +} \ No newline at end of file diff --git a/esp/src/src/Utility.ts b/esp/src/src/Utility.ts index cc78350ed6d..32c0a912f59 100644 --- a/esp/src/src/Utility.ts +++ b/esp/src/src/Utility.ts @@ -1307,4 +1307,12 @@ export function wuidToTime(wuid: string): string { export function wuidToDateTime(wuid: string): Date { return new Date(`${wuidToDate(wuid)}T${wuidToTime(wuid)}Z`); +} + +export function removeAllExcept(arr: any, keysToKeep: string[]): void { + for (const key of Object.keys(arr)) { + if (keysToKeep.indexOf(key) < 0) { + delete arr[key]; + } + } } \ No newline at end of file