From 748e2f7d7b0ee1de02f5397d0018c9f0aee65a06 Mon Sep 17 00:00:00 2001 From: ricoberger Date: Fri, 3 Sep 2021 15:07:34 +0200 Subject: [PATCH] Allow multiple queries for Jaeger Some days ago we change the Elasticsearch plugin to support multiple queries in the panel. In the same way we are chaning the options for the Jaeger plugin now. So that a user can specify multiple queries within a Jaeger panel. In the UI the user can then select the query he wants to see via the select box. This is a breaking change for the Jaeger panel, this means that old specification wont work anymore with the current version of kobs. --- CHANGELOG.md | 1 + .../demo/istio-system/jaeger-application.yaml | 4 +- deploy/demo/kobs/base/dashboards/traces.yaml | 4 +- docs/plugins/jaeger.md | 18 +- .../src/components/panel/LogsActions.tsx | 8 +- .../src/components/panel/SQLActions.tsx | 6 +- .../src/components/panel/LogsActions.tsx | 8 +- plugins/jaeger/src/components/page/Traces.tsx | 17 +- plugins/jaeger/src/components/panel/Panel.tsx | 9 +- .../jaeger/src/components/panel/Traces.tsx | 158 +++++++++++------- .../src/components/panel/TracesActions.tsx | 30 ++-- plugins/jaeger/src/utils/interfaces.ts | 7 +- 12 files changed, 166 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c2523cf4..921b4f69a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan - [#107](https://github.com/kobsio/kobs/pull/107): Add new option for Prometheus chart legend and change formatting of values. - [#108](https://github.com/kobsio/kobs/pull/108): Improve tooltip position in all nivo charts. - [#121](https://github.com/kobsio/kobs/pull/121): :warning: *Breaking change:* :warning: Allow multiple queries in the panel options for the Elasticsearch plugin. +- [#130](https://github.com/kobsio/kobs/pull/130): :warning: *Breaking change:* :warning: Allow multiple queries in the panel options for the Jaeger plugin. ## [v0.5.0](https://github.com/kobsio/kobs/releases/tag/v0.5.0) (2021-08-03) diff --git a/deploy/demo/istio-system/jaeger-application.yaml b/deploy/demo/istio-system/jaeger-application.yaml index b1c7c0ab4..56cb0f9d5 100644 --- a/deploy/demo/istio-system/jaeger-application.yaml +++ b/deploy/demo/istio-system/jaeger-application.yaml @@ -18,4 +18,6 @@ spec: plugin: name: elasticsearch options: - query: "kubernetes.namespace: istio-system AND kubernetes.labels.app: jaeger" + queries: + - name: All Jaeger Logs + query: "kubernetes.namespace: istio-system AND kubernetes.labels.app: jaeger" diff --git a/deploy/demo/kobs/base/dashboards/traces.yaml b/deploy/demo/kobs/base/dashboards/traces.yaml index 07e4084b2..c4e6fc1cb 100644 --- a/deploy/demo/kobs/base/dashboards/traces.yaml +++ b/deploy/demo/kobs/base/dashboards/traces.yaml @@ -17,5 +17,7 @@ spec: plugin: name: jaeger options: - service: "{{ .service }}" showChart: true + queries: + - name: "{{ .service }}" + service: "{{ .service }}" diff --git a/docs/plugins/jaeger.md b/docs/plugins/jaeger.md index f366eeaac..5e957af9e 100644 --- a/docs/plugins/jaeger.md +++ b/docs/plugins/jaeger.md @@ -14,15 +14,22 @@ The following options can be used for a panel with the Jaeger plugin: | Field | Type | Description | Required | | ----- | ---- | ----------- | -------- | +| showChart | boolean | If this is `true` the chart with the traces will be shown. | No | +| queries | [[]Query](#query) | A list of Jaeger queries, which can be selected by the user. | Yes | + +### Query + +| Field | Type | Description | Required | +| ----- | ---- | ----------- | -------- | +| name | string | A name for the Jaeger query, which is displayed in the select box. | Yes | | limit | string | The maximum number of traces which should be shown. The default value is `20`. | No | | maxDuration | string | The maximum duration for the retrieved traces (e.g. `1s`). | No | | minDuration | string | The minimum duration for the retrieved traces (e.g. `100ms`). | No | | service | string | The service to retrieve traces for. | Yes | | operation | string | An optional operation to retrieve traces for. | No | | tags | string | Tags, which the traces must be contain. | No | -| showChart | boolean | If this is `true` the chart with the traces will be shown. | No | -For example the following dashboard shows all traces for the specified service (e.g. `reviews.bookinfo`). +For example the following dashboard shows all requests and all slow requests from Jaeger for the specified service (e.g. `reviews.bookinfo`). ```yaml --- @@ -40,6 +47,11 @@ spec: plugin: name: jaeger options: - service: "{{ .service }}" showChart: true + queries: + - name: "{{ .service }} requests" + service: "{{ .service }}" + - name: "{{ .service }} slow requests" + service: "{{ .service }}" + minDuration: 1000ms ``` diff --git a/plugins/clickhouse/src/components/panel/LogsActions.tsx b/plugins/clickhouse/src/components/panel/LogsActions.tsx index b41a7637a..ca4f31552 100644 --- a/plugins/clickhouse/src/components/panel/LogsActions.tsx +++ b/plugins/clickhouse/src/components/panel/LogsActions.tsx @@ -21,9 +21,9 @@ export const Actions: React.FunctionComponent = ({ name, queries, isOpen={show} isPlain={true} position="right" - dropdownItems={queries.map((query) => [ + dropdownItems={queries.map((query, index) => ( = ({ name, queries, {query.name} } - />, - ])} + /> + ))} /> ); diff --git a/plugins/clickhouse/src/components/panel/SQLActions.tsx b/plugins/clickhouse/src/components/panel/SQLActions.tsx index ae6317269..e53d0a728 100644 --- a/plugins/clickhouse/src/components/panel/SQLActions.tsx +++ b/plugins/clickhouse/src/components/panel/SQLActions.tsx @@ -19,9 +19,9 @@ export const Actions: React.FunctionComponent = ({ name, queries isOpen={show} isPlain={true} position="right" - dropdownItems={queries.map((query) => [ - {query.name}} />, - ])} + dropdownItems={queries.map((query, index) => ( + {query.name}} /> + ))} /> ); diff --git a/plugins/elasticsearch/src/components/panel/LogsActions.tsx b/plugins/elasticsearch/src/components/panel/LogsActions.tsx index b41a7637a..ca4f31552 100644 --- a/plugins/elasticsearch/src/components/panel/LogsActions.tsx +++ b/plugins/elasticsearch/src/components/panel/LogsActions.tsx @@ -21,9 +21,9 @@ export const Actions: React.FunctionComponent = ({ name, queries, isOpen={show} isPlain={true} position="right" - dropdownItems={queries.map((query) => [ + dropdownItems={queries.map((query, index) => ( = ({ name, queries, {query.name} } - />, - ])} + /> + ))} /> ); diff --git a/plugins/jaeger/src/components/page/Traces.tsx b/plugins/jaeger/src/components/page/Traces.tsx index 0cd1abd76..99ff18661 100644 --- a/plugins/jaeger/src/components/page/Traces.tsx +++ b/plugins/jaeger/src/components/page/Traces.tsx @@ -77,13 +77,18 @@ const Traces: React.FunctionComponent = ({ name, displayName, desc name={name} title="" showDetails={setSelectedTrace} + queries={[ + { + limit: options.limit, + maxDuration: options.maxDuration, + minDuration: options.minDuration, + name: '', + operation: options.operation, + service: options.service, + tags: options.tags, + }, + ]} showChart={true} - limit={options.limit} - maxDuration={options.maxDuration} - minDuration={options.minDuration} - operation={options.operation} - service={options.service} - tags={options.tags} times={options.times} /> ) : null} diff --git a/plugins/jaeger/src/components/panel/Panel.tsx b/plugins/jaeger/src/components/panel/Panel.tsx index 762788353..d49253459 100644 --- a/plugins/jaeger/src/components/panel/Panel.tsx +++ b/plugins/jaeger/src/components/panel/Panel.tsx @@ -16,7 +16,7 @@ export const Panel: React.FunctionComponent = ({ options, showDetails, }: IPanelProps) => { - if (!options || !options.service || !times) { + if (!options || !options.queries || !Array.isArray(options.queries) || options.queries.length === 0 || !times) { return ( = ({ description={description} showDetails={showDetails} showChart={options.showChart || false} - limit={options.limit || '20'} - maxDuration={options.maxDuration || ''} - minDuration={options.minDuration || ''} - operation={options.operation || ''} - service={options.service} - tags={options.tags || ''} + queries={options.queries} times={times} /> ); diff --git a/plugins/jaeger/src/components/panel/Traces.tsx b/plugins/jaeger/src/components/panel/Traces.tsx index 0f77fa7d4..6126b7f12 100644 --- a/plugins/jaeger/src/components/panel/Traces.tsx +++ b/plugins/jaeger/src/components/panel/Traces.tsx @@ -1,45 +1,56 @@ -import { Alert, AlertActionLink, AlertVariant, Spinner } from '@patternfly/react-core'; +import { + Alert, + AlertActionLink, + AlertVariant, + Select, + SelectOption, + SelectOptionObject, + SelectVariant, + Spinner, +} from '@patternfly/react-core'; import { QueryObserverResult, useQuery } from 'react-query'; -import React from 'react'; +import React, { useState } from 'react'; -import { IOptions, ITrace } from '../../utils/interfaces'; +import { IPluginTimes, PluginCard } from '@kobsio/plugin-core'; +import { IQuery, ITrace } from '../../utils/interfaces'; import { encodeTags, transformTraceData } from '../../utils/helpers'; -import { PluginCard } from '@kobsio/plugin-core'; import TracesActions from './TracesActions'; import TracesChart from './TracesChart'; import TracesList from './TracesList'; import { addColorForProcesses } from '../../utils/colors'; -interface ITracesProps extends IOptions { +interface ITracesProps { name: string; title: string; description?: string; - showDetails?: (details: React.ReactNode) => void; showChart: boolean; + queries: IQuery[]; + times: IPluginTimes; + showDetails?: (details: React.ReactNode) => void; } const Traces: React.FunctionComponent = ({ name, title, description, + times, showDetails, showChart, - limit, - maxDuration, - minDuration, - operation, - service, - tags, - times, + queries, }: ITracesProps) => { + const [showSelect, setShowSelect] = useState(false); + const [selectedQuery, setSelectedQuery] = useState(queries[0]); + const { isError, isLoading, error, data, refetch } = useQuery( - ['jaeger/traces', name, limit, maxDuration, minDuration, operation, service, tags, times], + ['jaeger/traces', name, selectedQuery, times], async () => { try { const response = await fetch( - `/api/plugins/jaeger/traces/${name}?limit=${limit}&maxDuration=${maxDuration}&minDuration=${minDuration}&operation=${operation}&service=${service}&tags=${encodeTags( - tags, - )}&timeStart=${times.timeStart}&timeEnd=${times.timeEnd}`, + `/api/plugins/jaeger/traces/${name}?limit=${selectedQuery.limit || '20'}&maxDuration=${ + selectedQuery.maxDuration || '' + }&minDuration=${selectedQuery.minDuration || ''}&operation=${selectedQuery.operation || ''}&service=${ + selectedQuery.service || '' + }&tags=${encodeTags(selectedQuery.tags || '')}&timeStart=${times.timeStart}&timeEnd=${times.timeEnd}`, { method: 'get', }, @@ -71,56 +82,83 @@ const Traces: React.FunctionComponent = ({ }, ); + const select = ( + event: React.MouseEvent | React.ChangeEvent, + value: string | SelectOptionObject, + ): void => { + const query = queries.filter((query) => query.name === value); + if (query.length === 1) { + setSelectedQuery(query[0]); + } + setShowSelect(false); + }; + return ( - } + actions={} > - {isLoading ? ( -
- -
- ) : isError ? ( - - > => refetch()}> - Retry - - - } - > -

{error?.message}

-
- ) : data && data.length > 0 ? ( - - {showChart ? ( - - -

 

-

 

-

 

-
- ) : null} +
+ {queries.length > 1 ? ( +
+ +

 

+
+ ) : null} + + {isLoading ? ( +
+ +
+ ) : isError ? ( + + > => refetch()}> + Retry + + + } + > +

{error?.message}

+
+ ) : data && data.length > 0 ? ( + + {showChart ? ( + + +

 

+

 

+

 

+
+ ) : null} - -
- ) : null} + + + ) : null} +
); }; diff --git a/plugins/jaeger/src/components/panel/TracesActions.tsx b/plugins/jaeger/src/components/panel/TracesActions.tsx index bf9178820..f4238d998 100644 --- a/plugins/jaeger/src/components/panel/TracesActions.tsx +++ b/plugins/jaeger/src/components/panel/TracesActions.tsx @@ -2,20 +2,18 @@ import { CardActions, Dropdown, DropdownItem, KebabToggle } from '@patternfly/re import React, { useState } from 'react'; import { Link } from 'react-router-dom'; -import { IOptions } from '../../utils/interfaces'; +import { IPluginTimes } from '@kobsio/plugin-core'; +import { IQuery } from '../../utils/interfaces'; -interface ITracesActionsProps extends IOptions { +interface ITracesActionsProps { name: string; + queries: IQuery[]; + times: IPluginTimes; } export const TracesActions: React.FunctionComponent = ({ name, - limit, - maxDuration, - minDuration, - operation, - service, - tags, + queries, times, }: ITracesActionsProps) => { const [show, setShow] = useState(false); @@ -27,18 +25,22 @@ export const TracesActions: React.FunctionComponent = ({ isOpen={show} isPlain={true} position="right" - dropdownItems={[ + dropdownItems={queries.map((query, index) => ( - Explore + {query.name} } - />, - ]} + /> + ))} /> ); diff --git a/plugins/jaeger/src/utils/interfaces.ts b/plugins/jaeger/src/utils/interfaces.ts index 864938f23..29958b320 100644 --- a/plugins/jaeger/src/utils/interfaces.ts +++ b/plugins/jaeger/src/utils/interfaces.ts @@ -14,13 +14,18 @@ export interface IOptions { // IPanelOptions is the interface for the options property for the Jaeger panel component. A user can set the same // properties as he can select in the Jaeger page. export interface IPanelOptions { + queries?: IQuery[]; + showChart?: boolean; +} + +export interface IQuery { + name?: string; limit?: string; maxDuration?: string; minDuration?: string; operation?: string; service?: string; tags?: string; - showChart?: boolean; } // IOperation is the interface for a single operation as it is returned by the API.