Skip to content

Commit

Permalink
HPCC-32747 ECL Watch v9 Log grids no pagination
Browse files Browse the repository at this point in the history
changes the ECL Watch v9 Logs grid to not use pagination, as Azure Log
Analytics does not support it
also, fixes an issue with the EndDate time having the wrong timezone

Signed-off-by: Jeremy Clements <[email protected]>
  • Loading branch information
jeclrsg committed Oct 1, 2024
1 parent 2c551a4 commit 00d177a
Showing 1 changed file with 57 additions and 49 deletions.
106 changes: 57 additions & 49 deletions esp/src/src-react/components/Logs.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import * as React from "react";
import { CommandBar, ContextualMenuItemType, ICommandBarItemProps } from "@fluentui/react";
import { useConst } from "@fluentui/react-hooks";
import { GetLogsExRequest, TargetAudience, LogType } from "@hpcc-js/comms";
import { Level } from "@hpcc-js/util";
import { CreateLogsQueryStore } from "src/ESPLog";
import { GetLogsExRequest, LogaccessService, TargetAudience, LogType } from "@hpcc-js/comms";
import { Level, scopedLogger } from "@hpcc-js/util";
import nlsHPCC from "src/nlsHPCC";
import { logColor, wuidToDate, wuidToTime } from "src/Utility";
import { HolyGrail } from "../layouts/HolyGrail";
import { pushParams } from "../util/history";
import { FluentPagedGrid, FluentPagedFooter, useCopyButtons, useFluentStoreState, FluentColumns } from "./controls/Grid";
import { FluentGrid, useCopyButtons, useFluentStoreState, FluentColumns } from "./controls/Grid";
import { Filter } from "./forms/Filter";
import { Fields } from "./forms/Fields";
import { ShortVerticalDivider } from "./Common";

export const service = new LogaccessService({ baseUrl: "" });

const logger = scopedLogger("src-react/components/Logs.tsx");

const eightHours = 8 * 60 * 60 * 1000;
const startTimeOffset = 1 * 60 * 60 * 1000;
const endTimeOffset = 23 * 60 * 60 * 1000;
Expand Down Expand Up @@ -42,6 +44,14 @@ const FilterFields: Fields = {
processid: { type: "string", label: nlsHPCC.ProcessID },
threadid: { type: "string", label: nlsHPCC.ThreadID },
message: { type: "string", label: nlsHPCC.Message },
LogLineLimit: {
type: "dropdown", label: nlsHPCC.LogLineLimit, options: [
{ key: 100, text: "100" },
{ key: 250, text: "250" },
{ key: 500, text: "500" },
{ key: 1000, text: "1000" },
]
},
StartDate: { type: "datetime", label: nlsHPCC.FromDate },
EndDate: { type: "datetime", label: nlsHPCC.ToDate },
};
Expand Down Expand Up @@ -91,17 +101,37 @@ export const Logs: React.FunctionComponent<LogsProps> = ({

const hasFilter = React.useMemo(() => Object.keys(filter).length > 0, [filter]);
const [showFilter, setShowFilter] = React.useState(false);
const [data, setData] = React.useState<any[]>([]);
const {
selection, setSelection,
pageNum, setPageNum,
pageSize, setPageSize,
total, setTotal,
setTotal,
refreshTable } = useFluentStoreState({ page });

const now = React.useMemo(() => new Date(), []);

// Grid ---
const gridStore = useConst(() => CreateLogsQueryStore());
const columns = React.useMemo((): FluentColumns => {
return {
timestamp: { label: nlsHPCC.TimeStamp, width: 140, sortable: false, },
message: { label: nlsHPCC.Message, width: 600, sortable: false, },
components: { label: nlsHPCC.ContainerName, width: 150, sortable: false },
audience: { label: nlsHPCC.Audience, width: 60, sortable: false, },
class: {
label: nlsHPCC.Class, width: 40, sortable: false,
formatter: level => {
const colors = logColor(levelMap(level));
const styles = { backgroundColor: colors.background, padding: "2px 6px", color: colors.foreground };
return <span style={styles}>{level}</span>;
}
},
workunits: { label: nlsHPCC.JobID, width: 50, sortable: false, hidden: wuid !== undefined, },
processid: { label: nlsHPCC.ProcessID, width: 75, sortable: false, },
logid: { label: nlsHPCC.Sequence, width: 70, sortable: false, },
threadid: { label: nlsHPCC.ThreadID, width: 60, sortable: false, },
};
}, [wuid]);

const copyButtons = useCopyButtons(columns, selection, "logaccess");

const query = React.useMemo(() => {
if (wuid !== undefined) {
Expand All @@ -119,41 +149,27 @@ export const Logs: React.FunctionComponent<LogsProps> = ({
//assign a reasonable default start date if one isn't set
filter.StartDate = new Date(now.getTime() - eightHours);
}
if (typeof filter.EndDate === "string") {
filter.EndDate = new Date(filter.EndDate + ":00Z");
}
if (!filter.EndDate) {
filter.EndDate = new Date(now.getTime() + endTimeOffset);
}
}
return formatQuery(filter);
}, [filter, now, wuid]);

const columns = React.useMemo((): FluentColumns => {
return {
timestamp: { label: nlsHPCC.TimeStamp, width: 140, sortable: false, },
message: { label: nlsHPCC.Message, sortable: false, },
components: { label: nlsHPCC.ContainerName, width: 150, sortable: false },
audience: { label: nlsHPCC.Audience, width: 60, sortable: false, },
class: {
label: nlsHPCC.Class, width: 40, sortable: false,
formatter: level => {
const colors = logColor(levelMap(level));
const styles = { backgroundColor: colors.background, padding: "2px 6px", color: colors.foreground };
return <span style={styles}>{level}</span>;
}
},
workunits: { label: nlsHPCC.JobID, width: 50, sortable: false, hidden: wuid !== undefined, },
processid: { label: nlsHPCC.ProcessID, width: 75, sortable: false, },
logid: { label: nlsHPCC.Sequence, width: 70, sortable: false, },
threadid: { label: nlsHPCC.ThreadID, width: 60, sortable: false, },
};
}, [wuid]);

const copyButtons = useCopyButtons(columns, selection, "logaccess");
const refreshData = React.useCallback(() => {
service.GetLogsEx(query as any).then(response => {
setData(response.lines);
}).catch(err => logger.error(err));
}, [query]);

// Command Bar ---
const buttons = React.useMemo((): ICommandBarItemProps[] => [
{
key: "refresh", text: nlsHPCC.Refresh, iconProps: { iconName: "Refresh" },
onClick: () => refreshTable.call()
onClick: () => refreshData()
},
{ key: "divider_1", itemType: ContextualMenuItemType.Divider, onRender: () => <ShortVerticalDivider /> },
{
Expand All @@ -162,7 +178,11 @@ export const Logs: React.FunctionComponent<LogsProps> = ({
setShowFilter(true);
}
},
], [hasFilter, refreshTable]);
], [hasFilter, refreshData]);

React.useEffect(() => {
refreshData();
}, [refreshData]);

// Filter ---
const filterFields: Fields = React.useMemo(() => {
Expand All @@ -181,12 +201,9 @@ export const Logs: React.FunctionComponent<LogsProps> = ({
header={<CommandBar items={buttons} farItems={copyButtons} />}
main={
<div style={{ position: "relative", height: "100%" }}>
<FluentPagedGrid
store={gridStore}
query={query}
pageNum={pageNum}
pageSize={pageSize}
total={total}
<FluentGrid
data={data}
primaryID={""}
columns={columns}
setSelection={setSelection}
setTotal={(total) => {
Expand All @@ -196,18 +213,9 @@ export const Logs: React.FunctionComponent<LogsProps> = ({
}
}}
refresh={refreshTable}
></FluentPagedGrid>
></FluentGrid>
<Filter showFilter={showFilter} setShowFilter={setShowFilter} filterFields={filterFields} onApply={pushParams} />
</div>
}
footer={<FluentPagedFooter
persistID={"cloudlogs"}
pageNum={pageNum}
selectionCount={selection.length}
setPageNum={setPageNum}
setPageSize={setPageSize}
total={total}
></FluentPagedFooter>}
footerStyles={{}}
/>;
};

0 comments on commit 00d177a

Please sign in to comment.