Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan

- [#103](https://github.com/kobsio/kobs/pull/103): Add option to get user information from a request.
- [#104](https://github.com/kobsio/kobs/pull/104): Add actions for Opsgenie plugin to acknowledge, snooze and close alerts.
- [#105](https://github.com/kobsio/kobs/pull/105): Add Prometheus metrics for API requests.

### Fixed

- [#102](https://github.com/kobsio/kobs/pull/102): Fix GitHub Action for creating a new Helm release.

### Changed

- [#106](https://github.com/kobsio/kobs/pull/106): :warning: *Breaking change:* :warning: Change Prometheus sparkline chart to allow the usage of labels.

## [v0.5.0](https://github.com/kobsio/kobs/releases/tag/v0.5.0) (2021-08-03)

### Added
Expand Down
3 changes: 1 addition & 2 deletions deploy/demo/bookinfo/details-application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ spec:
options:
unit: "%"
queries:
- label: Incoming Success Rate
query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"details-v1",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"details-v1"}[5m])) * 100
- query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"details-v1",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"details-v1"}[5m])) * 100
dashboards:
- name: resources
namespace: kobs
Expand Down
3 changes: 1 addition & 2 deletions deploy/demo/bookinfo/productpage-application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ spec:
options:
unit: "%"
queries:
- label: Incoming Success Rate
query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"productpage-v1",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"productpage-v1"}[5m])) * 100
- query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"productpage-v1",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"productpage-v1"}[5m])) * 100
dashboards:
- name: resources
namespace: kobs
Expand Down
3 changes: 1 addition & 2 deletions deploy/demo/bookinfo/ratings-application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ spec:
options:
unit: "%"
queries:
- label: Incoming Success Rate
query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"ratings-v1",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"ratings-v1"}[5m])) * 100
- query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"ratings-v1",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"ratings-v1"}[5m])) * 100
dashboards:
- name: resources
namespace: kobs
Expand Down
3 changes: 1 addition & 2 deletions deploy/demo/bookinfo/reviews-application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ spec:
options:
unit: "%"
queries:
- label: Incoming Success Rate
query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"reviews-.*",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"reviews-.*"}[5m])) * 100
- query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"reviews-.*",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"reviews-.*"}[5m])) * 100
dashboards:
- name: resources
namespace: kobs
Expand Down
6 changes: 2 additions & 4 deletions deploy/demo/kobs/base/dashboards/istio-http.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ spec:
unit: req/s
type: sparkline
queries:
- label: Incoming Request Volume
query: round(sum(irate(istio_requests_total{reporter="{% .var_reporter %}",destination_workload_namespace=~"{{ .namespace }}",destination_workload=~"{% .var_workload %}"}[5m])), 0.001)
- query: round(sum(irate(istio_requests_total{reporter="{% .var_reporter %}",destination_workload_namespace=~"{{ .namespace }}",destination_workload=~"{% .var_workload %}"}[5m])), 0.001)
- title: Incoming Success Rate
colSpan: 6
plugin:
Expand All @@ -68,8 +67,7 @@ spec:
unit: "%"
type: sparkline
queries:
- label: Incoming Success Rate
query: sum(irate(istio_requests_total{reporter="{% .var_reporter %}",destination_workload_namespace=~"{{ .namespace }}",destination_workload=~"{% .var_workload %}",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="{% .var_reporter %}",destination_workload_namespace=~"{{ .namespace }}",destination_workload=~"{% .var_workload %}"}[5m])) * 100
- query: sum(irate(istio_requests_total{reporter="{% .var_reporter %}",destination_workload_namespace=~"{{ .namespace }}",destination_workload=~"{% .var_workload %}",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="{% .var_reporter %}",destination_workload_namespace=~"{{ .namespace }}",destination_workload=~"{% .var_workload %}"}[5m])) * 100
- size: 2
panels:
- title: Request Duration
Expand Down
9 changes: 3 additions & 6 deletions deploy/demo/kobs/base/dashboards/resource-usage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ spec:
type: sparkline
unit: Cores
queries:
- label: CPU Usage
query: sum(rate(container_cpu_usage_seconds_total{namespace="{{ .namespace }}", image!="", pod=~"{% .var_pod %}", container!="POD", container!=""}[2m]))
- query: sum(rate(container_cpu_usage_seconds_total{namespace="{{ .namespace }}", image!="", pod=~"{% .var_pod %}", container!="POD", container!=""}[2m]))
- title: Memory Usage
colSpan: 4
plugin:
Expand All @@ -42,17 +41,15 @@ spec:
type: sparkline
unit: MiB
queries:
- label: Memory Usage
query: sum(container_memory_working_set_bytes{namespace="{{ .namespace }}", pod=~"{% .var_pod %}", container!="POD", container!=""}) / 1024 / 1024
- query: sum(container_memory_working_set_bytes{namespace="{{ .namespace }}", pod=~"{% .var_pod %}", container!="POD", container!=""}) / 1024 / 1024
- title: Restarts
colSpan: 4
plugin:
name: prometheus
options:
type: sparkline
queries:
- label: Restarts
query: kube_pod_container_status_restarts_total{namespace="{{ .namespace }}", pod=~"{% .var_pod %}"}
- query: kube_pod_container_status_restarts_total{namespace="{{ .namespace }}", pod=~"{% .var_pod %}"}
- size: 3
panels:
- title: CPU Usage
Expand Down
14 changes: 7 additions & 7 deletions docs/plugins/prometheus.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ The following options can be used for a panel with the Prometheus plugin:
| Field | Type | Description | Required |
| ----- | ---- | ----------- | -------- |
| query | string | The PromQL query. | Yes |
| label | string | The label the results. The label can use the value of a variable or a label of the returned time series, e.g. `{% .<prometheus-label> %}`. If you want to use a Prometheus label make sure that the label name doesn't conflict with a variable name | Yes |
| label | string | The label the results. The label can use the value of a variable or a label of the returned time series, e.g. `{% .<prometheus-label> %}`. If you want to use a Prometheus label make sure that the label name doesn't conflict with a variable name. | Yes |

!!! note
In `sparkline` charts the label must not be provided. If the label is provided in a `sparkline` chart the label will be displayed instead of the current value.

### Column

Expand Down Expand Up @@ -73,8 +76,7 @@ spec:
type: sparkline
unit: Cores
queries:
- label: CPU Usage
query: sum(rate(container_cpu_usage_seconds_total{namespace="{{ .namespace }}", image!="", pod=~"{% .var_pod %}", container!="POD", container!=""}[2m]))
- query: sum(rate(container_cpu_usage_seconds_total{namespace="{{ .namespace }}", image!="", pod=~"{% .var_pod %}", container!="POD", container!=""}[2m]))
- title: Memory Usage
colSpan: 4
plugin:
Expand All @@ -83,17 +85,15 @@ spec:
type: sparkline
unit: MiB
queries:
- label: Memory Usage
query: sum(container_memory_working_set_bytes{namespace="{{ .namespace }}", pod=~"{% .var_pod %}", container!="POD", container!=""}) / 1024 / 1024
- query: sum(container_memory_working_set_bytes{namespace="{{ .namespace }}", pod=~"{% .var_pod %}", container!="POD", container!=""}) / 1024 / 1024
- title: Restarts
colSpan: 4
plugin:
name: prometheus
options:
type: sparkline
queries:
- label: Restarts
query: kube_pod_container_status_restarts_total{namespace="{{ .namespace }}", pod=~"{% .var_pod %}"}
- query: kube_pod_container_status_restarts_total{namespace="{{ .namespace }}", pod=~"{% .var_pod %}"}
- size: 3
panels:
- title: CPU Usage
Expand Down
3 changes: 1 addition & 2 deletions docs/resources/applications.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,7 @@ spec:
options:
unit: "%"
queries:
- label: Incoming Success Rate
query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"reviews-.*",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"reviews-.*"}[5m])) * 100
- query: sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"reviews-.*",response_code!~"5.*"}[5m])) / sum(irate(istio_requests_total{reporter="destination",destination_workload_namespace=~"bookinfo",destination_workload=~"reviews-.*"}[5m])) * 100
dashboards:
- name: resources
namespace: kobs
Expand Down
9 changes: 3 additions & 6 deletions docs/resources/dashboards.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ spec:
type: sparkline
unit: Cores
queries:
- label: CPU Usage
query: sum(rate(container_cpu_usage_seconds_total{namespace="{{ .namespace }}", image!="", pod=~"{% .var_pod %}", container!="POD", container!=""}[2m]))
- query: sum(rate(container_cpu_usage_seconds_total{namespace="{{ .namespace }}", image!="", pod=~"{% .var_pod %}", container!="POD", container!=""}[2m]))
- title: Memory Usage
colSpan: 4
plugin:
Expand All @@ -176,17 +175,15 @@ spec:
type: sparkline
unit: MiB
queries:
- label: Memory Usage
query: sum(container_memory_working_set_bytes{namespace="{{ .namespace }}", pod=~"{% .var_pod %}", container!="POD", container!=""}) / 1024 / 1024
- query: sum(container_memory_working_set_bytes{namespace="{{ .namespace }}", pod=~"{% .var_pod %}", container!="POD", container!=""}) / 1024 / 1024
- title: Restarts
colSpan: 4
plugin:
name: prometheus
options:
type: sparkline
queries:
- label: Restarts
query: kube_pod_container_status_restarts_total{namespace="{{ .namespace }}", pod=~"{% .var_pod %}"}
- query: kube_pod_container_status_restarts_total{namespace="{{ .namespace }}", pod=~"{% .var_pod %}"}
- size: 3
panels:
- title: CPU Usage
Expand Down
6 changes: 4 additions & 2 deletions plugins/prometheus/pkg/instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func (i *Instance) GetMetrics(ctx context.Context, queries []Query, resolution s
var min float64
var max float64
var avg float64
var count float64

var data []Datum
for index, value := range stream.Values {
Expand All @@ -109,6 +110,7 @@ func (i *Instance) GetMetrics(ctx context.Context, queries []Query, resolution s
})
} else {
avg = avg + val
count = count + 1

if index == 0 {
min = val
Expand All @@ -128,8 +130,8 @@ func (i *Instance) GetMetrics(ctx context.Context, queries []Query, resolution s
}
}

if avg != 0 {
avg = avg / float64(len(stream.Values))
if avg != 0 && count != 0 {
avg = avg / count
}

var labels map[string]string
Expand Down
28 changes: 16 additions & 12 deletions plugins/prometheus/src/components/panel/Sparkline.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Alert, AlertActionLink, AlertVariant } from '@patternfly/react-core';
import { QueryObserverResult, useQuery } from 'react-query';
import { ResponsiveLineCanvas, Serie } from '@nivo/line';
import React from 'react';
import { ResponsiveLineCanvas } from '@nivo/line';

import { IPanelOptions, ISeries } from '../../utils/interfaces';
import { IPluginTimes, PluginCard } from '@kobsio/plugin-core';
import { convertMetrics, getMappingValue } from '../../utils/helpers';
import Actions from './Actions';
import { COLOR_SCALE } from '../../utils/colors';
import { IPanelOptions } from '../../utils/interfaces';

interface ISpakrlineProps {
name: string;
Expand All @@ -28,7 +28,7 @@ export const Spakrline: React.FunctionComponent<ISpakrlineProps> = ({
times,
options,
}: ISpakrlineProps) => {
const { isError, isFetching, error, data, refetch } = useQuery<Serie[], Error>(
const { isError, isFetching, error, data, refetch } = useQuery<ISeries, Error>(
['prometheus/metrics', name, options.queries, times],
async () => {
try {
Expand All @@ -49,9 +49,9 @@ export const Spakrline: React.FunctionComponent<ISpakrlineProps> = ({

if (response.status >= 200 && response.status < 300) {
if (json) {
return convertMetrics(json).series;
return convertMetrics(json);
} else {
return [];
return { labels: {}, series: [] };
}
} else {
if (json.error) {
Expand All @@ -70,14 +70,18 @@ export const Spakrline: React.FunctionComponent<ISpakrlineProps> = ({
// Determine the label which should be shown above the chart. This is the last value in first metric of the returned
// data or a value from the user specified mappings.
let label = 'N/A';
if (data && data.length > 0) {
if (options.queries && Array.isArray(options.queries) && options.queries.length > 0 && options.queries[0].label) {
if (data && data.labels && data.labels.hasOwnProperty('0-0')) {
label = data.labels['0-0'];
}
} else if (data && data.series && data.series.length > 0) {
if (options.mappings && Object.keys(options.mappings).length > 0) {
label = getMappingValue(data[0].data[data[0].data.length - 1].y, options.mappings);
label = getMappingValue(data.series[0].data[data.series[0].data.length - 1].y, options.mappings);
} else {
label =
data[0].data[data[0].data.length - 1].y === null
data.series[0].data[data.series[0].data.length - 1].y === null
? 'N/A'
: `${data[0].data[data[0].data.length - 1].y} ${options.unit ? options.unit : ''}`;
: `${data.series[0].data[data.series[0].data.length - 1].y} ${options.unit ? options.unit : ''}`;
}
}

Expand All @@ -94,15 +98,15 @@ export const Spakrline: React.FunctionComponent<ISpakrlineProps> = ({
title="Could not get metrics"
actionLinks={
<React.Fragment>
<AlertActionLink onClick={(): Promise<QueryObserverResult<Serie[], Error>> => refetch()}>
<AlertActionLink onClick={(): Promise<QueryObserverResult<ISeries, Error>> => refetch()}>
Retry
</AlertActionLink>
</React.Fragment>
}
>
<p>{error?.message}</p>
</Alert>
) : data ? (
) : data && data.series ? (
<React.Fragment>
<div style={{ height: '100%', position: 'relative' }}>
<div style={{ fontSize: '24px', position: 'absolute', textAlign: 'center', top: '31px', width: '100%' }}>
Expand All @@ -111,7 +115,7 @@ export const Spakrline: React.FunctionComponent<ISpakrlineProps> = ({
<ResponsiveLineCanvas
colors={COLOR_SCALE[0]}
curve="monotoneX"
data={data}
data={data.series}
enableArea={true}
enableGridX={false}
enableGridY={false}
Expand Down
26 changes: 15 additions & 11 deletions plugins/prometheus/src/components/preview/Sparkline.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Alert, AlertVariant, Spinner } from '@patternfly/react-core';
import { ResponsiveLineCanvas, Serie } from '@nivo/line';
import React from 'react';
import { ResponsiveLineCanvas } from '@nivo/line';
import { useQuery } from 'react-query';

import { IPanelOptions, ISeries } from '../../utils/interfaces';
import { convertMetrics, getMappingValue } from '../../utils/helpers';
import { COLOR_SCALE } from '../../utils/colors';
import { IPanelOptions } from '../../utils/interfaces';
import { IPluginTimes } from '@kobsio/plugin-core';

interface ISpakrlineProps {
Expand All @@ -21,7 +21,7 @@ export const Spakrline: React.FunctionComponent<ISpakrlineProps> = ({
title,
options,
}: ISpakrlineProps) => {
const { isError, isLoading, error, data } = useQuery<Serie[], Error>(
const { isError, isLoading, error, data } = useQuery<ISeries, Error>(
['prometheus/metrics', name, options.queries, times],
async () => {
try {
Expand All @@ -42,9 +42,9 @@ export const Spakrline: React.FunctionComponent<ISpakrlineProps> = ({

if (response.status >= 200 && response.status < 300) {
if (json) {
return convertMetrics(json).series;
return convertMetrics(json);
} else {
return [];
return { labels: {}, series: [] };
}
} else {
if (json.error) {
Expand All @@ -63,14 +63,18 @@ export const Spakrline: React.FunctionComponent<ISpakrlineProps> = ({
// Determine the label which should be shown above the chart. This is the last value in first metric of the returned
// data or a value from the user specified mappings.
let label = 'N/A';
if (data && data.length > 0) {
if (options.queries && Array.isArray(options.queries) && options.queries.length > 0 && options.queries[0].label) {
if (data && data.labels && data.labels.hasOwnProperty('0-0')) {
label = data.labels['0-0'];
}
} else if (data && data.series && data.series.length > 0) {
if (options.mappings && Object.keys(options.mappings).length > 0) {
label = getMappingValue(data[0].data[data[0].data.length - 1].y, options.mappings);
label = getMappingValue(data.series[0].data[data.series[0].data.length - 1].y, options.mappings);
} else {
label =
data[0].data[data[0].data.length - 1].y === null
data.series[0].data[data.series[0].data.length - 1].y === null
? 'N/A'
: `${data[0].data[data[0].data.length - 1].y} ${options.unit ? options.unit : ''}`;
: `${data.series[0].data[data.series[0].data.length - 1].y} ${options.unit ? options.unit : ''}`;
}
}

Expand All @@ -82,15 +86,15 @@ export const Spakrline: React.FunctionComponent<ISpakrlineProps> = ({
</div>
) : isError ? (
<Alert variant={AlertVariant.danger} isInline={true} title={error?.message} />
) : data ? (
) : data && data.series ? (
<div>
<div className="pf-u-font-size-lg pf-u-text-nowrap pf-u-text-truncate">{label}</div>
<div className="pf-u-font-size-sm pf-u-color-400 pf-u-text-nowrap pf-u-text-truncate">{title}</div>
<div style={{ height: '75px' }}>
<ResponsiveLineCanvas
colors={COLOR_SCALE[0]}
curve="monotoneX"
data={data}
data={data.series}
enableArea={true}
enableGridX={false}
enableGridY={false}
Expand Down