From 83970c3af418f58185cefcaecc6d8e26f5162add Mon Sep 17 00:00:00 2001 From: Emily Guo Date: Mon, 19 Aug 2024 03:53:54 -0700 Subject: [PATCH] Integrate front end to include from and to with backend changes --- public/pages/QueryInsights/QueryInsights.tsx | 35 ++---- public/pages/TopNQueries/TopNQueries.tsx | 107 +++++++++++-------- server/clusters/queryInsightsPlugin.ts | 36 ++++++- server/routes/index.ts | 46 ++++---- 4 files changed, 134 insertions(+), 90 deletions(-) diff --git a/public/pages/QueryInsights/QueryInsights.tsx b/public/pages/QueryInsights/QueryInsights.tsx index 93baa90..a342f12 100644 --- a/public/pages/QueryInsights/QueryInsights.tsx +++ b/public/pages/QueryInsights/QueryInsights.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useEffect } from 'react'; import { EuiBasicTableColumn, EuiSuperDatePicker, EuiInMemoryTable, EuiLink } from '@elastic/eui'; import { useHistory, useLocation } from 'react-router-dom'; import { CoreStart } from '../../../../../src/core/public'; @@ -17,14 +17,18 @@ const METRIC_DEFAULT_MSG = 'Not enabled'; const QueryInsights = ({ queries, loading, - onQueriesChange, - defaultStart, + onTimeChange, + recentlyUsedRanges, + currStart, + currEnd, core, }: { queries: any[]; loading: boolean; - onQueriesChange: any; - defaultStart: string; + onTimeChange: any; + recentlyUsedRanges: any[]; + currStart: string; + currEnd: string; core: CoreStart; }) => { const history = useHistory(); @@ -116,25 +120,8 @@ const QueryInsights = ({ }, ]; - const [recentlyUsedRanges, setRecentlyUsedRanges] = useState([ - { start: defaultStart, end: 'now' }, - ]); - const [currStart, setStart] = useState(defaultStart); - const [currEnd, setEnd] = useState('now'); - - const onTimeChange = ({ start, end }: { start: string; end: string }) => { - const usedRange = recentlyUsedRanges.filter( - (range) => !(range.start === start && range.end === end) - ); - usedRange.unshift({ start, end }); - setStart(start); - setEnd(end); - setRecentlyUsedRanges(usedRange.length > 10 ? usedRange.slice(0, 9) : usedRange); - onQueriesChange(start, end); - }; - const onRefresh = async ({ start, end }: { start: string; end: string }) => { - onQueriesChange(start, end); + onTimeChange({ start, end }); }; return ( @@ -157,8 +144,8 @@ const QueryInsights = ({ , diff --git a/public/pages/TopNQueries/TopNQueries.tsx b/public/pages/TopNQueries/TopNQueries.tsx index e665c38..2d4a45f 100644 --- a/public/pages/TopNQueries/TopNQueries.tsx +++ b/public/pages/TopNQueries/TopNQueries.tsx @@ -21,7 +21,11 @@ const TopNQueries = ({ core }: { core: CoreStart }) => { const history = useHistory(); const location = useLocation(); const [loading, setLoading] = useState(false); - const defaultStart = 'now-1y'; + const [currStart, setStart] = useState('now-1y'); + const [currEnd, setEnd] = useState('now'); + const [recentlyUsedRanges, setRecentlyUsedRanges] = useState([ + { start: currStart, end: currEnd }, + ]); const [latencySettings, setLatencySettings] = useState({ isEnabled: false, currTopN: '', @@ -99,38 +103,42 @@ const TopNQueries = ({ core }: { core: CoreStart }) => { const retrieveQueries = useCallback( async (start: string, end: string) => { setLoading(true); - try { - const nullResponse = { response: { top_queries: [] } }; - const respLatency = latencySettings.isEnabled - ? await core.http.get('/api/top_queries/latency') - : nullResponse; - const respCpu = cpuSettings.isEnabled - ? await core.http.get('/api/top_queries/cpu') - : nullResponse; - const respMemory = memorySettings.isEnabled - ? await core.http.get('/api/top_queries/memory') - : nullResponse; - const newQueries = [ - ...respLatency.response.top_queries, - ...respCpu.response.top_queries, - ...respMemory.response.top_queries, - ]; - const startTimestamp = parseDateString(start); - const endTimestamp = parseDateString(end); - const noDuplicates = newQueries.filter( - (array, index, self) => - index === self.findIndex((t) => t.save === array.save && t.State === array.State) - ); - setQueries( - noDuplicates.filter( - (item: any) => item.timestamp >= startTimestamp && item.timestamp <= endTimestamp - ) - ); - } catch (error) { - console.error('Failed to retrieve queries:', error); - } finally { - setLoading(false); - } + const nullResponse = { response: { top_queries: [] } }; + const params = { + query: { + from: parseDateString(start), + to: parseDateString(end), + }, + }; + const fetchMetric = async (endpoint : string) => { + try { + const response = await core.http.get(endpoint, params); + return { response: { top_queries: Array.isArray(response?.response?.top_queries) ? response.response.top_queries : [] } }; + } catch { + return nullResponse; + } + }; + const respLatency = latencySettings.isEnabled ? await fetchMetric('/api/top_queries/latency'): nullResponse; + const respCpu = cpuSettings.isEnabled ? await fetchMetric('/api/top_queries/cpu'): nullResponse; + const respMemory = memorySettings.isEnabled ? await fetchMetric('/api/top_queries/latency'): nullResponse; + const newQueries = [ + ...respLatency.response.top_queries, + ...respCpu.response.top_queries, + ...respMemory.response.top_queries, + ]; + // const startTimestamp = parseDateString(start); + // const endTimestamp = parseDateString(end); + const noDuplicates = newQueries.filter( + (array: any, index, self) => + index === self.findIndex((t: any) => t.save === array.save && t.State === array.State) + ); + setQueries(noDuplicates); + // setQueries( + // noDuplicates.filter( + // (item: any) => item.timestamp >= startTimestamp && item.timestamp <= endTimestamp + // ) + // ); + setLoading(false); }, [latencySettings, cpuSettings, memorySettings, core] ); @@ -144,6 +152,7 @@ const TopNQueries = ({ core }: { core: CoreStart }) => { newWindowSize: string = '', newTimeUnit: string = '' ) => { + setLoading(true); if (get) { try { const resp = await core.http.get('/api/settings'); @@ -189,7 +198,7 @@ const TopNQueries = ({ core }: { core: CoreStart }) => { currWindowSize: newWindowSize, currTimeUnit: newTimeUnit, }); - const resp = await core.http.put('/api/update_settings', { + await core.http.put('/api/update_settings', { query: { metric, enabled, @@ -201,22 +210,30 @@ const TopNQueries = ({ core }: { core: CoreStart }) => { console.error('Failed to set settings:', error); } } + setLoading(false); }, [core] ); - const onQueriesChange = (start: string, end: string) => { - retrieveQueries(start, end); + const onTimeChange = ({ start, end }: { start: string; end: string }) => { + const usedRange = recentlyUsedRanges.filter( + (range) => !(range.start === start && range.end === end) + ); + usedRange.unshift({ start, end }); + setStart(start); + setEnd(end); + setRecentlyUsedRanges(usedRange.length > 10 ? usedRange.slice(0, 9) : usedRange); retrieveConfigInfo(true); + retrieveQueries(start, end); }; useEffect(() => { - retrieveQueries(defaultStart, 'now'); - }, [retrieveQueries, defaultStart]); - - useEffect(() => { - retrieveConfigInfo(true); - }, [retrieveConfigInfo]); + const asyncUpdates = async () => { + await retrieveConfigInfo(true); + await retrieveQueries(currStart, currEnd); + } + asyncUpdates(); + }, [currStart, currEnd]); return (
@@ -234,8 +251,10 @@ const TopNQueries = ({ core }: { core: CoreStart }) => { diff --git a/server/clusters/queryInsightsPlugin.ts b/server/clusters/queryInsightsPlugin.ts index 53a87ba..24b0f75 100644 --- a/server/clusters/queryInsightsPlugin.ts +++ b/server/clusters/queryInsightsPlugin.ts @@ -17,21 +17,51 @@ export const QueryInsightsPlugin = function (Client, config, components) { queryInsights.getTopNQueriesLatency = ca({ url: { - fmt: `/_insights/top_queries?type=latency`, + fmt: `/_insights/top_queries?type=latency&from=<%=from%>&to=<%=to%>`, + req: { + from: { + type: 'string', + required: true, + }, + to: { + type: 'string', + required: true, + }, + }, }, method: 'GET', }); queryInsights.getTopNQueriesCpu = ca({ url: { - fmt: `/_insights/top_queries?type=cpu`, + fmt: `/_insights/top_queries?type=cpu&from=<%=from%>&to=<%=to%>`, + req: { + from: { + type: 'string', + required: true, + }, + to: { + type: 'string', + required: true, + }, + }, }, method: 'GET', }); queryInsights.getTopNQueriesMemory = ca({ url: { - fmt: `/_insights/top_queries?type=memory`, + fmt: `/_insights/top_queries?type=memory&from=<%=from%>&to=<%=to%>`, + req: { + from: { + type: 'string', + required: true, + }, + to: { + type: 'string', + required: true, + }, + }, }, method: 'GET', }); diff --git a/server/routes/index.ts b/server/routes/index.ts index 3deefed..cd59293 100644 --- a/server/routes/index.ts +++ b/server/routes/index.ts @@ -1,19 +1,6 @@ import { schema } from '@osd/config-schema'; import { IRouter } from '../../../../src/core/server'; export function defineRoutes(router: IRouter) { - router.get( - { - path: '/api/query_insights_dashboards/example', - validate: false, - }, - async (context, request, response) => { - return response.ok({ - body: { - time: new Date().toISOString(), - }, - }); - } - ); router.get( { path: '/api/top_queries', @@ -46,13 +33,20 @@ export function defineRoutes(router: IRouter) { router.get( { path: '/api/top_queries/latency', - validate: false, + validate: { + query: schema.object({ + from: schema.maybe(schema.string({ defaultValue: '' })), + to: schema.maybe(schema.string({ defaultValue: '' })), + }), + }, }, async (context, request, response) => { try { + const { from, to } = request.query; + const params = { from, to }; const client = context.queryInsights_plugin.queryInsightsClient.asScoped(request) .callAsCurrentUser; - const res = await client('queryInsights.getTopNQueriesLatency'); + const res = await client('queryInsights.getTopNQueriesLatency', params); return response.custom({ statusCode: 200, body: { @@ -75,13 +69,20 @@ export function defineRoutes(router: IRouter) { router.get( { path: '/api/top_queries/cpu', - validate: false, + validate: { + query: schema.object({ + from: schema.maybe(schema.string({ defaultValue: '' })), + to: schema.maybe(schema.string({ defaultValue: '' })), + }), + }, }, async (context, request, response) => { try { + const { from, to } = request.query; + const params = { from, to }; const client = context.queryInsights_plugin.queryInsightsClient.asScoped(request) .callAsCurrentUser; - const res = await client('queryInsights.getTopNQueriesCpu'); + const res = await client('queryInsights.getTopNQueriesCpu', params); return response.custom({ statusCode: 200, body: { @@ -104,13 +105,20 @@ export function defineRoutes(router: IRouter) { router.get( { path: '/api/top_queries/memory', - validate: false, + validate: { + query: schema.object({ + from: schema.maybe(schema.string({ defaultValue: '' })), + to: schema.maybe(schema.string({ defaultValue: '' })), + }), + }, }, async (context, request, response) => { try { + const { from, to } = request.query; + const params = { from, to }; const client = context.queryInsights_plugin.queryInsightsClient.asScoped(request) .callAsCurrentUser; - const res = await client('queryInsights.getTopNQueriesMemory'); + const res = await client('queryInsights.getTopNQueriesMemory', params); return response.custom({ statusCode: 200, body: {