diff --git a/common/constants.ts b/common/constants.ts
new file mode 100644
index 0000000..2186516
--- /dev/null
+++ b/common/constants.ts
@@ -0,0 +1,13 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+export const TIMESTAMP = 'Timestamp';
+export const LATENCY = 'Latency';
+export const CPU_TIME = 'CPU Time';
+export const MEMORY_USAGE = 'Memory Usage';
+export const INDICES = 'Indices';
+export const SEARCH_TYPE = 'Search type';
+export const NODE_ID = 'Coordinator node ID';
+export const TOTAL_SHARDS = 'Total shards';
diff --git a/package.json b/package.json
index 43a0b8e..12b846f 100644
--- a/package.json
+++ b/package.json
@@ -43,6 +43,7 @@
"@testing-library/dom": "^8.11.3",
"@testing-library/user-event": "^14.4.3",
"@types/react-dom": "^16.9.8",
+ "@types/object-hash": "^3.0.0",
"@types/react-router-dom": "^5.3.2",
"cypress": "9.5.4",
"cypress-real-events": "1.7.6",
diff --git a/public/components/__snapshots__/app.test.tsx.snap b/public/components/__snapshots__/app.test.tsx.snap
index cbb837a..3571697 100644
--- a/public/components/__snapshots__/app.test.tsx.snap
+++ b/public/components/__snapshots__/app.test.tsx.snap
@@ -452,7 +452,7 @@ exports[` spec renders the component 1`] = `
aria-live="polite"
aria-sort="none"
class="euiTableHeaderCell"
- data-test-subj="tableHeaderCell_latency_1"
+ data-test-subj="tableHeaderCell_measurements_1"
role="columnheader"
scope="col"
>
@@ -477,7 +477,7 @@ exports[` spec renders the component 1`] = `
aria-live="polite"
aria-sort="none"
class="euiTableHeaderCell"
- data-test-subj="tableHeaderCell_cpu_2"
+ data-test-subj="tableHeaderCell_measurements_2"
role="columnheader"
scope="col"
>
@@ -491,9 +491,9 @@ exports[` spec renders the component 1`] = `
>
- CPU usage
+ CPU Time
@@ -502,7 +502,7 @@ exports[` spec renders the component 1`] = `
aria-live="polite"
aria-sort="none"
class="euiTableHeaderCell"
- data-test-subj="tableHeaderCell_memory_3"
+ data-test-subj="tableHeaderCell_measurements_3"
role="columnheader"
scope="col"
>
@@ -516,9 +516,9 @@ exports[` spec renders the component 1`] = `
>
- Memory
+ Memory Usage
diff --git a/public/pages/Configuration/Configuration.tsx b/public/pages/Configuration/Configuration.tsx
index 8978cf1..735fb6a 100644
--- a/public/pages/Configuration/Configuration.tsx
+++ b/public/pages/Configuration/Configuration.tsx
@@ -23,7 +23,7 @@ import {
EuiTitle,
} from '@elastic/eui';
import { useHistory, useLocation } from 'react-router-dom';
-import { CoreStart } from '../../../../../src/core/public';
+import { CoreStart } from 'opensearch-dashboards/public';
import { QUERY_INSIGHTS, MetricSettings } from '../TopNQueries/TopNQueries';
const Configuration = ({
diff --git a/public/pages/QueryDetails/Components/QuerySummary.tsx b/public/pages/QueryDetails/Components/QuerySummary.tsx
index 7110599..cd10517 100644
--- a/public/pages/QueryDetails/Components/QuerySummary.tsx
+++ b/public/pages/QueryDetails/Components/QuerySummary.tsx
@@ -5,13 +5,36 @@
import React from 'react';
import { EuiFlexGrid, EuiFlexItem, EuiHorizontalRule, EuiPanel, EuiText } from '@elastic/eui';
+import { SearchQueryRecord } from '../../../../types/types';
+import {
+ CPU_TIME,
+ INDICES,
+ LATENCY,
+ MEMORY_USAGE,
+ NODE_ID,
+ SEARCH_TYPE,
+ TIMESTAMP,
+ TOTAL_SHARDS,
+} from '../../../../common/constants';
-const QuerySummary = ({ query }: { query: any }) => {
+// Panel component for displaying query detail values
+const PanelItem = ({ label, value }: { label: string; value: string | number }) => (
+
+
+ {label}
+
+ {value}
+
+);
+
+const QuerySummary = ({ query }: { query: SearchQueryRecord }) => {
const convertTime = (unixTime: number) => {
const date = new Date(unixTime);
const loc = date.toDateString().split(' ');
return `${loc[1]} ${loc[2]}, ${loc[3]} @ ${date.toLocaleTimeString('en-US')}`;
};
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ const { timestamp, measurements, indices, search_type, node_id, total_shards } = query;
return (
@@ -19,54 +42,21 @@ const QuerySummary = ({ query }: { query: any }) => {
-
-
- Timestamp
-
- {convertTime(query.timestamp)}
-
-
-
- Latency
-
- {`${query.latency} ms`}
-
-
-
- CPU Usage
-
- {`${query.cpu} ns`}
-
-
-
- Memory
-
- {`${query.memory} B`}
-
-
-
- Indexes
-
- {query.indices.toString()}
-
-
-
- Search type
-
- {query.search_type.replaceAll('_', ' ')}
-
-
-
- Coordinator node ID
-
- {query.node_id}
-
-
-
- Total shards
-
- {query.total_shards}
-
+
+
+
+
+
+
+
+
);
diff --git a/public/pages/QueryDetails/QueryDetails.tsx b/public/pages/QueryDetails/QueryDetails.tsx
index 6bc091f..2da53a2 100644
--- a/public/pages/QueryDetails/QueryDetails.tsx
+++ b/public/pages/QueryDetails/QueryDetails.tsx
@@ -19,7 +19,7 @@ import {
} from '@elastic/eui';
import hash from 'object-hash';
import { useParams, useHistory, useLocation } from 'react-router-dom';
-import { CoreStart } from '../../../../../src/core/public';
+import { CoreStart } from 'opensearch-dashboards/public';
import QuerySummary from './Components/QuerySummary';
import { QUERY_INSIGHTS } from '../TopNQueries/TopNQueries';
diff --git a/public/pages/QueryInsights/QueryInsights.tsx b/public/pages/QueryInsights/QueryInsights.tsx
index 67912de..e5b7e93 100644
--- a/public/pages/QueryInsights/QueryInsights.tsx
+++ b/public/pages/QueryInsights/QueryInsights.tsx
@@ -7,13 +7,22 @@ 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 '../../../../../src/core/public';
+import { CoreStart } from 'opensearch-dashboards/public';
import { QUERY_INSIGHTS } from '../TopNQueries/TopNQueries';
+import { SearchQueryRecord } from '../../../types/types';
+import {
+ CPU_TIME,
+ INDICES,
+ LATENCY,
+ MEMORY_USAGE,
+ NODE_ID,
+ SEARCH_TYPE,
+ TIMESTAMP,
+ TOTAL_SHARDS,
+} from '../../../common/constants';
const TIMESTAMP_FIELD = 'timestamp';
-const LATENCY_FIELD = 'latency';
-const CPU_FIELD = 'cpu';
-const MEMORY_FIELD = 'memory';
+const MEASUREMENTS_FIELD = 'measurements';
const INDICES_FIELD = 'indices';
const SEARCH_TYPE_FIELD = 'search_type';
const NODE_ID_FIELD = 'node_id';
@@ -29,7 +38,7 @@ const QueryInsights = ({
currEnd,
core,
}: {
- queries: any[];
+ queries: SearchQueryRecord[];
loading: boolean;
onTimeChange: any;
recentlyUsedRanges: any[];
@@ -63,7 +72,7 @@ const QueryInsights = ({
const cols: Array> = [
{
// Make into flyout instead?
- name: 'Timestamp',
+ name: TIMESTAMP,
render: (query: any) => {
return (
@@ -77,51 +86,58 @@ const QueryInsights = ({
truncateText: true,
},
{
- field: LATENCY_FIELD,
- name: 'Latency',
- render: (latency: number) =>
- typeof latency !== 'undefined' ? `${latency} ms` : `${METRIC_DEFAULT_MSG}`,
+ field: MEASUREMENTS_FIELD,
+ name: LATENCY,
+ render: (measurements: any) => {
+ const latencyValue = measurements?.latency?.number;
+ return latencyValue !== undefined ? `${latencyValue} ms` : METRIC_DEFAULT_MSG;
+ },
sortable: true,
truncateText: true,
},
{
- field: CPU_FIELD,
- name: 'CPU usage',
- render: (cpu: number) => (typeof cpu !== 'undefined' ? `${cpu} ns` : `${METRIC_DEFAULT_MSG}`),
+ field: MEASUREMENTS_FIELD,
+ name: CPU_TIME,
+ render: (measurements: { cpu?: { number?: number } }) => {
+ const cpuValue = measurements?.cpu?.number;
+ return cpuValue !== undefined ? `${cpuValue / 1000000} ms` : METRIC_DEFAULT_MSG;
+ },
sortable: true,
truncateText: true,
},
{
- field: MEMORY_FIELD,
- name: 'Memory',
- render: (memory: number) =>
- typeof memory !== 'undefined' ? `${memory} B` : `${METRIC_DEFAULT_MSG}`,
+ field: MEASUREMENTS_FIELD,
+ name: MEMORY_USAGE,
+ render: (measurements: { memory?: { number?: number } }) => {
+ const memoryValue = measurements?.memory?.number;
+ return memoryValue !== undefined ? `${memoryValue} B` : METRIC_DEFAULT_MSG;
+ },
sortable: true,
truncateText: true,
},
{
field: INDICES_FIELD,
- name: 'Indices',
+ name: INDICES,
render: (indices: string[]) => Array.from(new Set(indices.flat())).join(', '),
sortable: true,
truncateText: true,
},
{
field: SEARCH_TYPE_FIELD,
- name: 'Search type',
+ name: SEARCH_TYPE,
render: (searchType: string) => searchType.replaceAll('_', ' '),
sortable: true,
truncateText: true,
},
{
field: NODE_ID_FIELD,
- name: 'Coordinator node ID',
+ name: NODE_ID,
sortable: true,
truncateText: true,
},
{
field: TOTAL_SHARDS_FIELD,
- name: 'Total shards',
+ name: TOTAL_SHARDS,
sortable: true,
truncateText: true,
},
@@ -158,7 +174,7 @@ const QueryInsights = ({
{
type: 'field_value_selection',
field: INDICES_FIELD,
- name: 'Indices',
+ name: INDICES,
multiSelect: true,
options: filterDuplicates(
queries.map((query) => {
@@ -174,7 +190,7 @@ const QueryInsights = ({
{
type: 'field_value_selection',
field: SEARCH_TYPE_FIELD,
- name: 'Search type',
+ name: SEARCH_TYPE,
multiSelect: false,
options: filterDuplicates(
queries.map((query) => ({
@@ -187,7 +203,7 @@ const QueryInsights = ({
{
type: 'field_value_selection',
field: NODE_ID_FIELD,
- name: 'Coordinator node ID',
+ name: NODE_ID,
multiSelect: true,
options: filterDuplicates(
queries.map((query) => ({
@@ -212,9 +228,7 @@ const QueryInsights = ({
executeQueryOptions={{
defaultFields: [
TIMESTAMP_FIELD,
- LATENCY_FIELD,
- CPU_FIELD,
- MEMORY_FIELD,
+ MEASUREMENTS_FIELD,
INDICES_FIELD,
SEARCH_TYPE_FIELD,
NODE_ID_FIELD,
diff --git a/public/pages/TopNQueries/TopNQueries.tsx b/public/pages/TopNQueries/TopNQueries.tsx
index cacec6e..d3e8d18 100644
--- a/public/pages/TopNQueries/TopNQueries.tsx
+++ b/public/pages/TopNQueries/TopNQueries.tsx
@@ -11,6 +11,7 @@ import { CoreStart } from 'opensearch-dashboards/public';
import QueryInsights from '../QueryInsights/QueryInsights';
import Configuration from '../Configuration/Configuration';
import QueryDetails from '../QueryDetails/QueryDetails';
+import { SearchQueryRecord } from "../../../types/types";
export const QUERY_INSIGHTS = '/queryInsights';
export const CONFIGURATION = '/configuration';
@@ -66,7 +67,7 @@ const TopNQueries = ({ core }: { core: CoreStart }) => {
}
};
- const [queries, setQueries] = useState([]);
+ const [queries, setQueries] = useState([]);
const tabs: Array<{ id: string; name: string; route: string }> = [
{
@@ -114,7 +115,11 @@ const TopNQueries = ({ core }: { core: CoreStart }) => {
};
const fetchMetric = async (endpoint: string) => {
try {
- const response = await core.http.get(endpoint, params);
+ // TODO: #13 refactor the interface definitions for requests and responses
+ const response: { response: { top_queries: SearchQueryRecord[] } } = await core.http.get(
+ endpoint,
+ params
+ );
return {
response: {
top_queries: Array.isArray(response?.response?.top_queries)
@@ -142,7 +147,7 @@ const TopNQueries = ({ core }: { core: CoreStart }) => {
...respCpu.response.top_queries,
...respMemory.response.top_queries,
];
- const noDuplicates = Array.from(
+ const noDuplicates: SearchQueryRecord[] = Array.from(
new Set(newQueries.map((item) => JSON.stringify(item)))
).map((item) => JSON.parse(item));
setQueries(noDuplicates);
diff --git a/types/types.ts b/types/types.ts
new file mode 100644
index 0000000..01f2f59
--- /dev/null
+++ b/types/types.ts
@@ -0,0 +1,47 @@
+/*
+ * Copyright OpenSearch Contributors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { ISearchSource } from 'src/plugins/data/public';
+
+export interface SearchQueryRecord {
+ timestamp: number;
+ measurements: {
+ latency?: Measurement;
+ cpu?: Measurement;
+ memory?: Measurement;
+ };
+ total_shards: number;
+ node_id: string;
+ source: ISearchSource;
+ labels: Record;
+ search_type: string;
+ indices: string[];
+ phase_latency_map: PhaseLatencyMap;
+ task_resource_usages: Task[];
+}
+
+export interface Measurement {
+ number: number;
+ count: number;
+ aggregationType: string;
+}
+
+export interface PhaseLatencyMap {
+ expand?: number;
+ query?: number;
+ fetch?: number;
+}
+
+export interface TaskResourceUsage {
+ cpu_time_in_nanos: number;
+ memory_in_bytes: number;
+}
+export interface Task {
+ action: string;
+ taskId: number;
+ parentTaskId: number;
+ nodeId: string;
+ taskResourceUsage: TaskResourceUsage;
+}
diff --git a/yarn.lock b/yarn.lock
index 6955c37..c5c5f59 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -841,6 +841,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b"
integrity sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==
+"@types/object-hash@^3.0.0":
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/@types/object-hash/-/object-hash-3.0.6.tgz#25c052428199d374ef723b7b0ed44b5bfe1b3029"
+ integrity sha512-fOBV8C1FIu2ELinoILQ+ApxcUKz4ngq+IWUYrxSGjXzzjUALijilampwkMgEtJ+h2njAW3pi853QpzNVCHB73w==
+
"@types/parse-json@^4.0.0":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239"