mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
expand rowy logging into tabs: extension, webhook, column(derivative/action/default value/connector)
This commit is contained in:
@@ -142,7 +142,7 @@ export const selectedCellAtom = atom<SelectedCell | null>(null);
|
||||
export const contextMenuTargetAtom = atom<HTMLElement | null>(null);
|
||||
|
||||
export type CloudLogFilters = {
|
||||
type: "rowy" | "audit" | "build";
|
||||
type: "extension" | "webhook" | "column" | "audit" | "build";
|
||||
timeRange:
|
||||
| { type: "seconds" | "minutes" | "hours" | "days"; value: number }
|
||||
| { type: "range"; start: Date; end: Date };
|
||||
|
||||
@@ -25,7 +25,6 @@ import {
|
||||
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
|
||||
import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
|
||||
import EditIcon from "@mui/icons-material/EditOutlined";
|
||||
// import ReorderIcon from "@mui/icons-material/Reorder";
|
||||
import SettingsIcon from "@mui/icons-material/SettingsOutlined";
|
||||
import EvalIcon from "@mui/icons-material/PlayCircleOutline";
|
||||
|
||||
@@ -319,24 +318,19 @@ export default function ColumnMenu({
|
||||
},
|
||||
disabled: !isConfigurable,
|
||||
},
|
||||
// {
|
||||
// label: "Re-order",
|
||||
// icon: <ReorderIcon />,
|
||||
// onClick: () => alert("REORDER"),
|
||||
// },
|
||||
|
||||
// {
|
||||
// label: "Hide for everyone",
|
||||
// activeLabel: "Show",
|
||||
// icon: <VisibilityOffIcon />,
|
||||
// activeIcon: <VisibilityIcon />,
|
||||
// onClick: () => {
|
||||
// actions.update(column.key, { hidden: !column.hidden });
|
||||
// handleClose();
|
||||
// },
|
||||
// active: column.hidden,
|
||||
// color: "error" as "error",
|
||||
// },
|
||||
{
|
||||
key: "logs",
|
||||
label: altPress ? "Logs" : "Logs…",
|
||||
icon: <LogsIcon />,
|
||||
onClick: () => {
|
||||
setModal("cloudLogs");
|
||||
setCloudLogFilters({
|
||||
type: "column",
|
||||
timeRange: { type: "days", value: 7 },
|
||||
column: [column.key],
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// TODO: Generalize
|
||||
@@ -388,19 +382,6 @@ export default function ColumnMenu({
|
||||
confirm: "Evaluate",
|
||||
}),
|
||||
},
|
||||
{
|
||||
key: "logs",
|
||||
label: altPress ? "Logs" : "Logs…",
|
||||
icon: <LogsIcon />,
|
||||
onClick: () => {
|
||||
setModal("cloudLogs");
|
||||
setCloudLogFilters({
|
||||
type: "rowy",
|
||||
timeRange: { type: "days", value: 7 },
|
||||
column: [column.key],
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const columnActions: IMenuContentsProps["menuItems"] = [
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
InputAdornment,
|
||||
Button,
|
||||
Box,
|
||||
CircularProgress,
|
||||
} from "@mui/material";
|
||||
import RefreshIcon from "@mui/icons-material/Refresh";
|
||||
import { CloudLogs as LogsIcon } from "@src/assets/icons";
|
||||
@@ -96,7 +97,7 @@ export default function CloudLogsModal({ onClose }: ITableModalProps) {
|
||||
"&, & .MuiTab-root": {
|
||||
minHeight: { md: "var(--dialog-title-height)" },
|
||||
},
|
||||
ml: { md: 18 },
|
||||
ml: { md: 20 },
|
||||
mr: { md: 40 / 8 + 3 },
|
||||
|
||||
minHeight: 32,
|
||||
@@ -114,15 +115,17 @@ export default function CloudLogsModal({ onClose }: ITableModalProps) {
|
||||
<ToggleButtonGroup
|
||||
value={cloudLogFilters.type}
|
||||
exclusive
|
||||
onChange={(_, v) =>
|
||||
onChange={(_, v) => {
|
||||
setCloudLogFilters((c) => ({
|
||||
type: v,
|
||||
timeRange: c.timeRange,
|
||||
}))
|
||||
}
|
||||
}));
|
||||
}}
|
||||
aria-label="Filter by log type"
|
||||
>
|
||||
<ToggleButton value="rowy">Rowy Logging</ToggleButton>
|
||||
<ToggleButton value="extension">Extension</ToggleButton>
|
||||
<ToggleButton value="webhook">Webhook</ToggleButton>
|
||||
<ToggleButton value="column">Column</ToggleButton>
|
||||
<ToggleButton value="audit">Audit</ToggleButton>
|
||||
<ToggleButton value="build">Build</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
@@ -142,154 +145,18 @@ export default function CloudLogsModal({ onClose }: ITableModalProps) {
|
||||
</ToggleButtonGroup>
|
||||
)}
|
||||
|
||||
{cloudLogFilters.type === "rowy" && <></>}
|
||||
{cloudLogFilters.type === "audit" && (
|
||||
<TextField
|
||||
id="auditRowId"
|
||||
label="Row ID:"
|
||||
value={cloudLogFilters.auditRowId}
|
||||
onChange={(e) =>
|
||||
setCloudLogFilters((prev) => ({
|
||||
...prev,
|
||||
auditRowId: e.target.value,
|
||||
}))
|
||||
}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
{tableSettings.collection}/
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
className="labelHorizontal"
|
||||
sx={{
|
||||
"& .MuiInputBase-root, & .MuiInputBase-input": {
|
||||
typography: "body2",
|
||||
fontFamily: "mono",
|
||||
},
|
||||
"& .MuiInputAdornment-positionStart": {
|
||||
m: "0 !important",
|
||||
pointerEvents: "none",
|
||||
},
|
||||
"& .MuiInputBase-input": { pl: 0 },
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div style={{ flexGrow: 1 }} />
|
||||
|
||||
{cloudLogFilters.type !== "build" && (
|
||||
<>
|
||||
{!isValidating && Array.isArray(data) && (
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.disabled"
|
||||
display="block"
|
||||
style={{ userSelect: "none" }}
|
||||
>
|
||||
{data.length} entries
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
{cloudLogFilters.type !== "rowy" && (
|
||||
<MultiSelect
|
||||
aria-label="Severity"
|
||||
labelPlural="severity levels"
|
||||
options={Object.keys(SEVERITY_LEVELS)}
|
||||
value={cloudLogFilters.severity ?? []}
|
||||
onChange={(severity) =>
|
||||
setCloudLogFilters((prev) => ({ ...prev, severity }))
|
||||
}
|
||||
TextFieldProps={{
|
||||
style: { width: 130 },
|
||||
placeholder: "Severity",
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
if (
|
||||
!Array.isArray(cloudLogFilters.severity) ||
|
||||
cloudLogFilters.severity.length === 0
|
||||
)
|
||||
return `Severity`;
|
||||
|
||||
if (cloudLogFilters.severity.length === 1)
|
||||
return (
|
||||
<>
|
||||
Severity{" "}
|
||||
<CloudLogSeverityIcon
|
||||
severity={cloudLogFilters.severity[0]}
|
||||
style={{ marginTop: -2, marginBottom: -7 }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
return `Severity (${cloudLogFilters.severity.length})`;
|
||||
},
|
||||
},
|
||||
}}
|
||||
itemRenderer={(option) => (
|
||||
<>
|
||||
<CloudLogSeverityIcon
|
||||
severity={option.value}
|
||||
sx={{ mr: 1 }}
|
||||
/>
|
||||
{startCase(option.value.toLowerCase())}
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<TimeRangeSelect
|
||||
aria-label="Time range"
|
||||
value={cloudLogFilters.timeRange}
|
||||
onChange={(value) =>
|
||||
setCloudLogFilters((c) => ({ ...c, timeRange: value }))
|
||||
}
|
||||
/>
|
||||
<TableToolbarButton
|
||||
onClick={() => mutate()}
|
||||
title="Refresh"
|
||||
icon={<RefreshIcon />}
|
||||
disabled={isValidating}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
{isValidating && (
|
||||
<LinearProgress
|
||||
style={{
|
||||
borderRadius: 0,
|
||||
marginTop: -4,
|
||||
marginBottom: -1,
|
||||
minHeight: 4,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
>
|
||||
{cloudLogFilters.type === "build" ? (
|
||||
<BuildLogs />
|
||||
) : (
|
||||
<Box
|
||||
sx={{
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
overflowY: "visible",
|
||||
}}
|
||||
>
|
||||
<Box mt={1}>
|
||||
{cloudLogFilters.type === "rowy" ? (
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={2}
|
||||
justifyContent="flex-start"
|
||||
alignItems="center"
|
||||
sx={{
|
||||
overflowX: "auto",
|
||||
overflowY: "hidden",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.disabled"
|
||||
display="block"
|
||||
style={{ userSelect: "none" }}
|
||||
>
|
||||
{isValidating ? "Loading" : `${data?.length ?? 0} entries`}
|
||||
</Typography>
|
||||
<Button
|
||||
onClick={(v) => {
|
||||
setCloudLogFilters((prev) => ({
|
||||
@@ -304,77 +171,101 @@ export default function CloudLogsModal({ onClose }: ITableModalProps) {
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
<MultiSelect
|
||||
multiple
|
||||
SearchBoxProps={{
|
||||
sx: { display: "none" },
|
||||
}}
|
||||
aria-label="Type:"
|
||||
options={[
|
||||
"extension",
|
||||
"hooks",
|
||||
"action",
|
||||
"derivative-script",
|
||||
"derivative-function",
|
||||
"defaultValue",
|
||||
"connector",
|
||||
]}
|
||||
value={cloudLogFilters.functionType ?? []}
|
||||
onChange={(v) => {
|
||||
setCloudLogFilters((prev) => ({
|
||||
...prev,
|
||||
functionType: v,
|
||||
}));
|
||||
}}
|
||||
TextFieldProps={{
|
||||
id: "functionType",
|
||||
className: "labelHorizontal",
|
||||
sx: { "& .MuiInputBase-root": { width: 200 } },
|
||||
fullWidth: false,
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
if (cloudLogFilters?.functionType?.length === 1) {
|
||||
return `Type (${cloudLogFilters.functionType[0]})`;
|
||||
} else if (cloudLogFilters?.functionType?.length) {
|
||||
return `Type (${cloudLogFilters.functionType.length})`;
|
||||
} else {
|
||||
return `Type`;
|
||||
}
|
||||
},
|
||||
},
|
||||
}}
|
||||
itemRenderer={(option) => <>{upperCase(option.value)}</>}
|
||||
|
||||
<TableToolbarButton
|
||||
onClick={() => mutate()}
|
||||
title="Refresh"
|
||||
icon={
|
||||
isValidating ? (
|
||||
<CircularProgress size={15} thickness={4} />
|
||||
) : (
|
||||
<RefreshIcon />
|
||||
)
|
||||
}
|
||||
disabled={isValidating}
|
||||
/>
|
||||
<MultiSelect
|
||||
multiple
|
||||
aria-label="Source:"
|
||||
options={["backend-scripts", "backend-function", "hooks"]}
|
||||
value={cloudLogFilters.loggingSource ?? []}
|
||||
onChange={(v) => {
|
||||
setCloudLogFilters((prev) => ({
|
||||
...prev,
|
||||
loggingSource: v,
|
||||
}));
|
||||
}}
|
||||
TextFieldProps={{
|
||||
id: "loggingSource",
|
||||
className: "labelHorizontal",
|
||||
sx: { "& .MuiInputBase-root": { width: 200 } },
|
||||
fullWidth: false,
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
if (cloudLogFilters?.loggingSource?.length === 1) {
|
||||
return `Source (${cloudLogFilters.loggingSource[0]})`;
|
||||
} else if (cloudLogFilters?.loggingSource?.length) {
|
||||
return `Source (${cloudLogFilters.loggingSource.length})`;
|
||||
} else {
|
||||
return `Source`;
|
||||
}
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</>
|
||||
}
|
||||
>
|
||||
{cloudLogFilters.type === "build" ? (
|
||||
<BuildLogs />
|
||||
) : (
|
||||
<Box
|
||||
sx={{
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
overflowY: "visible",
|
||||
}}
|
||||
>
|
||||
{["extension", "webhook", "column", "audit"].includes(
|
||||
cloudLogFilters.type
|
||||
) ? (
|
||||
<Stack
|
||||
width={"100%"}
|
||||
direction="row"
|
||||
spacing={2}
|
||||
justifyContent="flex-start"
|
||||
alignItems="center"
|
||||
sx={{
|
||||
overflowX: "auto",
|
||||
overflowY: "hidden",
|
||||
margin: "8px 0",
|
||||
flex: "0 0 32px",
|
||||
}}
|
||||
>
|
||||
{cloudLogFilters.type === "extension" ? (
|
||||
<>
|
||||
<MultiSelect
|
||||
multiple
|
||||
aria-label={"Extension"}
|
||||
labelPlural="extensions"
|
||||
options={
|
||||
Array.isArray(tableSchema.extensionObjects)
|
||||
? tableSchema.extensionObjects.map((x) => ({
|
||||
label: x.name,
|
||||
value: x.name,
|
||||
type: x.type,
|
||||
}))
|
||||
: []
|
||||
}
|
||||
value={cloudLogFilters.extension ?? []}
|
||||
onChange={(v) =>
|
||||
setCloudLogFilters((prev) => ({ ...prev, extension: v }))
|
||||
}
|
||||
TextFieldProps={{
|
||||
id: "extension",
|
||||
className: "labelHorizontal",
|
||||
sx: {
|
||||
width: "100%",
|
||||
"& .MuiInputBase-root": { width: "100%" },
|
||||
},
|
||||
},
|
||||
}}
|
||||
itemRenderer={(option) => <>{upperCase(option.value)}</>}
|
||||
/>
|
||||
fullWidth: false,
|
||||
placeholder: "Extension",
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
if (cloudLogFilters?.extension?.length === 1) {
|
||||
return `Extension (${cloudLogFilters.extension[0]})`;
|
||||
} else if (cloudLogFilters?.extension?.length) {
|
||||
return `Extension (${cloudLogFilters.extension.length})`;
|
||||
} else {
|
||||
return `Extension`;
|
||||
}
|
||||
},
|
||||
},
|
||||
}}
|
||||
itemRenderer={(option) => (
|
||||
<>
|
||||
{option.label} <code>{option.type}</code>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
{cloudLogFilters.type === "webhook" ? (
|
||||
<MultiSelect
|
||||
multiple
|
||||
aria-label="Webhook:"
|
||||
@@ -394,7 +285,10 @@ export default function CloudLogsModal({ onClose }: ITableModalProps) {
|
||||
TextFieldProps={{
|
||||
id: "webhook",
|
||||
className: "labelHorizontal",
|
||||
sx: { "& .MuiInputBase-root": { width: 180 } },
|
||||
sx: {
|
||||
width: "100%",
|
||||
"& .MuiInputBase-root": { width: "100%" },
|
||||
},
|
||||
fullWidth: false,
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
@@ -412,133 +306,145 @@ export default function CloudLogsModal({ onClose }: ITableModalProps) {
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<MultiSelect
|
||||
multiple
|
||||
aria-label={"Extension"}
|
||||
labelPlural="extensions"
|
||||
options={
|
||||
Array.isArray(tableSchema.extensionObjects)
|
||||
? tableSchema.extensionObjects.map((x) => ({
|
||||
label: x.name,
|
||||
value: x.name,
|
||||
type: x.type,
|
||||
}))
|
||||
: []
|
||||
}
|
||||
value={cloudLogFilters.extension ?? []}
|
||||
onChange={(v) =>
|
||||
setCloudLogFilters((prev) => ({ ...prev, extension: v }))
|
||||
}
|
||||
TextFieldProps={{
|
||||
id: "extension",
|
||||
className: "labelHorizontal",
|
||||
sx: { "& .MuiInputBase-root": { width: 180 } },
|
||||
fullWidth: false,
|
||||
placeholder: "Extension",
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
if (cloudLogFilters?.extension?.length === 1) {
|
||||
return `Extension (${cloudLogFilters.extension[0]})`;
|
||||
} else if (cloudLogFilters?.extension?.length) {
|
||||
return `Extension (${cloudLogFilters.extension.length})`;
|
||||
} else {
|
||||
return `Extension`;
|
||||
}
|
||||
) : null}
|
||||
{cloudLogFilters.type === "column" ? (
|
||||
<>
|
||||
<MultiSelect
|
||||
multiple
|
||||
aria-label={"Column"}
|
||||
options={Object.entries(tableSchema.columns ?? {}).map(
|
||||
([key, config]) => ({
|
||||
label: config.name,
|
||||
value: key,
|
||||
type: config.type,
|
||||
})
|
||||
)}
|
||||
value={cloudLogFilters.column ?? []}
|
||||
onChange={(v) =>
|
||||
setCloudLogFilters((prev) => ({ ...prev, column: v }))
|
||||
}
|
||||
TextFieldProps={{
|
||||
id: "column",
|
||||
className: "labelHorizontal",
|
||||
sx: {
|
||||
width: "100%",
|
||||
"& .MuiInputBase-root": { width: "100%" },
|
||||
},
|
||||
},
|
||||
}}
|
||||
itemRenderer={(option) => (
|
||||
<>
|
||||
{option.label} <code>{option.type}</code>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<MultiSelect
|
||||
multiple
|
||||
aria-label={"Column"}
|
||||
options={Object.entries(tableSchema.columns ?? {}).map(
|
||||
([key, config]) => ({
|
||||
label: config.name,
|
||||
value: key,
|
||||
type: config.type,
|
||||
})
|
||||
)}
|
||||
value={cloudLogFilters.column ?? []}
|
||||
onChange={(v) =>
|
||||
setCloudLogFilters((prev) => ({ ...prev, column: v }))
|
||||
}
|
||||
TextFieldProps={{
|
||||
id: "column",
|
||||
className: "labelHorizontal",
|
||||
sx: { "& .MuiInputBase-root": { width: 200 } },
|
||||
fullWidth: false,
|
||||
placeholder: "Column",
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
if (cloudLogFilters?.column?.length === 1) {
|
||||
return `Column (${cloudLogFilters.column[0]})`;
|
||||
} else if (cloudLogFilters?.column?.length) {
|
||||
return `Column (${cloudLogFilters.column.length})`;
|
||||
} else {
|
||||
return `Column`;
|
||||
}
|
||||
fullWidth: false,
|
||||
placeholder: "Column",
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
if (cloudLogFilters?.column?.length === 1) {
|
||||
return `Column (${cloudLogFilters.column[0]})`;
|
||||
} else if (cloudLogFilters?.column?.length) {
|
||||
return `Column (${cloudLogFilters.column.length})`;
|
||||
} else {
|
||||
return `Column`;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
itemRenderer={(option) => (
|
||||
<>
|
||||
{option.label} <code>{option.value}</code>
|
||||
<code>{option.type}</code>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<MultiSelect
|
||||
aria-label="Severity"
|
||||
labelPlural="severity levels"
|
||||
options={Object.keys(SEVERITY_LEVELS_ROWY)}
|
||||
value={cloudLogFilters.severity ?? []}
|
||||
onChange={(severity) =>
|
||||
setCloudLogFilters((prev) => ({ ...prev, severity }))
|
||||
}
|
||||
TextFieldProps={{
|
||||
style: { width: 130 },
|
||||
placeholder: "Severity",
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
if (
|
||||
!Array.isArray(cloudLogFilters.severity) ||
|
||||
cloudLogFilters.severity.length === 0
|
||||
)
|
||||
return `Severity`;
|
||||
}}
|
||||
itemRenderer={(option) => (
|
||||
<>
|
||||
{option.label} <code>{option.value}</code>
|
||||
<code>{option.type}</code>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
{cloudLogFilters.type === "audit" ? (
|
||||
<>
|
||||
<TextField
|
||||
id="auditRowId"
|
||||
label="Row ID:"
|
||||
value={cloudLogFilters.auditRowId}
|
||||
onChange={(e) =>
|
||||
setCloudLogFilters((prev) => ({
|
||||
...prev,
|
||||
auditRowId: e.target.value,
|
||||
}))
|
||||
}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
{tableSettings.collection}/
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
className="labelHorizontal"
|
||||
sx={{
|
||||
width: "100%",
|
||||
"& .MuiInputBase-root, & .MuiInputBase-input": {
|
||||
width: "100%",
|
||||
typography: "body2",
|
||||
fontFamily: "mono",
|
||||
},
|
||||
"& .MuiInputAdornment-positionStart": {
|
||||
m: "0 !important",
|
||||
pointerEvents: "none",
|
||||
},
|
||||
"& .MuiInputBase-input": { pl: 0 },
|
||||
"& .MuiFormLabel-root": {
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
<MultiSelect
|
||||
aria-label="Severity"
|
||||
labelPlural="severity levels"
|
||||
options={Object.keys(SEVERITY_LEVELS_ROWY)}
|
||||
value={cloudLogFilters.severity ?? []}
|
||||
onChange={(severity) =>
|
||||
setCloudLogFilters((prev) => ({ ...prev, severity }))
|
||||
}
|
||||
TextFieldProps={{
|
||||
style: { width: 200 },
|
||||
placeholder: "Severity",
|
||||
SelectProps: {
|
||||
renderValue: () => {
|
||||
if (
|
||||
!Array.isArray(cloudLogFilters.severity) ||
|
||||
cloudLogFilters.severity.length === 0
|
||||
)
|
||||
return `Severity`;
|
||||
|
||||
if (cloudLogFilters.severity.length === 1)
|
||||
return (
|
||||
<>
|
||||
Severity{" "}
|
||||
<CloudLogSeverityIcon
|
||||
severity={cloudLogFilters.severity[0]}
|
||||
style={{ marginTop: -2, marginBottom: -7 }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
if (cloudLogFilters.severity.length === 1)
|
||||
return (
|
||||
<>
|
||||
Severity{" "}
|
||||
<CloudLogSeverityIcon
|
||||
severity={cloudLogFilters.severity[0]}
|
||||
style={{ marginTop: -2, marginBottom: -7 }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
return `Severity (${cloudLogFilters.severity.length})`;
|
||||
},
|
||||
return `Severity (${cloudLogFilters.severity.length})`;
|
||||
},
|
||||
}}
|
||||
itemRenderer={(option) => (
|
||||
<>
|
||||
<CloudLogSeverityIcon
|
||||
severity={option.value}
|
||||
sx={{ mr: 1 }}
|
||||
/>
|
||||
{startCase(option.value.toLowerCase())}
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</Stack>
|
||||
) : null}
|
||||
</Box>
|
||||
},
|
||||
}}
|
||||
itemRenderer={(option) => (
|
||||
<>
|
||||
<CloudLogSeverityIcon
|
||||
severity={option.value}
|
||||
sx={{ mr: 1 }}
|
||||
/>
|
||||
{startCase(option.value.toLowerCase())}
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
<TimeRangeSelect
|
||||
aria-label="Time range"
|
||||
value={cloudLogFilters.timeRange}
|
||||
onChange={(value) =>
|
||||
setCloudLogFilters((c) => ({ ...c, timeRange: value }))
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
) : null}
|
||||
<Box
|
||||
sx={{
|
||||
overflowY: "scroll",
|
||||
@@ -580,7 +486,7 @@ export default function CloudLogsModal({ onClose }: ITableModalProps) {
|
||||
Icon={LogsIcon}
|
||||
message="No logs"
|
||||
description={
|
||||
cloudLogFilters.type === "rowy"
|
||||
cloudLogFilters.type !== "audit"
|
||||
? "There are no logs matching the filters"
|
||||
: cloudLogFilters.type === "audit" &&
|
||||
tableSettings.audit === false
|
||||
|
||||
@@ -19,7 +19,9 @@ export default function TimeRangeSelect({
|
||||
...props
|
||||
}: ITimeRangeSelectProps) {
|
||||
return (
|
||||
<fieldset style={{ appearance: "none", padding: 0, border: 0 }}>
|
||||
<fieldset
|
||||
style={{ appearance: "none", padding: 0, border: 0, display: "flex" }}
|
||||
>
|
||||
{value && value.type !== "range" && (
|
||||
<TextField
|
||||
aria-label={`Custom ${value.type} value`}
|
||||
|
||||
@@ -12,43 +12,21 @@ export const cloudLogFetcher = (
|
||||
// https://cloud.google.com/logging/docs/view/logging-query-language
|
||||
let logQuery: string[] = [];
|
||||
|
||||
if (["extension", "webhook", "column"].includes(cloudLogFilters.type)) {
|
||||
// mandatory filter to remove unwanted gcp diagnostic logs
|
||||
logQuery.push(
|
||||
["backend-scripts", "backend-function", "hooks"]
|
||||
.map((loggingSource) => {
|
||||
return `jsonPayload.loggingSource = "${loggingSource}"`;
|
||||
})
|
||||
.join(encodeURIComponent(" OR "))
|
||||
);
|
||||
}
|
||||
|
||||
switch (cloudLogFilters.type) {
|
||||
case "rowy":
|
||||
case "extension":
|
||||
logQuery.push(`logName = "projects/${projectId}/logs/rowy-logging"`);
|
||||
if (cloudLogFilters?.functionType?.length)
|
||||
logQuery.push(
|
||||
cloudLogFilters.functionType
|
||||
.map((functionType) => {
|
||||
return `jsonPayload.functionType = "${functionType}"`;
|
||||
})
|
||||
.join(encodeURIComponent(" OR "))
|
||||
);
|
||||
if (cloudLogFilters?.loggingSource?.length) {
|
||||
logQuery.push(
|
||||
cloudLogFilters.loggingSource
|
||||
.map((loggingSource) => {
|
||||
return `jsonPayload.loggingSource = "${loggingSource}"`;
|
||||
})
|
||||
.join(encodeURIComponent(" OR "))
|
||||
);
|
||||
} else {
|
||||
// mandatory filter to remove unwanted gcp diagnostic logs
|
||||
logQuery.push(
|
||||
["backend-scripts", "backend-function", "hooks"]
|
||||
.map((loggingSource) => {
|
||||
return `jsonPayload.loggingSource = "${loggingSource}"`;
|
||||
})
|
||||
.join(encodeURIComponent(" OR "))
|
||||
);
|
||||
}
|
||||
if (cloudLogFilters?.webhook?.length) {
|
||||
logQuery.push(
|
||||
cloudLogFilters.webhook
|
||||
.map((id) => `jsonPayload.url : "${id}"`)
|
||||
.join(encodeURIComponent(" OR "))
|
||||
);
|
||||
}
|
||||
if (cloudLogFilters?.extension?.length)
|
||||
if (cloudLogFilters?.extension?.length) {
|
||||
logQuery.push(
|
||||
cloudLogFilters.extension
|
||||
.map((extensionName) => {
|
||||
@@ -56,7 +34,25 @@ export const cloudLogFetcher = (
|
||||
})
|
||||
.join(encodeURIComponent(" OR "))
|
||||
);
|
||||
if (cloudLogFilters?.column?.length)
|
||||
} else {
|
||||
logQuery.push(`jsonPayload.functionType = "extension"`);
|
||||
}
|
||||
break;
|
||||
|
||||
case "webhook":
|
||||
if (cloudLogFilters?.webhook?.length) {
|
||||
logQuery.push(
|
||||
cloudLogFilters.webhook
|
||||
.map((id) => `jsonPayload.url : "${id}"`)
|
||||
.join(encodeURIComponent(" OR "))
|
||||
);
|
||||
} else {
|
||||
logQuery.push(`jsonPayload.functionType = "hooks"`);
|
||||
}
|
||||
break;
|
||||
|
||||
case "column":
|
||||
if (cloudLogFilters?.column?.length) {
|
||||
logQuery.push(
|
||||
cloudLogFilters.column
|
||||
.map((column) => {
|
||||
@@ -64,6 +60,21 @@ export const cloudLogFetcher = (
|
||||
})
|
||||
.join(encodeURIComponent(" OR "))
|
||||
);
|
||||
} else {
|
||||
logQuery.push(
|
||||
[
|
||||
"connector",
|
||||
"derivative-script",
|
||||
"action",
|
||||
"derivative-function",
|
||||
"defaultValue",
|
||||
]
|
||||
.map((functionType) => {
|
||||
return `jsonPayload.functionType = "${functionType}"`;
|
||||
})
|
||||
.join(encodeURIComponent(" OR "))
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case "audit":
|
||||
|
||||
@@ -107,8 +107,7 @@ export default function ExtensionList({
|
||||
onClick={() => {
|
||||
setModal("cloudLogs");
|
||||
setCloudLogFilters({
|
||||
type: "rowy",
|
||||
functionType: ["extension"],
|
||||
type: "extension",
|
||||
timeRange: { type: "days", value: 7 },
|
||||
extension: [extensionObject.name],
|
||||
});
|
||||
|
||||
@@ -126,8 +126,7 @@ export default function WebhookList({
|
||||
onClick={() => {
|
||||
setModal("cloudLogs");
|
||||
setCloudLogFilters({
|
||||
type: "rowy",
|
||||
functionType: ["hooks"],
|
||||
type: "webhook",
|
||||
timeRange: { type: "days", value: 7 },
|
||||
webhook: [webhook.endpoint],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user