mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 16:09:05 +00:00
fix: search jobs UI (#5706)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes - **New Features** - Introduced search job scheduling functionality. - Added ability to create, list, cancel, retry, and delete scheduled searches. - Enhanced user interface for managing scheduled search jobs, including a new component for displaying scheduled jobs. - Implemented conditional rendering for search history and search scheduler components. - Added new methods for handling scheduled searches within the service layer. - **Improvements** - Refined search bar interface with new scheduling options. - Updated pagination handling for job-related data. - Enhanced overall functionality related to job management and pagination. - Improved loading indicators and user experience during data retrieval. - **Bug Fixes** - Corrected conditional rendering of search history components. - Optimized job data retrieval and pagination logic. - Simplified sorting logic within the search history component. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -497,7 +497,7 @@ test.skip("should display error if timestamp past the ingestion time limit", asy
|
||||
await page.locator('[data-test="logs-search-bar-refresh-btn"]').click();
|
||||
await page.getByRole('button', { name: 'Search History' }).click();
|
||||
await page.locator('[data-test="add-alert-title"]').click();
|
||||
await page.getByText('arrow_back_ios_new').click();
|
||||
await page.getByText('arrow_back_ios_new').first().click()
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Use a more specific locator for 'e2e_automate' by targeting its unique container or parent element
|
||||
|
||||
+321
-112
@@ -81,6 +81,7 @@ const defaultObject = {
|
||||
runQuery: false,
|
||||
loading: false,
|
||||
loadingHistogram: false,
|
||||
loadingCounter: false,
|
||||
loadingStream: false,
|
||||
loadingSavedView: false,
|
||||
shouldIgnoreWatcher: false,
|
||||
@@ -144,6 +145,8 @@ const defaultObject = {
|
||||
},
|
||||
showPagination: true,
|
||||
},
|
||||
jobId: "",
|
||||
jobRecords: "100",
|
||||
scrollInfo: {},
|
||||
pageType: "logs", // 'logs' or 'stream
|
||||
regions: [],
|
||||
@@ -151,6 +154,7 @@ const defaultObject = {
|
||||
useUserDefinedSchemas: "user_defined_schema",
|
||||
hasUserDefinedSchemas: false,
|
||||
selectedTraceStream: "",
|
||||
showSearchScheduler: false,
|
||||
},
|
||||
data: {
|
||||
query: <any>"",
|
||||
@@ -599,7 +603,7 @@ const useLogs = () => {
|
||||
const query = generateURLQuery(false);
|
||||
if (
|
||||
Object.hasOwn(query, "type") &&
|
||||
query.type == "search_history_re_apply"
|
||||
query.type == "search_history_re_apply" || query.type == "search_scheduler"
|
||||
) {
|
||||
delete query.type;
|
||||
}
|
||||
@@ -1332,6 +1336,9 @@ const useLogs = () => {
|
||||
};
|
||||
|
||||
const refreshPartitionPagination = (regenrateFlag: boolean = false) => {
|
||||
if (searchObj.meta.jobId != "") {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const { rowsPerPage } = searchObj.meta.resultGrid;
|
||||
const { currentPage } = searchObj.data.resultGrid;
|
||||
@@ -1502,6 +1509,7 @@ const useLogs = () => {
|
||||
// window will have more priority
|
||||
// if window has use_web_socket property then use that
|
||||
// else use organization settings
|
||||
searchObj.meta.jobId = "";
|
||||
const shouldUseWebSocket = isWebSocketEnabled();
|
||||
|
||||
const isMultiStreamSearch =
|
||||
@@ -1618,6 +1626,7 @@ const useLogs = () => {
|
||||
JSON.stringify(queryReq),
|
||||
);
|
||||
|
||||
|
||||
// get the current page detail and set it into query request
|
||||
queryReq.query.start_time =
|
||||
searchObj.data.queryResults.partitionDetail.paginations[
|
||||
@@ -1688,6 +1697,7 @@ const useLogs = () => {
|
||||
searchObj.meta.refreshHistogram = false;
|
||||
if (searchObj.data.queryResults.hits.length > 0) {
|
||||
if (searchObj.data.stream.selectedStream.length > 1) {
|
||||
|
||||
searchObj.data.histogram = {
|
||||
xData: [],
|
||||
yData: [],
|
||||
@@ -1797,6 +1807,7 @@ const useLogs = () => {
|
||||
}
|
||||
|
||||
if (searchObj.data.stream.selectedStream.length > 1) {
|
||||
|
||||
searchObj.data.histogram = {
|
||||
xData: [],
|
||||
yData: [],
|
||||
@@ -1826,8 +1837,104 @@ const useLogs = () => {
|
||||
notificationMsg.value = "";
|
||||
}
|
||||
};
|
||||
const getJobData = async (isPagination = false) => {
|
||||
try {
|
||||
// get websocket enable config from store
|
||||
// window will have more priority
|
||||
// if window has use_web_socket property then use that
|
||||
// else use organization settings
|
||||
const queryReq: any = buildSearch();
|
||||
if (queryReq == false) {
|
||||
throw new Error(notificationMsg.value || "Something went wrong.");
|
||||
}
|
||||
if (searchObj.meta.jobId == "") {
|
||||
queryReq.query.size = parseInt(searchObj.meta.jobRecords);
|
||||
}
|
||||
// reset query data and get partition detail for given query.
|
||||
|
||||
if (queryReq != null) {
|
||||
// in case of live refresh, reset from to 0
|
||||
if (
|
||||
searchObj.meta.refreshInterval > 0 &&
|
||||
router.currentRoute.value.name == "logs"
|
||||
) {
|
||||
queryReq.query.from = 0;
|
||||
searchObj.meta.refreshHistogram = true;
|
||||
}
|
||||
|
||||
// get function definition
|
||||
if (
|
||||
searchObj.data.tempFunctionContent != "" &&
|
||||
searchObj.meta.toggleFunction
|
||||
) {
|
||||
queryReq.query["query_fn"] =
|
||||
b64EncodeUnicode(searchObj.data.tempFunctionContent) || "";
|
||||
}
|
||||
|
||||
// in case of relative time, set start_time and end_time to query
|
||||
// it will be used in pagination request
|
||||
if (searchObj.data.datetime.type === "relative") {
|
||||
if (!isPagination) initialQueryPayload.value = cloneDeep(queryReq);
|
||||
else {
|
||||
if (
|
||||
searchObj.meta.refreshInterval == 0 &&
|
||||
router.currentRoute.value.name == "logs" &&
|
||||
searchObj.data.queryResults.hasOwnProperty("hits")
|
||||
) {
|
||||
const start_time: number =
|
||||
initialQueryPayload.value?.query?.start_time || 0;
|
||||
const end_time: number =
|
||||
initialQueryPayload.value?.query?.end_time || 0;
|
||||
queryReq.query.start_time = start_time;
|
||||
queryReq.query.end_time = end_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete queryReq.aggs;
|
||||
}
|
||||
searchObj.data.queryResults.subpage = 1;
|
||||
if (searchObj.meta.jobId == "" ) {
|
||||
searchService
|
||||
.schedule_search(
|
||||
{
|
||||
org_identifier: searchObj.organizationIdentifier,
|
||||
query: queryReq,
|
||||
page_type: searchObj.data.stream.streamType,
|
||||
},
|
||||
"UI",
|
||||
).then((res: any) => {
|
||||
$q.notify({
|
||||
type: "positive",
|
||||
message: "Job Added Succesfully",
|
||||
timeout: 2000,
|
||||
actions: [
|
||||
{
|
||||
label: "Go To Job Scheduler",
|
||||
color: "white",
|
||||
handler: () => routeToSearchSchedule(),
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
}
|
||||
else {
|
||||
await getPaginatedData(queryReq);
|
||||
}
|
||||
if (searchObj.meta.jobId == ""){
|
||||
searchObj.data.histogram.chartParams.title = getHistogramTitle();
|
||||
}
|
||||
} catch (e: any) {
|
||||
searchObj.loading = false;
|
||||
showErrorNotification(
|
||||
notificationMsg.value || "Error occurred during the search operation.",
|
||||
);
|
||||
throw e;
|
||||
// notificationMsg.value = "";
|
||||
}
|
||||
};
|
||||
|
||||
function resetHistogramWithError(errorMsg: string, errorCode: number = 0) {
|
||||
|
||||
searchObj.data.histogram = {
|
||||
xData: [],
|
||||
yData: [],
|
||||
@@ -1859,6 +1966,7 @@ const useLogs = () => {
|
||||
}
|
||||
|
||||
function generateHistogramSkeleton() {
|
||||
|
||||
if (
|
||||
searchObj.data.queryResults.hasOwnProperty("aggs") &&
|
||||
searchObj.data.queryResults.aggs
|
||||
@@ -1962,101 +2070,114 @@ const useLogs = () => {
|
||||
|
||||
const getPageCount = async (queryReq: any) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
searchObj.data.countErrorMsg = "";
|
||||
queryReq.query.size = 0;
|
||||
delete queryReq.query.from;
|
||||
delete queryReq.query.quick_mode;
|
||||
queryReq.query["sql_mode"] = "full";
|
||||
|
||||
queryReq.query.track_total_hits = true;
|
||||
|
||||
const { traceparent, traceId } = generateTraceContext();
|
||||
addTraceId(traceId);
|
||||
|
||||
searchService
|
||||
.search(
|
||||
{
|
||||
org_identifier: searchObj.organizationIdentifier,
|
||||
query: queryReq,
|
||||
page_type: searchObj.data.stream.streamType,
|
||||
traceparent,
|
||||
},
|
||||
"UI",
|
||||
)
|
||||
.then(async (res) => {
|
||||
// check for total records update for the partition and update pagination accordingly
|
||||
// searchObj.data.queryResults.partitionDetail.partitions.forEach(
|
||||
// (item: any, index: number) => {
|
||||
searchObj.data.queryResults.scan_size += res.data.scan_size;
|
||||
searchObj.data.queryResults.took += res.data.took;
|
||||
for (const [
|
||||
index,
|
||||
item,
|
||||
] of searchObj.data.queryResults.partitionDetail.partitions.entries()) {
|
||||
if (
|
||||
(searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] == -1 ||
|
||||
searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] < res.data.total) &&
|
||||
queryReq.query.start_time == item[0]
|
||||
) {
|
||||
searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] = res.data.total;
|
||||
try {
|
||||
searchObj.loadingCounter = true;
|
||||
searchObj.data.countErrorMsg = "";
|
||||
queryReq.query.size = 0;
|
||||
delete queryReq.query.from;
|
||||
delete queryReq.query.quick_mode;
|
||||
queryReq.query["sql_mode"] = "full";
|
||||
|
||||
queryReq.query.track_total_hits = true;
|
||||
|
||||
const { traceparent, traceId } = generateTraceContext();
|
||||
addTraceId(traceId);
|
||||
|
||||
searchService
|
||||
.search(
|
||||
{
|
||||
org_identifier: searchObj.organizationIdentifier,
|
||||
query: queryReq,
|
||||
page_type: searchObj.data.stream.streamType,
|
||||
traceparent,
|
||||
},
|
||||
"UI",
|
||||
)
|
||||
.then(async (res) => {
|
||||
// check for total records update for the partition and update pagination accordingly
|
||||
// searchObj.data.queryResults.partitionDetail.partitions.forEach(
|
||||
// (item: any, index: number) => {
|
||||
searchObj.data.queryResults.scan_size += res.data.scan_size;
|
||||
searchObj.data.queryResults.took += res.data.took;
|
||||
if (searchObj.meta.jobId == "") {
|
||||
for (const [
|
||||
index,
|
||||
item,
|
||||
] of searchObj.data.queryResults.partitionDetail.partitions.entries()) {
|
||||
if (
|
||||
(searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] == -1 ||
|
||||
searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] < res.data.total) &&
|
||||
queryReq.query.start_time == item[0]
|
||||
) {
|
||||
searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] = res.data.total;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let regeratePaginationFlag = false;
|
||||
if (res.data.hits.length != searchObj.meta.resultGrid.rowsPerPage) {
|
||||
regeratePaginationFlag = true;
|
||||
}
|
||||
// if total records in partition is greater than recordsPerPage then we need to update pagination
|
||||
// setting up forceFlag to true to update pagination as we have check for pagination already created more than currentPage + 3 pages.
|
||||
refreshPartitionPagination(regeratePaginationFlag);
|
||||
searchObj.data.histogram.chartParams.title = getHistogramTitle();
|
||||
resolve(true);
|
||||
})
|
||||
.catch((err) => {
|
||||
searchObj.loading = false;
|
||||
|
||||
|
||||
let regeratePaginationFlag = false;
|
||||
if (res.data.hits.length != searchObj.meta.resultGrid.rowsPerPage) {
|
||||
regeratePaginationFlag = true;
|
||||
}
|
||||
// if total records in partition is greater than recordsPerPage then we need to update pagination
|
||||
// setting up forceFlag to true to update pagination as we have check for pagination already created more than currentPage + 3 pages.
|
||||
refreshPartitionPagination(regeratePaginationFlag);
|
||||
|
||||
searchObj.data.histogram.chartParams.title = getHistogramTitle();
|
||||
searchObj.loadingCounter = false;
|
||||
resolve(true);
|
||||
})
|
||||
.catch((err) => {
|
||||
searchObj.loading = false;
|
||||
searchObj.loadingCounter = false;
|
||||
|
||||
// Reset cancel query on search error
|
||||
searchObj.data.isOperationCancelled = false;
|
||||
|
||||
let trace_id = "";
|
||||
searchObj.data.countErrorMsg =
|
||||
"Error while retrieving total events: ";
|
||||
if (err.response != undefined) {
|
||||
if (err.response.data.hasOwnProperty("trace_id")) {
|
||||
trace_id = err.response.data?.trace_id;
|
||||
searchObj.data.countErrorMsg =
|
||||
"Error while retrieving total events: ";
|
||||
if (err.response != undefined) {
|
||||
if (err.response.data.hasOwnProperty("trace_id")) {
|
||||
trace_id = err.response.data?.trace_id;
|
||||
}
|
||||
} else {
|
||||
if (err.hasOwnProperty("trace_id")) {
|
||||
trace_id = err?.trace_id;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (err.hasOwnProperty("trace_id")) {
|
||||
trace_id = err?.trace_id;
|
||||
|
||||
const customMessage = logsErrorMessage(err?.response?.data.code);
|
||||
searchObj.data.errorCode = err?.response?.data.code;
|
||||
|
||||
notificationMsg.value = searchObj.data.countErrorMsg;
|
||||
|
||||
if (err?.request?.status >= 429) {
|
||||
notificationMsg.value = err?.response?.data?.message;
|
||||
searchObj.data.countErrorMsg += err?.response?.data?.message;
|
||||
}
|
||||
}
|
||||
|
||||
if (trace_id) {
|
||||
searchObj.data.countErrorMsg += " TraceID:" + trace_id;
|
||||
notificationMsg.value += " TraceID:" + trace_id;
|
||||
trace_id = "";
|
||||
}
|
||||
reject(false);
|
||||
})
|
||||
.finally(() => {
|
||||
removeTraceId(traceId);
|
||||
});
|
||||
} catch (e) {
|
||||
searchObj.loadingCounter = false;
|
||||
reject(false);
|
||||
}
|
||||
|
||||
const customMessage = logsErrorMessage(err?.response?.data.code);
|
||||
searchObj.data.errorCode = err?.response?.data.code;
|
||||
|
||||
notificationMsg.value = searchObj.data.countErrorMsg;
|
||||
|
||||
if (err?.request?.status >= 429) {
|
||||
notificationMsg.value = err?.response?.data?.message;
|
||||
searchObj.data.countErrorMsg += err?.response?.data?.message;
|
||||
}
|
||||
|
||||
if (trace_id) {
|
||||
searchObj.data.countErrorMsg += " TraceID:" + trace_id;
|
||||
notificationMsg.value += " TraceID:" + trace_id;
|
||||
trace_id = "";
|
||||
}
|
||||
reject(false);
|
||||
})
|
||||
.finally(() => {
|
||||
removeTraceId(traceId);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2070,8 +2191,8 @@ const useLogs = () => {
|
||||
updateGridColumns();
|
||||
|
||||
filterHitsColumns();
|
||||
searchObj.data.histogram.chartParams.title = getHistogramTitle();
|
||||
|
||||
searchObj.data.histogram.chartParams.title = getHistogramTitle();
|
||||
};
|
||||
|
||||
const getPaginatedData = async (
|
||||
@@ -2099,7 +2220,9 @@ const useLogs = () => {
|
||||
showCancelSearchNotification();
|
||||
return;
|
||||
}
|
||||
|
||||
if (searchObj.meta.jobId != ""){
|
||||
searchObj.meta.resultGrid.rowsPerPage = queryReq.query.size;
|
||||
}
|
||||
const parsedSQL: any = fnParsedSQL();
|
||||
searchObj.meta.resultGrid.showPagination = true;
|
||||
if (searchObj.meta.sqlMode == true) {
|
||||
@@ -2127,12 +2250,14 @@ const useLogs = () => {
|
||||
|
||||
const { traceparent, traceId } = generateTraceContext();
|
||||
addTraceId(traceId);
|
||||
|
||||
searchService
|
||||
.search(
|
||||
const decideSearch = searchObj.meta.jobId
|
||||
? "get_scheduled_search_result"
|
||||
: "search";
|
||||
searchService[decideSearch](
|
||||
{
|
||||
org_identifier: searchObj.organizationIdentifier,
|
||||
query: queryReq,
|
||||
jobId: searchObj.meta.jobId ? searchObj.meta.jobId : "",
|
||||
page_type: searchObj.data.stream.streamType,
|
||||
traceparent,
|
||||
},
|
||||
@@ -2179,19 +2304,21 @@ const useLogs = () => {
|
||||
// check for total records update for the partition and update pagination accordingly
|
||||
// searchObj.data.queryResults.partitionDetail.partitions.forEach(
|
||||
// (item: any, index: number) => {
|
||||
for (const [
|
||||
index,
|
||||
item,
|
||||
] of searchObj.data.queryResults.partitionDetail.partitions.entries()) {
|
||||
if (
|
||||
searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] == -1 &&
|
||||
queryReq.query.start_time == item[0]
|
||||
) {
|
||||
searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] = res.data.total;
|
||||
if (searchObj.meta.jobId == ""){
|
||||
for (const [
|
||||
index,
|
||||
item,
|
||||
] of searchObj.data.queryResults.partitionDetail.partitions.entries()) {
|
||||
if (
|
||||
searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] == -1 &&
|
||||
queryReq.query.start_time == item[0]
|
||||
) {
|
||||
searchObj.data.queryResults.partitionDetail.partitionTotal[
|
||||
index
|
||||
] = res.data.total;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2214,8 +2341,9 @@ const useLogs = () => {
|
||||
}
|
||||
// if total records in partition is greater than recordsPerPage then we need to update pagination
|
||||
// setting up forceFlag to true to update pagination as we have check for pagination already created more than currentPage + 3 pages.
|
||||
refreshPartitionPagination(regeratePaginationFlag);
|
||||
|
||||
if (searchObj.meta.jobId == "") {
|
||||
refreshPartitionPagination(regeratePaginationFlag);
|
||||
}
|
||||
// Scan-size and took time in histogram title
|
||||
// For the initial request, we get histogram and logs data. So, we need to sum the scan_size and took time of both the requests.
|
||||
// For the pagination request, we only get logs data. So, we need to consider scan_size and took time of only logs request.
|
||||
@@ -2251,6 +2379,10 @@ const useLogs = () => {
|
||||
);
|
||||
searchObj.data.queryResults.hits = res.data.hits;
|
||||
} else {
|
||||
if (searchObj.meta.jobId != ""){
|
||||
searchObj.data.queryResults.total = res.data.total;
|
||||
|
||||
}
|
||||
if (!queryReq.query.hasOwnProperty("track_total_hits")) {
|
||||
delete res.data.total;
|
||||
}
|
||||
@@ -2264,6 +2396,7 @@ const useLogs = () => {
|
||||
// check for pagination request for the partition and check for subpage if we have to pull data from multiple partitions
|
||||
// it will check for subpage and if subpage is present then it will send pagination request for next partition
|
||||
if (
|
||||
searchObj.meta.jobId == "" &&
|
||||
searchObj.data.queryResults.partitionDetail.paginations[
|
||||
searchObj.data.resultGrid.currentPage - 1
|
||||
].length > searchObj.data.queryResults.subpage &&
|
||||
@@ -2291,7 +2424,7 @@ const useLogs = () => {
|
||||
searchObj.data.queryResults.subpage++;
|
||||
|
||||
setTimeout(async () => {
|
||||
processPostPaginationData();
|
||||
processPostPaginationData();
|
||||
|
||||
// searchObj.data.functionError = "";
|
||||
// if (
|
||||
@@ -2303,6 +2436,11 @@ const useLogs = () => {
|
||||
}, 0);
|
||||
await getPaginatedData(queryReq, true);
|
||||
}
|
||||
if (searchObj.meta.jobId != ""){
|
||||
searchObj.meta.resultGrid.rowsPerPage = queryReq.query.size;
|
||||
searchObj.data.queryResults.pagination = [];
|
||||
refreshJobPagination(true);
|
||||
}
|
||||
|
||||
await processPostPaginationData();
|
||||
|
||||
@@ -2406,6 +2544,16 @@ const useLogs = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const routeToSearchSchedule = () => {
|
||||
router.push({
|
||||
query:{
|
||||
action: "search_scheduler",
|
||||
org_identifier: store.state.selectedOrganization.identifier,
|
||||
type: "search_scheduler_list"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const getHistogramQueryData = (queryReq: any) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (searchObj.data.isOperationCancelled) {
|
||||
@@ -2427,7 +2575,6 @@ const useLogs = () => {
|
||||
const { traceparent, traceId } = generateTraceContext();
|
||||
addTraceId(traceId);
|
||||
queryReq.query.size = -1;
|
||||
|
||||
searchService
|
||||
.search(
|
||||
{
|
||||
@@ -3351,7 +3498,7 @@ const useLogs = () => {
|
||||
endCount = searchObj.meta.resultGrid.rowsPerPage * (currentPage + 1);
|
||||
if (
|
||||
currentPage >=
|
||||
(searchObj.communicationMethod === "ws"
|
||||
(searchObj.communicationMethod === "ws" || searchObj.meta.jobId != ""
|
||||
? searchObj.data.queryResults?.pagination?.length
|
||||
: searchObj.data.queryResults.partitionDetail?.paginations
|
||||
?.length || 0) -
|
||||
@@ -3477,7 +3624,6 @@ const useLogs = () => {
|
||||
|
||||
searchObj.data.queryResults.total = num_records;
|
||||
}
|
||||
|
||||
const chartParams = {
|
||||
title: getHistogramTitle(),
|
||||
unparsed_x_data: unparsed_x_data,
|
||||
@@ -3751,7 +3897,27 @@ const useLogs = () => {
|
||||
// await getSavedViews();
|
||||
await getFunctions();
|
||||
await extractFields();
|
||||
await getQueryData();
|
||||
if (searchObj.meta.jobId == ""){
|
||||
await getQueryData();
|
||||
}
|
||||
else{
|
||||
|
||||
await getJobData();
|
||||
|
||||
}
|
||||
refreshData();
|
||||
} catch (e: any) {
|
||||
searchObj.loading = false;
|
||||
|
||||
}
|
||||
};
|
||||
const loadJobData = async () => {
|
||||
try {
|
||||
resetFunctions();
|
||||
await getStreamList();
|
||||
await getFunctions();
|
||||
await extractFields();
|
||||
await getJobData();
|
||||
refreshData();
|
||||
} catch (e: any) {
|
||||
searchObj.loading = false;
|
||||
@@ -3784,7 +3950,13 @@ const useLogs = () => {
|
||||
) {
|
||||
delete router.currentRoute.value.query.type;
|
||||
}
|
||||
const queryTimeout = setTimeout(() => {
|
||||
if (searchObj.loading) {
|
||||
searchObj.meta.showSearchScheduler = true;
|
||||
}
|
||||
}, 120000);
|
||||
await getQueryData();
|
||||
clearTimeout(queryTimeout);
|
||||
} catch (e: any) {
|
||||
console.log("Error while loading logs data");
|
||||
}
|
||||
@@ -5336,6 +5508,8 @@ const useLogs = () => {
|
||||
const { rowsPerPage } = searchObj.meta.resultGrid;
|
||||
const { currentPage } = searchObj.data.resultGrid;
|
||||
|
||||
if(searchObj.meta.jobId != "") searchObj.meta.resultGrid.rowsPerPage = 100;
|
||||
|
||||
let total = 0;
|
||||
let totalPages = 0;
|
||||
|
||||
@@ -5371,6 +5545,37 @@ const useLogs = () => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
const refreshJobPagination = (regenrateFlag: boolean = false) => {
|
||||
try {
|
||||
const { rowsPerPage } = searchObj.meta.resultGrid;
|
||||
const { currentPage } = searchObj.data.resultGrid;
|
||||
|
||||
if (searchObj.meta.jobId != "") {
|
||||
// searchObj.meta.resultGrid.rowsPerPage = 100;
|
||||
}
|
||||
|
||||
let totalPages = 0;
|
||||
|
||||
searchObj.data.queryResults.pagination = [];
|
||||
|
||||
totalPages = Math.ceil(searchObj.data.queryResults.total / rowsPerPage);
|
||||
|
||||
for (let i = 0; i < totalPages; i++) {
|
||||
if (i + 1 > currentPage + 10) {
|
||||
break;
|
||||
}
|
||||
searchObj.data.queryResults.pagination.push({
|
||||
from: i * rowsPerPage + 1,
|
||||
size: rowsPerPage,
|
||||
});
|
||||
}
|
||||
// console.log("searchObj.data.queryResults.pagination", searchObj.data.queryResults.pagination);
|
||||
} catch (e: any) {
|
||||
console.log("Error while refreshing pagination", e);
|
||||
notificationMsg.value = "Error while refreshing pagination.";
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const getPageCountThroughSocket = async (queryReq: any) => {
|
||||
if (
|
||||
@@ -5498,6 +5703,7 @@ const useLogs = () => {
|
||||
fieldValues,
|
||||
extractFields,
|
||||
getQueryData,
|
||||
getJobData,
|
||||
searchAroundData,
|
||||
updateGridColumns,
|
||||
refreshData,
|
||||
@@ -5532,10 +5738,13 @@ const useLogs = () => {
|
||||
extractValueQuery,
|
||||
initialQueryPayload,
|
||||
refreshPagination,
|
||||
loadJobData,
|
||||
refreshJobPagination,
|
||||
enableRefreshInterval,
|
||||
buildWebSocketPayload,
|
||||
initializeWebSocketConnection,
|
||||
addRequestId,
|
||||
routeToSearchSchedule,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
<!-- eslint-disable vue/v-on-event-hyphenation -->
|
||||
<template>
|
||||
<q-page class="logPage q-my-xs" id="logPage">
|
||||
<div v-show="!showSearchHistory" id="secondLevel" class="full-height">
|
||||
<div v-show="!showSearchHistory && !showSearchScheduler" id="secondLevel" class="full-height">
|
||||
<q-splitter
|
||||
class="logs-horizontal-splitter full-height"
|
||||
v-model="splitterModel"
|
||||
@@ -302,7 +302,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
@closeSearchHistory="closeSearchHistoryfn"
|
||||
:isClicked="showSearchHistory"
|
||||
/>
|
||||
<div v-else style="height: 200px">
|
||||
<div v-else-if="showSearchHistory && !store.state.zoConfig.usage_enabled " style="height: 200px">
|
||||
<div style="height: 80vh" class="text-center q-pa-md flex flex-center">
|
||||
<div>
|
||||
<div>
|
||||
@@ -344,7 +344,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div v-show="showSearchScheduler">
|
||||
<SearchSchedulersList
|
||||
ref="searchSchedulerRef"
|
||||
@closeSearchHistory="closeSearchSchedulerFn"
|
||||
:isClicked="showSearchScheduler"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</q-page>
|
||||
</template>
|
||||
|
||||
@@ -386,6 +395,7 @@ import { buildSqlQuery, getFieldsFromQuery } from "@/utils/query/sqlUtils";
|
||||
import useNotifications from "@/composables/useNotifications";
|
||||
import SearchBar from "@/plugins/logs/SearchBar.vue";
|
||||
import SearchHistory from "@/plugins/logs/SearchHistory.vue";
|
||||
import SearchSchedulersList from "@/plugins/logs/SearchSchedulersList.vue";
|
||||
import { type ActivationState, PageType } from "@/ts/interfaces/logs.ts";
|
||||
import { isWebSocketEnabled } from "@/utils/zincutils";
|
||||
|
||||
@@ -393,6 +403,7 @@ export default defineComponent({
|
||||
name: "PageSearch",
|
||||
components: {
|
||||
SearchBar,
|
||||
SearchSchedulersList,
|
||||
IndexList: defineAsyncComponent(
|
||||
() => import("@/plugins/logs/IndexList.vue"),
|
||||
),
|
||||
@@ -446,9 +457,14 @@ export default defineComponent({
|
||||
// so added this condition to avoid that
|
||||
this.searchObj.meta.refreshHistogram = true;
|
||||
this.searchObj.data.queryResults.aggs = null;
|
||||
if (this.searchObj.meta.jobId == "") {
|
||||
await this.getQueryData(false);
|
||||
this.refreshHistogramChart();
|
||||
}
|
||||
else{
|
||||
await this.getJobData(false);
|
||||
}
|
||||
|
||||
await this.getQueryData(false);
|
||||
this.refreshHistogramChart();
|
||||
|
||||
if (config.isCloud == "true") {
|
||||
segment.track("Button Click", {
|
||||
@@ -471,8 +487,14 @@ export default defineComponent({
|
||||
// this.searchObj.data.resultGrid.currentPage =
|
||||
// this.searchObj.data.resultGrid.currentPage + 1;
|
||||
this.searchObj.loading = true;
|
||||
await this.getQueryData(true);
|
||||
this.refreshHistogramChart();
|
||||
if(this.searchObj.meta.jobId == ""){
|
||||
await this.getQueryData(true);
|
||||
this.refreshHistogramChart();
|
||||
|
||||
}
|
||||
else{
|
||||
await this.getJobData(false);
|
||||
}
|
||||
|
||||
if (config.isCloud == "true") {
|
||||
segment.track("Button Click", {
|
||||
@@ -533,12 +555,14 @@ export default defineComponent({
|
||||
let {
|
||||
searchObj,
|
||||
getQueryData,
|
||||
getJobData,
|
||||
fieldValues,
|
||||
updateGridColumns,
|
||||
refreshData,
|
||||
updateUrlQueryParams,
|
||||
loadLogsData,
|
||||
updateStreams,
|
||||
loadJobData,
|
||||
restoreUrlQueryParams,
|
||||
handleRunQuery,
|
||||
generateHistogramData,
|
||||
@@ -561,6 +585,8 @@ export default defineComponent({
|
||||
const searchResultRef = ref(null);
|
||||
const searchBarRef = ref(null);
|
||||
const showSearchHistory = ref(false);
|
||||
const showSearchScheduler = ref(false);
|
||||
const showJobScheduler = ref(false);
|
||||
let parser: any;
|
||||
|
||||
const isLogsMounted = ref(false);
|
||||
@@ -630,6 +656,17 @@ export default defineComponent({
|
||||
) {
|
||||
showSearchHistory.value = true;
|
||||
}
|
||||
if (
|
||||
router.currentRoute.value.query.hasOwnProperty("action") &&
|
||||
router.currentRoute.value.query.action == "search_scheduler"
|
||||
) {
|
||||
if(config.isEnterprise == 'true'){
|
||||
showSearchScheduler.value = true;
|
||||
}
|
||||
else{
|
||||
router.back();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
onActivated(() => {
|
||||
@@ -662,6 +699,7 @@ export default defineComponent({
|
||||
() => {
|
||||
if (!router.currentRoute.value.query.hasOwnProperty("action")) {
|
||||
showSearchHistory.value = false;
|
||||
showSearchScheduler.value = false;
|
||||
}
|
||||
if (
|
||||
router.currentRoute.value.query.hasOwnProperty("action") &&
|
||||
@@ -669,6 +707,17 @@ export default defineComponent({
|
||||
) {
|
||||
showSearchHistory.value = true;
|
||||
}
|
||||
if (
|
||||
router.currentRoute.value.query.hasOwnProperty("action") &&
|
||||
router.currentRoute.value.query.action == "search_scheduler"
|
||||
) {
|
||||
if(config.isEnterprise == 'true'){
|
||||
showSearchScheduler.value = true;
|
||||
}
|
||||
else{
|
||||
router.back();
|
||||
}
|
||||
}
|
||||
},
|
||||
// (action) => {
|
||||
// if (action === "history") {
|
||||
@@ -680,6 +729,8 @@ export default defineComponent({
|
||||
() => router.currentRoute.value.query.type,
|
||||
async (type) => {
|
||||
if (type == "search_history_re_apply") {
|
||||
searchObj.meta.jobId = "";
|
||||
|
||||
searchObj.organizationIdetifier =
|
||||
router.currentRoute.value.query.org_identifier;
|
||||
searchObj.data.stream.selectedStream.value =
|
||||
@@ -709,6 +760,31 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
);
|
||||
watch(
|
||||
() => router.currentRoute.value.query.type,
|
||||
async (type) => {
|
||||
if (type == "search_scheduler") {
|
||||
searchObj.organizationIdetifier =
|
||||
router.currentRoute.value.query.org_identifier;
|
||||
searchObj.data.stream.selectedStream.value =
|
||||
router.currentRoute.value.query.stream;
|
||||
searchObj.data.stream.streamType =
|
||||
router.currentRoute.value.query.stream_type;
|
||||
resetSearchObj();
|
||||
|
||||
// As when redirecting from search history to logs page, date type was getting set as absolute, so forcefully keeping it relative.
|
||||
searchBarRef.value.dateTimeRef.setAbsoluteTime(
|
||||
router.currentRoute.value.query.from,
|
||||
router.currentRoute.value.query.to,
|
||||
);
|
||||
searchObj.data.datetime.type = "absolute";
|
||||
searchObj.meta.searchApplied = false;
|
||||
resetStreamData();
|
||||
await restoreUrlQueryParams();
|
||||
await loadLogsData();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const importSqlParser = async () => {
|
||||
const useSqlParser: any = await import("@/composables/useParser");
|
||||
@@ -722,6 +798,8 @@ export default defineComponent({
|
||||
try {
|
||||
await getQueryData();
|
||||
refreshHistogramChart();
|
||||
showJobScheduler.value = true;
|
||||
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
@@ -1359,6 +1437,10 @@ export default defineComponent({
|
||||
showSearchHistory.value = false;
|
||||
refreshHistogramChart();
|
||||
};
|
||||
const closeSearchSchedulerFn = () => {
|
||||
router.back();
|
||||
showSearchScheduler.value = false;
|
||||
};
|
||||
|
||||
// watch for changes in the visualize toggle
|
||||
// if it is in visualize mode, then set the query and stream name in the dashboard panel
|
||||
@@ -1472,6 +1554,7 @@ export default defineComponent({
|
||||
splitterModel,
|
||||
// loadPageData,
|
||||
getQueryData,
|
||||
getJobData,
|
||||
searchResultRef,
|
||||
runQueryFn,
|
||||
refreshData,
|
||||
@@ -1512,6 +1595,9 @@ export default defineComponent({
|
||||
initializeWebSocketConnection,
|
||||
addRequestId,
|
||||
isWebSocketEnabled,
|
||||
showJobScheduler,
|
||||
showSearchScheduler,
|
||||
closeSearchSchedulerFn,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -1596,7 +1682,10 @@ export default defineComponent({
|
||||
this.resetHistogramWithError(
|
||||
"Histogram is not available for multi stream search.",
|
||||
);
|
||||
} else if (this.searchObj.meta.histogramDirtyFlag == true) {
|
||||
} else if (
|
||||
this.searchObj.meta.histogramDirtyFlag == true &&
|
||||
this.searchObj.meta.jobId == ""
|
||||
) {
|
||||
this.searchObj.meta.histogramDirtyFlag = false;
|
||||
|
||||
// this.handleRunQuery();
|
||||
|
||||
@@ -399,6 +399,51 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
</q-btn-group>
|
||||
<q-btn-group v-if="config.isEnterprise == 'true'" class=" no-outline q-pa-none no-border">
|
||||
<q-btn-dropdown
|
||||
data-test="search-scheduler-dropdown-btn-group"
|
||||
class="q-mr-xs download-logs-btn q-px-xs "
|
||||
size="sm"
|
||||
icon="schedule_send"
|
||||
:title="t('search.exportLogs')"
|
||||
>
|
||||
<q-list>
|
||||
<q-item
|
||||
data-test="search-scheduler-create-new-btn"
|
||||
class="q-pa-sm saved-view-item"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="createScheduleJob"
|
||||
>
|
||||
<q-item-section v-close-popup>
|
||||
<q-item-label data-test="search-scheduler-create-new-label"
|
||||
>
|
||||
<q-icon name="save" />
|
||||
Create Scheduled Search</q-item-label
|
||||
>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-separator />
|
||||
<q-item
|
||||
data-test="search-scheduler-list-btn"
|
||||
|
||||
class="q-pa-sm saved-view-item"
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="routeToSearchSchedule"
|
||||
>
|
||||
<q-item-section v-close-popup>
|
||||
<q-item-label data-test="search-scheduler-list-label"
|
||||
>
|
||||
<q-icon name="list" />
|
||||
|
||||
List Scheduled Search</q-item-label
|
||||
>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-btn-dropdown>
|
||||
</q-btn-group>
|
||||
<q-btn-group class="no-outline q-pa-none no-border">
|
||||
<q-btn-dropdown
|
||||
data-test="logs-search-bar-reset-function-btn"
|
||||
@@ -952,6 +997,87 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<q-dialog v-model="searchSchedulerJob">
|
||||
<q-card style="width: 700px; max-width: 80vw">
|
||||
<q-card-section>
|
||||
<div class="text-h6">Schedule Search Job</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section class="q-pt-none">
|
||||
<div>
|
||||
<div class="text-left q-mb-xs">
|
||||
No of Records:
|
||||
<q-icon
|
||||
name="info"
|
||||
size="17px"
|
||||
class="q-ml-xs cursor-pointer"
|
||||
|
||||
>
|
||||
<q-tooltip
|
||||
anchor="center right"
|
||||
self="center left"
|
||||
max-width="300px"
|
||||
>
|
||||
<span style="font-size: 14px"
|
||||
>Number of records can be specified eg: if the no. of records is 1000 then user can get maximum of 1000 records</span
|
||||
>
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
<q-input
|
||||
type="number"
|
||||
data-test="search-scheuduler-max-number-of-records-input"
|
||||
v-model="searchObj.meta.jobRecords"
|
||||
default-value="100"
|
||||
color="input-border"
|
||||
bg-color="input-bg"
|
||||
class="showLabelOnTop"
|
||||
stack-label
|
||||
outlined
|
||||
filled
|
||||
dense
|
||||
tabindex="0"
|
||||
min="100"
|
||||
/>
|
||||
|
||||
</div>
|
||||
<div class="text-left">
|
||||
Maximum 100000 events can be returned in schedule job
|
||||
</div>
|
||||
<div style="opacity: 0.8;" class="text-left mapping-warning-msg q-mt-md">
|
||||
<q-icon name="warning" color="red" class="q-mr-sm" />
|
||||
<span>Histogram will be disabled for the schedule job</span>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
|
||||
<q-card-actions align="right" class=" text-teal">
|
||||
<q-btn
|
||||
data-test="search-scheduler-max-records-cancel-btn"
|
||||
unelevated
|
||||
no-caps
|
||||
class="q-mr-sm text-bold"
|
||||
:label="t('confirmDialog.cancel')"
|
||||
color="secondary"
|
||||
v-close-popup
|
||||
@click="{
|
||||
searchSchedulerJob = false;
|
||||
searchObj.meta.showSearchScheduler = false;
|
||||
}"
|
||||
/>
|
||||
<q-btn
|
||||
data-test="search-scheduler-max-records-submit-btn"
|
||||
unelevated
|
||||
no-caps
|
||||
:label="t('confirmDialog.ok')"
|
||||
color="primary"
|
||||
class="text-bold"
|
||||
@click="addJobScheduler"
|
||||
v-close-popup
|
||||
/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
<ConfirmDialog
|
||||
title="Delete Saved View"
|
||||
message="Are you sure you want to delete saved view?"
|
||||
@@ -1016,7 +1142,9 @@ import {
|
||||
useLocalSavedView,
|
||||
queryIndexSplit,
|
||||
timestampToTimezoneDate,
|
||||
b64EncodeUnicode,
|
||||
} from "@/utils/zincutils";
|
||||
|
||||
import savedviewsService from "@/services/saved_views";
|
||||
import ConfirmDialog from "@/components/ConfirmDialog.vue";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
@@ -1026,7 +1154,6 @@ import QueryEditor from "@/components/QueryEditor.vue";
|
||||
import useCancelQuery from "@/composables/dashboard/useCancelQuery";
|
||||
import { computed } from "vue";
|
||||
import { useLoading } from "@/composables/useLoading";
|
||||
|
||||
const defaultValue: any = () => {
|
||||
return {
|
||||
name: "",
|
||||
@@ -1043,8 +1170,7 @@ export default defineComponent({
|
||||
QueryEditor,
|
||||
SyntaxGuide,
|
||||
AutoRefreshInterval,
|
||||
ConfirmDialog,
|
||||
},
|
||||
ConfirmDialog, },
|
||||
emits: [
|
||||
"searchdata",
|
||||
"onChangeInterval",
|
||||
@@ -1191,6 +1317,8 @@ export default defineComponent({
|
||||
extractFields,
|
||||
cancelQuery,
|
||||
setSelectedStreams,
|
||||
getJobData,
|
||||
routeToSearchSchedule,
|
||||
} = useLogs();
|
||||
const queryEditorRef = ref(null);
|
||||
|
||||
@@ -1212,6 +1340,8 @@ export default defineComponent({
|
||||
|
||||
const confirmDialogVisible: boolean = ref(false);
|
||||
const confirmSavedViewDialogVisible: boolean = ref(false);
|
||||
const searchSchedulerJob = ref(false);
|
||||
const autoSearchSchedulerJob = ref(false);
|
||||
let confirmCallback;
|
||||
let streamName = "";
|
||||
|
||||
@@ -1270,6 +1400,56 @@ export default defineComponent({
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
watch(
|
||||
() => searchObj.meta.showSearchScheduler,
|
||||
(showSearchScheduler) => {
|
||||
if(showSearchScheduler){
|
||||
searchSchedulerJob.value = true;
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
watch(
|
||||
() => searchObj.meta.functionEditorPlaceholderFlag,
|
||||
(val) => {
|
||||
if (
|
||||
searchObj.meta.jobId != "" &&
|
||||
val == true &&
|
||||
(router.currentRoute.value.query.functionContent || searchObj.data.tempFunctionContent != "")
|
||||
) {
|
||||
if (!checkFnQuery(searchObj.data.tempFunctionContent)) {
|
||||
$q.notify({
|
||||
message: "Job Context have been removed",
|
||||
color: "warning",
|
||||
position: "bottom",
|
||||
timeout: 2000,
|
||||
});
|
||||
searchObj.meta.jobId = "";
|
||||
searchObj.data.queryResults.hits = [];
|
||||
// getQueryData(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
watch(
|
||||
() => searchObj.meta.showHistogram,
|
||||
(val) => {
|
||||
|
||||
if(val == true && searchObj.meta.jobId != "" ){
|
||||
$q.notify({
|
||||
message: "Histogram is not available for scheduled search",
|
||||
color: "negative",
|
||||
position: "bottom",
|
||||
timeout: 2000,
|
||||
});
|
||||
searchObj.meta.showHistogram = false;
|
||||
searchObj.loadingHistogram = false;
|
||||
}
|
||||
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
watch(
|
||||
() => searchObj.data.stream.functions,
|
||||
(funs) => {
|
||||
@@ -1278,6 +1458,7 @@ export default defineComponent({
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await importSqlParser();
|
||||
});
|
||||
@@ -1326,6 +1507,12 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
const updateQueryValue = (value: string) => {
|
||||
// if (searchObj.meta.jobId != "") {
|
||||
// searchObj.meta.jobId = "";
|
||||
// getQueryData(false);
|
||||
// }
|
||||
|
||||
|
||||
searchObj.data.editorValue = value;
|
||||
if (searchObj.meta.quickMode === true) {
|
||||
const parsedSQL = fnParsedSQL();
|
||||
@@ -1434,9 +1621,27 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
//here we reset the job id if user change the query and move outside of the editor
|
||||
if (
|
||||
searchObj.meta.jobId != "" &&
|
||||
searchObj.meta.queryEditorPlaceholderFlag == true
|
||||
) {
|
||||
if (!checkQuery(value)) {
|
||||
$q.notify({
|
||||
message: "Job Context have been removed",
|
||||
color: "warning",
|
||||
position: "bottom",
|
||||
timeout: 2000,
|
||||
});
|
||||
searchObj.meta.jobId = "";
|
||||
searchObj.data.queryResults.hits = [];
|
||||
// getQueryData(false);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e, "Logs: Error while updating query value");
|
||||
}
|
||||
|
||||
};
|
||||
const handleEscKey = (event: KeyboardEvent) => {
|
||||
if (event.key === "Escape") {
|
||||
@@ -2817,6 +3022,70 @@ export default defineComponent({
|
||||
)
|
||||
);
|
||||
});
|
||||
const addJobScheduler = async () => {
|
||||
|
||||
try{
|
||||
// if(searchObj.meta.jobId != ""){
|
||||
// searchObj.meta.jobId = "";
|
||||
// }
|
||||
if (searchObj.meta.jobId != "") {
|
||||
$q.notify({
|
||||
type: "negative",
|
||||
message: "Job Already Scheduled , please change some parameters to schedule new job",
|
||||
timeout: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (
|
||||
searchObj.meta.jobRecords > 100000 ||
|
||||
searchObj.meta.jobRecords == 0 ||
|
||||
searchObj.meta.jobRecords < 0
|
||||
) {
|
||||
$q.notify({
|
||||
type: "negative",
|
||||
message: "Job Scheduler should be between 1 and 100000",
|
||||
timeout: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
searchSchedulerJob.value = false;
|
||||
searchObj.meta.showSearchScheduler = false;
|
||||
await getJobData();
|
||||
|
||||
}
|
||||
catch (e){
|
||||
if(e.response.status != 403){
|
||||
$q.notify({
|
||||
type: "negative",
|
||||
message: "Error while adding job",
|
||||
timeout: 3000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const createScheduleJob = () => {
|
||||
searchSchedulerJob.value = true;
|
||||
searchObj.meta.jobRecords = 100;
|
||||
}
|
||||
|
||||
const checkQuery = (query) => {
|
||||
const jobQuery = router.currentRoute.value.query.query;
|
||||
if (jobQuery == b64EncodeUnicode(query)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const checkFnQuery = (fnQuery) => {
|
||||
const jobFnQuery = router.currentRoute.value.query.functionContent;
|
||||
if (jobFnQuery == b64EncodeUnicode(fnQuery)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// [END] cancel running queries
|
||||
|
||||
@@ -2909,11 +3178,18 @@ export default defineComponent({
|
||||
fnParsedSQL,
|
||||
iconRight,
|
||||
functionToggleIcon,
|
||||
searchSchedulerJob,
|
||||
autoSearchSchedulerJob,
|
||||
addJobScheduler,
|
||||
routeToSearchSchedule,
|
||||
createScheduleJob,
|
||||
searchTerm,
|
||||
filteredFunctionOptions,
|
||||
confirmUpdate,
|
||||
updateViewObj,
|
||||
updateSavedViews,
|
||||
checkQuery,
|
||||
checkFnQuery,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -491,12 +491,6 @@
|
||||
return data.sort((a, b) => a.rawExecutedTime - b.rawExecutedTime);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// return a.rawDuration - b.rawDuration;
|
||||
}
|
||||
const copyToClipboard = (text,type) => {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
|
||||
@@ -33,10 +33,29 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
:htmlContent="searchObj.data.countErrorMsg"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="col-6 text-left q-pl-lg q-mt-xs warning">
|
||||
<div v-else class="col-6 text-left q-pl-lg q-mt-xs warning flex">
|
||||
{{ noOfRecordsTitle }}
|
||||
<span v-if="searchObj.loadingCounter" class="q-ml-md">
|
||||
<q-spinner-hourglass
|
||||
color="primary"
|
||||
size="25px"
|
||||
style="margin: 0 auto; display: block"
|
||||
/>
|
||||
<q-tooltip
|
||||
anchor="center right"
|
||||
self="center left"
|
||||
max-width="300px"
|
||||
>
|
||||
<span style="font-size: 14px"
|
||||
>Fetching the search events</span
|
||||
>
|
||||
</q-tooltip>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="col-6 text-right q-pr-md q-gutter-xs pagination-block">
|
||||
|
||||
<q-pagination
|
||||
v-if="searchObj.meta.resultGrid.showPagination"
|
||||
:disable="searchObj.loading == true"
|
||||
@@ -49,7 +68,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
:max="
|
||||
Math.max(
|
||||
1,
|
||||
(searchObj.communicationMethod === 'ws'
|
||||
(searchObj.communicationMethod === 'ws' ||
|
||||
searchObj.meta.jobId != ''
|
||||
? searchObj.data.queryResults?.pagination?.length
|
||||
: searchObj.data.queryResults?.partitionDetail?.paginations
|
||||
?.length) || 0,
|
||||
@@ -310,19 +330,33 @@ export default defineComponent({
|
||||
} else if (actionType == "recordsPerPage") {
|
||||
this.searchObj.data.resultGrid.currentPage = 1;
|
||||
this.pageNumberInput = this.searchObj.data.resultGrid.currentPage;
|
||||
this.searchObj.communicationMethod === "ws"
|
||||
? this.refreshPagination()
|
||||
: this.refreshPartitionPagination(true);
|
||||
if (this.searchObj.communicationMethod === "ws") {
|
||||
if (this.searchObj.meta.jobId == "") {
|
||||
this.refreshPagination();
|
||||
} else {
|
||||
this.refreshJobPagination();
|
||||
}
|
||||
} else {
|
||||
if (this.searchObj.meta.jobId !== "") {
|
||||
this.refreshJobPagination();
|
||||
} else {
|
||||
this.refreshPartitionPagination(true);
|
||||
}
|
||||
}
|
||||
this.$emit("update:recordsPerPage");
|
||||
this.scrollTableToTop(0);
|
||||
} else if (actionType == "pageChange") {
|
||||
//here at first the queryResults is undefined so we are checking if it is undefined then we are setting it to empty array
|
||||
if(this.searchObj.meta.jobId != "" && this.searchObj.data.queryResults.paginations == undefined){
|
||||
this.searchObj.data.queryResults.pagination = [];
|
||||
}
|
||||
const maxPages =
|
||||
this.searchObj.communicationMethod === "ws"
|
||||
this.searchObj.communicationMethod === "ws" ||
|
||||
this.searchObj.meta.jobId != ""
|
||||
? this.searchObj.data.queryResults.pagination.length
|
||||
: this.searchObj.data.queryResults.partitionDetail.paginations
|
||||
: this.searchObj.data.queryResults?.partitionDetail?.paginations
|
||||
.length;
|
||||
|
||||
if (this.pageNumberInput > Math.ceil(maxPages)) {
|
||||
if (this.pageNumberInput > Math.ceil(maxPages) && this.searchObj.meta.jobId == "") {
|
||||
this.$q.notify({
|
||||
type: "negative",
|
||||
message:
|
||||
@@ -391,6 +425,7 @@ export default defineComponent({
|
||||
reorderSelectedFields,
|
||||
getFilterExpressionByFieldType,
|
||||
refreshPagination,
|
||||
refreshJobPagination,
|
||||
} = useLogs();
|
||||
const pageNumberInput = ref(1);
|
||||
const totalHeight = ref(0);
|
||||
@@ -609,6 +644,7 @@ export default defineComponent({
|
||||
reorderSelectedFields,
|
||||
getPaginations,
|
||||
refreshPagination,
|
||||
refreshJobPagination,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -225,6 +225,135 @@ const search = {
|
||||
payload, // Send the payload as the request body
|
||||
);
|
||||
},
|
||||
schedule_search: (
|
||||
{
|
||||
org_identifier,
|
||||
query,
|
||||
page_type = "logs",
|
||||
traceparent,
|
||||
}: {
|
||||
org_identifier: string;
|
||||
query: any;
|
||||
page_type: string;
|
||||
traceparent?: string;
|
||||
},
|
||||
search_type: string = "UI",
|
||||
) => {
|
||||
if (!traceparent) traceparent = generateTraceContext()?.traceparent;
|
||||
const use_cache: boolean =
|
||||
(window as any).use_cache !== undefined
|
||||
? (window as any).use_cache
|
||||
: true;
|
||||
const url = `/api/${org_identifier}/search_jobs?type=${page_type}&search_type=${search_type}&use_cache=${use_cache}`;
|
||||
return http({ headers: { traceparent } }).post(url, query);
|
||||
},
|
||||
cancel_scheduled_search: (
|
||||
{
|
||||
org_identifier,
|
||||
jobId,
|
||||
traceparent,
|
||||
}: {
|
||||
org_identifier: string;
|
||||
jobId: string;
|
||||
traceparent?: string;
|
||||
},
|
||||
search_type: string = "UI",
|
||||
) => {
|
||||
if (!traceparent) traceparent = generateTraceContext()?.traceparent;
|
||||
const use_cache: boolean =
|
||||
(window as any).use_cache !== undefined
|
||||
? (window as any).use_cache
|
||||
: true;
|
||||
const url = `/api/${org_identifier}/search_jobs/${jobId}/cancel`;
|
||||
return http({ headers: { traceparent } }).post(url);
|
||||
},
|
||||
retry_scheduled_search: (
|
||||
{
|
||||
org_identifier,
|
||||
jobId,
|
||||
traceparent,
|
||||
}: {
|
||||
org_identifier: string;
|
||||
jobId: string;
|
||||
traceparent?: string;
|
||||
},
|
||||
search_type: string = "UI",
|
||||
) => {
|
||||
if (!traceparent) traceparent = generateTraceContext()?.traceparent;
|
||||
const use_cache: boolean =
|
||||
(window as any).use_cache !== undefined
|
||||
? (window as any).use_cache
|
||||
: true;
|
||||
const url = `/api/${org_identifier}/search_jobs/${jobId}/retry`;
|
||||
return http({ headers: { traceparent } }).post(url);
|
||||
},
|
||||
delete_scheduled_search: (
|
||||
{
|
||||
org_identifier,
|
||||
jobId,
|
||||
traceparent,
|
||||
}: {
|
||||
org_identifier: string;
|
||||
jobId: string;
|
||||
traceparent?: string;
|
||||
},
|
||||
search_type: string = "UI",
|
||||
) => {
|
||||
if (!traceparent) traceparent = generateTraceContext()?.traceparent;
|
||||
const use_cache: boolean =
|
||||
(window as any).use_cache !== undefined
|
||||
? (window as any).use_cache
|
||||
: true;
|
||||
const url = `/api/${org_identifier}/search_jobs/${jobId}`;
|
||||
return http({ headers: { traceparent } }).delete(url);
|
||||
},
|
||||
get_scheduled_search_list: (
|
||||
{
|
||||
org_identifier,
|
||||
page_type = "logs",
|
||||
traceparent,
|
||||
}: {
|
||||
org_identifier: string;
|
||||
page_type: string;
|
||||
traceparent?: string;
|
||||
},
|
||||
search_type: string = "UI",
|
||||
) => {
|
||||
if (!traceparent) traceparent = generateTraceContext()?.traceparent;
|
||||
const use_cache: boolean =
|
||||
(window as any).use_cache !== undefined
|
||||
? (window as any).use_cache
|
||||
: true;
|
||||
const url = `/api/${org_identifier}/search_jobs?type=${page_type}&search_type=${search_type}&use_cache=${use_cache}`;
|
||||
return http({ headers: { traceparent } }).get(url);
|
||||
},
|
||||
get_scheduled_search_result: (
|
||||
{
|
||||
org_identifier,
|
||||
page_type = "logs",
|
||||
jobId,
|
||||
traceparent,
|
||||
query,
|
||||
}: {
|
||||
org_identifier: string;
|
||||
jobId: string;
|
||||
page_type: string;
|
||||
traceparent?: string;
|
||||
query: any;
|
||||
},
|
||||
search_type: string = "UI",
|
||||
) => {
|
||||
if (!traceparent) traceparent = generateTraceContext()?.traceparent;
|
||||
const { size, from } = query.query;
|
||||
const use_cache: boolean =
|
||||
(window as any).use_cache !== undefined
|
||||
? (window as any).use_cache
|
||||
: true;
|
||||
let url = `/api/${org_identifier}/search_jobs/${jobId}/result?type=${page_type}&search_type=${search_type}&use_cache=${use_cache}`;
|
||||
url += `&size=${size}&from=${from}`;
|
||||
|
||||
return http({ headers: { traceparent } }).get(url);
|
||||
},
|
||||
};
|
||||
|
||||
export default search;
|
||||
|
||||
Reference in New Issue
Block a user