From 8f50e60c41c2c3b128aa20c413104650e0544cc0 Mon Sep 17 00:00:00 2001 From: ricoberger Date: Sat, 24 Apr 2021 17:33:39 +0200 Subject: [PATCH] Improve the legend for Prometheus charts The legend in the Prometheus charts supports multiple types now. The user can set the legend type in the Application CR via the "legend" field. The value must be "bottom", "table" or "disabled". If no type is specified we render the legend at the bottom of the chart. --- CHANGELOG.md | 2 + .../prometheus/PrometheusAutocomplete.tsx | 2 +- .../prometheus/PrometheusChartDefault.tsx | 107 ++++++++++----- .../PrometheusChartDefaultLegend.tsx | 123 ++++++++++++++++++ .../plugins/prometheus/PrometheusPageData.tsx | 2 +- .../prometheus/PrometheusPluginChart.tsx | 8 +- app/src/plugins/prometheus/helpers.ts | 4 +- app/src/proto/prometheus_pb.d.ts | 4 + app/src/proto/prometheus_pb.js | 50 +++++-- deploy/helm/kobs/Chart.yaml | 2 +- .../templates/customresourcedefinition.yaml | 4 + .../kustomize/crds/kobs.io_applications.yaml | 4 + docs/plugins/prometheus.md | 1 + .../plugins/prometheus/proto/prometheus.pb.go | 93 +++++++------ proto/prometheus.proto | 5 +- 15 files changed, 317 insertions(+), 94 deletions(-) create mode 100644 app/src/plugins/prometheus/PrometheusChartDefaultLegend.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index cc8d05814..8d3b2c66e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan ### Changed +- [#46](https://github.com/kobsio/kobs/pull/46): Support multiple types for the legend in a Prometheus chart and use a custom component to render the legend. + ## [v0.2.0](https://github.com/kobsio/kobs/releases/tag/v0.2.0) (2021-04-23) ### Added diff --git a/app/src/plugins/prometheus/PrometheusAutocomplete.tsx b/app/src/plugins/prometheus/PrometheusAutocomplete.tsx index e1be416e8..5920f7ee5 100644 --- a/app/src/plugins/prometheus/PrometheusAutocomplete.tsx +++ b/app/src/plugins/prometheus/PrometheusAutocomplete.tsx @@ -22,7 +22,7 @@ export const PrometheusAutocomplete: React.FunctionComponent { +}: IPrometheusAutocomplete) => { const inputRef = useRef(null); const [data, setData] = useState([]); const [inputFocused, setInputFocused] = useState(false); diff --git a/app/src/plugins/prometheus/PrometheusChartDefault.tsx b/app/src/plugins/prometheus/PrometheusChartDefault.tsx index bfde835c4..58151982b 100644 --- a/app/src/plugins/prometheus/PrometheusChartDefault.tsx +++ b/app/src/plugins/prometheus/PrometheusChartDefault.tsx @@ -14,6 +14,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { Data, Metrics } from 'proto/prometheus_grpc_web_pb'; import { IData, transformData } from 'plugins/prometheus/helpers'; +import PrometheusChartDefaultLegend from 'plugins/prometheus/PrometheusChartDefaultLegend'; import { formatTime } from 'utils/helpers'; interface ILabels { @@ -24,7 +25,7 @@ export interface IPrometheusChartDefaultProps { type: string; unit: string; stacked: boolean; - disableLegend?: boolean; + legend: string; metrics: Metrics.AsObject[]; } @@ -42,12 +43,25 @@ const PrometheusChartDefault: React.FunctionComponent { const refChart = useRef(null); const [width, setWidth] = useState(0); const [height, setHeight] = useState(0); + const [hiddenMetrics, setHiddenMetrics] = useState([]); + + const toogleMetric = (index: string): void => { + let tmpHiddenMetrics = [...hiddenMetrics]; + + if (tmpHiddenMetrics.includes(index)) { + tmpHiddenMetrics = tmpHiddenMetrics.filter((f) => f !== index); + } else { + tmpHiddenMetrics.push(index); + } + + setHiddenMetrics(tmpHiddenMetrics); + }; // useEffect is executed on every render of this component. This is needed, so that we are able to use a width of 100% // and a static height for the chart. @@ -64,45 +78,70 @@ const PrometheusChartDefault: React.FunctionComponent ({ childName: `index${index}`, name: metric.label })); const series = metrics.map((metric, index) => type === 'area' ? ( - + ) : type === 'bar' ? ( - + ) : ( - + ), ); return ( -
- (datum.y ? `${datum.y} ${unit}` : 'N/A')} - labelComponent={ - formatTime(Math.floor(point.x / 1000))} - /> - } - mouseFollowTooltips - voronoiDimension="x" - voronoiPadding={0} - /> - } - height={height} - legendData={legendData} - legendPosition={disableLegend ? undefined : 'bottom'} - padding={{ bottom: disableLegend ? 0 : 60, left: 60, right: 0, top: 0 }} - scale={{ x: 'time', y: 'linear' }} - themeColor={ChartThemeColor.multiOrdered} - width={width} + +
- - - {stacked ? {series} : {series}} - -
+ (datum.y ? `${datum.y} ${unit}` : null)} + labelComponent={ + formatTime(Math.floor(point.x / 1000))} + /> + } + mouseFollowTooltips + voronoiDimension="x" + voronoiPadding={{ bottom: 30, left: 60, right: 0, top: 0 }} + /> + } + height={height} + legendPosition={undefined} + padding={{ bottom: 30, left: 60, right: 0, top: 0 }} + scale={{ x: 'time', y: 'linear' }} + themeColor={ChartThemeColor.multiOrdered} + width={width} + > + + + {stacked ? {series} : {series}} + +
+ + ); }; diff --git a/app/src/plugins/prometheus/PrometheusChartDefaultLegend.tsx b/app/src/plugins/prometheus/PrometheusChartDefaultLegend.tsx new file mode 100644 index 000000000..95d8dde52 --- /dev/null +++ b/app/src/plugins/prometheus/PrometheusChartDefaultLegend.tsx @@ -0,0 +1,123 @@ +import { Button, ButtonVariant } from '@patternfly/react-core'; +import { ChartThemeColor, getDarkThemeColors } from '@patternfly/react-charts'; +import { EyeSlashIcon, SquareIcon } from '@patternfly/react-icons'; +import { TableComposable, TableVariant, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; +import React from 'react'; + +import { Metrics } from 'proto/prometheus_grpc_web_pb'; + +// colors is an array with all the supported colors for a chart. These are the same colors as they are used for the +// bars, lines, areas in a chart. +export const colors = getDarkThemeColors(ChartThemeColor.multiOrdered).area.colorScale; + +// getLegendColorClass returns the color class for an item in the legend. When we have more series then colors, we start +// again with the first color. +const getLegendColorClass = (index: number): string => { + return colors[index % colors.length]; +}; + +interface ILegendItem { + childName: string; + name: string; +} + +export interface IPrometheusChartDefaultLegendProps { + legend: string; + legendData: ILegendItem[]; + metrics: Metrics.AsObject[]; + hiddenMetrics: string[]; + toogleMetric: (index: string) => void; +} + +// +const PrometheusChartDefaultLegend: React.FunctionComponent = ({ + legend, + legendData, + metrics, + hiddenMetrics, + toogleMetric, +}: IPrometheusChartDefaultLegendProps) => { + if (legend === 'disabled') { + return null; + } + + if (legend === 'table') { + return ( +
+ + + + Name + Min + Max + Avg + Current + + + + {legendData.map((legend, index) => ( + + + + + + {metrics[index].min} + + + {metrics[index].max} + + + {metrics[index].avg} + + + {metrics[index].dataList[metrics[index].dataList.length - 1].y} + + + ))} + + +
+ ); + } + + return ( +
+ {legendData.map((legend, index) => ( + + ))} +
+ ); +}; + +export default PrometheusChartDefaultLegend; diff --git a/app/src/plugins/prometheus/PrometheusPageData.tsx b/app/src/plugins/prometheus/PrometheusPageData.tsx index 7c0261656..4395ddcf0 100644 --- a/app/src/plugins/prometheus/PrometheusPageData.tsx +++ b/app/src/plugins/prometheus/PrometheusPageData.tsx @@ -68,7 +68,7 @@ const PrometheusPageData: React.FunctionComponent = ({ type={type} unit="" stacked={stacked} - disableLegend={true} + legend="disabled" metrics={selectedMetrics.length === 0 ? metrics : selectedMetrics} /> diff --git a/app/src/plugins/prometheus/PrometheusPluginChart.tsx b/app/src/plugins/prometheus/PrometheusPluginChart.tsx index e63c5077e..67a805b1f 100644 --- a/app/src/plugins/prometheus/PrometheusPluginChart.tsx +++ b/app/src/plugins/prometheus/PrometheusPluginChart.tsx @@ -135,7 +135,13 @@ const PrometheusPluginChart: React.FunctionComponent ) : ( - + )} diff --git a/app/src/plugins/prometheus/helpers.ts b/app/src/plugins/prometheus/helpers.ts index 90a290974..47154ae33 100644 --- a/app/src/plugins/prometheus/helpers.ts +++ b/app/src/plugins/prometheus/helpers.ts @@ -115,8 +115,8 @@ export interface IData { // transformData is used to transform the returned data from the API. This is needed because, the API returns a NaN // value for missing values, but Victory requires a null value. // See: https://formidable.com/open-source/victory/gallery/victory-line-with-null-data/ -export const transformData = (data: Data.AsObject[]): IData[] => { +export const transformData = (data: Data.AsObject[], isHidden?: boolean): IData[] => { return data.map((d) => { - return { x: d.x, y: isNaN(d.y) ? null : d.y }; + return { x: d.x, y: isNaN(d.y) || isHidden ? null : d.y }; }); }; diff --git a/app/src/proto/prometheus_pb.d.ts b/app/src/proto/prometheus_pb.d.ts index d70a763b6..f9b72a9e8 100644 --- a/app/src/proto/prometheus_pb.d.ts +++ b/app/src/proto/prometheus_pb.d.ts @@ -329,6 +329,9 @@ export class Chart extends jspb.Message { getSize(): number; setSize(value: number): void; + getLegend(): string; + setLegend(value: string): void; + getMappingsMap(): jspb.Map; clearMappingsMap(): void; clearQueriesList(): void; @@ -353,6 +356,7 @@ export namespace Chart { unit: string, stacked: boolean, size: number, + legend: string, mappingsMap: Array<[string, string]>, queriesList: Array, } diff --git a/app/src/proto/prometheus_pb.js b/app/src/proto/prometheus_pb.js index f322275eb..659ea115d 100644 --- a/app/src/proto/prometheus_pb.js +++ b/app/src/proto/prometheus_pb.js @@ -2541,7 +2541,7 @@ proto.plugins.prometheus.Variable.prototype.setValue = function(value) { * @private {!Array} * @const */ -proto.plugins.prometheus.Chart.repeatedFields_ = [7]; +proto.plugins.prometheus.Chart.repeatedFields_ = [8]; @@ -2579,6 +2579,7 @@ proto.plugins.prometheus.Chart.toObject = function(includeInstance, msg) { unit: jspb.Message.getFieldWithDefault(msg, 3, ""), stacked: jspb.Message.getBooleanFieldWithDefault(msg, 4, false), size: jspb.Message.getFieldWithDefault(msg, 5, 0), + legend: jspb.Message.getFieldWithDefault(msg, 6, ""), mappingsMap: (f = msg.getMappingsMap()) ? f.toObject(includeInstance, undefined) : [], queriesList: jspb.Message.toObjectList(msg.getQueriesList(), proto.plugins.prometheus.Query.toObject, includeInstance) @@ -2639,12 +2640,16 @@ proto.plugins.prometheus.Chart.deserializeBinaryFromReader = function(msg, reade msg.setSize(value); break; case 6: + var value = /** @type {string} */ (reader.readString()); + msg.setLegend(value); + break; + case 7: var value = msg.getMappingsMap(); reader.readMessage(value, function(message, reader) { jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readString, null, "", ""); }); break; - case 7: + case 8: var value = new proto.plugins.prometheus.Query; reader.readMessage(value,proto.plugins.prometheus.Query.deserializeBinaryFromReader); msg.addQueries(value); @@ -2713,14 +2718,21 @@ proto.plugins.prometheus.Chart.serializeBinaryToWriter = function(message, write f ); } + f = message.getLegend(); + if (f.length > 0) { + writer.writeString( + 6, + f + ); + } f = message.getMappingsMap(true); if (f && f.getLength() > 0) { - f.serializeBinary(6, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeString); + f.serializeBinary(7, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeString); } f = message.getQueriesList(); if (f.length > 0) { writer.writeRepeatedMessage( - 7, + 8, f, proto.plugins.prometheus.Query.serializeBinaryToWriter ); @@ -2819,14 +2831,32 @@ proto.plugins.prometheus.Chart.prototype.setSize = function(value) { /** - * map mappings = 6; + * optional string legend = 6; + * @return {string} + */ +proto.plugins.prometheus.Chart.prototype.getLegend = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.prometheus.Chart} returns this + */ +proto.plugins.prometheus.Chart.prototype.setLegend = function(value) { + return jspb.Message.setProto3StringField(this, 6, value); +}; + + +/** + * map mappings = 7; * @param {boolean=} opt_noLazyCreate Do not create the map if * empty, instead returning `undefined` * @return {!jspb.Map} */ proto.plugins.prometheus.Chart.prototype.getMappingsMap = function(opt_noLazyCreate) { return /** @type {!jspb.Map} */ ( - jspb.Message.getMapField(this, 6, opt_noLazyCreate, + jspb.Message.getMapField(this, 7, opt_noLazyCreate, null)); }; @@ -2841,12 +2871,12 @@ proto.plugins.prometheus.Chart.prototype.clearMappingsMap = function() { /** - * repeated Query queries = 7; + * repeated Query queries = 8; * @return {!Array} */ proto.plugins.prometheus.Chart.prototype.getQueriesList = function() { return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.plugins.prometheus.Query, 7)); + jspb.Message.getRepeatedWrapperField(this, proto.plugins.prometheus.Query, 8)); }; @@ -2855,7 +2885,7 @@ proto.plugins.prometheus.Chart.prototype.getQueriesList = function() { * @return {!proto.plugins.prometheus.Chart} returns this */ proto.plugins.prometheus.Chart.prototype.setQueriesList = function(value) { - return jspb.Message.setRepeatedWrapperField(this, 7, value); + return jspb.Message.setRepeatedWrapperField(this, 8, value); }; @@ -2865,7 +2895,7 @@ proto.plugins.prometheus.Chart.prototype.setQueriesList = function(value) { * @return {!proto.plugins.prometheus.Query} */ proto.plugins.prometheus.Chart.prototype.addQueries = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 7, opt_value, proto.plugins.prometheus.Query, opt_index); + return jspb.Message.addToRepeatedWrapperField(this, 8, opt_value, proto.plugins.prometheus.Query, opt_index); }; diff --git a/deploy/helm/kobs/Chart.yaml b/deploy/helm/kobs/Chart.yaml index e5059375f..5961eb217 100644 --- a/deploy/helm/kobs/Chart.yaml +++ b/deploy/helm/kobs/Chart.yaml @@ -4,5 +4,5 @@ description: Kubernetes Observability Platform type: application home: https://kobs.io icon: https://kobs.io/assets/images/logo.svg -version: 0.3.2 +version: 0.3.3 appVersion: v0.2.0 diff --git a/deploy/helm/kobs/templates/customresourcedefinition.yaml b/deploy/helm/kobs/templates/customresourcedefinition.yaml index 24d4d0dbc..59db01209 100644 --- a/deploy/helm/kobs/templates/customresourcedefinition.yaml +++ b/deploy/helm/kobs/templates/customresourcedefinition.yaml @@ -177,6 +177,8 @@ spec: are executed against the datasource (e.g. For Prometheus this will be a list of PromQL queries). properties: + legend: + type: string mappings: additionalProperties: type: string @@ -336,6 +338,8 @@ spec: datasource (e.g. For Prometheus this will be a list of PromQL queries). properties: + legend: + type: string mappings: additionalProperties: type: string diff --git a/deploy/kustomize/crds/kobs.io_applications.yaml b/deploy/kustomize/crds/kobs.io_applications.yaml index fab9619d5..bf11ee185 100644 --- a/deploy/kustomize/crds/kobs.io_applications.yaml +++ b/deploy/kustomize/crds/kobs.io_applications.yaml @@ -177,6 +177,8 @@ spec: are executed against the datasource (e.g. For Prometheus this will be a list of PromQL queries). properties: + legend: + type: string mappings: additionalProperties: type: string @@ -336,6 +338,8 @@ spec: datasource (e.g. For Prometheus this will be a list of PromQL queries). properties: + legend: + type: string mappings: additionalProperties: type: string diff --git a/docs/plugins/prometheus.md b/docs/plugins/prometheus.md index e80d754b9..a637c17b2 100644 --- a/docs/plugins/prometheus.md +++ b/docs/plugins/prometheus.md @@ -33,6 +33,7 @@ The following specification can be used, within an application. | unit | string | An optional unit for the y axis of the chart. | No | | stacked | boolean | When this is `true` all time series in the chart will be stacked. | No | | size | number | An optional size for the chart. Must be a number between `1` and `12`. This is used to customize the grid of charts in the Prometheus tab. | No | +| legend | string | The type which should be used for the legend. Must be `bottom`, `table` or `disabled`. The default is `bottom` | No | | mappings | map | Specify value mappings for your data. **Note:** The value must be provided as string (e.g. `"1": "Green"`). | No | | queries | [[]Query](#query) | A list of queries, which are used to get the data for the chart. | Yes | diff --git a/pkg/api/plugins/prometheus/proto/prometheus.pb.go b/pkg/api/plugins/prometheus/proto/prometheus.pb.go index 0c7716cef..24c9a0dcf 100644 --- a/pkg/api/plugins/prometheus/proto/prometheus.pb.go +++ b/pkg/api/plugins/prometheus/proto/prometheus.pb.go @@ -707,8 +707,9 @@ type Chart struct { Unit string `protobuf:"bytes,3,opt,name=unit,proto3" json:"unit,omitempty"` Stacked bool `protobuf:"varint,4,opt,name=stacked,proto3" json:"stacked,omitempty"` Size int64 `protobuf:"varint,5,opt,name=size,proto3" json:"size,omitempty"` - Mappings map[string]string `protobuf:"bytes,6,rep,name=mappings,proto3" json:"mappings,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Queries []*Query `protobuf:"bytes,7,rep,name=queries,proto3" json:"queries,omitempty"` + Legend string `protobuf:"bytes,6,opt,name=legend,proto3" json:"legend,omitempty"` + Mappings map[string]string `protobuf:"bytes,7,rep,name=mappings,proto3" json:"mappings,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Queries []*Query `protobuf:"bytes,8,rep,name=queries,proto3" json:"queries,omitempty"` } func (x *Chart) Reset() { @@ -778,6 +779,13 @@ func (x *Chart) GetSize() int64 { return 0 } +func (x *Chart) GetLegend() string { + if x != nil { + return x.Legend + } + return "" +} + func (x *Chart) GetMappings() map[string]string { if x != nil { return x.Mappings @@ -930,53 +938,54 @@ var file_prometheus_proto_rawDesc = []byte{ 0x08, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xaa, 0x02, 0x0a, 0x05, 0x43, 0x68, 0x61, 0x72, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc2, 0x02, 0x0a, 0x05, 0x43, 0x68, 0x61, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x43, 0x0a, - 0x08, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x27, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, - 0x68, 0x65, 0x75, 0x73, 0x2e, 0x43, 0x68, 0x61, 0x72, 0x74, 0x2e, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x33, 0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x07, - 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x1a, 0x3b, 0x0a, 0x0d, 0x4d, 0x61, 0x70, 0x70, 0x69, - 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0x33, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x32, 0xb5, 0x02, 0x0a, 0x0a, 0x50, 0x72, - 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x56, - 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x47, 0x65, - 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, - 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, - 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5d, 0x0a, - 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x25, 0x2e, 0x70, 0x6c, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x6c, 0x65, 0x67, 0x65, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, + 0x65, 0x67, 0x65, 0x6e, 0x64, 0x12, 0x43, 0x0a, 0x08, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x43, 0x68, 0x61, + 0x72, 0x74, 0x2e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x08, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x33, 0x0a, 0x07, 0x71, 0x75, + 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, - 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x63, 0x0a, 0x0c, - 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x12, 0x27, 0x2e, 0x70, - 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, - 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x6b, 0x6f, 0x62, 0x73, 0x69, 0x6f, 0x2f, 0x6b, 0x6f, 0x62, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x6d, - 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x1a, + 0x3b, 0x0a, 0x0d, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x33, 0x0a, 0x05, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x32, 0xb5, 0x02, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, + 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, + 0x12, 0x27, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, + 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x47, + 0x65, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x12, 0x25, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, + 0x47, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x63, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4c, 0x6f, + 0x6f, 0x6b, 0x75, 0x70, 0x12, 0x27, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, + 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x6f, 0x62, 0x73, 0x69, 0x6f, 0x2f, 0x6b, + 0x6f, 0x62, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/prometheus.proto b/proto/prometheus.proto index 14697ed4b..287551f1f 100644 --- a/proto/prometheus.proto +++ b/proto/prometheus.proto @@ -104,8 +104,9 @@ message Chart { string unit = 3; bool stacked = 4; int64 size = 5; - map mappings = 6; - repeated Query queries = 7; + string legend = 6; + map mappings = 7; + repeated Query queries = 8; } // Query presents a single query to get the data, which should be shown in the chart for the metrics section. A query