Skip to content

Commit 0f276e5

Browse files
authored
feat(webui): Add compression job submission for local files only. (#1294)
1 parent 2f79349 commit 0f276e5

File tree

37 files changed

+581
-98
lines changed

37 files changed

+581
-98
lines changed

components/clp-package-utils/clp_package_utils/controller.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ def _set_up_env_for_webui(self, container_clp_config: ClpConfig) -> EnvVarsDict:
488488
client_settings_json_updates = {
489489
"ClpStorageEngine": self._clp_config.package.storage_engine,
490490
"ClpQueryEngine": self._clp_config.package.query_engine,
491+
"LogsInputType": self._clp_config.logs_input.type,
491492
"MongoDbSearchResultsMetadataCollectionName": (
492493
self._clp_config.webui.results_metadata_collection_name
493494
),

components/webui/client/public/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"ClpStorageEngine": "clp-s",
33
"ClpQueryEngine": "clp-s",
4+
"LogsInputType": "fs",
45
"MongoDbSearchResultsMetadataCollectionName": "results-metadata",
56
"SqlDbClpArchivesTableName": "clp_archives",
67
"SqlDbClpDatasetsTableName": "clp_datasets",
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {
2+
CompressionJob,
3+
CompressionJobCreation,
4+
} from "@webui/common/schemas/compression";
5+
import axios from "axios";
6+
7+
8+
/**
9+
* Submits a compression job.
10+
*
11+
* @param payload
12+
* @return
13+
*/
14+
const submitCompressionJob = async (payload: CompressionJobCreation): Promise<CompressionJob> => {
15+
console.log("Submitting compression job:", JSON.stringify(payload));
16+
const {data} = await axios.post<CompressionJob>("/api/compress", payload);
17+
18+
return data;
19+
};
20+
21+
22+
export {submitCompressionJob};

components/webui/client/src/config/index.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
import {CLP_QUERY_ENGINES} from "@webui/common/config";
1+
import {
2+
CLP_QUERY_ENGINES,
3+
CLP_STORAGE_ENGINES,
4+
STORAGE_TYPE,
5+
} from "@webui/common/config";
26

37
import {settings} from "../settings";
48

59

6-
/**
7-
* CLP variants.
8-
*/
9-
enum CLP_STORAGE_ENGINES {
10-
CLP = "clp",
11-
CLP_S = "clp-s",
12-
}
13-
10+
const SETTINGS_LOGS_INPUT_TYPE = settings.LogsInputType as STORAGE_TYPE;
1411
const SETTINGS_STORAGE_ENGINE = settings.ClpStorageEngine as CLP_STORAGE_ENGINES;
1512
const SETTINGS_QUERY_ENGINE = settings.ClpQueryEngine as CLP_QUERY_ENGINES;
1613

@@ -22,8 +19,7 @@ const STREAM_TYPE = CLP_STORAGE_ENGINES.CLP === SETTINGS_STORAGE_ENGINE ?
2219
"json";
2320

2421
export {
25-
CLP_QUERY_ENGINES,
26-
CLP_STORAGE_ENGINES,
22+
SETTINGS_LOGS_INPUT_TYPE,
2723
SETTINGS_QUERY_ENGINE,
2824
SETTINGS_STORAGE_ENGINE,
2925
STREAM_TYPE,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {CLP_DEFAULT_DATASET_NAME} from "@webui/common/config";
2+
import {
3+
Form,
4+
Input,
5+
} from "antd";
6+
7+
8+
const DATASET_HELPER_TEXT = `If left empty, dataset "${CLP_DEFAULT_DATASET_NAME}" will be used.`;
9+
const DATASET_PLACEHOLDER_TEXT = "The dataset for new archives";
10+
const TIMESTAMP_KEY_HELPER_TEXT = "If not provided, events will not have assigned" +
11+
" timestamps and can only be searched from the command line without a timestamp filter.";
12+
const TIMESTAMP_KEY_PLACEHOLDER_TEXT =
13+
"The path (e.g. x.y) for the field containing the log event's timestamp";
14+
15+
/**
16+
* Renders additional compression job submission form items for CLP-S storage engine.
17+
*
18+
* @return
19+
*/
20+
const ClpSFormItems = () => (
21+
<>
22+
<Form.Item
23+
label={"Dataset"}
24+
name={"dataset"}
25+
tooltip={DATASET_HELPER_TEXT}
26+
>
27+
<Input placeholder={DATASET_PLACEHOLDER_TEXT}/>
28+
</Form.Item>
29+
<Form.Item
30+
label={"Timestamp Key"}
31+
name={"timestampKey"}
32+
tooltip={TIMESTAMP_KEY_HELPER_TEXT}
33+
>
34+
<Input placeholder={TIMESTAMP_KEY_PLACEHOLDER_TEXT}/>
35+
</Form.Item>
36+
</>
37+
);
38+
39+
40+
export default ClpSFormItems;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {
2+
Form,
3+
Input,
4+
} from "antd";
5+
6+
7+
/**
8+
* Renders a form item for inputting file paths for compression job submission.
9+
*
10+
* @return
11+
*/
12+
const PathsInputFormItem = () => (
13+
<Form.Item
14+
label={"Paths"}
15+
name={"paths"}
16+
rules={[{required: true, message: "Please enter at least one path"}]}
17+
>
18+
<Input.TextArea
19+
autoSize={{minRows: 4, maxRows: 10}}
20+
placeholder={"Enter paths to compress, one per line"}/>
21+
</Form.Item>
22+
);
23+
24+
25+
export default PathsInputFormItem;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {
2+
Button,
3+
Form,
4+
} from "antd";
5+
6+
7+
interface SubmitFormItemProps {
8+
isSubmitting: boolean;
9+
}
10+
11+
/**
12+
* Render a submit button for a form.
13+
*
14+
* @param props
15+
* @param props.isSubmitting
16+
* @return
17+
*/
18+
const SubmitFormItem = ({isSubmitting}: SubmitFormItemProps) => (
19+
<Form.Item>
20+
<Button
21+
htmlType={"submit"}
22+
loading={isSubmitting}
23+
type={"primary"}
24+
>
25+
Submit
26+
</Button>
27+
</Form.Item>
28+
);
29+
30+
31+
export default SubmitFormItem;
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import {
2+
useMutation,
3+
useQueryClient,
4+
} from "@tanstack/react-query";
5+
import {
6+
CLP_DEFAULT_DATASET_NAME,
7+
CLP_STORAGE_ENGINES,
8+
} from "@webui/common/config";
9+
import {CompressionJobCreation} from "@webui/common/schemas/compression";
10+
import {
11+
Form,
12+
Typography,
13+
} from "antd";
14+
15+
import {submitCompressionJob} from "../../../api/compress";
16+
import {DashboardCard} from "../../../components/DashboardCard";
17+
import {SETTINGS_STORAGE_ENGINE} from "../../../config";
18+
import ClpSFormItems from "./ClpSFormItems";
19+
import PathsInputFormItem from "./PathsInputFormItem";
20+
import SubmitFormItem from "./SubmitFormItem";
21+
22+
23+
type FormValues = {
24+
paths: string;
25+
dataset?: string;
26+
timestampKey?: string;
27+
};
28+
29+
30+
/**
31+
* Renders a compression job submission form.
32+
*
33+
* @return
34+
*/
35+
const Compress = () => {
36+
const [form] = Form.useForm<FormValues>();
37+
38+
const queryClient = useQueryClient();
39+
const {
40+
mutate,
41+
isPending: isSubmitting,
42+
isSuccess,
43+
isError,
44+
data,
45+
error,
46+
} = useMutation({
47+
mutationFn: submitCompressionJob,
48+
onSettled: async () => {
49+
// Invalidate queries that are affected by a new compression job.
50+
await queryClient.invalidateQueries({queryKey: ["jobs"]});
51+
},
52+
onSuccess: () => {
53+
form.resetFields();
54+
},
55+
});
56+
57+
const handleSubmit = (values: FormValues) => {
58+
// eslint-disable-next-line no-warning-comments
59+
// TODO: replace the UI with a file selector and remove below string manipulation.
60+
// Convert multiline input to array of paths.
61+
const paths = values.paths
62+
.split("\n")
63+
.map((path) => path.trim())
64+
.filter((path) => 0 < path.length);
65+
66+
const payload: CompressionJobCreation = {paths};
67+
68+
if (CLP_STORAGE_ENGINES.CLP_S === SETTINGS_STORAGE_ENGINE) {
69+
payload.dataset = ("undefined" === typeof values.dataset) ?
70+
CLP_DEFAULT_DATASET_NAME :
71+
values.dataset;
72+
if ("undefined" !== typeof values.timestampKey) {
73+
payload.timestampKey = values.timestampKey;
74+
}
75+
}
76+
77+
mutate(payload);
78+
};
79+
80+
return (
81+
<DashboardCard title={"Submit Compression Job"}>
82+
<Form
83+
form={form}
84+
layout={"vertical"}
85+
onFinish={handleSubmit}
86+
>
87+
<PathsInputFormItem/>
88+
{CLP_STORAGE_ENGINES.CLP_S === SETTINGS_STORAGE_ENGINE && <ClpSFormItems/>}
89+
<SubmitFormItem isSubmitting={isSubmitting}/>
90+
91+
{isSuccess && (
92+
<Typography.Text type={"success"}>
93+
Compression job submitted successfully with ID:
94+
{" "}
95+
{data.jobId}
96+
</Typography.Text>
97+
)}
98+
{isError && (
99+
<Typography.Text type={"danger"}>
100+
Failed to submit compression job:
101+
{" "}
102+
{error instanceof Error ?
103+
error.message :
104+
"Unknown error"}
105+
</Typography.Text>
106+
)}
107+
</Form>
108+
</DashboardCard>
109+
);
110+
};
111+
112+
113+
export default Compress;

components/webui/client/src/pages/IngestPage/Details/index.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import {useQuery} from "@tanstack/react-query";
2+
import {CLP_STORAGE_ENGINES} from "@webui/common/config";
23
import dayjs from "dayjs";
34

4-
import {
5-
CLP_STORAGE_ENGINES,
6-
SETTINGS_STORAGE_ENGINE,
7-
} from "../../../config";
5+
import {SETTINGS_STORAGE_ENGINE} from "../../../config";
86
import {fetchDatasetNames} from "../../SearchPage/SearchControls/Dataset/sql";
97
import Files from "./Files";
108
import styles from "./index.module.css";

components/webui/client/src/pages/IngestPage/SpaceSavings/index.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import {useQuery} from "@tanstack/react-query";
2+
import {CLP_STORAGE_ENGINES} from "@webui/common/config";
23
import {theme} from "antd";
34

45
import {DashboardCard} from "../../../components/DashboardCard";
56
import Stat from "../../../components/Stat";
6-
import {
7-
CLP_STORAGE_ENGINES,
8-
SETTINGS_STORAGE_ENGINE,
9-
} from "../../../config";
7+
import {SETTINGS_STORAGE_ENGINE} from "../../../config";
108
import {fetchDatasetNames} from "../../SearchPage/SearchControls/Dataset/sql";
119
import CompressedSize from "./CompressedSize";
1210
import styles from "./index.module.css";

0 commit comments

Comments
 (0)