Skip to content

Commit

Permalink
Top n queries connected to api (#10)
Browse files Browse the repository at this point in the history
* Add 2 tabs to home screen

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* two tabs for query insights and configuration

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Breadcrumbs + restructuring

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Top n queries table + search

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* search in general

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Search includes indices and time selection fully works

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Fix tabs display

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Basic functionalities of configuration page

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Save button + cancel button working

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Fixing lint and including relevant files

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Typo

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* ignore lintcache

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Delete .eslintcache

Signed-off-by: Emily Guo <35637792+LilyCaroline17@users.noreply.github.com>

* remove commented out lines

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Update based on comments on overview page

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Rerun security check?

Signed-off-by: Emily Guo <emilyguo@amazon.com>

* Added updates to all configurations

Signed-off-by: Emily Guo <LilyCaroline1717@gmail.com>

* Updated unit test

Signed-off-by: Emily Guo <LilyCaroline1717@gmail.com>

* Fix based on comments

Signed-off-by: Emily Guo <LilyCaroline1717@gmail.com>

* Fixed lint issues

Signed-off-by: Emily Guo <LilyCaroline1717@gmail.com>

* Update TopNQueries.tsx

Signed-off-by: Emily Guo <35637792+LilyCaroline17@users.noreply.github.com>

* Connected api to frontend

Signed-off-by: Emily Guo <LilyCaroline1717@gmail.com>

---------

Signed-off-by: Emily Guo <emilyguo@amazon.com>
Signed-off-by: Emily Guo <35637792+LilyCaroline17@users.noreply.github.com>
Signed-off-by: Emily Guo <LilyCaroline1717@gmail.com>
  • Loading branch information
LilyCaroline17 authored Sep 4, 2024
1 parent afe9a0c commit 405f5e7
Show file tree
Hide file tree
Showing 4 changed files with 435 additions and 20 deletions.
145 changes: 132 additions & 13 deletions public/pages/TopNQueries/TopNQueries.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Redirect, Route, Switch, useHistory, useLocation } from 'react-router-dom';
import { EuiTab, EuiTabs, EuiTitle, EuiSpacer } from '@elastic/eui';
import dateMath from '@elastic/datemath';
import QueryInsights from '../QueryInsights/QueryInsights';
import Configuration from '../Configuration/Configuration';
import { CoreStart } from '../../../../../src/core/public';
Expand Down Expand Up @@ -91,18 +92,135 @@ const TopNQueries = ({ core }: { core: CoreStart }) => {
</EuiTab>
);

const retrieveQueries = useCallback(async (start: string, end: string) => {
try {
setLoading(true);
const noDuplicates: any[] = [];
setQueries(noDuplicates);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error retrieving queries:', error);
} finally {
setLoading(false);
}
}, []);
const parseDateString = (dateString: string) => {
const date = dateMath.parse(dateString);
return date ? date.toDate().getTime() : new Date().getTime();
};

const retrieveQueries = useCallback(
async (start: string, end: string) => {
const nullResponse = { response: { top_queries: [] } };
const params = {
query: {
from: new Date(parseDateString(start)).toISOString(),
to: new Date(parseDateString(end)).toISOString(),
},
};
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;
}
};
try {
setLoading(true);
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/memory')
: nullResponse;
const newQueries = [
...respLatency.response.top_queries,
...respCpu.response.top_queries,
...respMemory.response.top_queries,
];
const noDuplicates = Array.from(
new Set(newQueries.map((item) => JSON.stringify(item)))
).map((item) => JSON.parse(item));
setQueries(noDuplicates);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error retrieving queries:', error);
} finally {
setLoading(false);
}
},
[latencySettings, cpuSettings, memorySettings, core]
);

const retrieveConfigInfo = useCallback(
async (
get: boolean,
enabled: boolean = false,
metric: string = '',
newTopN: string = '',
newWindowSize: string = '',
newTimeUnit: string = ''
) => {
if (get) {
try {
const resp = await core.http.get('/api/settings');
const settings = resp.response.persistent.search.insights.top_queries;
const latency = settings.latency;
const cpu = settings.cpu;
const memory = settings.memory;
if (latency !== undefined && latency.enabled === 'true') {
const [time, timeUnits] = latency.window_size.match(/\D+|\d+/g);
setMetricSettings('latency', {
isEnabled: true,
currTopN: latency.top_n_size,
currWindowSize: time,
currTimeUnit: timeUnits === 'm' ? 'MINUTES' : 'HOURS',
});
}
if (cpu !== undefined && cpu.enabled === 'true') {
const [time, timeUnits] = cpu.window_size.match(/\D+|\d+/g);
setMetricSettings('cpu', {
isEnabled: true,
currTopN: cpu.top_n_size,
currWindowSize: time,
currTimeUnit: timeUnits === 'm' ? 'MINUTES' : 'HOURS',
});
}
if (memory !== undefined && memory.enabled === 'true') {
const [time, timeUnits] = memory.window_size.match(/\D+|\d+/g);
setMetricSettings('memory', {
isEnabled: true,
currTopN: memory.top_n_size,
currWindowSize: time,
currTimeUnit: timeUnits === 'm' ? 'MINUTES' : 'HOURS',
});
}
} catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to retrieve settings:', error);
}
} else {
try {
setMetricSettings(metric, {
isEnabled: enabled,
currTopN: newTopN,
currWindowSize: newWindowSize,
currTimeUnit: newTimeUnit,
});
await core.http.put('/api/update_settings', {
query: {
metric,
enabled,
top_n_size: newTopN,
window_size: `${newWindowSize}${newTimeUnit === 'MINUTES' ? 'm' : 'h'}`,
},
});
} catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to set settings:', error);
}
}
},
[core]
);

const retrieveConfigInfo = useCallback(
async (
Expand Down Expand Up @@ -136,6 +254,7 @@ const TopNQueries = ({ core }: { core: CoreStart }) => {
setStart(start);
setEnd(end);
setRecentlyUsedRanges(usedRange.length > 10 ? usedRange.slice(0, 9) : usedRange);
retrieveConfigInfo(true);
retrieveQueries(start, end);
};

Expand All @@ -146,7 +265,7 @@ const TopNQueries = ({ core }: { core: CoreStart }) => {

useEffect(() => {
retrieveQueries(currStart, currEnd);
}, [currStart, currEnd, retrieveQueries]);
}, [latencySettings, cpuSettings, memorySettings, currStart, currEnd, retrieveQueries]);

return (
<div style={{ padding: '35px 35px' }}>
Expand Down
83 changes: 83 additions & 0 deletions server/clusters/queryInsightsPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export const QueryInsightsPlugin = function (Client, config, components) {
const ca = components.clientAction.factory;
Client.prototype.queryInsights = components.clientAction.namespaceFactory();
const queryInsights = Client.prototype.queryInsights.prototype;

queryInsights.getTopNQueries = ca({
url: {
fmt: `/_insights/top_queries`,
},
method: 'GET',
});

queryInsights.getTopNQueriesLatency = ca({
url: {
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&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&from=<%=from%>&to=<%=to%>`,
req: {
from: {
type: 'string',
required: true,
},
to: {
type: 'string',
required: true,
},
},
},
method: 'GET',
});

queryInsights.getSettings = ca({
url: {
fmt: `_cluster/settings?include_defaults=true`,
},
method: 'GET',
});

queryInsights.setSettings = ca({
url: {
fmt: `_cluster/settings`,
},
method: 'PUT',
needBody: true,
});
};
15 changes: 15 additions & 0 deletions server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
CoreStart,
Plugin,
Logger,
ILegacyCustomClusterClient,
} from '../../../src/core/server';
import { QueryInsightsPlugin } from './clusters/queryInsightsPlugin';

import { QueryInsightsDashboardsPluginSetup, QueryInsightsDashboardsPluginStart } from './types';
import { defineRoutes } from './routes';
Expand All @@ -20,6 +22,19 @@ export class QueryInsightsDashboardsPlugin
public setup(core: CoreSetup) {
this.logger.debug('query-insights-dashboards: Setup');
const router = core.http.createRouter();
const queryInsightsClient: ILegacyCustomClusterClient = core.opensearch.legacy.createClient(
'opensearch_queryInsights',
{
plugins: [QueryInsightsPlugin],
}
);
// @ts-ignore
core.http.registerRouteHandlerContext('queryInsights_plugin', (_context, _request) => {
return {
logger: this.logger,
queryInsightsClient,
};
});

// Register server side APIs
defineRoutes(router);
Expand Down
Loading

0 comments on commit 405f5e7

Please sign in to comment.