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.