();
- useEffect(() => {
- core.chrome.setBreadcrumbs([
- {
- text: 'Query insights',
- href: QUERY_INSIGHTS,
- onClick: (e) => {
- e.preventDefault();
- history.push(QUERY_INSIGHTS);
- },
- },
- { text: `Query details: ${convertTime(query.timestamp)}` },
- ]);
- }, [core.chrome, history, location, query.timestamp]);
+ // Get query from state or sessionStorage
+ const query = location.state?.query || getQueryFromSession();
+ function getQueryFromSession(): SearchQueryRecord | null {
+ try {
+ const cachedQuery = sessionStorage.getItem(QUERY_DETAILS_CACHE_KEY);
+ return cachedQuery ? JSON.parse(cachedQuery) : null;
+ } catch (error) {
+ console.error('Error reading query from sessionStorage:', error);
+ return null;
+ }
+ }
+ // Cache query if it exists
useEffect(() => {
- let x: number[] = Object.values(query.phase_latency_map);
- if (x.length < 3) {
- x = [0, 0, 0];
+ if (query) {
+ sessionStorage.setItem(QUERY_DETAILS_CACHE_KEY, JSON.stringify(query));
+ } else {
+ // if query doesn't exist, return to overview page
+ history.push(QUERY_INSIGHTS);
}
+ }, [query, history]);
+
+ // Convert UNIX time to a readable format
+ const convertTime = useCallback((unixTime: number) => {
+ const date = new Date(unixTime);
+ const [_weekDay, month, day, year] = date.toDateString().split(' ');
+ return `${month} ${day}, ${year} @ ${date.toLocaleTimeString('en-US')}`;
+ }, []);
+
+ // Initialize the Plotly chart
+ const initPlotlyChart = useCallback(() => {
+ const latencies = Object.values(query?.phase_latency_map || [0, 0, 0]);
const data = [
{
- x: x.reverse(),
+ x: latencies.reverse(),
y: ['Fetch ', 'Query ', 'Expand '],
type: 'bar',
orientation: 'h',
width: 0.5,
marker: { color: ['#F990C0', '#1BA9F5', '#7DE2D1'] },
- base: [x[2] + x[1], x[2], 0],
- text: x.map((value) => `${value}ms`),
+ base: [latencies[2] + latencies[1], latencies[2], 0],
+ text: latencies.map((value) => `${value}ms`),
textposition: 'outside',
cliponaxis: false,
},
@@ -72,7 +81,6 @@ const QueryDetails = ({ queries, core }: { queries: any; core: CoreStart }) => {
const layout = {
autosize: true,
margin: { l: 80, r: 80, t: 25, b: 15, pad: 0 },
- autorange: true,
height: 120,
xaxis: {
side: 'top',
@@ -89,7 +97,28 @@ const QueryDetails = ({ queries, core }: { queries: any; core: CoreStart }) => {
Plotly.newPlot('latency', data, layout, config);
}, [query]);
- const queryString = JSON.stringify(JSON.parse(JSON.stringify(query.source)), null, 2);
+ useEffect(() => {
+ if (query) {
+ core.chrome.setBreadcrumbs([
+ {
+ text: 'Query insights',
+ href: QUERY_INSIGHTS,
+ onClick: (e) => {
+ e.preventDefault();
+ history.push(QUERY_INSIGHTS);
+ },
+ },
+ { text: `Query details: ${convertTime(query.timestamp)}` },
+ ]);
+ initPlotlyChart();
+ }
+ }, [query, history, core.chrome, convertTime, initPlotlyChart]);
+
+ if (!query) {
+ return ;
+ }
+
+ const queryString = JSON.stringify(query.source, null, 2);
const queryDisplay = `{\n "query": ${queryString ? queryString.replace(/\n/g, '\n ') : ''}\n}`;
return (
@@ -117,7 +146,7 @@ const QueryDetails = ({ queries, core }: { queries: any; core: CoreStart }) => {
target="_blank"
href="https://playground.opensearch.org/app/searchRelevance#/"
>
- Open in search comparision
+ Open in search comparison
diff --git a/public/pages/QueryInsights/QueryInsights.tsx b/public/pages/QueryInsights/QueryInsights.tsx
index e5b7e93..7ca7007 100644
--- a/public/pages/QueryInsights/QueryInsights.tsx
+++ b/public/pages/QueryInsights/QueryInsights.tsx
@@ -6,7 +6,6 @@
import React, { useEffect, useState } from 'react';
import { EuiBasicTableColumn, EuiInMemoryTable, EuiLink, EuiSuperDatePicker } from '@elastic/eui';
import { useHistory, useLocation } from 'react-router-dom';
-import hash from 'object-hash';
import { CoreStart } from 'opensearch-dashboards/public';
import { QUERY_INSIGHTS } from '../TopNQueries/TopNQueries';
import { SearchQueryRecord } from '../../../types/types';
@@ -73,10 +72,17 @@ const QueryInsights = ({
{
// Make into flyout instead?
name: TIMESTAMP,
- render: (query: any) => {
+ render: (query: SearchQueryRecord) => {
return (
- history.push(`/query-details/${hash(query)}`)}>
+
+ history.push({
+ pathname: `/query-details`,
+ state: { query },
+ })
+ }
+ >
{convertTime(query.timestamp)}
diff --git a/public/pages/TopNQueries/TopNQueries.tsx b/public/pages/TopNQueries/TopNQueries.tsx
index fd70c00..c6f5650 100644
--- a/public/pages/TopNQueries/TopNQueries.tsx
+++ b/public/pages/TopNQueries/TopNQueries.tsx
@@ -254,8 +254,8 @@ const TopNQueries = ({ core }: { core: CoreStart }) => {
return (
-
-
+
+
diff --git a/public/plugin.ts b/public/plugin.ts
index 9371fdf..752fc4d 100644
--- a/public/plugin.ts
+++ b/public/plugin.ts
@@ -7,6 +7,7 @@ import { i18n } from '@osd/i18n';
import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '../../../src/core/public';
import { QueryInsightsDashboardsPluginSetup, QueryInsightsDashboardsPluginStart } from './types';
import { PLUGIN_NAME } from '../common';
+import { QUERY_DETAILS_CACHE_KEY } from '../common/constants';
export class QueryInsightsDashboardsPlugin
implements Plugin {
@@ -50,5 +51,7 @@ export class QueryInsightsDashboardsPlugin
return {};
}
- public stop() {}
+ public stop() {
+ sessionStorage.removeItem(QUERY_DETAILS_CACHE_KEY);
+ }
}
diff --git a/test/testUtils.ts b/test/testUtils.ts
new file mode 100644
index 0000000..55ad71d
--- /dev/null
+++ b/test/testUtils.ts
@@ -0,0 +1,99 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { SearchQueryRecord } from '../types/types';
+
+export const MockQueries = (): SearchQueryRecord[] => {
+ return [
+ {
+ timestamp: 1726178995210,
+ task_resource_usages: [
+ {
+ action: 'indices:data/read/search[phase/query]',
+ taskId: 18809,
+ parentTaskId: 18808,
+ nodeId: 'Q36D2z_NRGKim6EZZMgi6A',
+ taskResourceUsage: {
+ cpu_time_in_nanos: 3612000,
+ memory_in_bytes: 123944,
+ },
+ },
+ {
+ action: 'indices:data/read/search',
+ taskId: 18808,
+ parentTaskId: -1,
+ nodeId: 'Q36D2z_NRGKim6EZZMgi6A',
+ taskResourceUsage: {
+ cpu_time_in_nanos: 1898000,
+ memory_in_bytes: 24176,
+ },
+ },
+ ],
+ source: {
+ query: {
+ bool: {
+ must: [
+ {
+ range: {
+ timestamp: {
+ from: 1726092595177,
+ to: 1726178995177,
+ include_lower: true,
+ include_upper: true,
+ boost: 1.0,
+ },
+ },
+ },
+ ],
+ must_not: [
+ {
+ match: {
+ indices: {
+ query: 'top_queries*',
+ operator: 'OR',
+ prefix_length: 0,
+ max_expansions: 50,
+ fuzzy_transpositions: true,
+ lenient: false,
+ zero_terms_query: 'NONE',
+ auto_generate_synonyms_phrase_query: true,
+ boost: 1.0,
+ },
+ },
+ },
+ ],
+ adjust_pure_negative: true,
+ boost: 1.0,
+ },
+ },
+ },
+ query_hashcode: '80a17984b847133b8bf5e7d5dfbfa96c',
+ phase_latency_map: {
+ expand: 0,
+ query: 5,
+ fetch: 0,
+ },
+ labels: {
+ 'X-Opaque-Id': 'ae6c1170-5f98-47f4-b7fc-09ebcf574b81',
+ },
+ total_shards: 1,
+ search_type: 'query_then_fetch',
+ node_id: 'Q36D2z_NRGKim6EZZMgi6A',
+ indices: ['top_queries-2024.09.12'],
+ measurements: {
+ latency: {
+ number: 8,
+ count: 1,
+ aggregationType: 'NONE',
+ },
+ cpu: {
+ number: 5510000,
+ count: 1,
+ aggregationType: 'NONE',
+ },
+ },
+ },
+ ];
+};
diff --git a/types/types.ts b/types/types.ts
index 01f2f59..ca4ec71 100644
--- a/types/types.ts
+++ b/types/types.ts
@@ -3,8 +3,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { ISearchSource } from 'src/plugins/data/public';
-
export interface SearchQueryRecord {
timestamp: number;
measurements: {
@@ -14,12 +12,13 @@ export interface SearchQueryRecord {
};
total_shards: number;
node_id: string;
- source: ISearchSource;
+ source: Record;
labels: Record;
search_type: string;
indices: string[];
phase_latency_map: PhaseLatencyMap;
task_resource_usages: Task[];
+ query_hashcode: string;
}
export interface Measurement {
diff --git a/yarn.lock b/yarn.lock
index c5c5f59..77f03ac 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,6 +2,11 @@
# yarn lockfile v1
+"@adobe/css-tools@^4.0.1":
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.0.tgz#728c484f4e10df03d5a3acd0d8adcbbebff8ad63"
+ integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==
+
"@ampproject/remapping@^2.2.0":
version "2.3.0"
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4"
@@ -248,7 +253,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.24.8"
-"@babel/runtime@^7.12.5":
+"@babel/runtime@^7.12.5", "@babel/runtime@^7.9.2":
version "7.25.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.6.tgz#9afc3289f7184d8d7f98b099884c26317b9264d2"
integrity sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==
@@ -735,6 +740,21 @@
lz-string "^1.5.0"
pretty-format "^27.0.2"
+"@testing-library/jest-dom@^5.16.2":
+ version "5.17.0"
+ resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz#5e97c8f9a15ccf4656da00fecab505728de81e0c"
+ integrity sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==
+ dependencies:
+ "@adobe/css-tools" "^4.0.1"
+ "@babel/runtime" "^7.9.2"
+ "@types/testing-library__jest-dom" "^5.9.1"
+ aria-query "^5.0.0"
+ chalk "^3.0.0"
+ css.escape "^1.5.1"
+ dom-accessibility-api "^0.5.6"
+ lodash "^4.17.15"
+ redent "^3.0.0"
+
"@testing-library/user-event@^14.4.3":
version "14.5.2"
resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd"
@@ -821,7 +841,7 @@
dependencies:
"@types/istanbul-lib-report" "*"
-"@types/jest@^29.3.1":
+"@types/jest@*", "@types/jest@^29.3.1":
version "29.5.12"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544"
integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==
@@ -914,6 +934,13 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8"
integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==
+"@types/testing-library__jest-dom@^5.9.1":
+ version "5.14.9"
+ resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz#0fb1e6a0278d87b6737db55af5967570b67cb466"
+ integrity sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==
+ dependencies:
+ "@types/jest" "*"
+
"@types/yargs-parser@*":
version "21.0.3"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
@@ -1239,6 +1266,11 @@ aria-query@5.1.3:
dependencies:
deep-equal "^2.0.5"
+aria-query@^5.0.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.1.tgz#ebcb2c0d7fc43e68e4cb22f774d1209cb627ab42"
+ integrity sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==
+
arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@@ -1752,6 +1784,14 @@ chalk@^2.3.0, chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
+chalk@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
+ integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
chalk@^4.0.0, chalk@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@@ -2103,6 +2143,11 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
+css.escape@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
+ integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==
+
cssom@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
@@ -2385,7 +2430,7 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"
-dom-accessibility-api@^0.5.9:
+dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9:
version "0.5.16"
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453"
integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==
@@ -4526,7 +4571,7 @@ lodash.once@^4.1.1:
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
-lodash@^4.17.21, lodash@^4.7.0:
+lodash@^4.17.15, lodash@^4.17.21, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -4690,6 +4735,11 @@ mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+min-indent@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+ integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
@@ -5353,6 +5403,14 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
+redent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
+ integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
+ dependencies:
+ indent-string "^4.0.0"
+ strip-indent "^3.0.0"
+
regenerator-runtime@^0.14.0:
version "0.14.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
@@ -5965,6 +6023,13 @@ strip-final-newline@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+strip-indent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+ integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+ dependencies:
+ min-indent "^1.0.0"
+
strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"