diff --git a/.drone.yml b/.drone.yml index 10a2ebb7746..aec33809cfa 100644 --- a/.drone.yml +++ b/.drone.yml @@ -235,6 +235,9 @@ services: MYSQL_ROOT_PASSWORD: rootpass MYSQL_USER: grafana +node: + type: no-parallel + trigger: event: - pull_request @@ -563,6 +566,9 @@ services: MYSQL_ROOT_PASSWORD: rootpass MYSQL_USER: grafana +node: + type: no-parallel + trigger: branch: - main @@ -663,6 +669,9 @@ steps: depends_on: - initialize +node: + type: no-parallel + trigger: branch: - main @@ -1005,6 +1014,9 @@ services: MYSQL_ROOT_PASSWORD: rootpass MYSQL_USER: grafana +node: + type: no-parallel + trigger: ref: - refs/tags/v* @@ -1477,6 +1489,9 @@ services: image_pull_secrets: - dockerconfigjson +node: + type: no-parallel + trigger: ref: - refs/tags/v* @@ -1617,6 +1632,9 @@ steps: depends_on: - initialize +node: + type: no-parallel + trigger: ref: - refs/tags/v* @@ -1948,6 +1966,9 @@ services: MYSQL_ROOT_PASSWORD: rootpass MYSQL_USER: grafana +node: + type: no-parallel + trigger: event: - custom @@ -2414,6 +2435,9 @@ services: image_pull_secrets: - dockerconfigjson +node: + type: no-parallel + trigger: event: - custom @@ -2554,6 +2578,9 @@ steps: depends_on: - initialize +node: + type: no-parallel + trigger: event: - custom @@ -2860,6 +2887,9 @@ services: MYSQL_ROOT_PASSWORD: rootpass MYSQL_USER: grafana +node: + type: no-parallel + trigger: ref: - refs/heads/v* @@ -3325,6 +3355,9 @@ services: image_pull_secrets: - dockerconfigjson +node: + type: no-parallel + trigger: ref: - refs/heads/v* @@ -3496,6 +3529,6 @@ get: --- kind: signature -hmac: 68edb93a18f2e16f8a9b2bf3d21073e181e56d2420feec37ae80b121fc2faeeb +hmac: 4f23649a1678c66fb96af929675bcf569cca3b208d425eace86150d981ee9fbb ... diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d3e0fb182a..9533c8acc16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ + + + +# 8.1.1 (2021-08-09) + +### Bug fixes + +* **CloudWatch Logs:** Fix crash when no region is selected. [#37639](https://github.com/grafana/grafana/pull/37639), [@aocenas](https://github.com/aocenas) +* **Reporting:** Fix timezone parsing for scheduler (enterprise) + + # 8.1.0 (2021-08-05) diff --git a/cue/data/gen.cue b/cue/data/gen.cue index d831033e321..c70dc314874 100644 --- a/cue/data/gen.cue +++ b/cue/data/gen.cue @@ -22,7 +22,7 @@ Family: scuemata.#Family & { // Theme of dashboard. style: *"light" | "dark" // Timezone of dashboard, - timezone?: *"browser" | "utc" + timezone?: *"browser" | "utc" | "" // Whether a dashboard is editable or not. editable: bool | *true // 0 for no shared crosshair or tooltip (default). @@ -66,14 +66,62 @@ Family: scuemata.#Family & { showIn: number | *0 }] // Auto-refresh interval. - refresh?: string + refresh?: string | false // Version of the JSON schema, incremented each time a Grafana update brings // changes to said schema. - schemaVersion: number | *25 + // FIXME this is the old schema numbering system, and will be replaced by scuemata + schemaVersion: number | *30 // Version of the dashboard, incremented each time the dashboard is updated. version?: number panels?: [...#Panel] + // TODO docs + #FieldColorModeId: "thresholds" | "palette-classic" | "palette-saturated" | "continuous-GrYlRd" | "fixed" @cuetsy(targetType="enum") + + // TODO docs + #FieldColorSeriesByMode: "min" | "max" | "last" @cuetsy(targetType="type") + + // TODO docs + #FieldColor: { + // The main color scheme mode + mode: #FieldColorModeId | string + // Stores the fixed color value if mode is fixed + fixedColor?: string + // Some visualizations need to know how to assign a series color from by value color schemes + seriesBy?: #FieldColorSeriesByMode + } @cuetsy(targetType="interface") + + // TODO docs + #Threshold: { + // TODO docs + // FIXME the corresponding typescript field is required/non-optional, but nulls currently appear here when serializing -Infinity to JSON + value?: number + // TODO docs + color: string + // TODO docs + // TODO are the values here enumerable into a disjunction? + // Some seem to be listed in typescript comment + state?: string + } @cuetsy(targetType="interface") + + #ThresholdsMode: "absolute" | "percentage" @cuetsy(targetType="enum") + + #ThresholdsConfig: { + mode: #ThresholdsMode + + // Must be sorted by 'value', first value is always -Infinity + steps: [...#Threshold] + } @cuetsy(targetType="interface") + + // Schema for panel targets is specified by datasource + // plugins. We use a placeholder definition, which the Go + // schema loader either left open/as-is with the Base + // variant of the Dashboard and Panel families, or filled + // with types derived from plugins in the Instance variant. + // When working directly from CUE, importers can extend this + // type directly to achieve the same effect. + #Target: {...} + // Dashboard panels. Panels are canonically defined inline // because they share a version timeline with the dashboard // schema; they do not vary independently. We create a separate, @@ -83,6 +131,15 @@ Family: scuemata.#Family & { // The panel plugin type id. type: !="" + // TODO docs + id?: number + + // FIXME this almost certainly has to be changed in favor of scuemata versions + pluginVersion?: string + + // TODO docs + tags?: [...string] + // Internal - the exact major and minor versions of the panel plugin // schema. Hidden and therefore not a part of the data model, but // expected to be filled with panel plugin schema versions so that it's @@ -93,6 +150,9 @@ Family: scuemata.#Family & { // TODO 2-tuple list instead of struct? panelSchema?: { maj: number, min: number } + // TODO docs + targets?: [...#Target] + // Panel title. title?: string // Description. @@ -115,20 +175,33 @@ Family: scuemata.#Family & { static?: bool } // Panel links. - // links?: [..._panelLink] + // FIXME this is temporarily specified as a closed list so + // that validation will pass when no links are present, but + // to force a failure as soon as it's checked against there + // being anything in the list so it can be fixed in + // accordance with that object + links?: [] + // Name of template variable to repeat for. repeat?: string // Direction to repeat in if 'repeat' is set. // "h" for horizontal, "v" for vertical. repeatDirection: *"h" | "v" - // Schema for panel targets is specified by datasource - // plugins. We use a placeholder definition, which the Go - // schema loader either left open/as-is with the Base - // variant of the Dashboard and Panel families, or filled - // with types derived from plugins in the Instance variant. - // When working directly from CUE, importers can extend this - // type directly to achieve the same effect. - targets?: [...{...}] + + // TODO docs + maxDataPoints?: number + + // TODO docs + // TODO tighter constraint + interval?: string + + // TODO docs + // TODO tighter constraint + timeFrom?: string + + // TODO docs + // TODO tighter constraint + timeShift?: string // The values depend on panel type options: {...} @@ -166,17 +239,25 @@ Family: scuemata.#Family & { min?: number max?: number - // // Convert input values into a display string - // mappings?: ValueMapping[]; + // Convert input values into a display string + // + // TODO this one corresponds to a complex type with + // generics on the typescript side. Ouch. Will + // either need special care, or we'll just need to + // accept a very loosely specified schema. It's very + // unlikely we'll be able to translate cue to + // typescript generics in the general case, though + // this particular one *may* be able to work. + mappings?: [...{...}] - // // Map numeric values to states - // thresholds?: ThresholdsConfig; + // Map numeric values to states + thresholds?: #ThresholdsConfig // // Map values to a display color - // color?: FieldColor; + color?: #FieldColor // // Used when reducing field values - // nullValueMode?: NullValueMode; + // nullValueMode?: NullValueMode // // The behavior when clicking on a result links?: [...] @@ -184,10 +265,17 @@ Family: scuemata.#Family & { // Alternative to empty string noValue?: string + // TODO conundrum: marking this struct as open would + // - i think - preclude closed validation of + // plugin-defined config bits. But, marking it + // closed makes it impossible to use just this + // schema (the "base" variant) to validate the base + // components of a dashboard. + // // Can always exist. Valid fields within this are // defined by the panel plugin - that's the // PanelFieldConfig that comes from the plugin. - custom?: {} + custom?: {...} } overrides: [...{ matcher: { diff --git a/cue/ui/gen.cue b/cue/ui/gen.cue index bd790839694..c52a1535b66 100644 --- a/cue/ui/gen.cue +++ b/cue/ui/gen.cue @@ -33,7 +33,7 @@ ScaleDistribution: "linear" | "log" @c GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(targetType="enum") LineStyle: { fill?: "solid" | "dash" | "dot" | "square" - dash?: [number] + dash?: [...number] } @cuetsy(targetType="interface") LineConfig: { lineColor?: string @@ -68,7 +68,7 @@ AxisConfig: { HideSeriesConfig: { tooltip: bool legend: bool - graph: bool + viz: bool } @cuetsy(targetType="interface") LegendPlacement: "bottom" | "right" @cuetsy(targetType="type") LegendDisplayMode: "list" | "table" | "hidden" @cuetsy(targetType="enum") @@ -86,7 +86,7 @@ GraphFieldConfig: LineConfig & FillConfig & PointsConfig & AxisConfig & { VizLegendOptions: { displayMode: LegendDisplayMode placement: LegendPlacement - calcs: [string] + calcs: [...string] } @cuetsy(targetType="interface") VizTooltipOptions: { mode: TooltipDisplayMode diff --git a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_compare.json b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_compare.json index 82df5a1b18c..1b0698addfc 100644 --- a/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_compare.json +++ b/devenv/dev-dashboards/datasource-elasticsearch/elasticsearch_compare.json @@ -15,7 +15,6 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "iteration": 1620904436360, "links": [ @@ -34,7 +33,6 @@ "panels": [ { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -112,9 +110,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Basic (version one) - interval auto", "tooltip": { "shared": true, @@ -123,33 +119,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -221,9 +208,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Basic (version two) - interval auto", "tooltip": { "shared": true, @@ -232,33 +217,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -311,8 +287,7 @@ "id": "2", "settings": { "interval": "1m", - "min_doc_count": 50, - "trimEdges": null + "min_doc_count": 50 }, "type": "date_histogram" } @@ -330,9 +305,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Basic (version one) - interval 1m + min doc count 50", "tooltip": { "shared": true, @@ -341,33 +314,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -420,8 +384,7 @@ "id": "2", "settings": { "interval": "1m", - "min_doc_count": 50, - "trimEdges": null + "min_doc_count": 50 }, "type": "date_histogram" } @@ -439,9 +402,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Basic (version two) - interval 1m + min doc count 50", "tooltip": { "shared": true, @@ -450,33 +411,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -548,9 +500,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Basic (version one) - interval 5m + trim edges=10", "tooltip": { "shared": true, @@ -559,33 +509,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -657,9 +598,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Basic (version two) - interval 5m + trim edges=10", "tooltip": { "shared": true, @@ -668,33 +607,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -703,7 +633,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -762,8 +691,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -774,7 +702,6 @@ "id": "1", "meta": {}, "settings": { - "missing": null }, "type": "avg" } @@ -785,9 +712,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "avg (version one) - interval auto", "tooltip": { "shared": true, @@ -796,33 +721,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -875,8 +791,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -887,7 +802,6 @@ "id": "1", "meta": {}, "settings": { - "missing": null }, "type": "avg" } @@ -898,9 +812,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "avg (version two) - interval auto", "tooltip": { "shared": true, @@ -909,33 +821,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -988,8 +891,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -1000,7 +902,6 @@ "id": "1", "meta": {}, "settings": { - "missing": null }, "type": "sum" } @@ -1011,9 +912,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "sum (version one) - interval auto", "tooltip": { "shared": true, @@ -1022,33 +921,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -1101,8 +991,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -1113,7 +1002,6 @@ "id": "1", "meta": {}, "settings": { - "missing": null }, "type": "sum" } @@ -1124,9 +1012,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "sum (version two) - interval auto", "tooltip": { "shared": true, @@ -1135,33 +1021,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -1216,8 +1093,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -1237,9 +1113,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "max (version one) - interval auto", "tooltip": { "shared": true, @@ -1248,33 +1122,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -1329,8 +1194,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -1350,9 +1214,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "max (version two) - interval auto", "tooltip": { "shared": true, @@ -1361,33 +1223,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -1442,8 +1295,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -1463,9 +1315,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "min (version one) - interval auto", "tooltip": { "shared": true, @@ -1474,33 +1324,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -1555,8 +1396,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -1576,9 +1416,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "min (version two) - interval auto", "tooltip": { "shared": true, @@ -1587,33 +1425,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -1671,8 +1500,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -1701,9 +1529,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "extended stats (version one) - interval auto", "tooltip": { "shared": true, @@ -1712,33 +1538,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -1796,8 +1613,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -1826,9 +1642,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "extended stats (version two) - interval auto", "tooltip": { "shared": true, @@ -1837,33 +1651,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -1919,8 +1724,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -1948,9 +1752,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "percentiles (version one) - interval auto", "tooltip": { "shared": true, @@ -1959,33 +1761,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -2041,8 +1834,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -2053,7 +1845,6 @@ "id": "1", "meta": {}, "settings": { - "missing": null, "percents": [ 25, 50, @@ -2071,9 +1862,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "percentiles (version two) - interval auto", "tooltip": { "shared": true, @@ -2082,33 +1871,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -2164,8 +1944,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -2185,9 +1964,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "unique count (version one) - interval auto", "tooltip": { "shared": true, @@ -2196,33 +1973,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -2278,8 +2046,7 @@ "id": "2", "settings": { "interval": "auto", - "min_doc_count": 0, - "trimEdges": null + "min_doc_count": 0 }, "type": "date_histogram" } @@ -2299,9 +2066,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "unique count (version two) - interval auto", "tooltip": { "shared": true, @@ -2310,33 +2075,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -2345,7 +2101,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -2445,9 +2200,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count (version one) - interval 5m", "tooltip": { "shared": true, @@ -2456,33 +2209,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -2576,9 +2320,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count (version two) - interval 5m", "tooltip": { "shared": true, @@ -2587,33 +2329,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -2707,9 +2440,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "avg (version one) - interval 5m", "tooltip": { "shared": true, @@ -2718,33 +2449,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -2838,9 +2560,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "avg (version two) - interval 5m", "tooltip": { "shared": true, @@ -2849,33 +2569,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -2969,9 +2680,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "sum (version one) - interval 5m", "tooltip": { "shared": true, @@ -2980,33 +2689,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -3100,9 +2800,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "sum (version two) - interval 5m", "tooltip": { "shared": true, @@ -3111,33 +2809,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -3231,9 +2920,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "max (version one) - interval 5m", "tooltip": { "shared": true, @@ -3242,33 +2929,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -3362,9 +3040,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "max (version two) - interval 5m", "tooltip": { "shared": true, @@ -3373,33 +3049,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -3493,9 +3160,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "min (version one) - interval auto", "tooltip": { "shared": true, @@ -3504,33 +3169,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -3624,9 +3280,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "min (version two) - interval auto", "tooltip": { "shared": true, @@ -3635,33 +3289,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -3755,9 +3400,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "unique count (version one) - interval 5m", "tooltip": { "shared": true, @@ -3766,33 +3409,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -3886,9 +3520,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "unique count (version two) - interval 5m", "tooltip": { "shared": true, @@ -3897,33 +3529,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -3932,7 +3555,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -4027,9 +3649,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count (version one) - interval auto", "tooltip": { "shared": true, @@ -4038,33 +3658,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -4153,9 +3764,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count (version two) - interval auto", "tooltip": { "shared": true, @@ -4164,33 +3773,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -4279,9 +3879,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "avg (version one) - interval auto", "tooltip": { "shared": true, @@ -4290,33 +3888,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -4405,9 +3994,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "avg (version two) - interval auto", "tooltip": { "shared": true, @@ -4416,33 +4003,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -4531,9 +4109,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "sum (version one) - interval auto", "tooltip": { "shared": true, @@ -4542,33 +4118,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -4657,9 +4224,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "sum (version two) - interval auto", "tooltip": { "shared": true, @@ -4668,33 +4233,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -4783,9 +4339,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "max (version one) - interval 5m", "tooltip": { "shared": true, @@ -4794,33 +4348,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -4909,9 +4454,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "max (version two) - interval 5m", "tooltip": { "shared": true, @@ -4920,33 +4463,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -5035,9 +4569,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "min (version one) - interval auto", "tooltip": { "shared": true, @@ -5046,33 +4578,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -5161,9 +4684,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "min (version two) - interval auto", "tooltip": { "shared": true, @@ -5172,33 +4693,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -5287,9 +4799,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "unique count (version one) - interval 5m", "tooltip": { "shared": true, @@ -5298,33 +4808,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -5413,9 +4914,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "unique count (version two) - interval 5m", "tooltip": { "shared": true, @@ -5424,33 +4923,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -5459,7 +4949,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -5558,9 +5047,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count (version one) - interval 5m", "tooltip": { "shared": true, @@ -5569,33 +5056,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -5688,9 +5166,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count (version two) - interval 5m", "tooltip": { "shared": true, @@ -5699,33 +5175,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -5818,9 +5285,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "avg (version one) - interval 5m", "tooltip": { "shared": true, @@ -5829,33 +5294,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -5948,9 +5404,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "avg (version two) - interval 5m", "tooltip": { "shared": true, @@ -5959,33 +5413,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -6078,9 +5523,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "sum (version one) - interval 5m", "tooltip": { "shared": true, @@ -6089,33 +5532,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -6208,9 +5642,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "sum (version two) - interval 5m", "tooltip": { "shared": true, @@ -6219,33 +5651,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -6338,9 +5761,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "max (version one) - interval 5m", "tooltip": { "shared": true, @@ -6349,33 +5770,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -6468,9 +5880,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "max (version two) - interval 5m", "tooltip": { "shared": true, @@ -6479,33 +5889,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -6598,9 +5999,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "min (version one) - interval auto", "tooltip": { "shared": true, @@ -6609,33 +6008,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -6728,9 +6118,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "min (version two) - interval auto", "tooltip": { "shared": true, @@ -6739,33 +6127,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -6858,9 +6237,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "unique count (version one) - interval 5m", "tooltip": { "shared": true, @@ -6869,33 +6246,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -6988,9 +6356,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "unique count (version two) - interval 5m", "tooltip": { "shared": true, @@ -6999,33 +6365,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -7034,7 +6391,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -7133,9 +6489,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count * 1000 (version one) - interval auto", "tooltip": { "shared": true, @@ -7144,33 +6498,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -7263,9 +6608,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count * 1000 (version two) - interval auto", "tooltip": { "shared": true, @@ -7274,33 +6617,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -7405,9 +6739,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count * avg (version one) - interval auto", "tooltip": { "shared": true, @@ -7416,33 +6748,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -7547,9 +6870,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count * avg (version two) - interval auto", "tooltip": { "shared": true, @@ -7558,33 +6879,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -7593,7 +6905,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -7726,9 +7037,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count/average with triple terms agg (version one) - interval auto", "tooltip": { "shared": true, @@ -7737,33 +7046,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -7890,9 +7190,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "count/average with triple terms agg (version two) - interval auto", "tooltip": { "shared": true, @@ -7901,33 +7199,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -7936,7 +7225,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -8027,9 +7315,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by Doc Count", "tooltip": { "shared": true, @@ -8038,33 +7324,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -8149,9 +7426,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by Doc Count", "tooltip": { "shared": true, @@ -8160,33 +7435,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -8271,9 +7537,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by Term value", "tooltip": { "shared": true, @@ -8282,33 +7546,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -8393,9 +7648,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by Term value", "tooltip": { "shared": true, @@ -8404,33 +7657,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -8516,9 +7760,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by avg", "tooltip": { "shared": true, @@ -8527,33 +7769,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -8639,9 +7872,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by avg", "tooltip": { "shared": true, @@ -8650,33 +7881,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -8762,9 +7984,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by unique count", "tooltip": { "shared": true, @@ -8773,33 +7993,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -8885,9 +8096,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by unique count", "tooltip": { "shared": true, @@ -8896,33 +8105,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -8931,7 +8131,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -9027,9 +8226,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (avg)", "tooltip": { "shared": true, @@ -9038,33 +8235,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -9154,9 +8342,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (avg)", "tooltip": { "shared": true, @@ -9165,33 +8351,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -9281,9 +8458,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (min)", "tooltip": { "shared": true, @@ -9292,33 +8467,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -9408,9 +8574,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (min)", "tooltip": { "shared": true, @@ -9419,33 +8583,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -9535,9 +8690,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (max)", "tooltip": { "shared": true, @@ -9546,33 +8699,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -9662,9 +8806,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (max)", "tooltip": { "shared": true, @@ -9673,33 +8815,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -9789,9 +8922,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (sum)", "tooltip": { "shared": true, @@ -9800,33 +8931,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -9916,9 +9038,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (sum)", "tooltip": { "shared": true, @@ -9927,33 +9047,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -10043,9 +9154,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (count)", "tooltip": { "shared": true, @@ -10054,33 +9163,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -10170,9 +9270,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (count)", "tooltip": { "shared": true, @@ -10181,33 +9279,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -10297,9 +9386,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (std dev)", "tooltip": { "shared": true, @@ -10308,33 +9395,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -10424,9 +9502,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (std dev)", "tooltip": { "shared": true, @@ -10435,33 +9511,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -10551,9 +9618,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (std dev upper)", "tooltip": { "shared": true, @@ -10562,33 +9627,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -10678,9 +9734,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (std dev upper)", "tooltip": { "shared": true, @@ -10689,33 +9743,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -10805,9 +9850,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (std dev lower)", "tooltip": { "shared": true, @@ -10816,33 +9859,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -10932,9 +9966,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by extended stats (std dev lower)", "tooltip": { "shared": true, @@ -10943,33 +9975,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -10978,7 +10001,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -11069,9 +10091,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by percentile (25)", "tooltip": { "shared": true, @@ -11080,33 +10100,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -11191,9 +10202,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by percentile (25)", "tooltip": { "shared": true, @@ -11202,33 +10211,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -11313,9 +10313,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by percentile (99)", "tooltip": { "shared": true, @@ -11324,33 +10322,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -11435,9 +10424,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Terms order by percentile (99)", "tooltip": { "shared": true, @@ -11446,33 +10433,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -11481,7 +10459,6 @@ }, { "collapsed": true, - "datasource": null, "gridPos": { "h": 1, "w": 24, @@ -11533,8 +10510,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -11662,8 +10638,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -11768,8 +10743,6 @@ "text": "gdev-elasticsearch-v5-metrics", "value": "gdev-elasticsearch-v5-metrics" }, - "description": null, - "error": null, "hide": 0, "includeAll": false, "label": "Version One", @@ -11789,8 +10762,6 @@ "text": "gdev-elasticsearch-v56-metrics", "value": "gdev-elasticsearch-v56-metrics" }, - "description": null, - "error": null, "hide": 0, "includeAll": false, "label": "Version Two", @@ -11839,4 +10810,4 @@ "title": "Datasource tests - Elasticsearch comparison", "uid": "fuFWehBmk", "version": 4 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/datasource-opentsdb/opentsdb_v2.3.json b/devenv/dev-dashboards/datasource-opentsdb/opentsdb_v2.3.json index b2b4a969ce7..287d5b434f1 100644 --- a/devenv/dev-dashboards/datasource-opentsdb/opentsdb_v2.3.json +++ b/devenv/dev-dashboards/datasource-opentsdb/opentsdb_v2.3.json @@ -13,7 +13,6 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "id": 3151, "links": [], @@ -90,9 +89,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "CPU per host", "tooltip": { "shared": true, @@ -101,33 +98,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } }, { @@ -199,9 +187,7 @@ } ], "thresholds": [], - "timeFrom": null, "timeRegions": [], - "timeShift": null, "title": "Login Count per host", "tooltip": { "shared": true, @@ -210,33 +196,24 @@ }, "type": "graph", "xaxis": { - "buckets": null, "mode": "time", - "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true }, { "format": "short", - "label": null, "logBase": 1, - "max": null, - "min": null, "show": true } ], "yaxis": { - "align": false, - "alignLevel": null + "align": false } } ], @@ -255,4 +232,4 @@ "title": "Datasource tests - OpenTSDB v2.3", "uid": "rZRUGik7k", "version": 3 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/datasource-testdata/new_features_in_v8.json b/devenv/dev-dashboards/datasource-testdata/new_features_in_v8.json index e0170fe82c0..2c476f956ca 100644 --- a/devenv/dev-dashboards/datasource-testdata/new_features_in_v8.json +++ b/devenv/dev-dashboards/datasource-testdata/new_features_in_v8.json @@ -13,13 +13,11 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "id": 625, "links": [], "panels": [ { - "datasource": null, "gridPos": { "h": 4, "w": 24, @@ -38,13 +36,10 @@ "target": "" } ], - "timeFrom": null, - "timeShift": null, "transparent": true, "type": "text" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 8, @@ -107,8 +102,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -166,7 +160,6 @@ "type": "state-timeline" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 15, @@ -207,8 +200,7 @@ "mode": "absolute", "steps": [ { - "color": "blue", - "value": null + "color": "blue" }, { "color": "green", @@ -293,8 +285,7 @@ "mode": "absolute", "steps": [ { - "color": "blue", - "value": null + "color": "blue" }, { "color": "green", @@ -343,7 +334,6 @@ "type": "timeseries" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 13, @@ -386,8 +376,7 @@ "mode": "absolute", "steps": [ { - "color": "blue", - "value": null + "color": "blue" }, { "color": "#EAB839", @@ -473,8 +462,7 @@ "mode": "absolute", "steps": [ { - "color": "blue", - "value": null + "color": "blue" }, { "color": "#EAB839", @@ -522,7 +510,6 @@ "type": "status-history" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 3, @@ -573,8 +560,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -713,8 +699,7 @@ "mode": "absolute", "steps": [ { - "color": "blue", - "value": null + "color": "blue" } ] }, @@ -757,7 +742,6 @@ "type": "barchart" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 3, @@ -783,7 +767,6 @@ "type": "text" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 6, @@ -848,8 +831,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -924,8 +906,6 @@ "stringInput": "" } ], - "timeFrom": null, - "timeShift": null, "title": "Interpolation mode: smooth", "type": "timeseries" }, @@ -969,8 +949,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1045,8 +1024,6 @@ "stringInput": "1,20,90,30,5,0" } ], - "timeFrom": null, - "timeShift": null, "title": "Interpolation mode: Step before", "type": "timeseries" }, @@ -1090,8 +1067,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1166,13 +1142,10 @@ "stringInput": "1,20,90,30,5,0" } ], - "timeFrom": null, - "timeShift": null, "title": "Interpolation mode: Step after", "type": "timeseries" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 8, @@ -1240,8 +1213,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1300,8 +1272,6 @@ "stringInput": "10,11,12,11,10,11,12,12,11,10,9,10,11,12,10,10,11,12,13,11,10,9,10,11,12,13,14,10,10" } ], - "timeFrom": null, - "timeShift": null, "title": "Auto min max", "type": "timeseries" }, @@ -1351,8 +1321,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1411,8 +1380,6 @@ "stringInput": "10,11,12,11,10,11,12,12,11,10,9,10,11,12,200,10,11,12,13,11,10,9,10,11,12,13,14,10,10" } ], - "timeFrom": null, - "timeShift": null, "title": "Hard min 0, max 30", "type": "timeseries" }, @@ -1462,8 +1429,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1522,13 +1488,10 @@ "stringInput": "10,11,12,11,10,11,12,12,11,10,9,10,11,12,200,10,11,12,13,11,10,9,10,11,12,13,14,10,10" } ], - "timeFrom": null, - "timeShift": null, "title": "Soft min 0, soft max 30", "type": "timeseries" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 5, @@ -1595,8 +1558,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1769,7 +1731,6 @@ "type": "timeseries" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 5, @@ -1844,8 +1805,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2170,8 +2130,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2493,8 +2452,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2573,7 +2531,6 @@ "type": "timeseries" }, { - "cacheTimeout": null, "datasource": "gdev-testdata", "gridPos": { "h": 3, @@ -2620,8 +2577,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2655,7 +2611,6 @@ "y": 83 }, "id": 49, - "maxDataPoints": null, "options": { "bucketOffset": 0, "bucketSize": 10, @@ -2719,8 +2674,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2754,7 +2708,6 @@ "y": 83 }, "id": 77, - "maxDataPoints": null, "options": { "showHeader": true }, @@ -2838,4 +2791,4 @@ "title": "New Features in v8.0", "uid": "8mux8PqGz", "version": 17 - } \ No newline at end of file + } diff --git a/devenv/dev-dashboards/home.json b/devenv/dev-dashboards/home.json index a65bd3eeecd..3fd98704fff 100644 --- a/devenv/dev-dashboards/home.json +++ b/devenv/dev-dashboards/home.json @@ -19,12 +19,10 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "links": [], "panels": [ { - "datasource": null, "gridPos": { "h": 26, "w": 6, @@ -34,7 +32,6 @@ "id": 7, "links": [], "options": { - "folderId": null, "maxItems": 100, "query": "", "showHeadings": true, @@ -45,13 +42,10 @@ }, "pluginVersion": "8.1.0-pre", "tags": [], - "timeFrom": null, - "timeShift": null, "title": "Starred", "type": "dashlist" }, { - "datasource": null, "gridPos": { "h": 13, "w": 6, @@ -75,13 +69,10 @@ "tags": [ "panel-tests" ], - "timeFrom": null, - "timeShift": null, "title": "tag: panel-tests", "type": "dashlist" }, { - "datasource": null, "gridPos": { "h": 13, "w": 6, @@ -91,7 +82,6 @@ "id": 3, "links": [], "options": { - "folderId": null, "maxItems": 1000, "query": "", "showHeadings": false, @@ -108,13 +98,10 @@ "gdev", "demo" ], - "timeFrom": null, - "timeShift": null, "title": "tag: dashboard-demo", "type": "dashlist" }, { - "datasource": null, "gridPos": { "h": 26, "w": 6, @@ -124,7 +111,6 @@ "id": 5, "links": [], "options": { - "folderId": null, "maxItems": 1000, "query": "", "showHeadings": false, @@ -141,13 +127,10 @@ "gdev", "datasource-test" ], - "timeFrom": null, - "timeShift": null, "title": "Data source tests", "type": "dashlist" }, { - "datasource": null, "gridPos": { "h": 13, "w": 6, @@ -173,13 +156,10 @@ "templating", "gdev" ], - "timeFrom": null, - "timeShift": null, "title": "tag: templating ", "type": "dashlist" }, { - "datasource": null, "gridPos": { "h": 13, "w": 6, @@ -205,8 +185,6 @@ "gdev", "demo" ], - "timeFrom": null, - "timeShift": null, "title": "tag: transforms", "type": "dashlist" } @@ -250,4 +228,4 @@ "title": "Grafana Dev Overview & Home", "uid": "j6T00KRZz", "version": 2 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-barchart/barchart-autosizing.json b/devenv/dev-dashboards/panel-barchart/barchart-autosizing.json index 14440800c6a..064fbb20979 100644 --- a/devenv/dev-dashboards/panel-barchart/barchart-autosizing.json +++ b/devenv/dev-dashboards/panel-barchart/barchart-autosizing.json @@ -19,12 +19,10 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "links": [], "panels": [ { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -49,8 +47,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -96,7 +93,6 @@ "type": "barchart" }, { - "datasource": null, "description": "Should be smaller given the longer value", "fieldConfig": { "defaults": { @@ -123,8 +119,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -170,7 +165,6 @@ "type": "barchart" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -195,8 +189,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -242,7 +235,6 @@ "type": "barchart" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -267,8 +259,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -339,8 +330,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -386,7 +376,6 @@ "type": "barchart" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -412,8 +401,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -459,7 +447,6 @@ "type": "barchart" }, { - "datasource": null, "description": "", "fieldConfig": { "defaults": { @@ -485,8 +472,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -552,4 +538,4 @@ "title": "BarChart - Panel Tests - Value sizing", "uid": "WFlOM-jM1", "version": 9 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-graph/graph-ng-by-value-color-schemes.json b/devenv/dev-dashboards/panel-graph/graph-ng-by-value-color-schemes.json index 8e071d22fab..29e6d92cc0c 100644 --- a/devenv/dev-dashboards/panel-graph/graph-ng-by-value-color-schemes.json +++ b/devenv/dev-dashboards/panel-graph/graph-ng-by-value-color-schemes.json @@ -13,7 +13,6 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "links": [], "panels": [ @@ -59,8 +58,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -104,7 +102,6 @@ "type": "timeseries" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -145,8 +142,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -192,7 +188,6 @@ "startValue": 1 } ], - "timeFrom": null, "title": "Color bars by discrete thresholds", "type": "timeseries" }, @@ -238,8 +233,7 @@ "mode": "absolute", "steps": [ { - "color": "blue", - "value": null + "color": "blue" }, { "color": "green", @@ -328,8 +322,7 @@ "mode": "absolute", "steps": [ { - "color": "blue", - "value": null + "color": "blue" }, { "color": "green", @@ -418,8 +411,7 @@ "mode": "absolute", "steps": [ { - "color": "blue", - "value": null + "color": "blue" }, { "color": "green", @@ -467,7 +459,6 @@ "type": "timeseries" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -508,8 +499,7 @@ "mode": "absolute", "steps": [ { - "color": "blue", - "value": null + "color": "blue" }, { "color": "green", @@ -590,4 +580,4 @@ "title": "Panel Tests - Graph NG - By value color schemes", "uid": "aBXrJ0R7z", "version": 20 - } \ No newline at end of file + } diff --git a/devenv/dev-dashboards/panel-graph/graph-ng-nulls.json b/devenv/dev-dashboards/panel-graph/graph-ng-nulls.json index 2c86c73b870..1914a99e80d 100644 --- a/devenv/dev-dashboards/panel-graph/graph-ng-nulls.json +++ b/devenv/dev-dashboards/panel-graph/graph-ng-nulls.json @@ -13,7 +13,6 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "links": [ { @@ -69,8 +68,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -132,8 +130,6 @@ "target": "" } ], - "timeFrom": null, - "timeShift": null, "title": "Show gaps", "type": "timeseries" }, @@ -180,8 +176,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -251,8 +246,6 @@ "target": "" } ], - "timeFrom": null, - "timeShift": null, "title": "Gaps & null between every point for series B", "type": "timeseries" }, @@ -299,8 +292,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -390,8 +382,6 @@ "target": "" } ], - "timeFrom": null, - "timeShift": null, "title": "No nulls but unaligned series", "type": "timeseries" }, @@ -436,8 +426,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -499,8 +488,6 @@ "target": "" } ], - "timeFrom": null, - "timeShift": null, "title": "Connected", "type": "timeseries" }, @@ -547,8 +534,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -618,8 +604,6 @@ "target": "" } ], - "timeFrom": null, - "timeShift": null, "title": "Same as above but connected", "type": "timeseries" }, @@ -666,8 +650,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -757,8 +740,6 @@ "target": "" } ], - "timeFrom": null, - "timeShift": null, "title": "Same as above but connected", "type": "timeseries" }, @@ -803,8 +784,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -903,8 +883,6 @@ "stringInput": "1,20,90,30,5,0" } ], - "timeFrom": null, - "timeShift": null, "title": "Null values in first series & show gaps ", "transformations": [], "type": "timeseries" @@ -950,8 +928,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1050,14 +1027,11 @@ "stringInput": "10,25,null,null,50,10" } ], - "timeFrom": null, - "timeShift": null, "title": "Null values in second series show gaps (bugged)", "transformations": [], "type": "timeseries" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -1097,8 +1071,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1157,13 +1130,10 @@ "stringInput": "1,20,90,null,30,5,0" } ], - "timeFrom": null, - "timeShift": null, "title": "Span nulls below 1hr", "type": "timeseries" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -1205,8 +1175,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1264,4 +1233,4 @@ "title": "Panel Tests - Graph NG - Gaps and Connected", "uid": "8mmCAF1Mz", "version": 12 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-histogram/histogram_tests.json b/devenv/dev-dashboards/panel-histogram/histogram_tests.json index 4b7588efd55..370432cce46 100644 --- a/devenv/dev-dashboards/panel-histogram/histogram_tests.json +++ b/devenv/dev-dashboards/panel-histogram/histogram_tests.json @@ -13,13 +13,11 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "id": 632, "links": [], "panels": [ { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -40,8 +38,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -100,8 +97,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -139,7 +135,6 @@ "type": "histogram" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -160,8 +155,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -212,7 +206,6 @@ "type": "histogram" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -233,8 +226,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -285,7 +277,6 @@ "type": "histogram" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -300,8 +291,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -353,7 +343,6 @@ "type": "table" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -368,8 +357,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -439,4 +427,4 @@ "title": "Panel Tests - Histogram", "uid": "UTv--wqMk", "version": 4 - } \ No newline at end of file + } diff --git a/devenv/dev-dashboards/panel-timeline/timeline-demo.json b/devenv/dev-dashboards/panel-timeline/timeline-demo.json index e2aec6e61db..0d6523350ad 100644 --- a/devenv/dev-dashboards/panel-timeline/timeline-demo.json +++ b/devenv/dev-dashboards/panel-timeline/timeline-demo.json @@ -13,12 +13,10 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "links": [], "panels": [ { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -55,8 +53,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -113,7 +110,6 @@ "type": "state-timeline" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -151,8 +147,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -207,7 +202,6 @@ "type": "state-timeline" }, { - "datasource": null, "description": "Should show gaps", "fieldConfig": { "defaults": { @@ -246,8 +240,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -301,7 +294,6 @@ "type": "state-timeline" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -319,8 +311,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -339,7 +330,6 @@ "y": 19 }, "id": 4, - "interval": null, "maxDataPoints": 20, "options": { "alignValue": "center", @@ -411,4 +401,4 @@ "title": "Timeline Demo", "uid": "mIJjFy8Kz", "version": 13 -} \ No newline at end of file +} diff --git a/devenv/dev-dashboards/panel-timeline/timeline-modes.json b/devenv/dev-dashboards/panel-timeline/timeline-modes.json index 8600d3274e8..cd613c34ccd 100644 --- a/devenv/dev-dashboards/panel-timeline/timeline-modes.json +++ b/devenv/dev-dashboards/panel-timeline/timeline-modes.json @@ -13,13 +13,11 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "id": 329, "links": [], "panels": [ { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -34,8 +32,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -165,7 +162,6 @@ 1616557148000 ], [ - null, 1616558756000 ], [ @@ -173,7 +169,6 @@ 1616561658000 ], [ - null, 1616562446000 ], [ @@ -181,7 +176,6 @@ 1616564104000 ], [ - null, 1616564548000 ], [ @@ -197,7 +191,6 @@ "type": "state-timeline" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -212,8 +205,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -267,7 +259,6 @@ "type": "state-timeline" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -282,8 +273,7 @@ "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "#EAB839", @@ -306,7 +296,6 @@ "y": 21 }, "id": 4, - "interval": null, "maxDataPoints": 20, "options": { "colWidth": 0.9, diff --git a/devenv/dev-dashboards/transforms/config-from-query.json b/devenv/dev-dashboards/transforms/config-from-query.json index ce834663b66..2139b024fb6 100644 --- a/devenv/dev-dashboards/transforms/config-from-query.json +++ b/devenv/dev-dashboards/transforms/config-from-query.json @@ -20,12 +20,10 @@ }, "description": "", "editable": true, - "gnetId": null, "graphTooltip": 0, "links": [], "panels": [ { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -64,8 +62,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -122,7 +119,6 @@ "type": "timeseries" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -137,8 +133,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -209,7 +204,6 @@ "type": "table" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -224,8 +218,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -291,7 +284,6 @@ "type": "table" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -306,8 +298,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -377,7 +368,6 @@ "type": "table" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -392,8 +382,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -446,7 +435,6 @@ "type": "table" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -470,8 +458,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -565,4 +552,4 @@ "title": "Transforms - Config from query", "uid": "Juj4_7ink", "version": 1 - } \ No newline at end of file + } diff --git a/devenv/dev-dashboards/transforms/rows-to-fields.json b/devenv/dev-dashboards/transforms/rows-to-fields.json index 4e27d9b94ec..fd3665a8be5 100644 --- a/devenv/dev-dashboards/transforms/rows-to-fields.json +++ b/devenv/dev-dashboards/transforms/rows-to-fields.json @@ -19,7 +19,6 @@ ] }, "editable": true, - "gnetId": null, "graphTooltip": 0, "links": [], "panels": [ @@ -39,8 +38,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -87,8 +85,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -146,7 +143,6 @@ "type": "table" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -157,8 +153,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -209,7 +204,6 @@ "type": "stat" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -221,8 +215,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -286,8 +279,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -334,8 +326,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -393,7 +384,6 @@ "type": "table" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -404,8 +394,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -454,7 +443,6 @@ "type": "bargauge" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -466,8 +454,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" } ] } @@ -530,7 +517,6 @@ "type": "gauge" }, { - "datasource": null, "fieldConfig": { "defaults": { "color": { @@ -541,8 +527,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -612,4 +597,4 @@ "title": "Transforms - Rows to fields", "uid": "PMtIInink", "version": 1 - } \ No newline at end of file + } diff --git a/docs/sources/basics/exemplars/_index.md b/docs/sources/basics/exemplars/_index.md index fb069e0f2fb..de4f063aebe 100644 --- a/docs/sources/basics/exemplars/_index.md +++ b/docs/sources/basics/exemplars/_index.md @@ -9,7 +9,7 @@ weight = 400 An exemplar is a specific trace representative of a repeated pattern of data in a given time interval. It helps you identify higher cardinality metadata from specific events within time series data. -Suppose your company website is experiencing a surge in traffic volumes. While more than eighty percent of the users are able to access the website in under two seconds, some users are experiencing a higher than normal response time resulting in bad user experience +Suppose your company website is experiencing a surge in traffic volumes. While more than eighty percent of the users are able to access the website in under two seconds, some users are experiencing a higher than normal response time resulting in bad user experience. To identify the factors that are contributing to the latency, you must compare a trace for a fast response against a trace for a slow response. Given the vast amount of data in a typical production environment, it will be extremely laborious and time-consuming effort. diff --git a/docs/sources/datasources/alertmanager.md b/docs/sources/datasources/alertmanager.md index ccfbc2f974d..4c181b91057 100644 --- a/docs/sources/datasources/alertmanager.md +++ b/docs/sources/datasources/alertmanager.md @@ -3,16 +3,14 @@ title = "Alertmanager" description = "Guide for using Alertmanager in Grafana" keywords = ["grafana", "prometheus", "guide"] aliases = ["/docs/grafana/latest/features/datasources/alertmanager"] -weight = 1300 +weight = 150 +++ # Alertmanager data source Grafana includes built-in support for Prometheus Alertmanager. It is presently in alpha and not accessible unless [alpha plugins are enabled in Grafana settings](https://grafana.com/docs/grafana/latest/administration/configuration/#enable_alpha). Once you add it as a data source, you can use the [Grafana alerting UI](https://grafana.com/docs/grafana/latest/alerting/) to manage silences, contact points as well as notification policies. A drop down option in these pages allows you to switch between Grafana and any configured Alertmanager data sources . -> **Note:** New in Grafana 8.0. - -> **Note:** Currently only the [Cortex implementation of Prometheus alertmanager](https://cortexmetrics.io/docs/proposals/scalable-alertmanager/) is supported. +> **Note:** Currently, the [Cortex implementation of Prometheus Alertmanager](https://cortexmetrics.io/docs/proposals/scalable-alertmanager/) is required to edit rules. ## Provision the Alertmanager data source diff --git a/docs/sources/datasources/cloudwatch.md b/docs/sources/datasources/cloudwatch.md index 28dcb244913..5283220d342 100644 --- a/docs/sources/datasources/cloudwatch.md +++ b/docs/sources/datasources/cloudwatch.md @@ -41,7 +41,7 @@ There are three different authentication methods available. `AWS SDK Default` pe ### IAM roles -Currently all access to CloudWatch is done server side by the Grafana backend using the official AWS SDK. Providing you have chosen the _AWS SDK Default_ authentication method, and your Grafana server is running on AWS, you can use IAM Roles to handle authentication automically. +Currently all access to CloudWatch is done server side by the Grafana backend using the official AWS SDK. Providing you have chosen the _AWS SDK Default_ authentication method, and your Grafana server is running on AWS, you can use IAM Roles to handle authentication automatically. See the AWS documentation on [IAM Roles](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) diff --git a/docs/sources/datasources/elasticsearch.md b/docs/sources/datasources/elasticsearch.md index 1c5eeb1d31e..b7aad264c7a 100644 --- a/docs/sources/datasources/elasticsearch.md +++ b/docs/sources/datasources/elasticsearch.md @@ -3,7 +3,7 @@ title = "Elasticsearch" description = "Guide for using Elasticsearch in Grafana" keywords = ["grafana", "elasticsearch", "guide"] aliases = ["/docs/grafana/latest/features/datasources/elasticsearch"] -weight = 400 +weight = 325 +++ # Using Elasticsearch in Grafana diff --git a/docs/sources/datasources/google-cloud-monitoring/_index.md b/docs/sources/datasources/google-cloud-monitoring/_index.md index e4764534b3f..c93ce340c77 100644 --- a/docs/sources/datasources/google-cloud-monitoring/_index.md +++ b/docs/sources/datasources/google-cloud-monitoring/_index.md @@ -3,7 +3,7 @@ title = "Google Cloud Monitoring" description = "Guide for using Google Cloud Monitoring in Grafana" keywords = ["grafana", "stackdriver", "google", "guide", "cloud", "monitoring"] aliases = ["/docs/grafana/latest/features/datasources/stackdriver", "/docs/grafana/next/datasources/cloudmonitoring/", "/docs/grafana/next/features/datasources/cloudmonitoring/"] -weight = 200 +weight = 350 +++ # Using Google Cloud Monitoring in Grafana diff --git a/docs/sources/datasources/influxdb/provision-influxdb.md b/docs/sources/datasources/influxdb/provision-influxdb.md index 1498906ce1a..f8be6fb0582 100644 --- a/docs/sources/datasources/influxdb/provision-influxdb.md +++ b/docs/sources/datasources/influxdb/provision-influxdb.md @@ -21,10 +21,11 @@ datasources: access: proxy database: site user: grafana - password: grafana url: http://localhost:8086 jsonData: httpMode: GET + secureJsonData: + password: grafana ``` ## InfluxDB 2.x for Flux example diff --git a/docs/sources/developers/plugins/add-authentication-for-data-source-plugins.md b/docs/sources/developers/plugins/add-authentication-for-data-source-plugins.md index d0c5c2c4a70..bb0b333e998 100644 --- a/docs/sources/developers/plugins/add-authentication-for-data-source-plugins.md +++ b/docs/sources/developers/plugins/add-authentication-for-data-source-plugins.md @@ -285,9 +285,9 @@ func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataReque If your data source uses the same OAuth provider as Grafana itself, for example using [Generic OAuth Authentication]({{< relref "../../auth/generic-oauth.md" >}}), your data source plugin can reuse the access token for the logged-in Grafana user. -To allow Grafana to pass the access token to the plugin, the user needs to enable **Forward OAuth Identity** on the data source configuration page. This tells Grafana to pass the token to the plugin in a Authorization header. Note that your plugin needs to use the [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) component in the configuration editor to expose the setting for your data source plugin. +To allow Grafana to pass the access token to the plugin, update the data source configuration and set the` jsonData.oauthPassThru` property to `true`. The [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) provides a toggle, the **Forward OAuth Identity** option, for this. You can also build an appropriate toggle to set `jsonData.oauthPassThru` in your data source configuration page UI. -The Authorization header is available on the `DataQuery` object on the query data request in your backend data source. +When configured, Grafana will pass the user's token to the plugin in an Authorization header, available on the `QueryDataRequest` object on the `QueryData` request in your backend data source. ```go func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { diff --git a/docs/sources/enterprise/access-control/permissions.md b/docs/sources/enterprise/access-control/permissions.md index 6b0996b5474..c292502125f 100644 --- a/docs/sources/enterprise/access-control/permissions.md +++ b/docs/sources/enterprise/access-control/permissions.md @@ -39,7 +39,7 @@ The following list contains fine-grained access control actions. | `reports:send` | `reports:*` | Send a report email. | | `reports.settings:write` | n/a | Update report settings. | | `reports.settings:read` | n/a | Read report settings. | -| `provisioning:reload` | `service:accesscontrol` | Reload provisioning files. | +| `provisioning:reload` | `services:accesscontrol` | Reload provisioning files. | | `users:read` | `global:users:*` | Read or search user profiles. | | `users:write` | `global:users:*` | Update a user’s profile. | | `users.teams:read` | `global:users:*` | Read a user’s teams. | @@ -62,7 +62,7 @@ The following list contains fine-grained access control actions. | `ldap.user:sync` | n/a | Sync a user via LDAP. | | `ldap.status:read` | n/a | Verify the LDAP servers’ availability. | | `ldap.config:reload` | n/a | Reload the LDAP configuration. | -| `status:accesscontrol` | `service:accesscontrol` | Get access-control enabled status. | +| `status:accesscontrol` | `services:accesscontrol` | Get access-control enabled status. | | `settings:read` | `settings:**`
`settings:auth.saml:*`
`settings:auth.saml:enabled` (property level) | Read settings | | `settings:write` | `settings:**`
`settings:auth.saml:*`
`settings:auth.saml:enabled` (property level) | Update settings | | `server.stats:read` | n/a | Read server stats | @@ -72,12 +72,12 @@ The following list contains fine-grained access control actions. The following list contains fine-grained access control scopes. -| Scopes | Descriptions | -| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `roles:*` | Restrict an action to a set of roles. For example, `roles:*` matches any role, `roles:randomuid` matches only the role with UID `randomuid` and `roles:custom:reports:{editor,viewer}` matches both `custom:reports:editor` and `custom:reports:viewer` roles. | -| `permissions:delegate` | The scope is only applicable for roles associated with the Access Control itself and indicates that you can delegate your permissions only, or a subset of it, by creating a new role or making an assignment. | -| `reports:*` | Restrict an action to a set of reports. For example, `reports:*` matches any report and `reports:1` matches the report with id `1`. | -| `service:accesscontrol` | Restrict an action to target only the fine-grained access control service. For example, you can use this in conjunction with the `provisioning:reload` or the `status:accesscontrol` actions. | -| `global:users:*` | Restrict an action to a set of global users. | -| `users:*` | Restrict an action to a set of users from an organization. | -| `settings:**` | Restrict an action to a subset of settings. For example, `settings:**` matches all settings, `settings:auth.saml:*` matches all SAML settings, and `settings:auth.saml:enabled` matches the enable property on the SAML settings. | +| Scopes | Descriptions | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `roles:*` | Restrict an action to a set of roles. For example, `roles:*` matches any role, `roles:randomuid` matches only the role with UID `randomuid` and `roles:custom:reports:{editor,viewer}` matches both `custom:reports:editor` and `custom:reports:viewer` roles. | +| `permissions:delegate` | The scope is only applicable for roles associated with the Access Control itself and indicates that you can delegate your permissions only, or a subset of it, by creating a new role or making an assignment. | +| `reports:*` | Restrict an action to a set of reports. For example, `reports:*` matches any report and `reports:1` matches the report with id `1`. | +| `services:accesscontrol` | Restrict an action to target only the fine-grained access control service. For example, you can use this in conjunction with the `provisioning:reload` or the `status:accesscontrol` actions. | +| `global:users:*` | Restrict an action to a set of global users. | +| `users:*` | Restrict an action to a set of users from an organization. | +| `settings:**` | Restrict an action to a subset of settings. For example, `settings:**` matches all settings, `settings:auth.saml:*` matches all SAML settings, and `settings:auth.saml:enabled` matches the enable property on the SAML settings. | diff --git a/docs/sources/http_api/access_control.md b/docs/sources/http_api/access_control.md index cbb021dde4b..3937fb72294 100644 --- a/docs/sources/http_api/access_control.md +++ b/docs/sources/http_api/access_control.md @@ -26,10 +26,11 @@ Returns an indicator to check if fine-grained access control is enabled or not. | -------------------- | ---------------------- | | status:accesscontrol | services:accesscontrol | + #### Example request ```http -GET /api/access-control/check +GET /api/access-control/status Accept: application/json Content-Type: application/json ``` @@ -61,6 +62,7 @@ Content-Type: application/json; charset=UTF-8 `GET /api/access-control/roles` Gets all existing roles. The response contains all global and organization local roles, for the organization which user is signed in. + Refer to the [Role scopes]({{< relref "../enterprise/access-control/roles.md#built-in-role-assignments" >}}) for more information. #### Required permissions @@ -254,6 +256,7 @@ Content-Type: application/json; charset=UTF-8 #### Status codes + | Code | Description | | ---- | ---------------------------------------------------------------------------------- | | 200 | Role is updated. | @@ -276,6 +279,7 @@ For example, if a user does not have required permissions for creating users, th | ----------- | -------------------- | | roles:write | permissions:delegate | + #### Example request ```http @@ -284,16 +288,17 @@ Accept: application/json Content-Type: application/json { - "version": 2, - "name": "custom:delete:create:roles", - "description": "My custom role which gives users permissions to delete and create roles", + "version": 3, + "name": "custom:delete:write:roles", + "description": "My custom role which gives users permissions to delete and write roles", + "global": true, "permissions": [ { "action": "roles:delete", "scope": "permissions:delegate" }, - { - "action": "roles:create", + { + "action": "roles:write", "scope": "permissions:delegate" } ] @@ -323,25 +328,27 @@ HTTP/1.1 200 OK Content-Type: application/json; charset=UTF-8 { - "version": 3, - "name": "custom:delete:create:roles", - "description": "My custom role which gives users permissions to delete and create roles", - "permissions": [ + "version":3, + "uid":"jZrmlLCGka", + "name":"custom:delete:write:roles", + "description":"My custom role which gives users permissions to delete and write roles", + "permissions":[ { - "action": "roles:delete", - "scope": "permissions:delegate", - "updated": "2021-05-13T23:19:46.546146+02:00", - "created": "2021-05-13T23:19:46.546146+02:00" + "action":"roles:delete", + "scope":"permissions:delegate", + "updated":"2021-08-06T18:27:40+02:00", + "created":"2021-08-06T18:27:40+02:00" }, - { - "action": "roles:create", - "scope": "permissions:delegate", - "updated": "2021-05-13T23:19:46.546146+02:00", - "created": "2021-05-13T23:19:46.546146+02:00" + { + "action":"roles:write", + "scope":"permissions:delegate", + "updated":"2021-08-06T18:27:41+02:00", + "created":"2021-08-06T18:27:41+02:00" } ], - "updated": "2021-05-13T23:19:46.540987+02:00", - "created": "2021-05-13T23:19:46.540986+02:00" + "updated":"2021-08-06T18:27:41+02:00", + "created":"2021-08-06T18:27:40+02:00", + "global":true } ``` @@ -370,10 +377,11 @@ For example, if a user does not have required permissions for creating users, th | ------------ | -------------------- | | roles:delete | permissions:delegate | + #### Example request ```http -DELETE /api/access-control/roles/jZrmlLCGka?force=true +DELETE /api/access-control/roles/jZrmlLCGka?force=true&global=true Accept: application/json ``` diff --git a/docs/sources/http_api/admin.md b/docs/sources/http_api/admin.md index 8a2fd007893..fb84bc295ff 100644 --- a/docs/sources/http_api/admin.md +++ b/docs/sources/http_api/admin.md @@ -612,9 +612,9 @@ Only works with Basic Authentication (username and password). See [introduction] See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation. -| Action | Scope | Provision entity | -| ------------------- | --------------------- | ---------------- | -| provisioning:reload | service:accesscontrol | accesscontrol | +| Action | Scope | Provision entity | +| ------------------- | ---------------------- | ---------------- | +| provisioning:reload | services:accesscontrol | accesscontrol | **Example Request**: diff --git a/docs/sources/release-notes/_index.md b/docs/sources/release-notes/_index.md index 43035fed2ad..8f713d5d1b0 100644 --- a/docs/sources/release-notes/_index.md +++ b/docs/sources/release-notes/_index.md @@ -8,6 +8,7 @@ weight = 10000 Here you can find detailed release notes that list everything that is included in every release as well as notices about deprecations, breaking changes as well as changes that relate to plugin development. +- [Release notes for 8.1.1]({{< relref "release-notes-8-1-1" >}}) - [Release notes for 8.1.0]({{< relref "release-notes-8-1-0" >}}) - [Release notes for 8.1.0-beta3]({{< relref "release-notes-8-1-0-beta3" >}}) - [Release notes for 8.1.0-beta2]({{< relref "release-notes-8-1-0-beta2" >}}) diff --git a/docs/sources/release-notes/release-notes-8-1-1.md b/docs/sources/release-notes/release-notes-8-1-1.md new file mode 100644 index 00000000000..b5e51b3cd23 --- /dev/null +++ b/docs/sources/release-notes/release-notes-8-1-1.md @@ -0,0 +1,14 @@ ++++ +title = "Release notes for Grafana 8.1.1" +[_build] +list = false ++++ + + + +# Release notes for Grafana 8.1.1 + +### Bug fixes + +* **CloudWatch Logs:** Fix crash when no region is selected. [#37639](https://github.com/grafana/grafana/pull/37639), [@aocenas](https://github.com/aocenas) + diff --git a/docs/sources/sharing/share-panel.md b/docs/sources/sharing/share-panel.md index 8d016f2b1f1..00e224b0f5f 100644 --- a/docs/sources/sharing/share-panel.md +++ b/docs/sources/sharing/share-panel.md @@ -62,7 +62,7 @@ If you created a snapshot by mistake, click **delete snapshot** to remove the sn You can embed a panel using an iframe on another web site. A viewer must be signed into Grafana to view the graph. -**> Note:** As of Grafana 8.0, anonymous access permission is no available for Grafana Cloud. +**> Note:** As of Grafana 8.0, anonymous access permission is no longer available for Grafana Cloud. ![Panel share embed](/static/img/docs/sharing/share-panel-embedded-link-8-0.png) diff --git a/latest.json b/latest.json index a8345d75e63..b03a91f50c7 100644 --- a/latest.json +++ b/latest.json @@ -1,4 +1,4 @@ { - "stable": "8.1.0", - "testing": "8.1.0" + "stable": "8.1.1", + "testing": "8.1.1" } diff --git a/packages/grafana-data/src/field/displayProcessor.ts b/packages/grafana-data/src/field/displayProcessor.ts index b59f5743f38..f189bbdd2fe 100644 --- a/packages/grafana-data/src/field/displayProcessor.ts +++ b/packages/grafana-data/src/field/displayProcessor.ts @@ -6,7 +6,7 @@ import { Field, FieldType } from '../types/dataFrame'; import { DisplayProcessor, DisplayValue } from '../types/displayValue'; import { getValueFormat, isBooleanUnit } from '../valueFormats/valueFormats'; import { getValueMappingResult } from '../utils/valueMappings'; -import { dateTime } from '../datetime'; +import { dateTime, dateTimeParse } from '../datetime'; import { KeyValue, TimeZone } from '../types'; import { getScaleCalculator } from './scale'; import { GrafanaTheme2 } from '../themes/types'; @@ -45,10 +45,23 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP let unit = config.unit; let hasDateUnit = unit && (timeFormats[unit] || unit.startsWith('time:')); + let showMs = false; if (field.type === FieldType.time && !hasDateUnit) { unit = `dateTimeAsSystem`; hasDateUnit = true; + if (field.values && field.values.length > 1) { + let start = field.values.get(0); + let end = field.values.get(field.values.length - 1); + if (typeof start === 'string') { + start = dateTimeParse(start).unix(); + end = dateTimeParse(end).unix(); + } else { + start /= 1e3; + end /= 1e3; + } + showMs = end - start < 60; //show ms when minute or less + } } else if (field.type === FieldType.boolean) { if (!isBooleanUnit(unit)) { unit = 'bool'; @@ -93,7 +106,7 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP if (!isNaN(numeric)) { if (shouldFormat && !isBoolean(value)) { - const v = formatFunc(numeric, config.decimals, null, options.timeZone); + const v = formatFunc(numeric, config.decimals, null, options.timeZone, showMs); text = v.text; suffix = v.suffix; prefix = v.prefix; diff --git a/packages/grafana-data/src/field/getFieldDisplayValuesProxy.test.tsx b/packages/grafana-data/src/field/getFieldDisplayValuesProxy.test.tsx index 010fdafd3ce..685824158c5 100644 --- a/packages/grafana-data/src/field/getFieldDisplayValuesProxy.test.tsx +++ b/packages/grafana-data/src/field/getFieldDisplayValuesProxy.test.tsx @@ -4,28 +4,25 @@ import { toDataFrame } from '../dataframe'; import { createTheme } from '../themes'; describe('getFieldDisplayValuesProxy', () => { - const data = applyFieldOverrides({ - data: [ - toDataFrame({ - fields: [ - { name: 'Time', values: [1, 2, 3] }, - { - name: 'power', - values: [100, 200, 300], - labels: { - name: 'POWAH!', - }, - config: { - displayName: 'The Power', - }, - }, - { - name: 'Last', - values: ['a', 'b', 'c'], - }, - ], - }), - ], + const shortTimeField = [{ name: 'Time', values: [1, 2, 3] }]; + + const longTimeField = [{ name: 'Time', values: [1000, 2000, 61000] }]; + + const dataFields = [ + { + name: 'power', + values: [100, 200, 300], + labels: { + name: 'POWAH!', + }, + config: { + displayName: 'The Power', + }, + }, + { name: 'Last', values: ['a', 'b', 'c'] }, + ]; + + const overrides = { fieldConfig: { defaults: {}, overrides: [], @@ -33,29 +30,45 @@ describe('getFieldDisplayValuesProxy', () => { replaceVariables: (val: string) => val, timeZone: 'utc', theme: createTheme(), + }; + + const dataShortTimeRange = applyFieldOverrides({ + ...{ data: [toDataFrame({ fields: [...shortTimeField, ...dataFields] })] }, + ...overrides, + })[0]; + + const dataLongTimeRange = applyFieldOverrides({ + ...{ data: [toDataFrame({ fields: [...longTimeField, ...dataFields] })] }, + ...overrides, })[0]; it('should define all display functions', () => { // Field display should be set - for (const field of data.fields) { + for (const field of dataShortTimeRange.fields) { expect(field.display).toBeDefined(); } }); - it('should format the time values in UTC', () => { + it('should format the time values in UTC with ms when time range is minute or less', () => { // Test Proxies in general - const p = getFieldDisplayValuesProxy({ frame: data, rowIndex: 0 }); + const p = getFieldDisplayValuesProxy({ frame: dataShortTimeRange, rowIndex: 0 }); const time = p.Time; expect(time.numeric).toEqual(1); - expect(time.text).toEqual('1970-01-01 00:00:00'); + expect(time.text).toEqual('1970-01-01 00:00:00.001'); // Should get to the same values by name or index const time2 = p[0]; expect(time2.toString()).toEqual(time.toString()); }); + it('should format the time values in UTC without ms when time range is over a minute', () => { + const p = getFieldDisplayValuesProxy({ frame: dataLongTimeRange, rowIndex: 0 }); + const time = p.Time; + expect(time.text).toEqual('1970-01-01 00:00:01'); + }); + it('Lookup by name, index, or displayName', () => { - const p = getFieldDisplayValuesProxy({ frame: data, rowIndex: 2 }); + const p = getFieldDisplayValuesProxy({ frame: dataShortTimeRange, rowIndex: 2 }); expect(p.power.numeric).toEqual(300); expect(p['power'].numeric).toEqual(300); expect(p['POWAH!'].numeric).toEqual(300); @@ -64,7 +77,7 @@ describe('getFieldDisplayValuesProxy', () => { }); it('should return undefined when missing', () => { - const p = getFieldDisplayValuesProxy({ frame: data, rowIndex: 0 }); + const p = getFieldDisplayValuesProxy({ frame: dataShortTimeRange, rowIndex: 0 }); expect(p.xyz).toBeUndefined(); expect(p[100]).toBeUndefined(); }); diff --git a/packages/grafana-data/src/types/annotations.ts b/packages/grafana-data/src/types/annotations.ts index 7cfa10225a3..559504ee7b9 100644 --- a/packages/grafana-data/src/types/annotations.ts +++ b/packages/grafana-data/src/types/annotations.ts @@ -1,14 +1,16 @@ import { Observable } from 'rxjs'; import { ComponentType } from 'react'; -import { DataQuery, QueryEditorProps } from './datasource'; +import { QueryEditorProps } from './datasource'; import { DataFrame } from './dataFrame'; +import { DataQuery, DatasourceRef } from './query'; /** * This JSON object is stored in the dashboard json model. */ export interface AnnotationQuery { - datasource?: string | null; + datasource?: DatasourceRef | string | null; + enable: boolean; name: string; iconColor: string; diff --git a/packages/grafana-data/src/types/dashboard.ts b/packages/grafana-data/src/types/dashboard.ts index 85dbe95adab..df1af6165a7 100644 --- a/packages/grafana-data/src/types/dashboard.ts +++ b/packages/grafana-data/src/types/dashboard.ts @@ -1,5 +1,40 @@ +import { FieldConfigSource } from './fieldOverrides'; +import { DataQuery, DatasourceRef } from './query'; + export enum DashboardCursorSync { Off, Crosshair, Tooltip, } + +/** + * @public + */ +export interface PanelModel { + /** ID of the panel within the current dashboard */ + id: number; + + /** Panel title */ + title?: string; + + /** Description */ + description?: string; + + /** Panel options */ + options: TOptions; + + /** Field options configuration */ + fieldConfig: FieldConfigSource; + + /** Version of the panel plugin */ + pluginVersion?: string; + + /** The datasource used in all targets */ + datasource?: DatasourceRef | null; + + /** The queries in a panel */ + targets?: DataQuery[]; + + /** alerting v1 object */ + alert?: any; +} diff --git a/packages/grafana-data/src/types/data.ts b/packages/grafana-data/src/types/data.ts index 344c119b4fb..1722c44369e 100644 --- a/packages/grafana-data/src/types/data.ts +++ b/packages/grafana-data/src/types/data.ts @@ -2,6 +2,7 @@ import { FieldConfig } from './dataFrame'; import { DataTransformerConfig } from './transformations'; import { ApplyFieldOverrideOptions } from './fieldOverrides'; import { PanelPluginDataSupport } from '.'; +import { DataTopic } from './query'; export type KeyValue = Record; @@ -17,10 +18,6 @@ export enum LoadingState { Error = 'Error', } -export enum DataTopic { - Annotations = 'annotations', -} - // Should be kept in sync with grafana-plugin-sdk-go/data/frame_meta.go export type PreferredVisualisationType = 'graph' | 'table' | 'logs' | 'trace' | 'nodeGraph'; diff --git a/packages/grafana-data/src/types/dataLink.ts b/packages/grafana-data/src/types/dataLink.ts index e846f411bfd..2d69aedfc7a 100644 --- a/packages/grafana-data/src/types/dataLink.ts +++ b/packages/grafana-data/src/types/dataLink.ts @@ -1,4 +1,4 @@ -import { DataQuery } from './datasource'; +import { DataQuery } from './query'; import { InterpolateFunction } from './panel'; /** diff --git a/packages/grafana-data/src/types/datasource.ts b/packages/grafana-data/src/types/datasource.ts index a370e1a5913..9f3cef1700e 100644 --- a/packages/grafana-data/src/types/datasource.ts +++ b/packages/grafana-data/src/types/datasource.ts @@ -4,7 +4,7 @@ import { GrafanaPlugin, PluginMeta } from './plugin'; import { PanelData } from './panel'; import { LogRowModel } from './logs'; import { AnnotationEvent, AnnotationQuery, AnnotationSupport } from './annotations'; -import { DataTopic, KeyValue, LoadingState, TableData, TimeSeries } from './data'; +import { KeyValue, LoadingState, TableData, TimeSeries } from './data'; import { DataFrame, DataFrameDTO } from './dataFrame'; import { RawTimeRange, TimeRange } from './time'; import { ScopedVars } from './ScopedVars'; @@ -12,6 +12,7 @@ import { CoreApp } from './app'; import { LiveChannelSupport } from './live'; import { CustomVariableSupport, DataSourceVariableSupport, StandardVariableSupport } from './variables'; import { makeClassES5Compatible } from '../utils/makeClassES5Compatible'; +import { DataQuery } from './query'; export interface DataSourcePluginOptionsEditorProps { options: DataSourceSettings; @@ -205,6 +206,9 @@ abstract class DataSourceApi< this.type = instanceSettings.type; this.meta = {} as DataSourcePluginMeta; this.uid = instanceSettings.uid; + if (!this.uid) { + this.uid = this.name; // Internal datasources do not have a UID (-- Grafana --) + } } /** @@ -430,44 +434,6 @@ export interface DataQueryResponse { state?: LoadingState; } -/** - * These are the common properties available to all queries in all datasources - * Specific implementations will extend this interface adding the required properties - * for the given context - */ -export interface DataQuery { - /** - * A - Z - */ - refId: string; - - /** - * true if query is disabled (ie should not be returned to the dashboard) - */ - hide?: boolean; - - /** - * Unique, guid like, string used in explore mode - */ - key?: string; - - /** - * Specify the query flavor - */ - queryType?: string; - - /** - * The data topic results should be attached to - */ - dataTopic?: DataTopic; - - /** - * For mixed data sources the selected datasource is on the query level. - * For non mixed scenarios this is undefined. - */ - datasource?: string | null; -} - export enum DataQueryErrorType { Cancelled = 'cancelled', Timeout = 'timeout', diff --git a/packages/grafana-data/src/types/index.ts b/packages/grafana-data/src/types/index.ts index afc91463a8e..5cb9ed3df37 100644 --- a/packages/grafana-data/src/types/index.ts +++ b/packages/grafana-data/src/types/index.ts @@ -2,6 +2,7 @@ export * from './data'; export * from './dataFrame'; export * from './dataLink'; export * from './dashboard'; +export * from './query'; export * from './annotations'; export * from './logs'; export * from './navModel'; diff --git a/packages/grafana-data/src/types/logs.ts b/packages/grafana-data/src/types/logs.ts index 2d64eed4767..aec5de66df9 100644 --- a/packages/grafana-data/src/types/logs.ts +++ b/packages/grafana-data/src/types/logs.ts @@ -1,7 +1,7 @@ import { Labels } from './data'; import { DataFrame } from './dataFrame'; +import { DataQuery } from './query'; import { AbsoluteTimeRange } from './time'; -import { DataQuery } from './datasource'; /** * Mapping of log level abbreviation to canonical log level. diff --git a/packages/grafana-data/src/types/panel.ts b/packages/grafana-data/src/types/panel.ts index 8da91ebe6a2..e6fd6e1f729 100644 --- a/packages/grafana-data/src/types/panel.ts +++ b/packages/grafana-data/src/types/panel.ts @@ -11,6 +11,7 @@ import { StandardEditorProps } from '../field'; import { OptionsEditorItem } from './OptionsUIRegistryBuilder'; import { OptionEditorConfig } from './options'; import { AlertStateInfo } from './alerts'; +import { PanelModel } from './dashboard'; export type InterpolateFunction = (value: string, scopedVars?: ScopedVars, format?: string | Function) => string; @@ -121,19 +122,6 @@ export interface PanelEditorProps { data?: PanelData; } -export interface PanelModel { - /** ID of the panel within the current dashboard */ - id: number; - alert?: any; - /** Panel options */ - options: TOptions; - /** Field options configuration */ - fieldConfig: FieldConfigSource; - /** Version of the panel plugin */ - pluginVersion?: string; - scopedVars?: ScopedVars; -} - /** * Called when a panel is first loaded with current panel model */ diff --git a/packages/grafana-data/src/types/query.ts b/packages/grafana-data/src/types/query.ts new file mode 100644 index 00000000000..84025ce1bb0 --- /dev/null +++ b/packages/grafana-data/src/types/query.ts @@ -0,0 +1,50 @@ +/** + * Attached to query results (not persisted) + * + * @public + */ +export enum DataTopic { + Annotations = 'annotations', +} + +/** + * In 8.2, this will become an interface + * + * @public + */ +export type DatasourceRef = string; + +/** + * These are the common properties available to all queries in all datasources + * Specific implementations will *extend* this interface adding the required properties + * for the given context + * + * @public + */ +export interface DataQuery { + /** + * A - Z + */ + refId: string; + + /** + * true if query is disabled (ie should not be returned to the dashboard) + */ + hide?: boolean; + + /** + * Unique, guid like, string used in explore mode + */ + key?: string; + + /** + * Specify the query flavor + */ + queryType?: string; + + /** + * For mixed data sources the selected datasource is on the query level. + * For non mixed scenarios this is undefined. + */ + datasource?: DatasourceRef; +} diff --git a/packages/grafana-data/src/types/queryRunner.ts b/packages/grafana-data/src/types/queryRunner.ts index b2d0496e870..ff526eb8dbd 100644 --- a/packages/grafana-data/src/types/queryRunner.ts +++ b/packages/grafana-data/src/types/queryRunner.ts @@ -1,5 +1,6 @@ import { Observable } from 'rxjs'; -import { DataQuery, DataSourceApi } from './datasource'; +import { DataQuery, DatasourceRef } from './query'; +import { DataSourceApi } from './datasource'; import { PanelData } from './panel'; import { ScopedVars } from './ScopedVars'; import { TimeRange, TimeZone } from './time'; @@ -10,7 +11,7 @@ import { TimeRange, TimeZone } from './time'; * @internal */ export interface QueryRunnerOptions { - datasource: string | DataSourceApi | null; + datasource: DatasourceRef | DataSourceApi | null; queries: DataQuery[]; panelId?: number; dashboardId?: number; diff --git a/packages/grafana-data/src/types/variables.ts b/packages/grafana-data/src/types/variables.ts index 5c0aac20832..1c90dcd7b3e 100644 --- a/packages/grafana-data/src/types/variables.ts +++ b/packages/grafana-data/src/types/variables.ts @@ -1,8 +1,8 @@ import { ComponentType } from 'react'; import { Observable } from 'rxjs'; +import { DataQuery } from './query'; import { - DataQuery, DataQueryRequest, DataQueryResponse, DataSourceApi, diff --git a/packages/grafana-data/src/valueFormats/dateTimeFormatters.ts b/packages/grafana-data/src/valueFormats/dateTimeFormatters.ts index 93f9a815943..c56dd5fe34a 100644 --- a/packages/grafana-data/src/valueFormats/dateTimeFormatters.ts +++ b/packages/grafana-data/src/valueFormats/dateTimeFormatters.ts @@ -405,9 +405,15 @@ export function dateTimeSystemFormatter( value: number, decimals: DecimalCount, scaledDecimals: DecimalCount, - timeZone?: TimeZone + timeZone?: TimeZone, + showMs?: boolean ): FormattedValue { - return { text: dateTimeFormat(value, { format: systemDateFormats.fullDate, timeZone }) }; + return { + text: dateTimeFormat(value, { + format: showMs ? systemDateFormats.fullDateMS : systemDateFormats.fullDate, + timeZone, + }), + }; } export function dateTimeFromNow( diff --git a/packages/grafana-data/src/valueFormats/valueFormats.ts b/packages/grafana-data/src/valueFormats/valueFormats.ts index 2753426170a..a23253b0c2c 100644 --- a/packages/grafana-data/src/valueFormats/valueFormats.ts +++ b/packages/grafana-data/src/valueFormats/valueFormats.ts @@ -18,7 +18,8 @@ export type ValueFormatter = ( value: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount, - timeZone?: TimeZone + timeZone?: TimeZone, + showMs?: boolean ) => FormattedValue; export interface ValueFormat { diff --git a/packages/grafana-e2e-selectors/src/selectors/components.ts b/packages/grafana-e2e-selectors/src/selectors/components.ts index 7997356efb2..d032d9c5b74 100644 --- a/packages/grafana-e2e-selectors/src/selectors/components.ts +++ b/packages/grafana-e2e-selectors/src/selectors/components.ts @@ -213,9 +213,9 @@ export const Components = { items: 'Search items', }, DashboardLinks: { - container: 'Dashboard link container', - dropDown: 'Dashboard link dropdown', - link: 'Dashboard link', + container: 'data-testid Dashboard link container', + dropDown: 'data-testid Dashboard link dropdown', + link: 'data-testid Dashboard link', }, LoadingIndicator: { icon: 'Loading indicator', diff --git a/packages/grafana-toolkit/src/config/jest.plugin.config.ts b/packages/grafana-toolkit/src/config/jest.plugin.config.ts index 86da5b70de6..f8a34d5b819 100644 --- a/packages/grafana-toolkit/src/config/jest.plugin.config.ts +++ b/packages/grafana-toolkit/src/config/jest.plugin.config.ts @@ -50,7 +50,7 @@ export const jestConfig = (baseDir: string = process.cwd()) => { const setupFile = getSetupFile(setupFilePath); const shimsFile = getSetupFile(shimsFilePath); - const setupFiles = [setupFile, shimsFile, 'jest-canvas-mock'].filter((f) => f); + const setupFiles = [setupFile, shimsFile, `${__dirname}/matchMedia.js`, 'jest-canvas-mock'].filter((f) => f); const defaultJestConfig = { preset: 'ts-jest', verbose: false, diff --git a/packages/grafana-toolkit/src/config/matchMedia.js b/packages/grafana-toolkit/src/config/matchMedia.js new file mode 100644 index 00000000000..f4489dec143 --- /dev/null +++ b/packages/grafana-toolkit/src/config/matchMedia.js @@ -0,0 +1,14 @@ +// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom +Object.defineProperty(global, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // deprecated + removeListener: jest.fn(), // deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeOption.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeOption.tsx index a622e8d6f0c..14627ea9589 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeOption.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeOption.tsx @@ -52,7 +52,7 @@ export const TimeRangeOption = memo(({ value, onSelect, selected = false, const id = uuidv4(); return ( -
  • +
  • onSelect(value)} className={cx(styles.container, selected && styles.selected)}> = (args) => { return ; }; + +export const WithCustomFileList: Story = () => { + return
    Custom rendered item {file.file.name}
    } />; +}; diff --git a/packages/grafana-ui/src/components/FileDropzone/FileDropzone.test.tsx b/packages/grafana-ui/src/components/FileDropzone/FileDropzone.test.tsx index 09074c95a15..2d589f69ef6 100644 --- a/packages/grafana-ui/src/components/FileDropzone/FileDropzone.test.tsx +++ b/packages/grafana-ui/src/components/FileDropzone/FileDropzone.test.tsx @@ -107,6 +107,17 @@ describe('The FileDropzone component', () => { screen.getByText('Custom dropzone text'); }); + + it('should handle file list overwrite when fileListRenderer is passed', async () => { + render( null} />); + + dispatchEvt(screen.getByTestId('dropzone'), 'drop', mockData([file({})])); + + // need to await this in order to have the drop finished + await screen.findByTestId('dropzone'); + + expect(screen.queryByText('ping.json')).not.toBeInTheDocument(); + }); }); function dispatchEvt(node: HTMLElement, type: string, data: any) { diff --git a/packages/grafana-ui/src/components/FileDropzone/FileDropzone.tsx b/packages/grafana-ui/src/components/FileDropzone/FileDropzone.tsx index 215d67c1642..3c49ffbc176 100644 --- a/packages/grafana-ui/src/components/FileDropzone/FileDropzone.tsx +++ b/packages/grafana-ui/src/components/FileDropzone/FileDropzone.tsx @@ -30,6 +30,11 @@ export interface FileDropzoneProps { * Use the onLoad function to get the result from FileReader. */ onLoad?: (result: string | ArrayBuffer | null) => void; + /** + * The fileListRenderer property can be used to overwrite the list of files. To not to show + * any list return null in the function. + */ + fileListRenderer?: (file: DropzoneFile, removeFile: (file: DropzoneFile) => void) => ReactNode; } export interface DropzoneFile { @@ -41,7 +46,7 @@ export interface DropzoneFile { retryUpload?: () => void; } -export function FileDropzone({ options, children, readAs, onLoad }: FileDropzoneProps) { +export function FileDropzone({ options, children, readAs, onLoad, fileListRenderer }: FileDropzoneProps) { const [files, setFiles] = useState([]); const setFileProperty = useCallback( @@ -133,7 +138,12 @@ export function FileDropzone({ options, children, readAs, onLoad }: FileDropzone const { getRootProps, getInputProps, isDragActive } = useDropzone({ ...options, onDrop }); const theme = useTheme2(); const styles = getStyles(theme, isDragActive); - const fileList = files.map((file) => ); + const fileList = files.map((file) => { + if (fileListRenderer) { + return fileListRenderer(file, removeFile); + } + return ; + }); return (
    diff --git a/packages/grafana-ui/src/components/FileDropzone/FileListItem.test.tsx b/packages/grafana-ui/src/components/FileDropzone/FileListItem.test.tsx index 95b5caf5ae2..e1a0e75f2de 100644 --- a/packages/grafana-ui/src/components/FileDropzone/FileListItem.test.tsx +++ b/packages/grafana-ui/src/components/FileDropzone/FileListItem.test.tsx @@ -30,7 +30,7 @@ describe('The FileListItem component', () => { it('should show a progressbar when the progress prop has a value', () => { render(); - expect(screen.queryByText('Cancel')).not.toBeInTheDocument(); + expect(screen.queryByText('Cancel upload')).not.toBeInTheDocument(); expect(screen.getByText('46%')).toBeInTheDocument(); expect(screen.getByRole('progressbar')).toBeInTheDocument(); }); @@ -45,7 +45,7 @@ describe('The FileListItem component', () => { const abortUpload = jest.fn(); render(); - fireEvent.click(screen.getByRole('button', { name: 'Cancel' })); + fireEvent.click(screen.getByRole('button', { name: /cancel/i })); expect(abortUpload).toBeCalledTimes(1); }); diff --git a/packages/grafana-ui/src/components/FileDropzone/FileListItem.tsx b/packages/grafana-ui/src/components/FileDropzone/FileListItem.tsx index 27255b55731..cf039248391 100644 --- a/packages/grafana-ui/src/components/FileDropzone/FileListItem.tsx +++ b/packages/grafana-ui/src/components/FileDropzone/FileListItem.tsx @@ -24,11 +24,19 @@ export function FileListItem({ file: customFile, removeFile }: FileListItemProps <> {error.message} {retryUpload && ( - + )} {removeFile && ( removeFile(customFile)} tooltip={REMOVE_FILE} @@ -46,7 +54,7 @@ export function FileListItem({ file: customFile, removeFile }: FileListItemProps {Math.round((progress / file.size) * 100)}% {abortUpload && ( )} @@ -59,6 +67,7 @@ export function FileListItem({ file: customFile, removeFile }: FileListItemProps onClick={() => removeFile(customFile)} tooltip={REMOVE_FILE} aria-label={REMOVE_FILE} + type="button" tooltipPlacement="top" /> ) @@ -70,7 +79,7 @@ export function FileListItem({ file: customFile, removeFile }: FileListItemProps return (
    - + {trimFileName(file.name)} {formattedValueToString(valueFormat)} diff --git a/packages/grafana-ui/src/components/Graph/utils.test.ts b/packages/grafana-ui/src/components/Graph/utils.test.ts index 9f85d14237b..f1209a088d5 100644 --- a/packages/grafana-ui/src/components/Graph/utils.test.ts +++ b/packages/grafana-ui/src/components/Graph/utils.test.ts @@ -45,11 +45,11 @@ function passThroughFieldOverrides(frame: DataFrame) { const aSeries = passThroughFieldOverrides( toDataFrame({ fields: [ - { name: 'time', type: FieldType.time, values: [10000, 20000, 30000] }, + { name: 'time', type: FieldType.time, values: [10000, 20000, 30000, 80000] }, { name: 'value', type: FieldType.number, - values: [10, 20, 10], + values: [10, 20, 10, 25], config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'red' } }, }, ], @@ -59,11 +59,11 @@ const aSeries = passThroughFieldOverrides( const bSeries = passThroughFieldOverrides( toDataFrame({ fields: [ - { name: 'time', type: FieldType.time, values: [10000, 20000, 30000] }, + { name: 'time', type: FieldType.time, values: [10000, 20000, 30000, 80000] }, { name: 'value', type: FieldType.number, - values: [30, 60, 30], + values: [30, 60, 30, 40], config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'blue' } }, }, ], @@ -74,11 +74,11 @@ const bSeries = passThroughFieldOverrides( const cSeries = passThroughFieldOverrides( toDataFrame({ fields: [ - { name: 'time', type: FieldType.time, values: [10000, 30000] }, + { name: 'time', type: FieldType.time, values: [10000, 30000, 80000] }, { name: 'value', type: FieldType.number, - values: [30, 30], + values: [30, 30, 30], config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'yellow' } }, }, ], diff --git a/packages/grafana-ui/src/components/Logs/LogRowContext.tsx b/packages/grafana-ui/src/components/Logs/LogRowContext.tsx index 0f1981f4cfa..f5f2a38667d 100644 --- a/packages/grafana-ui/src/components/Logs/LogRowContext.tsx +++ b/packages/grafana-ui/src/components/Logs/LogRowContext.tsx @@ -4,7 +4,7 @@ import { css, cx } from '@emotion/css'; import { Alert } from '../Alert/Alert'; import { LogRowContextRows, LogRowContextQueryErrors, HasMoreContextRows } from './LogRowContextProvider'; -import { useStyles } from '../../themes/ThemeContext'; +import { useStyles, useTheme } from '../../themes/ThemeContext'; import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar'; import { List } from '../List/List'; import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper'; @@ -13,18 +13,41 @@ import { LogMessageAnsi } from './LogMessageAnsi'; interface LogRowContextProps { row: LogRowModel; context: LogRowContextRows; + wrapLogMessage: boolean; errors?: LogRowContextQueryErrors; hasMoreContextRows?: HasMoreContextRows; onOutsideClick: () => void; onLoadMoreContext: () => void; } -const getLogRowContextStyles = (theme: GrafanaTheme) => { +const getLogRowContextStyles = (theme: GrafanaTheme, wrapLogMessage?: boolean) => { + /** + * This is workaround for displaying uncropped context when we have unwrapping log messages. + * We are using margins to correctly position context. Because non-wrapped logs have always 1 line of log + * and 1 line of Show/Hide context switch. Therefore correct position can be reliably achieved by margins. + * We also adjust width to 75%. + */ + + const afterContext = wrapLogMessage + ? css` + top: -250px; + ` + : css` + margin-top: -250px; + width: 75%; + `; + + const beforeContext = wrapLogMessage + ? css` + top: 100%; + ` + : css` + margin-top: 40px; + width: 75%; + `; return { commonStyles: css` position: absolute; - width: calc(100% + 20px); - left: -13px; height: 250px; z-index: ${theme.zIndex.dropdown}; overflow: hidden; @@ -32,6 +55,7 @@ const getLogRowContextStyles = (theme: GrafanaTheme) => { box-shadow: 0 0 10px ${theme.colors.dropdownShadow}; border: 1px solid ${theme.colors.bg2}; border-radius: ${theme.border.radius.md}; + width: 100%; `, header: css` height: 30px; @@ -44,6 +68,8 @@ const getLogRowContextStyles = (theme: GrafanaTheme) => { height: 220px; padding: 10px; `, + afterContext, + beforeContext, }; }; @@ -56,7 +82,7 @@ interface LogRowContextGroupHeaderProps { } interface LogRowContextGroupProps extends LogRowContextGroupHeaderProps { rows: Array; - className: string; + className?: string; error?: string; } @@ -122,11 +148,11 @@ export const LogRowContextGroup: React.FunctionComponent +
    {/* When displaying "after" context */} {shouldScrollToBottom && !error && }
    - +
    {!error && ( = ({ onOutsideClick, onLoadMoreContext, hasMoreContextRows, + wrapLogMessage, }) => { useEffect(() => { const handleEscKeyDown = (e: KeyboardEvent): void => { @@ -173,6 +200,8 @@ export const LogRowContext: React.FunctionComponent = ({ document.removeEventListener('keydown', handleEscKeyDown, false); }; }, [onOutsideClick]); + const theme = useTheme(); + const { afterContext, beforeContext } = getLogRowContextStyles(theme, wrapLogMessage); return ( @@ -184,9 +213,7 @@ export const LogRowContext: React.FunctionComponent = ({ rows={context.after} error={errors && errors.after} row={row} - className={css` - top: -250px; - `} + className={afterContext} shouldScrollToBottom canLoadMoreRows={hasMoreContextRows ? hasMoreContextRows.after : false} onLoadMoreContext={onLoadMoreContext} @@ -200,9 +227,7 @@ export const LogRowContext: React.FunctionComponent = ({ row={row} rows={context.before} error={errors && errors.before} - className={css` - top: 100%; - `} + className={beforeContext} /> )}
    diff --git a/packages/grafana-ui/src/components/Logs/LogRowMessage.tsx b/packages/grafana-ui/src/components/Logs/LogRowMessage.tsx index c190de58ce7..96bd173f877 100644 --- a/packages/grafana-ui/src/components/Logs/LogRowMessage.tsx +++ b/packages/grafana-ui/src/components/Logs/LogRowMessage.tsx @@ -51,6 +51,10 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => { label: verticalScroll; white-space: pre; `, + contextNewline: css` + display: block; + margin-left: 0px; + `, }; }); @@ -124,12 +128,15 @@ class UnThemedLogRowMessage extends PureComponent { return ( -
    +
    {contextIsOpen && context && ( { @@ -143,7 +150,10 @@ class UnThemedLogRowMessage extends PureComponent { {renderLogMessage(hasAnsi, restructuredEntry, highlights, highlightClassName)} {showContextToggle?.(row) && ( - + {contextIsOpen ? 'Hide' : 'Show'} context )} diff --git a/packages/grafana-ui/src/components/Logs/getLogRowStyles.ts b/packages/grafana-ui/src/components/Logs/getLogRowStyles.ts index 9fd2b6d2539..0a0b1ebabb7 100644 --- a/packages/grafana-ui/src/components/Logs/getLogRowStyles.ts +++ b/packages/grafana-ui/src/components/Logs/getLogRowStyles.ts @@ -48,13 +48,13 @@ export const getLogRowStyles = stylesFactory((theme: GrafanaTheme, logLevel?: Lo font-family: ${theme.typography.fontFamily.monospace}; font-size: ${theme.typography.size.sm}; width: 100%; - overflow: hidden; `, context: css` label: context; visibility: hidden; white-space: nowrap; position: relative; + margin-left: 10px; `, logsRow: css` label: logs-row; @@ -66,7 +66,6 @@ export const getLogRowStyles = stylesFactory((theme: GrafanaTheme, logLevel?: Lo .log-row-context { visibility: visible; z-index: 1; - margin-left: 10px; text-decoration: underline; &:hover { color: ${theme.palette.yellow}; diff --git a/packages/grafana-ui/src/components/uPlot/models.cue b/packages/grafana-ui/src/components/uPlot/models.cue index a7394e56206..71c80392870 100644 --- a/packages/grafana-ui/src/components/uPlot/models.cue +++ b/packages/grafana-ui/src/components/uPlot/models.cue @@ -50,9 +50,12 @@ AxisConfig: { HideSeriesConfig: { tooltip: bool legend: bool - graph: bool + viz: bool } @cuetsy(targetType="interface") +// TODO This is the same composition as what's used in the timeseries panel's +// PanelFieldConfig. If that's the only place it's used, it probably shouldn't +// be assembled here, too GraphFieldConfig: LineConfig & FillConfig & PointsConfig & AxisConfig & { drawStyle?: DrawStyle gradientMode?: GraphGradientMode diff --git a/pkg/api/avatar/avatar.go b/pkg/api/avatar/avatar.go index 2c3952684c0..7ef583e0fe1 100644 --- a/pkg/api/avatar/avatar.go +++ b/pkg/api/avatar/avatar.go @@ -118,7 +118,7 @@ func (a *CacheServer) Handler(ctx *models.ReqContext) { if err := avatar.Encode(ctx.Resp); err != nil { log.Warnf("avatar encode error: %v", err) - ctx.WriteHeader(500) + ctx.Resp.WriteHeader(500) } } diff --git a/pkg/api/common_test.go b/pkg/api/common_test.go index db083c30e26..e5a95a0525e 100644 --- a/pkg/api/common_test.go +++ b/pkg/api/common_test.go @@ -217,10 +217,7 @@ func setupScenarioContext(t *testing.T, url string) *scenarioContext { require.Truef(t, exists, "Views should be in %q", viewsPath) sc.m = macaron.New() - sc.m.Use(macaron.Renderer(macaron.RenderOptions{ - Directory: viewsPath, - Delims: macaron.Delims{Left: "[[", Right: "]]"}, - })) + sc.m.UseMiddleware(macaron.Renderer(viewsPath, "[[", "]]")) sc.m.Use(getContextHandler(t, cfg).Middleware) return sc diff --git a/pkg/api/frontendsettings_test.go b/pkg/api/frontendsettings_test.go index bd9b4dfcbea..11c858be3a8 100644 --- a/pkg/api/frontendsettings_test.go +++ b/pkg/api/frontendsettings_test.go @@ -58,11 +58,7 @@ func setupTestEnvironment(t *testing.T, cfg *setting.Cfg) (*macaron.Macaron, *HT m := macaron.New() m.Use(getContextHandler(t, cfg).Middleware) - m.Use(macaron.Renderer(macaron.RenderOptions{ - Directory: filepath.Join(setting.StaticRootPath, "views"), - IndentJSON: true, - Delims: macaron.Delims{Left: "[[", Right: "]]"}, - })) + m.UseMiddleware(macaron.Renderer(filepath.Join(setting.StaticRootPath, "views"), "[[", "]]")) m.Get("/api/frontend/settings/", hs.GetFrontendSettings) return m, hs diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 2fd0a608118..4e8be016ffa 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -335,7 +335,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() { m.Use(middleware.Logger(hs.Cfg)) if hs.Cfg.EnableGzip { - m.Use(middleware.Gziper()) + m.UseMiddleware(middleware.Gziper()) } m.Use(middleware.Recovery(hs.Cfg)) @@ -354,11 +354,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() { m.SetURLPrefix(hs.Cfg.AppSubURL) } - m.Use(macaron.Renderer(macaron.RenderOptions{ - Directory: filepath.Join(hs.Cfg.StaticRootPath, "views"), - IndentJSON: macaron.Env != macaron.PROD, - Delims: macaron.Delims{Left: "[[", Right: "]]"}, - })) + m.UseMiddleware(macaron.Renderer(filepath.Join(hs.Cfg.StaticRootPath, "views"), "[[", "]]")) // These endpoints are used for monitoring the Grafana instance // and should not be redirected or rejected. @@ -375,7 +371,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() { } m.Use(middleware.HandleNoCacheHeader) - m.Use(middleware.AddCSPHeader(hs.Cfg, hs.log)) + m.UseMiddleware(middleware.AddCSPHeader(hs.Cfg, hs.log)) for _, mw := range hs.middlewares { m.Use(mw) @@ -408,7 +404,7 @@ func (hs *HTTPServer) healthzHandler(ctx *macaron.Context) { return } - ctx.WriteHeader(200) + ctx.Resp.WriteHeader(200) _, err := ctx.Resp.Write([]byte("Ok")) if err != nil { hs.log.Error("could not write to response", "err", err) diff --git a/pkg/api/plugins.go b/pkg/api/plugins.go index 5f44bf939e3..b7bc2e2b47f 100644 --- a/pkg/api/plugins.go +++ b/pkg/api/plugins.go @@ -21,6 +21,14 @@ import ( "github.com/grafana/grafana/pkg/setting" ) +var permittedFileExts = []string{ + ".html", ".xhtml", ".css", ".js", ".json", ".jsonld", ".map", ".mjs", + ".jpeg", ".jpg", ".png", ".gif", ".svg", ".webp", ".ico", + ".woff", ".woff2", ".eot", ".ttf", ".otf", + ".wav", ".mp3", + ".md", ".pdf", ".txt", +} + func (hs *HTTPServer) GetPluginList(c *models.ReqContext) response.Response { typeFilter := c.Query("type") enabledFilter := c.Query("enabled") @@ -292,9 +300,9 @@ func (hs *HTTPServer) GetPluginAssets(c *models.ReqContext) { return } - if shouldExclude(fi) { + if accessForbidden(fi.Name()) { c.JsonApiErr(403, "Plugin file access forbidden", - fmt.Errorf("access is forbidden to executable plugin file %s", pluginFilePath)) + fmt.Errorf("access is forbidden to plugin file %s", pluginFilePath)) return } @@ -441,12 +449,13 @@ func translatePluginRequestErrorToAPIError(err error) response.Response { return response.Error(500, "Plugin request failed", err) } -func shouldExclude(fi os.FileInfo) bool { - normalizedFilename := strings.ToLower(fi.Name()) +func accessForbidden(pluginFilename string) bool { + ext := filepath.Ext(pluginFilename) - isUnixExecutable := fi.Mode()&0111 == 0111 - isWindowsExecutable := strings.HasSuffix(normalizedFilename, ".exe") - isScript := strings.HasSuffix(normalizedFilename, ".sh") - - return isUnixExecutable || isWindowsExecutable || isScript + for _, permittedExt := range permittedFileExts { + if strings.EqualFold(permittedExt, ext) { + return false + } + } + return true } diff --git a/pkg/api/plugins_test.go b/pkg/api/plugins_test.go new file mode 100644 index 00000000000..47ea607cda6 --- /dev/null +++ b/pkg/api/plugins_test.go @@ -0,0 +1,89 @@ +package api + +import ( + "testing" +) + +func Test_accessForbidden(t *testing.T) { + type testCase struct { + filename string + } + tests := []struct { + name string + t testCase + accessForbidden bool + }{ + { + name: ".exe files are forbidden", + t: testCase{ + filename: "test.exe", + }, + accessForbidden: true, + }, + { + name: ".sh files are forbidden", + t: testCase{ + filename: "test.sh", + }, + accessForbidden: true, + }, + { + name: "js is not forbidden", + t: testCase{ + + filename: "module.js", + }, + accessForbidden: false, + }, + { + name: "logos are not forbidden", + t: testCase{ + + filename: "logo.svg", + }, + accessForbidden: false, + }, + { + name: "JPGs are not forbidden", + t: testCase{ + filename: "img/test.jpg", + }, + accessForbidden: false, + }, + { + name: "JPEGs are not forbidden", + t: testCase{ + filename: "img/test.jpeg", + }, + accessForbidden: false, + }, + { + name: "ext case is ignored", + t: testCase{ + filename: "scripts/runThis.SH", + }, + accessForbidden: true, + }, + { + name: "no file ext is forbidden", + t: testCase{ + filename: "scripts/runThis", + }, + accessForbidden: true, + }, + { + name: "empty file ext is forbidden", + t: testCase{ + filename: "scripts/runThis.", + }, + accessForbidden: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := accessForbidden(tt.t.filename); got != tt.accessForbidden { + t.Errorf("accessForbidden() = %v, accessForbidden %v", got, tt.accessForbidden) + } + }) + } +} diff --git a/pkg/expr/nodes.go b/pkg/expr/nodes.go index f88d054e0a9..e8914c0e7ff 100644 --- a/pkg/expr/nodes.go +++ b/pkg/expr/nodes.go @@ -186,7 +186,7 @@ func (s *Service) buildDSNode(dp *simple.DirectedGraph, rn *rawNode, req *Reques } var floatIntervalMS float64 - if rawIntervalMS := rn.Query["intervalMs"]; ok { + if rawIntervalMS, ok := rn.Query["intervalMs"]; ok { if floatIntervalMS, ok = rawIntervalMS.(float64); !ok { return nil, fmt.Errorf("expected intervalMs to be an float64, got type %T for refId %v", rawIntervalMS, rn.RefID) } @@ -194,7 +194,7 @@ func (s *Service) buildDSNode(dp *simple.DirectedGraph, rn *rawNode, req *Reques } var floatMaxDP float64 - if rawMaxDP := rn.Query["maxDataPoints"]; ok { + if rawMaxDP, ok := rn.Query["maxDataPoints"]; ok { if floatMaxDP, ok = rawMaxDP.(float64); !ok { return nil, fmt.Errorf("expected maxDataPoints to be an float64, got type %T for refId %v", rawMaxDP, rn.RefID) } diff --git a/pkg/macaron/context.go b/pkg/macaron/context.go index 2920f834af8..a26b37aafdb 100644 --- a/pkg/macaron/context.go +++ b/pkg/macaron/context.go @@ -15,6 +15,8 @@ package macaron import ( + "encoding/json" + "html/template" "net/http" "net/url" "reflect" @@ -44,11 +46,11 @@ type Context struct { index int *Router - Req Request - Resp ResponseWriter - params Params - Render - Data map[string]interface{} + Req Request + Resp ResponseWriter + params Params + template *template.Template + Data map[string]interface{} } func (ctx *Context) handler() Handler { @@ -108,19 +110,31 @@ func (ctx *Context) RemoteAddr() string { return addr } -func (ctx *Context) renderHTML(status int, setName, tplName string, data ...interface{}) { - if len(data) <= 0 { - ctx.Render.HTMLSet(status, setName, tplName, ctx.Data) - } else if len(data) == 1 { - ctx.Render.HTMLSet(status, setName, tplName, data[0]) - } else { - ctx.Render.HTMLSet(status, setName, tplName, data[0], data[1].(HTMLOptions)) +const ( + headerContentType = "Content-Type" + contentTypeJSON = "application/json; charset=UTF-8" + contentTypeHTML = "text/html; charset=UTF-8" +) + +// HTML renders the HTML with default template set. +func (ctx *Context) HTML(status int, name string, data interface{}) { + ctx.Resp.Header().Set(headerContentType, contentTypeHTML) + ctx.Resp.WriteHeader(status) + if err := ctx.template.ExecuteTemplate(ctx.Resp, name, data); err != nil { + panic("Context.HTML:" + err.Error()) } } -// HTML renders the HTML with default template set. -func (ctx *Context) HTML(status int, name string, data ...interface{}) { - ctx.renderHTML(status, DEFAULT_TPL_SET_NAME, name, data...) +func (ctx *Context) JSON(status int, data interface{}) { + ctx.Resp.Header().Set(headerContentType, contentTypeJSON) + ctx.Resp.WriteHeader(status) + enc := json.NewEncoder(ctx.Resp) + if Env != PROD { + enc.SetIndent("", " ") + } + if err := enc.Encode(data); err != nil { + panic("Context.JSON: " + err.Error()) + } } // Redirect sends a redirect response @@ -142,7 +156,7 @@ func (ctx *Context) parseForm() { return } - contentType := ctx.Req.Header.Get(_CONTENT_TYPE) + contentType := ctx.Req.Header.Get(headerContentType) if (ctx.Req.Method == "POST" || ctx.Req.Method == "PUT") && len(contentType) > 0 && strings.Contains(contentType, "multipart/form-data") { _ = ctx.Req.ParseMultipartForm(MaxMemory) diff --git a/pkg/macaron/macaron.go b/pkg/macaron/macaron.go index 40701d7bfcd..ce44a6ebf26 100644 --- a/pkg/macaron/macaron.go +++ b/pkg/macaron/macaron.go @@ -182,7 +182,6 @@ func (m *Macaron) createContext(rw http.ResponseWriter, req *http.Request) *Cont index: 0, Router: m.Router, Resp: NewResponseWriter(req.Method, rw), - Render: &DummyRender{rw}, Data: make(map[string]interface{}), } req = req.WithContext(context.WithValue(req.Context(), macaronContextKey{}, c)) diff --git a/pkg/macaron/render.go b/pkg/macaron/render.go index 8aec82bee59..c6acbee5bb0 100644 --- a/pkg/macaron/render.go +++ b/pkg/macaron/render.go @@ -16,708 +16,57 @@ package macaron import ( - "bytes" - "encoding/json" - "encoding/xml" - "fmt" "html/template" - "io" - "io/ioutil" + "io/fs" "net/http" "os" - "path" "path/filepath" - "strings" - "sync" - "time" ) -const ( - _CONTENT_TYPE = "Content-Type" - _CONTENT_BINARY = "application/octet-stream" - _CONTENT_JSON = "application/json" - _CONTENT_HTML = "text/html" - _CONTENT_PLAIN = "text/plain" - _CONTENT_XHTML = "application/xhtml+xml" - _CONTENT_XML = "text/xml" - _DEFAULT_CHARSET = "UTF-8" -) - -var ( - // Provides a temporary buffer to execute templates into and catch errors. - bufpool = sync.Pool{ - New: func() interface{} { return new(bytes.Buffer) }, +// Renderer is a Middleware that injects a template renderer into the macaron context, enabling ctx.HTML calls in the handlers. +// If MACARON_ENV is set to "development" then templates will be recompiled on every request. For more performance, set the +// MACARON_ENV environment variable to "production". +func Renderer(dir, leftDelim, rightDelim string) func(http.Handler) http.Handler { + fs := os.DirFS(dir) + t, err := compileTemplates(fs, leftDelim, rightDelim) + if err != nil { + panic("Renderer: " + err.Error()) } - - // Included helper functions for use when rendering html - helperFuncs = template.FuncMap{ - "yield": func() (string, error) { - return "", fmt.Errorf("yield called with no layout defined") - }, - "current": func() (string, error) { - return "", nil - }, + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + ctx := FromContext(req.Context()) + if Env == DEV { + if t, err = compileTemplates(fs, leftDelim, rightDelim); err != nil { + panic("Context.HTML:" + err.Error()) + } + } + ctx.template = t + next.ServeHTTP(rw, req) + }) } -) - -type ( - // TemplateFile represents a interface of template file that has name and can be read. - TemplateFile interface { - Name() string - Data() []byte - Ext() string - } - // TemplateFileSystem represents a interface of template file system that able to list all files. - TemplateFileSystem interface { - ListFiles() []TemplateFile - Get(string) (io.Reader, error) - } - - // Delims represents a set of Left and Right delimiters for HTML template rendering - Delims struct { - // Left delimiter, defaults to {{ - Left string - // Right delimiter, defaults to }} - Right string - } - - // RenderOptions represents a struct for specifying configuration options for the Render middleware. - RenderOptions struct { - // Directory to load templates. Default is "templates". - Directory string - // Addtional directories to overwite templates. - AppendDirectories []string - // Layout template name. Will not render a layout if "". Default is to "". - Layout string - // Extensions to parse template files from. Defaults are [".tmpl", ".html"]. - Extensions []string - // Funcs is a slice of FuncMaps to apply to the template upon compilation. This is useful for helper functions. Default is []. - Funcs []template.FuncMap - // Delims sets the action delimiters to the specified strings in the Delims struct. - Delims Delims - // Appends the given charset to the Content-Type header. Default is "UTF-8". - Charset string - // Outputs human readable JSON. - IndentJSON bool - // Outputs human readable XML. - IndentXML bool - // Prefixes the JSON output with the given bytes. - PrefixJSON []byte - // Prefixes the XML output with the given bytes. - PrefixXML []byte - // Allows changing of output to XHTML instead of HTML. Default is "text/html" - HTMLContentType string - // TemplateFileSystem is the interface for supporting any implmentation of template file system. - TemplateFileSystem - } - - // HTMLOptions is a struct for overriding some rendering Options for specific HTML call - HTMLOptions struct { - // Layout template name. Overrides Options.Layout. - Layout string - } - - Render interface { - http.ResponseWriter - SetResponseWriter(http.ResponseWriter) - - JSON(int, interface{}) - JSONString(interface{}) (string, error) - RawData(int, []byte) // Serve content as binary - PlainText(int, []byte) // Serve content as plain text - HTML(int, string, interface{}, ...HTMLOptions) - HTMLSet(int, string, string, interface{}, ...HTMLOptions) - HTMLSetString(string, string, interface{}, ...HTMLOptions) (string, error) - HTMLString(string, interface{}, ...HTMLOptions) (string, error) - HTMLSetBytes(string, string, interface{}, ...HTMLOptions) ([]byte, error) - HTMLBytes(string, interface{}, ...HTMLOptions) ([]byte, error) - XML(int, interface{}) - Error(int, ...string) - Status(int) - SetTemplatePath(string, string) - HasTemplateSet(string) bool - } -) - -// TplFile implements TemplateFile interface. -type TplFile struct { - name string - data []byte - ext string } -// NewTplFile cerates new template file with given name and data. -func NewTplFile(name string, data []byte, ext string) *TplFile { - return &TplFile{name, data, ext} -} - -func (f *TplFile) Name() string { - return f.name -} - -func (f *TplFile) Data() []byte { - return f.data -} - -func (f *TplFile) Ext() string { - return f.ext -} - -// TplFileSystem implements TemplateFileSystem interface. -type TplFileSystem struct { - files []TemplateFile -} - -// NewTemplateFileSystem creates new template file system with given options. -func NewTemplateFileSystem(opt RenderOptions, omitData bool) TplFileSystem { - fs := TplFileSystem{} - fs.files = make([]TemplateFile, 0, 10) - - // Directories are composed in reverse order because later one overwrites previous ones, - // so once found, we can directly jump out of the loop. - dirs := make([]string, 0, len(opt.AppendDirectories)+1) - for i := len(opt.AppendDirectories) - 1; i >= 0; i-- { - dirs = append(dirs, opt.AppendDirectories[i]) - } - dirs = append(dirs, opt.Directory) - - var err error - for i := range dirs { - // Skip ones that does not exists for symlink test, - // but allow non-symlink ones added after start. - if _, err := os.Stat(dirs[i]); err != nil && os.IsNotExist(err) { - continue +func compileTemplates(filesystem fs.FS, leftDelim, rightDelim string) (*template.Template, error) { + t := template.New("") + t.Delims(leftDelim, rightDelim) + err := fs.WalkDir(filesystem, ".", func(path string, d fs.DirEntry, e error) error { + if e != nil { + return nil // skip unreadable or erroneous filesystem items } - - dirs[i], err = filepath.EvalSymlinks(dirs[i]) - if err != nil { - panic("EvalSymlinks(" + dirs[i] + "): " + err.Error()) + if d.IsDir() { + return nil } - } - lastDir := dirs[len(dirs)-1] - - // We still walk the last (original) directory because it's non-sense we load templates not exist in original directory. - if err = filepath.Walk(lastDir, func(path string, info os.FileInfo, _ error) error { - r, err := filepath.Rel(lastDir, path) + ext := filepath.Ext(path) + if ext != ".html" && ext != ".tmpl" { + return nil + } + data, err := fs.ReadFile(filesystem, path) if err != nil { return err } - - ext := GetExt(r) - - for _, extension := range opt.Extensions { - if ext != extension { - continue - } - - var data []byte - if !omitData { - // Loop over candidates of directory, break out once found. - // The file always exists because it's inside the walk function, - // and read original file is the worst case. - for i := range dirs { - path = filepath.Join(dirs[i], r) - if f, err := os.Stat(path); err != nil || f.IsDir() { - continue - } - - data, err = ioutil.ReadFile(path) - if err != nil { - return err - } - break - } - } - - name := filepath.ToSlash((r[0 : len(r)-len(ext)])) - fs.files = append(fs.files, NewTplFile(name, data, ext)) - } - - return nil - }); err != nil { - panic("NewTemplateFileSystem: " + err.Error()) - } - - return fs -} - -func (fs TplFileSystem) ListFiles() []TemplateFile { - return fs.files -} - -func (fs TplFileSystem) Get(name string) (io.Reader, error) { - for i := range fs.files { - if fs.files[i].Name()+fs.files[i].Ext() == name { - return bytes.NewReader(fs.files[i].Data()), nil - } - } - return nil, fmt.Errorf("file '%s' not found", name) -} - -func PrepareCharset(charset string) string { - if len(charset) != 0 { - return "; charset=" + charset - } - - return "; charset=" + _DEFAULT_CHARSET -} - -func GetExt(s string) string { - index := strings.Index(s, ".") - if index == -1 { - return "" - } - return s[index:] -} - -func compile(opt RenderOptions) *template.Template { - t := template.New(opt.Directory) - t.Delims(opt.Delims.Left, opt.Delims.Right) - // Parse an initial template in case we don't have any. - template.Must(t.Parse("Macaron")) - - if opt.TemplateFileSystem == nil { - opt.TemplateFileSystem = NewTemplateFileSystem(opt, false) - } - - for _, f := range opt.TemplateFileSystem.ListFiles() { - tmpl := t.New(f.Name()) - for _, funcs := range opt.Funcs { - tmpl.Funcs(funcs) - } - // Bomb out if parse fails. We don't want any silent server starts. - template.Must(tmpl.Funcs(helperFuncs).Parse(string(f.Data()))) - } - - return t -} - -const ( - DEFAULT_TPL_SET_NAME = "DEFAULT" -) - -// TemplateSet represents a template set of type *template.Template. -type TemplateSet struct { - lock sync.RWMutex - sets map[string]*template.Template - dirs map[string]string -} - -// NewTemplateSet initializes a new empty template set. -func NewTemplateSet() *TemplateSet { - return &TemplateSet{ - sets: make(map[string]*template.Template), - dirs: make(map[string]string), - } -} - -func (ts *TemplateSet) Set(name string, opt *RenderOptions) *template.Template { - t := compile(*opt) - - ts.lock.Lock() - defer ts.lock.Unlock() - - ts.sets[name] = t - ts.dirs[name] = opt.Directory - return t -} - -func (ts *TemplateSet) Get(name string) *template.Template { - ts.lock.RLock() - defer ts.lock.RUnlock() - - return ts.sets[name] -} - -func (ts *TemplateSet) GetDir(name string) string { - ts.lock.RLock() - defer ts.lock.RUnlock() - - return ts.dirs[name] -} - -func prepareRenderOptions(options []RenderOptions) RenderOptions { - var opt RenderOptions - if len(options) > 0 { - opt = options[0] - } - - // Defaults. - if len(opt.Directory) == 0 { - opt.Directory = "templates" - } - if len(opt.Extensions) == 0 { - opt.Extensions = []string{".tmpl", ".html"} - } - if len(opt.HTMLContentType) == 0 { - opt.HTMLContentType = _CONTENT_HTML - } - - return opt -} - -func ParseTplSet(tplSet string) (tplName string, tplDir string) { - tplSet = strings.TrimSpace(tplSet) - if len(tplSet) == 0 { - panic("empty template set argument") - } - infos := strings.Split(tplSet, ":") - if len(infos) == 1 { - tplDir = infos[0] - tplName = path.Base(tplDir) - } else { - tplName = infos[0] - tplDir = infos[1] - } - - dir, err := os.Stat(tplDir) - if err != nil || !dir.IsDir() { - panic("template set path does not exist or is not a directory") - } - return tplName, tplDir -} - -func renderHandler(opt RenderOptions, tplSets []string) Handler { - cs := PrepareCharset(opt.Charset) - ts := NewTemplateSet() - ts.Set(DEFAULT_TPL_SET_NAME, &opt) - - var tmpOpt RenderOptions - for _, tplSet := range tplSets { - tplName, tplDir := ParseTplSet(tplSet) - tmpOpt = opt - tmpOpt.Directory = tplDir - ts.Set(tplName, &tmpOpt) - } - - return func(ctx *Context) { - r := &TplRender{ - ResponseWriter: ctx.Resp, - TemplateSet: ts, - Opt: &opt, - CompiledCharset: cs, - } - ctx.Data["TmplLoadTimes"] = func() string { - if r.startTime.IsZero() { - return "" - } - return fmt.Sprint(time.Since(r.startTime).Nanoseconds()/1e6) + "ms" - } - - ctx.Render = r - ctx.MapTo(r, (*Render)(nil)) - } -} - -// Renderer is a Middleware that maps a macaron.Render service into the Macaron handler chain. -// An single variadic macaron.RenderOptions struct can be optionally provided to configure -// HTML rendering. The default directory for templates is "templates" and the default -// file extension is ".tmpl" and ".html". -// -// If MACARON_ENV is set to "" or "development" then templates will be recompiled on every request. For more performance, set the -// MACARON_ENV environment variable to "production". -func Renderer(options ...RenderOptions) Handler { - return renderHandler(prepareRenderOptions(options), []string{}) -} - -func Renderers(options RenderOptions, tplSets ...string) Handler { - return renderHandler(prepareRenderOptions([]RenderOptions{options}), tplSets) -} - -type TplRender struct { - http.ResponseWriter - *TemplateSet - Opt *RenderOptions - CompiledCharset string - - startTime time.Time -} - -func (r *TplRender) SetResponseWriter(rw http.ResponseWriter) { - r.ResponseWriter = rw -} - -func (r *TplRender) JSON(status int, v interface{}) { - var ( - result []byte - err error - ) - if r.Opt.IndentJSON { - result, err = json.MarshalIndent(v, "", " ") - } else { - result, err = json.Marshal(v) - } - if err != nil { - http.Error(r, err.Error(), 500) - return - } - - // json rendered fine, write out the result - r.Header().Set(_CONTENT_TYPE, _CONTENT_JSON+r.CompiledCharset) - r.WriteHeader(status) - if len(r.Opt.PrefixJSON) > 0 { - _, _ = r.Write(r.Opt.PrefixJSON) - } - _, _ = r.Write(result) -} - -func (r *TplRender) JSONString(v interface{}) (string, error) { - var result []byte - var err error - if r.Opt.IndentJSON { - result, err = json.MarshalIndent(v, "", " ") - } else { - result, err = json.Marshal(v) - } - if err != nil { - return "", err - } - return string(result), nil -} - -func (r *TplRender) XML(status int, v interface{}) { - var result []byte - var err error - if r.Opt.IndentXML { - result, err = xml.MarshalIndent(v, "", " ") - } else { - result, err = xml.Marshal(v) - } - if err != nil { - http.Error(r, err.Error(), 500) - return - } - - // XML rendered fine, write out the result - r.Header().Set(_CONTENT_TYPE, _CONTENT_XML+r.CompiledCharset) - r.WriteHeader(status) - if len(r.Opt.PrefixXML) > 0 { - _, _ = r.Write(r.Opt.PrefixXML) - } - _, _ = r.Write(result) -} - -func (r *TplRender) data(status int, contentType string, v []byte) { - if r.Header().Get(_CONTENT_TYPE) == "" { - r.Header().Set(_CONTENT_TYPE, contentType) - } - r.WriteHeader(status) - _, _ = r.Write(v) -} - -func (r *TplRender) RawData(status int, v []byte) { - r.data(status, _CONTENT_BINARY, v) -} - -func (r *TplRender) PlainText(status int, v []byte) { - r.data(status, _CONTENT_PLAIN, v) -} - -func (r *TplRender) execute(t *template.Template, name string, data interface{}) (*bytes.Buffer, error) { - buf := bufpool.Get().(*bytes.Buffer) - return buf, t.ExecuteTemplate(buf, name, data) -} - -func (r *TplRender) addYield(t *template.Template, tplName string, data interface{}) { - funcs := template.FuncMap{ - "yield": func() (template.HTML, error) { - buf, err := r.execute(t, tplName, data) - // return safe html here since we are rendering our own template - return template.HTML(buf.String()), err - }, - "current": func() (string, error) { - return tplName, nil - }, - } - t.Funcs(funcs) -} - -func (r *TplRender) renderBytes(setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) (*bytes.Buffer, error) { - t := r.TemplateSet.Get(setName) - if Env == DEV { - opt := *r.Opt - opt.Directory = r.TemplateSet.GetDir(setName) - t = r.TemplateSet.Set(setName, &opt) - } - if t == nil { - return nil, fmt.Errorf("html/template: template \"%s\" is undefined", tplName) - } - - opt := r.prepareHTMLOptions(htmlOpt) - - if len(opt.Layout) > 0 { - r.addYield(t, tplName, data) - tplName = opt.Layout - } - - out, err := r.execute(t, tplName, data) - if err != nil { - return nil, err - } - - return out, nil -} - -func (r *TplRender) renderHTML(status int, setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) { - r.startTime = time.Now() - - out, err := r.renderBytes(setName, tplName, data, htmlOpt...) - if err != nil { - http.Error(r, err.Error(), http.StatusInternalServerError) - return - } - - r.Header().Set(_CONTENT_TYPE, r.Opt.HTMLContentType+r.CompiledCharset) - r.WriteHeader(status) - - if _, err := out.WriteTo(r); err != nil { - out.Reset() - } - bufpool.Put(out) -} - -func (r *TplRender) HTML(status int, name string, data interface{}, htmlOpt ...HTMLOptions) { - r.renderHTML(status, DEFAULT_TPL_SET_NAME, name, data, htmlOpt...) -} - -func (r *TplRender) HTMLSet(status int, setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) { - r.renderHTML(status, setName, tplName, data, htmlOpt...) -} - -func (r *TplRender) HTMLSetBytes(setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) ([]byte, error) { - out, err := r.renderBytes(setName, tplName, data, htmlOpt...) - if err != nil { - return []byte(""), err - } - return out.Bytes(), nil -} - -func (r *TplRender) HTMLBytes(name string, data interface{}, htmlOpt ...HTMLOptions) ([]byte, error) { - return r.HTMLSetBytes(DEFAULT_TPL_SET_NAME, name, data, htmlOpt...) -} - -func (r *TplRender) HTMLSetString(setName, tplName string, data interface{}, htmlOpt ...HTMLOptions) (string, error) { - p, err := r.HTMLSetBytes(setName, tplName, data, htmlOpt...) - return string(p), err -} - -func (r *TplRender) HTMLString(name string, data interface{}, htmlOpt ...HTMLOptions) (string, error) { - p, err := r.HTMLBytes(name, data, htmlOpt...) - return string(p), err -} - -// Error writes the given HTTP status to the current ResponseWriter -func (r *TplRender) Error(status int, message ...string) { - r.WriteHeader(status) - if len(message) > 0 { - _, _ = r.Write([]byte(message[0])) - } -} - -func (r *TplRender) Status(status int) { - r.WriteHeader(status) -} - -func (r *TplRender) prepareHTMLOptions(htmlOpt []HTMLOptions) HTMLOptions { - if len(htmlOpt) > 0 { - return htmlOpt[0] - } - - return HTMLOptions{ - Layout: r.Opt.Layout, - } -} - -func (r *TplRender) SetTemplatePath(setName, dir string) { - if len(setName) == 0 { - setName = DEFAULT_TPL_SET_NAME - } - opt := *r.Opt - opt.Directory = dir - r.TemplateSet.Set(setName, &opt) -} - -func (r *TplRender) HasTemplateSet(name string) bool { - return r.TemplateSet.Get(name) != nil -} - -// DummyRender is used when user does not choose any real render to use. -// This way, we can print out friendly message which asks them to register one, -// instead of ugly and confusing 'nil pointer' panic. -type DummyRender struct { - http.ResponseWriter -} - -func renderNotRegistered() { - panic("middleware render hasn't been registered") -} - -func (r *DummyRender) SetResponseWriter(http.ResponseWriter) { - renderNotRegistered() -} - -func (r *DummyRender) JSON(int, interface{}) { - renderNotRegistered() -} - -func (r *DummyRender) JSONString(interface{}) (string, error) { - renderNotRegistered() - return "", nil -} - -func (r *DummyRender) RawData(int, []byte) { - renderNotRegistered() -} - -func (r *DummyRender) PlainText(int, []byte) { - renderNotRegistered() -} - -func (r *DummyRender) HTML(int, string, interface{}, ...HTMLOptions) { - renderNotRegistered() -} - -func (r *DummyRender) HTMLSet(int, string, string, interface{}, ...HTMLOptions) { - renderNotRegistered() -} - -func (r *DummyRender) HTMLSetString(string, string, interface{}, ...HTMLOptions) (string, error) { - renderNotRegistered() - return "", nil -} - -func (r *DummyRender) HTMLString(string, interface{}, ...HTMLOptions) (string, error) { - renderNotRegistered() - return "", nil -} - -func (r *DummyRender) HTMLSetBytes(string, string, interface{}, ...HTMLOptions) ([]byte, error) { - renderNotRegistered() - return nil, nil -} - -func (r *DummyRender) HTMLBytes(string, interface{}, ...HTMLOptions) ([]byte, error) { - renderNotRegistered() - return nil, nil -} - -func (r *DummyRender) XML(int, interface{}) { - renderNotRegistered() -} - -func (r *DummyRender) Error(int, ...string) { - renderNotRegistered() -} - -func (r *DummyRender) Status(int) { - renderNotRegistered() -} - -func (r *DummyRender) SetTemplatePath(string, string) { - renderNotRegistered() -} - -func (r *DummyRender) HasTemplateSet(string) bool { - renderNotRegistered() - return false + basename := path[:len(path)-len(ext)] + _, err = t.New(basename).Parse(string(data)) + return err + }) + return t, err } diff --git a/pkg/middleware/csp.go b/pkg/middleware/csp.go index 3fff0cbe04f..2ea9614dfe0 100644 --- a/pkg/middleware/csp.go +++ b/pkg/middleware/csp.go @@ -10,45 +10,44 @@ import ( "strings" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/models" + "github.com/grafana/grafana/pkg/services/contexthandler" "github.com/grafana/grafana/pkg/setting" - macaron "gopkg.in/macaron.v1" ) // AddCSPHeader adds the Content Security Policy header. -func AddCSPHeader(cfg *setting.Cfg, logger log.Logger) macaron.Handler { - return func(w http.ResponseWriter, req *http.Request, c *macaron.Context) { - if !cfg.CSPEnabled { - return - } +func AddCSPHeader(cfg *setting.Cfg, logger log.Logger) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + if !cfg.CSPEnabled { + next.ServeHTTP(rw, req) + return + } - logger.Debug("Adding CSP header to response", "cfg", fmt.Sprintf("%p", cfg)) + logger.Debug("Adding CSP header to response", "cfg", fmt.Sprintf("%p", cfg)) - ctx, ok := c.Data["ctx"].(*models.ReqContext) - if !ok { - panic("Failed to convert context into models.ReqContext") - } + ctx := contexthandler.FromContext(req.Context()) + if cfg.CSPTemplate == "" { + logger.Debug("CSP template not configured, so returning 500") + ctx.JsonApiErr(500, "CSP template has to be configured", nil) + return + } - if cfg.CSPTemplate == "" { - logger.Debug("CSP template not configured, so returning 500") - ctx.JsonApiErr(500, "CSP template has to be configured", nil) - return - } + var buf [16]byte + if _, err := io.ReadFull(rand.Reader, buf[:]); err != nil { + logger.Error("Failed to generate CSP nonce", "err", err) + ctx.JsonApiErr(500, "Failed to generate CSP nonce", err) + } - var buf [16]byte - if _, err := io.ReadFull(rand.Reader, buf[:]); err != nil { - logger.Error("Failed to generate CSP nonce", "err", err) - ctx.JsonApiErr(500, "Failed to generate CSP nonce", err) - } + nonce := base64.RawStdEncoding.EncodeToString(buf[:]) + val := strings.ReplaceAll(cfg.CSPTemplate, "$NONCE", fmt.Sprintf("'nonce-%s'", nonce)) - nonce := base64.RawStdEncoding.EncodeToString(buf[:]) - val := strings.ReplaceAll(cfg.CSPTemplate, "$NONCE", fmt.Sprintf("'nonce-%s'", nonce)) - - re := regexp.MustCompile(`^\w+:(//)?`) - rootPath := re.ReplaceAllString(cfg.AppURL, "") - val = strings.ReplaceAll(val, "$ROOT_PATH", rootPath) - w.Header().Set("Content-Security-Policy", val) - ctx.RequestNonce = nonce - logger.Debug("Successfully generated CSP nonce", "nonce", nonce) + re := regexp.MustCompile(`^\w+:(//)?`) + rootPath := re.ReplaceAllString(cfg.AppURL, "") + val = strings.ReplaceAll(val, "$ROOT_PATH", rootPath) + rw.Header().Set("Content-Security-Policy", val) + ctx.RequestNonce = nonce + logger.Debug("Successfully generated CSP nonce", "nonce", nonce) + next.ServeHTTP(rw, req) + }) } } diff --git a/pkg/middleware/gziper.go b/pkg/middleware/gziper.go index 5427edd1aef..d0248b345b8 100644 --- a/pkg/middleware/gziper.go +++ b/pkg/middleware/gziper.go @@ -1,43 +1,81 @@ package middleware import ( + "bufio" + "compress/gzip" + "fmt" + "net" + "net/http" "strings" - "github.com/go-macaron/gzip" - "github.com/grafana/grafana/pkg/infra/log" - "gopkg.in/macaron.v1" + macaron "gopkg.in/macaron.v1" ) -const resourcesPath = "/resources" - -var gzipIgnoredPathPrefixes = []string{ - "/api/datasources/proxy", // Ignore datasource proxy requests. - "/api/plugin-proxy/", - "/metrics", - "/api/live/ws", // WebSocket does not support gzip compression. - "/api/live/push", // WebSocket does not support gzip compression. +type gzipResponseWriter struct { + w *gzip.Writer + macaron.ResponseWriter } -func Gziper() macaron.Handler { - gziperLogger := log.New("gziper") - gziper := gzip.Gziper() +func (grw *gzipResponseWriter) WriteHeader(c int) { + grw.Header().Del("Content-Length") + grw.ResponseWriter.WriteHeader(c) +} - return func(ctx *macaron.Context) { - requestPath := ctx.Req.URL.RequestURI() +func (grw gzipResponseWriter) Write(p []byte) (int, error) { + if grw.Header().Get("Content-Type") == "" { + grw.Header().Set("Content-Type", http.DetectContentType(p)) + } + grw.Header().Del("Content-Length") + return grw.w.Write(p) +} - for _, pathPrefix := range gzipIgnoredPathPrefixes { - if strings.HasPrefix(requestPath, pathPrefix) { +func (grw gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + if hijacker, ok := grw.ResponseWriter.(http.Hijacker); ok { + return hijacker.Hijack() + } + return nil, nil, fmt.Errorf("GZIP ResponseWriter doesn't implement the Hijacker interface") +} + +type matcher func(s string) bool + +func prefix(p string) matcher { return func(s string) bool { return strings.HasPrefix(s, p) } } +func substr(p string) matcher { return func(s string) bool { return strings.Contains(s, p) } } + +var gzipIgnoredPaths = []matcher{ + prefix("/api/datasources"), + prefix("/api/plugins"), + prefix("/api/plugin-proxy/"), + prefix("/metrics"), + prefix("/api/live/ws"), // WebSocket does not support gzip compression. + prefix("/api/live/push"), // WebSocket does not support gzip compression. + substr("/resources"), +} + +func Gziper() func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + requestPath := req.URL.RequestURI() + + for _, pathMatcher := range gzipIgnoredPaths { + if pathMatcher(requestPath) { + fmt.Println("skip path", requestPath) + next.ServeHTTP(rw, req) + return + } + } + + if !strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { + next.ServeHTTP(rw, req) return } - } - // ignore resources - if (strings.HasPrefix(requestPath, "/api/datasources/") || strings.HasPrefix(requestPath, "/api/plugins/")) && strings.Contains(requestPath, resourcesPath) { - return - } + grw := &gzipResponseWriter{gzip.NewWriter(rw), rw.(macaron.ResponseWriter)} + grw.Header().Set("Content-Encoding", "gzip") + grw.Header().Set("Vary", "Accept-Encoding") - if _, err := ctx.Invoke(gziper); err != nil { - gziperLogger.Error("Invoking gzip handler failed", "err", err) - } + next.ServeHTTP(grw, req) + // We can't really handle close errors at this point and we can't report them to the caller + _ = grw.w.Close() + }) } } diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index 30ea0b1aff1..f7cbdf5102e 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -111,7 +111,7 @@ func TestMiddlewareContext(t *testing.T) { Settings: map[string]interface{}{}, NavTree: []*dtos.NavLink{}, } - t.Log("Calling HTML", "data", data, "render", c.Render) + t.Log("Calling HTML", "data", data) c.HTML(200, "index-template", data) t.Log("Returned HTML with code 200") } @@ -632,11 +632,8 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func( sc.m = macaron.New() sc.m.Use(AddDefaultResponseHeaders(cfg)) - sc.m.Use(AddCSPHeader(cfg, logger)) - sc.m.Use(macaron.Renderer(macaron.RenderOptions{ - Directory: viewsPath, - Delims: macaron.Delims{Left: "[[", Right: "]]"}, - })) + sc.m.UseMiddleware(AddCSPHeader(cfg, logger)) + sc.m.UseMiddleware(macaron.Renderer(viewsPath, "[[", "]]")) ctxHdlr := getContextHandler(t, cfg) sc.sqlStore = ctxHdlr.SQLStore diff --git a/pkg/middleware/org_redirect.go b/pkg/middleware/org_redirect.go index cb1813ade7f..59cbddf58e9 100644 --- a/pkg/middleware/org_redirect.go +++ b/pkg/middleware/org_redirect.go @@ -37,7 +37,7 @@ func OrgRedirect(cfg *setting.Cfg) macaron.Handler { if ctx.IsApiRequest() { ctx.JsonApiErr(404, "Not found", nil) } else { - ctx.Error(404, "Not found") + http.Error(ctx.Resp, "Not found", http.StatusNotFound) } return diff --git a/pkg/middleware/rate_limit_test.go b/pkg/middleware/rate_limit_test.go index c78bbe9136a..109a2e1220c 100644 --- a/pkg/middleware/rate_limit_test.go +++ b/pkg/middleware/rate_limit_test.go @@ -32,10 +32,7 @@ func rateLimiterScenario(t *testing.T, desc string, rps int, burst int, fn rateL cfg := setting.NewCfg() m := macaron.New() - m.Use(macaron.Renderer(macaron.RenderOptions{ - Directory: "", - Delims: macaron.Delims{Left: "[[", Right: "]]"}, - })) + m.UseMiddleware(macaron.Renderer("../../public/views", "[[", "]]")) m.Use(getContextHandler(t, cfg).Middleware) m.Get("/foo", RateLimit(rps, burst, func() time.Time { return currentTime }), defaultHandler) diff --git a/pkg/middleware/recovery.go b/pkg/middleware/recovery.go index 336a3425da9..88a4f8b32e0 100644 --- a/pkg/middleware/recovery.go +++ b/pkg/middleware/recovery.go @@ -158,7 +158,7 @@ func Recovery(cfg *setting.Cfg) macaron.Handler { c.JSON(500, resp) } else { - c.HTML(500, cfg.ErrTemplateName) + c.HTML(500, cfg.ErrTemplateName, c.Data) } } }() diff --git a/pkg/middleware/recovery_test.go b/pkg/middleware/recovery_test.go index 0bc002b8b5d..c62079372b2 100644 --- a/pkg/middleware/recovery_test.go +++ b/pkg/middleware/recovery_test.go @@ -65,10 +65,7 @@ func recoveryScenario(t *testing.T, desc string, url string, fn scenarioFunc) { sc.m.Use(Recovery(cfg)) sc.m.Use(AddDefaultResponseHeaders(cfg)) - sc.m.Use(macaron.Renderer(macaron.RenderOptions{ - Directory: viewsPath, - Delims: macaron.Delims{Left: "[[", Right: "]]"}, - })) + sc.m.UseMiddleware(macaron.Renderer(viewsPath, "[[", "]]")) sc.userAuthTokenService = auth.NewFakeUserAuthTokenService() sc.remoteCacheService = remotecache.NewFakeStore(t) diff --git a/pkg/models/context.go b/pkg/models/context.go index 42f7036551e..a3bb6838985 100644 --- a/pkg/models/context.go +++ b/pkg/models/context.go @@ -36,7 +36,7 @@ func (ctx *ReqContext) Handle(cfg *setting.Cfg, status int, title string, err er ctx.Data["AppSubUrl"] = cfg.AppSubURL ctx.Data["Theme"] = "dark" - ctx.HTML(status, cfg.ErrTemplateName) + ctx.HTML(status, cfg.ErrTemplateName, ctx.Data) } func (ctx *ReqContext) IsApiRequest() bool { diff --git a/pkg/services/ngalert/notifier/alertmanager.go b/pkg/services/ngalert/notifier/alertmanager.go index afd395c71cf..f68cb3a8b6a 100644 --- a/pkg/services/ngalert/notifier/alertmanager.go +++ b/pkg/services/ngalert/notifier/alertmanager.go @@ -475,7 +475,7 @@ func (am *Alertmanager) buildReceiverIntegrations(receiver *apimodels.PostableAp n, err = channels.NewDiscordNotifier(cfg, tmpl) case "googlechat": n, err = channels.NewGoogleChatNotifier(cfg, tmpl) - case "line": + case "LINE": n, err = channels.NewLineNotifier(cfg, tmpl) case "threema": n, err = channels.NewThreemaNotifier(cfg, tmpl) diff --git a/pkg/tests/api/alerting/api_notification_channel_test.go b/pkg/tests/api/alerting/api_notification_channel_test.go index c7d9e59dc35..ee0c898af1f 100644 --- a/pkg/tests/api/alerting/api_notification_channel_test.go +++ b/pkg/tests/api/alerting/api_notification_channel_test.go @@ -723,7 +723,7 @@ const alertmanagerConfig = ` "grafana_managed_receiver_configs": [ { "name": "line_test", - "type": "line", + "type": "LINE", "settings": {}, "secureSettings": { "token": "mysecrettoken" @@ -1217,7 +1217,7 @@ var expAlertmanagerConfigFromAPI = ` { "uid": "", "name": "line_test", - "type": "line", + "type": "LINE", "disableResolveMessage": false, "settings": {}, "secureFields": { diff --git a/pkg/tsdb/testdatasource/testdata/usa-timeseries-wide.txt b/pkg/tsdb/testdatasource/testdata/usa-timeseries-wide.txt index 53a51e8d091..e6a63a4a612 100644 --- a/pkg/tsdb/testdatasource/testdata/usa-timeseries-wide.txt +++ b/pkg/tsdb/testdatasource/testdata/usa-timeseries-wide.txt @@ -3,23 +3,23 @@ Frame[0] Name: Dimensions: 7 Fields by 10 Rows -+-------------------------------+----------------------+----------------------+----------------------+----------------------+----------------------+----------------------+ -| Name: Time | Name: foo | Name: foo | Name: foo | Name: bar | Name: bar | Name: bar | -| Labels: | Labels: state=CA | Labels: state=OR | Labels: state=NV | Labels: state=CA | Labels: state=OR | Labels: state=NV | -| Type: []time.Time | Type: []float64 | Type: []float64 | Type: []float64 | Type: []float64 | Type: []float64 | Type: []float64 | -+-------------------------------+----------------------+----------------------+----------------------+----------------------+----------------------+----------------------+ -| 2020-01-10 23:00:00 +0000 UTC | 0.7591864109375384 | 0.9882682601465907 | 0 | 0.6508732545187114 | -0.1527280131044415 | 1 | -| 2020-01-10 23:00:01 +0000 UTC | 0.9913874643906261 | 0.7446917214252602 | 0.5458434494486994 | 0.13096142733310906 | -0.6674086005144695 | 0.8378871813639024 | -| 2020-01-10 23:00:02 +0000 UTC | 0.9021552854179972 | 0.25966703475349645 | 0.9147104586490411 | -0.4314114520876468 | -0.9656982091017495 | 0.40410985738788996 | -| 2020-01-10 23:00:03 +0000 UTC | 0.520421234112239 | -0.309548361739801 | 0.9870048864743552 | -0.8539096785287623 | -0.9508837004303972 | -0.16069024262768705 | -| 2020-01-10 23:00:04 +0000 UTC | -0.03004672347354234 | -0.7784002433814474 | 0.7392870259917509 | -0.9995484952759943 | -0.6277683180152559 | -0.6733904463238785 | -| 2020-01-10 23:00:05 +0000 UTC | -0.5707727629931729 | -0.994874810059912 | 0.2518733583799049 | -0.8211080641579032 | -0.10111435263232425 | -0.9677602034277024 | -| 2020-01-10 23:00:06 +0000 UTC | -0.9264396396937303 | -0.8887854574406474 | -0.31720410936455373 | -0.37644334766887727 | 0.4583234781701883 | -0.9483572918485101 | -| 2020-01-10 23:00:07 +0000 UTC | -0.981731033820365 | -0.4945290734844293 | -0.7834358726049309 | 0.19027395311496903 | 0.8691610871861625 | -0.6214726329580013 | -| 2020-01-10 23:00:08 +0000 UTC | -0.7187200578767007 | 0.060066314471906294 | -0.9956576407880757 | 0.6952995601938146 | 0.998194388817009 | -0.09309061359945539 | -| 2020-01-10 23:00:09 +0000 UTC | -0.22268161314765392 | 0.5951866633399958 | -0.8850616758817763 | 0.9748912242737435 | 0.8035874786121313 | 0.46547376927743367 | -+-------------------------------+----------------------+----------------------+----------------------+----------------------+----------------------+----------------------+ ++-------------------------------+------------------+------------------+------------------+------------------+------------------+------------------+ +| Name: Time | Name: foo | Name: foo | Name: foo | Name: bar | Name: bar | Name: bar | +| Labels: | Labels: state=CA | Labels: state=OR | Labels: state=NV | Labels: state=CA | Labels: state=OR | Labels: state=NV | +| Type: []time.Time | Type: []float64 | Type: []float64 | Type: []float64 | Type: []float64 | Type: []float64 | Type: []float64 | ++-------------------------------+------------------+------------------+------------------+------------------+------------------+------------------+ +| 2020-01-10 23:00:00 +0000 UTC | 0.7591864109 | 0.9882682601 | 0 | 0.6508732545 | -0.1527280131 | 1 | +| 2020-01-10 23:00:01 +0000 UTC | 0.9913874643 | 0.7446917214 | 0.5458434494 | 0.1309614273 | -0.6674086005 | 0.8378871813 | +| 2020-01-10 23:00:02 +0000 UTC | 0.9021552854 | 0.2596670347 | 0.9147104586 | -0.431411452 | -0.9656982091 | 0.4041098573 | +| 2020-01-10 23:00:03 +0000 UTC | 0.5204212341 | -0.3095483617 | 0.9870048864 | -0.8539096785 | -0.9508837004 | -0.1606902426 | +| 2020-01-10 23:00:04 +0000 UTC | -0.0300467234 | -0.7784002433 | 0.7392870259 | -0.9995484952 | -0.627768318 | -0.6733904463 | +| 2020-01-10 23:00:05 +0000 UTC | -0.5707727629 | -0.99487481 | 0.2518733583 | -0.8211080641 | -0.1011143526 | -0.9677602034 | +| 2020-01-10 23:00:06 +0000 UTC | -0.9264396396 | -0.8887854574 | -0.3172041093 | -0.3764433476 | 0.4583234781 | -0.9483572918 | +| 2020-01-10 23:00:07 +0000 UTC | -0.9817310338 | -0.4945290734 | -0.7834358726 | 0.1902739531 | 0.8691610871 | -0.6214726329 | +| 2020-01-10 23:00:08 +0000 UTC | -0.7187200578 | 0.0600663144 | -0.9956576407 | 0.6952995601 | 0.9981943888 | -0.0930906135 | +| 2020-01-10 23:00:09 +0000 UTC | -0.2226816131 | 0.5951866633 | -0.8850616758 | 0.9748912242 | 0.8035874786 | 0.4654737692 | ++-------------------------------+------------------+------------------+------------------+------------------+------------------+------------------+ ====== TEST DATA RESPONSE (arrow base64) ====== -FRAME=QVJST1cxAAD/////OAQAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAABU/P//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAHT8//8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAABwAAAEgDAACsAgAAJAIAAJwBAAAUAQAAjAAAAAQAAADm/P//FAAAAGgAAABoAAAAAAAAA2gAAAACAAAAKAAAAAQAAADY/P//CAAAAAwAAAADAAAAYmFyAAQAAABuYW1lAAAAAPj8//8IAAAAGAAAAA4AAAB7InN0YXRlIjoiTlYifQAABgAAAGxhYmVscwAAAAAAAPb8//8AAAIAAwAAAGJhcgBq/f//FAAAAGgAAABoAAAAAAAAA2gAAAACAAAAKAAAAAQAAABc/f//CAAAAAwAAAADAAAAYmFyAAQAAABuYW1lAAAAAHz9//8IAAAAGAAAAA4AAAB7InN0YXRlIjoiT1IifQAABgAAAGxhYmVscwAAAAAAAHr9//8AAAIAAwAAAGJhcgDu/f//FAAAAGgAAABoAAAAAAAAA2gAAAACAAAAKAAAAAQAAADg/f//CAAAAAwAAAADAAAAYmFyAAQAAABuYW1lAAAAAAD+//8IAAAAGAAAAA4AAAB7InN0YXRlIjoiQ0EifQAABgAAAGxhYmVscwAAAAAAAP79//8AAAIAAwAAAGJhcgBy/v//FAAAAGgAAABoAAAAAAAAA2gAAAACAAAAKAAAAAQAAABk/v//CAAAAAwAAAADAAAAZm9vAAQAAABuYW1lAAAAAIT+//8IAAAAGAAAAA4AAAB7InN0YXRlIjoiTlYifQAABgAAAGxhYmVscwAAAAAAAIL+//8AAAIAAwAAAGZvbwD2/v//FAAAAGgAAABoAAAAAAAAA2gAAAACAAAAKAAAAAQAAADo/v//CAAAAAwAAAADAAAAZm9vAAQAAABuYW1lAAAAAAj///8IAAAAGAAAAA4AAAB7InN0YXRlIjoiT1IifQAABgAAAGxhYmVscwAAAAAAAAb///8AAAIAAwAAAGZvbwB6////FAAAAGgAAABoAAAAAAAAA2gAAAACAAAAKAAAAAQAAABs////CAAAAAwAAAADAAAAZm9vAAQAAABuYW1lAAAAAIz///8IAAAAGAAAAA4AAAB7InN0YXRlIjoiQ0EifQAABgAAAGxhYmVscwAAAAAAAIr///8AAAIAAwAAAGZvbwAAABIAGAAUAAAAEwAMAAAACAAEABIAAAAUAAAARAAAAEwAAAAAAAAKTAAAAAEAAAAMAAAACAAMAAgABAAIAAAACAAAABAAAAAEAAAAVGltZQAAAAAEAAAAbmFtZQAAAAAAAAAAAAAGAAgABgAGAAAAAAADAAQAAABUaW1lAAAAAP////+oAQAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAMAIAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAA+AAAAAoAAAAAAAAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAUAAAAAAAAADwAAAAAAAAAAAAAAAAAAAA8AAAAAAAAABQAAAAAAAAAEABAAAAAAAAAAAAAAAAAABAAQAAAAAAAFAAAAAAAAAAkAEAAAAAAAAAAAAAAAAAAJABAAAAAAAAUAAAAAAAAADgAQAAAAAAAAAAAAAAAAAA4AEAAAAAAABQAAAAAAAAAAAAAAAHAAAACgAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVRGvRTEFL6D95Gyc0crnvPz8V2cJ03uw/Kv6Ubkqn4D9o6656kcSev4Qa0D3FQ+K/qXtGvmSl7b9vQXczV2rvv7Xo8TTB/+a/meHxwtSAzL9FJCDC5J/vPy7zo7uD1Oc/YWWHe2Ke0D8N+4zuo8/TvzyykKCn6Oi/AUqasgPW779/xhsz7nDsvwJbYkVdpt+/hwV/EAPBrj/M8MHmxAvjPwAAAAAAAAAAmsaDrox34T8KnibeTkXtPxrJjEWLle8/x7vfQz2o5z+cbD5vsR7QPwkq+HYSTdS/rD5rG+gR6b9KUKZpbdzvv6VdG91sUuy/Zfe/JfTT5D+ScrcTWMPAPyuGdcc+nNu/5JrgYzpT67+4Pj8gTfzvvzRIQWuERuq/pzbC1qUX2L8uaPSa5VrIP2qU/tzkP+Y/XDitFE8y7z+4urtul4zDv7rrCEhpW+W/pbo87v/m7r+OvHSno23uv/vkapWtFuS/h0i2VaHiub8nt27/K1XdP7Fzjekq0Os/46HgWzXx7z+Op4MW/bbpPwAAAAAAAPA/NEI2x/jP6j+2OF6X79zZP/Ckb3R/kcS//ssMH2qM5b8I9AI/5PfuvwYzLWTxWO6/bzw9kxrj479iZ/lUydS3v7pQDH5Syt0/EAAAAAwAFAASAAwACAAEAAwAAAAQAAAALAAAADwAAAAAAAMAAQAAAEgEAAAAAAAAsAEAAAAAAAAwAgAAAAAAAAAAAAAAAAAAAAAAAAAACgAMAAAACAAEAAoAAAAIAAAAUAAAAAIAAAAoAAAABAAAAFT8//8IAAAADAAAAAAAAAAAAAAABQAAAHJlZklkAAAAdPz//wgAAAAMAAAAAAAAAAAAAAAEAAAAbmFtZQAAAAAHAAAASAMAAKwCAAAkAgAAnAEAABQBAACMAAAABAAAAOb8//8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAANj8//8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAA+Pz//wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAA9vz//wAAAgADAAAAYmFyAGr9//8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAFz9//8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAfP3//wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAev3//wAAAgADAAAAYmFyAO79//8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAOD9//8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAP7//wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAA/v3//wAAAgADAAAAYmFyAHL+//8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAGT+//8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAhP7//wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAAgv7//wAAAgADAAAAZm9vAPb+//8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAOj+//8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAACP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAABv///wAAAgADAAAAZm9vAHr///8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAGz///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgADAAAAZm9vAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAaAQAAEFSUk9XMQ== +FRAME=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 diff --git a/pkg/tsdb/testdatasource/testdata/usa-timeseries.txt b/pkg/tsdb/testdatasource/testdata/usa-timeseries.txt index 7dcdc92daef..38fd2980802 100644 --- a/pkg/tsdb/testdatasource/testdata/usa-timeseries.txt +++ b/pkg/tsdb/testdatasource/testdata/usa-timeseries.txt @@ -3,138 +3,138 @@ Frame[0] Name: foo Dimensions: 2 Fields by 10 Rows -+-------------------------------+----------------------+ -| Name: Time | Name: Value | -| Labels: | Labels: state=CA | -| Type: []time.Time | Type: []float64 | -+-------------------------------+----------------------+ -| 2020-01-10 23:00:00 +0000 UTC | 0.7591864109375384 | -| 2020-01-10 23:00:01 +0000 UTC | 0.9913874643906261 | -| 2020-01-10 23:00:02 +0000 UTC | 0.9021552854179972 | -| 2020-01-10 23:00:03 +0000 UTC | 0.520421234112239 | -| 2020-01-10 23:00:04 +0000 UTC | -0.03004672347354234 | -| 2020-01-10 23:00:05 +0000 UTC | -0.5707727629931729 | -| 2020-01-10 23:00:06 +0000 UTC | -0.9264396396937303 | -| 2020-01-10 23:00:07 +0000 UTC | -0.981731033820365 | -| 2020-01-10 23:00:08 +0000 UTC | -0.7187200578767007 | -| 2020-01-10 23:00:09 +0000 UTC | -0.22268161314765392 | -+-------------------------------+----------------------+ ++-------------------------------+------------------+ +| Name: Time | Name: Value | +| Labels: | Labels: state=CA | +| Type: []time.Time | Type: []float64 | ++-------------------------------+------------------+ +| 2020-01-10 23:00:00 +0000 UTC | 0.7591864109 | +| 2020-01-10 23:00:01 +0000 UTC | 0.9913874643 | +| 2020-01-10 23:00:02 +0000 UTC | 0.9021552854 | +| 2020-01-10 23:00:03 +0000 UTC | 0.5204212341 | +| 2020-01-10 23:00:04 +0000 UTC | -0.0300467234 | +| 2020-01-10 23:00:05 +0000 UTC | -0.5707727629 | +| 2020-01-10 23:00:06 +0000 UTC | -0.9264396396 | +| 2020-01-10 23:00:07 +0000 UTC | -0.9817310338 | +| 2020-01-10 23:00:08 +0000 UTC | -0.7187200578 | +| 2020-01-10 23:00:09 +0000 UTC | -0.2226816131 | ++-------------------------------+------------------+ Frame[1] Name: foo Dimensions: 2 Fields by 10 Rows -+-------------------------------+----------------------+ -| Name: Time | Name: Value | -| Labels: | Labels: state=OR | -| Type: []time.Time | Type: []float64 | -+-------------------------------+----------------------+ -| 2020-01-10 23:00:00 +0000 UTC | 0.9882682601465907 | -| 2020-01-10 23:00:01 +0000 UTC | 0.7446917214252602 | -| 2020-01-10 23:00:02 +0000 UTC | 0.25966703475349645 | -| 2020-01-10 23:00:03 +0000 UTC | -0.309548361739801 | -| 2020-01-10 23:00:04 +0000 UTC | -0.7784002433814474 | -| 2020-01-10 23:00:05 +0000 UTC | -0.994874810059912 | -| 2020-01-10 23:00:06 +0000 UTC | -0.8887854574406474 | -| 2020-01-10 23:00:07 +0000 UTC | -0.4945290734844293 | -| 2020-01-10 23:00:08 +0000 UTC | 0.060066314471906294 | -| 2020-01-10 23:00:09 +0000 UTC | 0.5951866633399958 | -+-------------------------------+----------------------+ ++-------------------------------+------------------+ +| Name: Time | Name: Value | +| Labels: | Labels: state=OR | +| Type: []time.Time | Type: []float64 | ++-------------------------------+------------------+ +| 2020-01-10 23:00:00 +0000 UTC | 0.9882682601 | +| 2020-01-10 23:00:01 +0000 UTC | 0.7446917214 | +| 2020-01-10 23:00:02 +0000 UTC | 0.2596670347 | +| 2020-01-10 23:00:03 +0000 UTC | -0.3095483617 | +| 2020-01-10 23:00:04 +0000 UTC | -0.7784002433 | +| 2020-01-10 23:00:05 +0000 UTC | -0.99487481 | +| 2020-01-10 23:00:06 +0000 UTC | -0.8887854574 | +| 2020-01-10 23:00:07 +0000 UTC | -0.4945290734 | +| 2020-01-10 23:00:08 +0000 UTC | 0.0600663144 | +| 2020-01-10 23:00:09 +0000 UTC | 0.5951866633 | ++-------------------------------+------------------+ Frame[2] Name: foo Dimensions: 2 Fields by 10 Rows -+-------------------------------+----------------------+ -| Name: Time | Name: Value | -| Labels: | Labels: state=NV | -| Type: []time.Time | Type: []float64 | -+-------------------------------+----------------------+ -| 2020-01-10 23:00:00 +0000 UTC | 0 | -| 2020-01-10 23:00:01 +0000 UTC | 0.5458434494486994 | -| 2020-01-10 23:00:02 +0000 UTC | 0.9147104586490411 | -| 2020-01-10 23:00:03 +0000 UTC | 0.9870048864743552 | -| 2020-01-10 23:00:04 +0000 UTC | 0.7392870259917509 | -| 2020-01-10 23:00:05 +0000 UTC | 0.2518733583799049 | -| 2020-01-10 23:00:06 +0000 UTC | -0.31720410936455373 | -| 2020-01-10 23:00:07 +0000 UTC | -0.7834358726049309 | -| 2020-01-10 23:00:08 +0000 UTC | -0.9956576407880757 | -| 2020-01-10 23:00:09 +0000 UTC | -0.8850616758817763 | -+-------------------------------+----------------------+ ++-------------------------------+------------------+ +| Name: Time | Name: Value | +| Labels: | Labels: state=NV | +| Type: []time.Time | Type: []float64 | ++-------------------------------+------------------+ +| 2020-01-10 23:00:00 +0000 UTC | 0 | +| 2020-01-10 23:00:01 +0000 UTC | 0.5458434494 | +| 2020-01-10 23:00:02 +0000 UTC | 0.9147104586 | +| 2020-01-10 23:00:03 +0000 UTC | 0.9870048864 | +| 2020-01-10 23:00:04 +0000 UTC | 0.7392870259 | +| 2020-01-10 23:00:05 +0000 UTC | 0.2518733583 | +| 2020-01-10 23:00:06 +0000 UTC | -0.3172041093 | +| 2020-01-10 23:00:07 +0000 UTC | -0.7834358726 | +| 2020-01-10 23:00:08 +0000 UTC | -0.9956576407 | +| 2020-01-10 23:00:09 +0000 UTC | -0.8850616758 | ++-------------------------------+------------------+ Frame[3] Name: bar Dimensions: 2 Fields by 10 Rows -+-------------------------------+----------------------+ -| Name: Time | Name: Value | -| Labels: | Labels: state=CA | -| Type: []time.Time | Type: []float64 | -+-------------------------------+----------------------+ -| 2020-01-10 23:00:00 +0000 UTC | 0.6508732545187114 | -| 2020-01-10 23:00:01 +0000 UTC | 0.13096142733310906 | -| 2020-01-10 23:00:02 +0000 UTC | -0.4314114520876468 | -| 2020-01-10 23:00:03 +0000 UTC | -0.8539096785287623 | -| 2020-01-10 23:00:04 +0000 UTC | -0.9995484952759943 | -| 2020-01-10 23:00:05 +0000 UTC | -0.8211080641579032 | -| 2020-01-10 23:00:06 +0000 UTC | -0.37644334766887727 | -| 2020-01-10 23:00:07 +0000 UTC | 0.19027395311496903 | -| 2020-01-10 23:00:08 +0000 UTC | 0.6952995601938146 | -| 2020-01-10 23:00:09 +0000 UTC | 0.9748912242737435 | -+-------------------------------+----------------------+ ++-------------------------------+------------------+ +| Name: Time | Name: Value | +| Labels: | Labels: state=CA | +| Type: []time.Time | Type: []float64 | ++-------------------------------+------------------+ +| 2020-01-10 23:00:00 +0000 UTC | 0.6508732545 | +| 2020-01-10 23:00:01 +0000 UTC | 0.1309614273 | +| 2020-01-10 23:00:02 +0000 UTC | -0.431411452 | +| 2020-01-10 23:00:03 +0000 UTC | -0.8539096785 | +| 2020-01-10 23:00:04 +0000 UTC | -0.9995484952 | +| 2020-01-10 23:00:05 +0000 UTC | -0.8211080641 | +| 2020-01-10 23:00:06 +0000 UTC | -0.3764433476 | +| 2020-01-10 23:00:07 +0000 UTC | 0.1902739531 | +| 2020-01-10 23:00:08 +0000 UTC | 0.6952995601 | +| 2020-01-10 23:00:09 +0000 UTC | 0.9748912242 | ++-------------------------------+------------------+ Frame[4] Name: bar Dimensions: 2 Fields by 10 Rows -+-------------------------------+----------------------+ -| Name: Time | Name: Value | -| Labels: | Labels: state=OR | -| Type: []time.Time | Type: []float64 | -+-------------------------------+----------------------+ -| 2020-01-10 23:00:00 +0000 UTC | -0.1527280131044415 | -| 2020-01-10 23:00:01 +0000 UTC | -0.6674086005144695 | -| 2020-01-10 23:00:02 +0000 UTC | -0.9656982091017495 | -| 2020-01-10 23:00:03 +0000 UTC | -0.9508837004303972 | -| 2020-01-10 23:00:04 +0000 UTC | -0.6277683180152559 | -| 2020-01-10 23:00:05 +0000 UTC | -0.10111435263232425 | -| 2020-01-10 23:00:06 +0000 UTC | 0.4583234781701883 | -| 2020-01-10 23:00:07 +0000 UTC | 0.8691610871861625 | -| 2020-01-10 23:00:08 +0000 UTC | 0.998194388817009 | -| 2020-01-10 23:00:09 +0000 UTC | 0.8035874786121313 | -+-------------------------------+----------------------+ ++-------------------------------+------------------+ +| Name: Time | Name: Value | +| Labels: | Labels: state=OR | +| Type: []time.Time | Type: []float64 | ++-------------------------------+------------------+ +| 2020-01-10 23:00:00 +0000 UTC | -0.1527280131 | +| 2020-01-10 23:00:01 +0000 UTC | -0.6674086005 | +| 2020-01-10 23:00:02 +0000 UTC | -0.9656982091 | +| 2020-01-10 23:00:03 +0000 UTC | -0.9508837004 | +| 2020-01-10 23:00:04 +0000 UTC | -0.627768318 | +| 2020-01-10 23:00:05 +0000 UTC | -0.1011143526 | +| 2020-01-10 23:00:06 +0000 UTC | 0.4583234781 | +| 2020-01-10 23:00:07 +0000 UTC | 0.8691610871 | +| 2020-01-10 23:00:08 +0000 UTC | 0.9981943888 | +| 2020-01-10 23:00:09 +0000 UTC | 0.8035874786 | ++-------------------------------+------------------+ Frame[5] Name: bar Dimensions: 2 Fields by 10 Rows -+-------------------------------+----------------------+ -| Name: Time | Name: Value | -| Labels: | Labels: state=NV | -| Type: []time.Time | Type: []float64 | -+-------------------------------+----------------------+ -| 2020-01-10 23:00:00 +0000 UTC | 1 | -| 2020-01-10 23:00:01 +0000 UTC | 0.8378871813639024 | -| 2020-01-10 23:00:02 +0000 UTC | 0.40410985738788996 | -| 2020-01-10 23:00:03 +0000 UTC | -0.16069024262768705 | -| 2020-01-10 23:00:04 +0000 UTC | -0.6733904463238785 | -| 2020-01-10 23:00:05 +0000 UTC | -0.9677602034277024 | -| 2020-01-10 23:00:06 +0000 UTC | -0.9483572918485101 | -| 2020-01-10 23:00:07 +0000 UTC | -0.6214726329580013 | -| 2020-01-10 23:00:08 +0000 UTC | -0.09309061359945539 | -| 2020-01-10 23:00:09 +0000 UTC | 0.46547376927743367 | -+-------------------------------+----------------------+ ++-------------------------------+------------------+ +| Name: Time | Name: Value | +| Labels: | Labels: state=NV | +| Type: []time.Time | Type: []float64 | ++-------------------------------+------------------+ +| 2020-01-10 23:00:00 +0000 UTC | 1 | +| 2020-01-10 23:00:01 +0000 UTC | 0.8378871813 | +| 2020-01-10 23:00:02 +0000 UTC | 0.4041098573 | +| 2020-01-10 23:00:03 +0000 UTC | -0.1606902426 | +| 2020-01-10 23:00:04 +0000 UTC | -0.6733904463 | +| 2020-01-10 23:00:05 +0000 UTC | -0.9677602034 | +| 2020-01-10 23:00:06 +0000 UTC | -0.9483572918 | +| 2020-01-10 23:00:07 +0000 UTC | -0.6214726329 | +| 2020-01-10 23:00:08 +0000 UTC | -0.0930906135 | +| 2020-01-10 23:00:09 +0000 UTC | 0.4654737692 | ++-------------------------------+------------------+ ====== TEST DATA RESPONSE (arrow base64) ====== -FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVRGvRTEFL6D95Gyc0crnvPz8V2cJ03uw/Kv6Ubkqn4D9o6656kcSev4Qa0D3FQ+K/qXtGvmSl7b9vQXczV2rvv7Xo8TTB/+a/meHxwtSAzL8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== -FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVRSQgwuSf7z8u86O7g9TnP2Flh3tintA/DfuM7qPP0788spCgp+jovwFKmrID1u+/f8YbM+5w7L8CW2JFXabfv4cFfxADwa4/zPDB5sQL4z8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== -FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVAAAAAAAAAACaxoOujHfhPwqeJt5ORe0/GsmMRYuV7z/Hu99DPajnP5xsPm+xHtA/CSr4dhJN1L+sPmsb6BHpv0pQpmlt3O+/pV0b3WxS7L8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== -FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVZfe/JfTT5D+ScrcTWMPAPyuGdcc+nNu/5JrgYzpT67+4Pj8gTfzvvzRIQWuERuq/pzbC1qUX2L8uaPSa5VrIP2qU/tzkP+Y/XDitFE8y7z8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== -FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVuLq7bpeMw7+66whIaVvlv6W6PO7/5u6/jrx0p6Nt7r/75GqVrRbkv4dItlWh4rm/J7du/ytV3T+xc43pKtDrP+Oh4Fs18e8/jqeDFv226T8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== -FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVAAAAAAAA8D80QjbH+M/qP7Y4Xpfv3Nk/8KRvdH+RxL/+ywwfaozlvwj0Aj/k9+6/BjMtZPFY7r9vPD2TGuPjv2Jn+VTJ1Le/ulAMflLK3T8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== +FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVgULMTEFL6D/apho0crnvPwec1sJ03uw/i0+Tbkqn4D8Xemt5kcSev0lMwz3FQ+K/0Zk5vmSl7b/odHQzV2rvvwte5zTB/+a/6K7XwtSAzL8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== +FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVAb0ZwuSf7z9qeqC7g9TnP+eweHtintA/TgqC7qPP07+PgIWgp+jovwoOkrID1u+/WDAWM+5w7L/TJUtFXabfv+Ll4A8Dwa4/knG85sQL4z8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== +FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVAAAAAAAAAAAkFX2ujHfhP4/gH95ORe0/9ZCCRYuV7z+UH9NDPajnP851KG+xHtA/eGvmdhJN1L8vkWob6BHpv2Y1mmlt3O+/ZSAQ3WxS7L8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== +FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVDGW9JfTT5D/iPqUTWMPAP5JuXcc+nNu/6KbcYzpT67/ozDQgTfzvv+tSOWuERuq/2Eev1qUX2L96Leya5VrIP5yv8dzkP+Y/vRWjFE8y7z8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== +FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVokm5bpeMw7+g7gZIaVvlvxd9PO7/5u6/DY9wp6Nt7r82zGiVrRbkvw++klWh4rm/F2xb/ytV3T8enIHpKtDrP3BL3ls18e8/ufyBFv226T8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== +FRAME=QVJST1cxAAD/////mAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAAAAAAP////+4AAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAoAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAWAAAAAoAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAFAAAAAAAAAAAAAAAAIAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAABg5zW9qOgVACqCcb2o6BUA9BytvajoFQC+t+i9qOgVAIhSJL6o6BUAUu1fvqjoFQAciJu+qOgVAOYi176o6BUAsL0Sv6joFQB6WE6/qOgVAAAAAAAA8D/WeS3H+M/qPwEQRpfv3Nk/VWxgdH+RxL/Ygwkfaozlv1cl/z7k9+6/OYgmZPFY7r+yQzWTGuPjvy4NjFTJ1Le/0Qf3fVLK3T8QAAAADAAUABIADAAIAAQADAAAABAAAAAsAAAAOAAAAAAAAwABAAAAqAEAAAAAAADAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAAD4/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAABj///8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAgAAAKQAAAAEAAAAdv///xQAAABsAAAAbAAAAAAAAANsAAAAAgAAACwAAAAEAAAAaP///wgAAAAQAAAABQAAAFZhbHVlAAAABAAAAG5hbWUAAAAAjP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAAiv///wAAAgAFAAAAVmFsdWUAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAATAAAAAAAAApMAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABUaW1lAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAMABAAAAFRpbWUAAAAAwAEAAEFSUk9XMQ== diff --git a/pkg/tsdb/testdatasource/testdata/usa-values-as-fields.txt b/pkg/tsdb/testdatasource/testdata/usa-values-as-fields.txt index 8655d43df6d..7f3359e2f8d 100644 --- a/pkg/tsdb/testdatasource/testdata/usa-values-as-fields.txt +++ b/pkg/tsdb/testdatasource/testdata/usa-values-as-fields.txt @@ -3,28 +3,28 @@ Frame[0] Name: foo Dimensions: 3 Fields by 1 Rows -+--------------------+--------------------+----------------------+ -| Name: CA | Name: OR | Name: NV | -| Labels: | Labels: | Labels: | -| Type: []float64 | Type: []float64 | Type: []float64 | -+--------------------+--------------------+----------------------+ -| 0.3455559195129913 | 0.9373322369907638 | -0.48750602508751073 | -+--------------------+--------------------+----------------------+ ++-----------------+-----------------+-----------------+ +| Name: CA | Name: OR | Name: NV | +| Labels: | Labels: | Labels: | +| Type: []float64 | Type: []float64 | Type: []float64 | ++-----------------+-----------------+-----------------+ +| 0.3455559195 | 0.9373322369 | -0.487506025 | ++-----------------+-----------------+-----------------+ Frame[1] Name: bar Dimensions: 3 Fields by 1 Rows -+--------------------+--------------------+-------------------+ -| Name: CA | Name: OR | Name: NV | -| Labels: | Labels: | Labels: | -| Type: []float64 | Type: []float64 | Type: []float64 | -+--------------------+--------------------+-------------------+ -| 0.9383981598924473 | 0.3484369060502785 | 0.873119622676856 | -+--------------------+--------------------+-------------------+ ++-----------------+-----------------+-----------------+ +| Name: CA | Name: OR | Name: NV | +| Labels: | Labels: | Labels: | +| Type: []float64 | Type: []float64 | Type: []float64 | ++-----------------+-----------------+-----------------+ +| 0.9383981598 | 0.348436906 | 0.8731196226 | ++-----------------+-----------------+-----------------+ ====== TEST DATA RESPONSE (arrow base64) ====== -FRAME=QVJST1cxAAD/////sAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAADU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAPT+//8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAwAAAMgAAABcAAAABAAAAFb///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAARP///wgAAAAMAAAAAgAAAE5WAAAEAAAAbmFtZQAAAAAAAAAAOv///wAAAgACAAAATlYAAKr///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAAmP///wgAAAAMAAAAAgAAAE9SAAAEAAAAbmFtZQAAAAAAAAAAjv///wAAAgACAAAAT1IAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABAAAAASAAAAAAAAANIAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAADAAAAAIAAABDQQAABAAAAG5hbWUAAAAAAAAAAAAABgAIAAYABgAAAAAAAgACAAAAQ0EAAP/////oAAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAGAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAeAAAAAEAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAAAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAACPXT5OWHdY/S5TrLKD+7T/kpJZ4TDPfvxAAAAAMABQAEgAMAAgABAAMAAAAEAAAACwAAAA8AAAAAAADAAEAAADAAQAAAAAAAPAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAADU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAPT+//8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAwAAAMgAAABcAAAABAAAAFb///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAARP///wgAAAAMAAAAAgAAAE5WAAAEAAAAbmFtZQAAAAAAAAAAOv///wAAAgACAAAATlYAAKr///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAAmP///wgAAAAMAAAAAgAAAE9SAAAEAAAAbmFtZQAAAAAAAAAAjv///wAAAgACAAAAT1IAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABAAAAASAAAAAAAAANIAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAADAAAAAIAAABDQQAABAAAAG5hbWUAAAAAAAAAAAAABgAIAAYABgAAAAAAAgACAAAAQ0EAAOABAABBUlJPVzE= -FRAME=QVJST1cxAAD/////sAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAADU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAPT+//8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAwAAAMgAAABcAAAABAAAAFb///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAARP///wgAAAAMAAAAAgAAAE5WAAAEAAAAbmFtZQAAAAAAAAAAOv///wAAAgACAAAATlYAAKr///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAAmP///wgAAAAMAAAAAgAAAE9SAAAEAAAAbmFtZQAAAAAAAAAAjv///wAAAgACAAAAT1IAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABAAAAASAAAAAAAAANIAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAADAAAAAIAAABDQQAABAAAAG5hbWUAAAAAAAAAAAAABgAIAAYABgAAAAAAAgACAAAAQ0EAAP/////oAAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAGAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAeAAAAAEAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAAAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAACKr65NbB+4/yyQNT8pM1j8akxyQmPDrPxAAAAAMABQAEgAMAAgABAAMAAAAEAAAACwAAAA8AAAAAAADAAEAAADAAQAAAAAAAPAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAADU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAPT+//8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAwAAAMgAAABcAAAABAAAAFb///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAARP///wgAAAAMAAAAAgAAAE5WAAAEAAAAbmFtZQAAAAAAAAAAOv///wAAAgACAAAATlYAAKr///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAAmP///wgAAAAMAAAAAgAAAE9SAAAEAAAAbmFtZQAAAAAAAAAAjv///wAAAgACAAAAT1IAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABAAAAASAAAAAAAAANIAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAADAAAAAIAAABDQQAABAAAAG5hbWUAAAAAAAAAAAAABgAIAAYABgAAAAAAAgACAAAAQ0EAAOABAABBUlJPVzE= +FRAME=QVJST1cxAAD/////sAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAADU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAPT+//8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAwAAAMgAAABcAAAABAAAAFb///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAARP///wgAAAAMAAAAAgAAAE5WAAAEAAAAbmFtZQAAAAAAAAAAOv///wAAAgACAAAATlYAAKr///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAAmP///wgAAAAMAAAAAgAAAE9SAAAEAAAAbmFtZQAAAAAAAAAAjv///wAAAgACAAAAT1IAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABAAAAASAAAAAAAAANIAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAADAAAAAIAAABDQQAABAAAAG5hbWUAAAAAAAAAAAAABgAIAAYABgAAAAAAAgACAAAAQ0EAAP/////oAAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAGAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAeAAAAAEAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAAAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAPRETJOWHdY/0xrfLKD+7T/fln54TDPfvxAAAAAMABQAEgAMAAgABAAMAAAAEAAAACwAAAA8AAAAAAADAAEAAADAAQAAAAAAAPAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAADU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAPT+//8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAwAAAMgAAABcAAAABAAAAFb///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAARP///wgAAAAMAAAAAgAAAE5WAAAEAAAAbmFtZQAAAAAAAAAAOv///wAAAgACAAAATlYAAKr///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAAmP///wgAAAAMAAAAAgAAAE9SAAAEAAAAbmFtZQAAAAAAAAAAjv///wAAAgACAAAAT1IAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABAAAAASAAAAAAAAANIAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAADAAAAAIAAABDQQAABAAAAG5hbWUAAAAAAAAAAAAABgAIAAYABgAAAAAAAgACAAAAQ0EAAOABAABBUlJPVzE= +FRAME=QVJST1cxAAD/////sAEAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAADU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAPT+//8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAwAAAMgAAABcAAAABAAAAFb///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAARP///wgAAAAMAAAAAgAAAE5WAAAEAAAAbmFtZQAAAAAAAAAAOv///wAAAgACAAAATlYAAKr///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAAmP///wgAAAAMAAAAAgAAAE9SAAAEAAAAbmFtZQAAAAAAAAAAjv///wAAAgACAAAAT1IAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABAAAAASAAAAAAAAANIAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAADAAAAAIAAABDQQAABAAAAG5hbWUAAAAAAAAAAAAABgAIAAYABgAAAAAAAgACAAAAQ0EAAP/////oAAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAGAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAeAAAAAEAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAAAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAG723pNbB+4/wlL/TspM1j/4AhKQmPDrPxAAAAAMABQAEgAMAAgABAAMAAAAEAAAACwAAAA8AAAAAAADAAEAAADAAQAAAAAAAPAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAADU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAPT+//8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAwAAAMgAAABcAAAABAAAAFb///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAARP///wgAAAAMAAAAAgAAAE5WAAAEAAAAbmFtZQAAAAAAAAAAOv///wAAAgACAAAATlYAAKr///8UAAAAOAAAADgAAAAAAAADOAAAAAEAAAAEAAAAmP///wgAAAAMAAAAAgAAAE9SAAAEAAAAbmFtZQAAAAAAAAAAjv///wAAAgACAAAAT1IAAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABAAAAASAAAAAAAAANIAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAADAAAAAIAAABDQQAABAAAAG5hbWUAAAAAAAAAAAAABgAIAAYABgAAAAAAAgACAAAAQ0EAAOABAABBUlJPVzE= diff --git a/pkg/tsdb/testdatasource/testdata/usa-values-as-labeled-fields.txt b/pkg/tsdb/testdatasource/testdata/usa-values-as-labeled-fields.txt index 188181b1b47..c2503b1f5c2 100644 --- a/pkg/tsdb/testdatasource/testdata/usa-values-as-labeled-fields.txt +++ b/pkg/tsdb/testdatasource/testdata/usa-values-as-labeled-fields.txt @@ -3,28 +3,28 @@ Frame[0] Name: foo Dimensions: 3 Fields by 1 Rows -+--------------------+--------------------+----------------------+ -| Name: | Name: | Name: | -| Labels: state=CA | Labels: state=OR | Labels: state=NV | -| Type: []float64 | Type: []float64 | Type: []float64 | -+--------------------+--------------------+----------------------+ -| 0.3455559195129913 | 0.9373322369907638 | -0.48750602508751073 | -+--------------------+--------------------+----------------------+ ++------------------+------------------+------------------+ +| Name: | Name: | Name: | +| Labels: state=CA | Labels: state=OR | Labels: state=NV | +| Type: []float64 | Type: []float64 | Type: []float64 | ++------------------+------------------+------------------+ +| 0.3455559195 | 0.9373322369 | -0.487506025 | ++------------------+------------------+------------------+ Frame[1] Name: bar Dimensions: 3 Fields by 1 Rows -+--------------------+--------------------+-------------------+ -| Name: | Name: | Name: | -| Labels: state=CA | Labels: state=OR | Labels: state=NV | -| Type: []float64 | Type: []float64 | Type: []float64 | -+--------------------+--------------------+-------------------+ -| 0.9383981598924473 | 0.3484369060502785 | 0.873119622676856 | -+--------------------+--------------------+-------------------+ ++------------------+------------------+------------------+ +| Name: | Name: | Name: | +| Labels: state=CA | Labels: state=OR | Labels: state=NV | +| Type: []float64 | Type: []float64 | Type: []float64 | ++------------------+------------------+------------------+ +| 0.9383981598 | 0.348436906 | 0.8731196226 | ++------------------+------------------+------------------+ ====== TEST DATA RESPONSE (arrow base64) ====== -FRAME=QVJST1cxAAD/////QAIAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAABU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAHT+//8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAwAAACQBAACMAAAABAAAAPr+//8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAMj+//8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAA6P7//wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAA3v7//wAAAgAAAAAAAAAAAH7///8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAEz///8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAAbP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAYv///wAAAgAAAAAAAAASABgAFAAAABMADAAAAAgABAASAAAAFAAAAHAAAAB4AAAAAAAAA3gAAAACAAAAMAAAAAQAAADg////CAAAAAwAAAAAAAAAAAAAAAQAAABuYW1lAAAAAAgADAAIAAQACAAAAAgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAAAAGAAgABgAGAAAAAAACAAAAAAAAAAAAAAAAAP/////oAAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAGAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAeAAAAAEAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAAAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAACPXT5OWHdY/S5TrLKD+7T/kpJZ4TDPfvxAAAAAMABQAEgAMAAgABAAMAAAAEAAAACwAAAA4AAAAAAADAAEAAABQAgAAAAAAAPAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAACgAMAAAACAAEAAoAAAAIAAAAUAAAAAIAAAAoAAAABAAAAFT+//8IAAAADAAAAAAAAAAAAAAABQAAAHJlZklkAAAAdP7//wgAAAAMAAAAAwAAAGZvbwAEAAAAbmFtZQAAAAADAAAAJAEAAIwAAAAEAAAA+v7//xQAAABoAAAAaAAAAAAAAANoAAAAAgAAACgAAAAEAAAAyP7//wgAAAAMAAAAAAAAAAAAAAAEAAAAbmFtZQAAAADo/v//CAAAABgAAAAOAAAAeyJzdGF0ZSI6Ik5WIn0AAAYAAABsYWJlbHMAAAAAAADe/v//AAACAAAAAAAAAAAAfv///xQAAABoAAAAaAAAAAAAAANoAAAAAgAAACgAAAAEAAAATP///wgAAAAMAAAAAAAAAAAAAAAEAAAAbmFtZQAAAABs////CAAAABgAAAAOAAAAeyJzdGF0ZSI6Ik9SIn0AAAYAAABsYWJlbHMAAAAAAABi////AAACAAAAAAAAABIAGAAUAAAAEwAMAAAACAAEABIAAAAUAAAAcAAAAHgAAAAAAAADeAAAAAIAAAAwAAAABAAAAOD///8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAACAAMAAgABAAIAAAACAAAABgAAAAOAAAAeyJzdGF0ZSI6IkNBIn0AAAYAAABsYWJlbHMAAAAAAAAAAAYACAAGAAYAAAAAAAIAAAAAAAAAAABoAgAAQVJST1cx -FRAME=QVJST1cxAAD/////QAIAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAABU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAHT+//8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAwAAACQBAACMAAAABAAAAPr+//8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAMj+//8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAA6P7//wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAA3v7//wAAAgAAAAAAAAAAAH7///8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAEz///8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAAbP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAYv///wAAAgAAAAAAAAASABgAFAAAABMADAAAAAgABAASAAAAFAAAAHAAAAB4AAAAAAAAA3gAAAACAAAAMAAAAAQAAADg////CAAAAAwAAAAAAAAAAAAAAAQAAABuYW1lAAAAAAgADAAIAAQACAAAAAgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAAAAGAAgABgAGAAAAAAACAAAAAAAAAAAAAAAAAP/////oAAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAGAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAeAAAAAEAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAAAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAACKr65NbB+4/yyQNT8pM1j8akxyQmPDrPxAAAAAMABQAEgAMAAgABAAMAAAAEAAAACwAAAA4AAAAAAADAAEAAABQAgAAAAAAAPAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAACgAMAAAACAAEAAoAAAAIAAAAUAAAAAIAAAAoAAAABAAAAFT+//8IAAAADAAAAAAAAAAAAAAABQAAAHJlZklkAAAAdP7//wgAAAAMAAAAAwAAAGJhcgAEAAAAbmFtZQAAAAADAAAAJAEAAIwAAAAEAAAA+v7//xQAAABoAAAAaAAAAAAAAANoAAAAAgAAACgAAAAEAAAAyP7//wgAAAAMAAAAAAAAAAAAAAAEAAAAbmFtZQAAAADo/v//CAAAABgAAAAOAAAAeyJzdGF0ZSI6Ik5WIn0AAAYAAABsYWJlbHMAAAAAAADe/v//AAACAAAAAAAAAAAAfv///xQAAABoAAAAaAAAAAAAAANoAAAAAgAAACgAAAAEAAAATP///wgAAAAMAAAAAAAAAAAAAAAEAAAAbmFtZQAAAABs////CAAAABgAAAAOAAAAeyJzdGF0ZSI6Ik9SIn0AAAYAAABsYWJlbHMAAAAAAABi////AAACAAAAAAAAABIAGAAUAAAAEwAMAAAACAAEABIAAAAUAAAAcAAAAHgAAAAAAAADeAAAAAIAAAAwAAAABAAAAOD///8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAACAAMAAgABAAIAAAACAAAABgAAAAOAAAAeyJzdGF0ZSI6IkNBIn0AAAYAAABsYWJlbHMAAAAAAAAAAAYACAAGAAYAAAAAAAIAAAAAAAAAAABoAgAAQVJST1cx +FRAME=QVJST1cxAAD/////QAIAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAABU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAHT+//8IAAAADAAAAAMAAABmb28ABAAAAG5hbWUAAAAAAwAAACQBAACMAAAABAAAAPr+//8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAMj+//8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAA6P7//wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAA3v7//wAAAgAAAAAAAAAAAH7///8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAEz///8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAAbP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAYv///wAAAgAAAAAAAAASABgAFAAAABMADAAAAAgABAASAAAAFAAAAHAAAAB4AAAAAAAAA3gAAAACAAAAMAAAAAQAAADg////CAAAAAwAAAAAAAAAAAAAAAQAAABuYW1lAAAAAAgADAAIAAQACAAAAAgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAAAAGAAgABgAGAAAAAAACAAAAAAAAAAAAAAAAAP/////oAAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAGAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAeAAAAAEAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAAAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAPRETJOWHdY/0xrfLKD+7T/fln54TDPfvxAAAAAMABQAEgAMAAgABAAMAAAAEAAAACwAAAA4AAAAAAADAAEAAABQAgAAAAAAAPAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAACgAMAAAACAAEAAoAAAAIAAAAUAAAAAIAAAAoAAAABAAAAFT+//8IAAAADAAAAAAAAAAAAAAABQAAAHJlZklkAAAAdP7//wgAAAAMAAAAAwAAAGZvbwAEAAAAbmFtZQAAAAADAAAAJAEAAIwAAAAEAAAA+v7//xQAAABoAAAAaAAAAAAAAANoAAAAAgAAACgAAAAEAAAAyP7//wgAAAAMAAAAAAAAAAAAAAAEAAAAbmFtZQAAAADo/v//CAAAABgAAAAOAAAAeyJzdGF0ZSI6Ik5WIn0AAAYAAABsYWJlbHMAAAAAAADe/v//AAACAAAAAAAAAAAAfv///xQAAABoAAAAaAAAAAAAAANoAAAAAgAAACgAAAAEAAAATP///wgAAAAMAAAAAAAAAAAAAAAEAAAAbmFtZQAAAABs////CAAAABgAAAAOAAAAeyJzdGF0ZSI6Ik9SIn0AAAYAAABsYWJlbHMAAAAAAABi////AAACAAAAAAAAABIAGAAUAAAAEwAMAAAACAAEABIAAAAUAAAAcAAAAHgAAAAAAAADeAAAAAIAAAAwAAAABAAAAOD///8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAACAAMAAgABAAIAAAACAAAABgAAAAOAAAAeyJzdGF0ZSI6IkNBIn0AAAYAAABsYWJlbHMAAAAAAAAAAAYACAAGAAYAAAAAAAIAAAAAAAAAAABoAgAAQVJST1cx +FRAME=QVJST1cxAAD/////QAIAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEDAAoADAAAAAgABAAKAAAACAAAAFAAAAACAAAAKAAAAAQAAABU/v//CAAAAAwAAAAAAAAAAAAAAAUAAAByZWZJZAAAAHT+//8IAAAADAAAAAMAAABiYXIABAAAAG5hbWUAAAAAAwAAACQBAACMAAAABAAAAPr+//8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAMj+//8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAA6P7//wgAAAAYAAAADgAAAHsic3RhdGUiOiJOViJ9AAAGAAAAbGFiZWxzAAAAAAAA3v7//wAAAgAAAAAAAAAAAH7///8UAAAAaAAAAGgAAAAAAAADaAAAAAIAAAAoAAAABAAAAEz///8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAAbP///wgAAAAYAAAADgAAAHsic3RhdGUiOiJPUiJ9AAAGAAAAbGFiZWxzAAAAAAAAYv///wAAAgAAAAAAAAASABgAFAAAABMADAAAAAgABAASAAAAFAAAAHAAAAB4AAAAAAAAA3gAAAACAAAAMAAAAAQAAADg////CAAAAAwAAAAAAAAAAAAAAAQAAABuYW1lAAAAAAgADAAIAAQACAAAAAgAAAAYAAAADgAAAHsic3RhdGUiOiJDQSJ9AAAGAAAAbGFiZWxzAAAAAAAAAAAGAAgABgAGAAAAAAACAAAAAAAAAAAAAAAAAP/////oAAAAFAAAAAAAAAAMABYAFAATAAwABAAMAAAAGAAAAAAAAAAUAAAAAAAAAwMACgAYAAwACAAEAAoAAAAUAAAAeAAAAAEAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAACAAAAAAAAAAAAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAG723pNbB+4/wlL/TspM1j/4AhKQmPDrPxAAAAAMABQAEgAMAAgABAAMAAAAEAAAACwAAAA4AAAAAAADAAEAAABQAgAAAAAAAPAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAACgAMAAAACAAEAAoAAAAIAAAAUAAAAAIAAAAoAAAABAAAAFT+//8IAAAADAAAAAAAAAAAAAAABQAAAHJlZklkAAAAdP7//wgAAAAMAAAAAwAAAGJhcgAEAAAAbmFtZQAAAAADAAAAJAEAAIwAAAAEAAAA+v7//xQAAABoAAAAaAAAAAAAAANoAAAAAgAAACgAAAAEAAAAyP7//wgAAAAMAAAAAAAAAAAAAAAEAAAAbmFtZQAAAADo/v//CAAAABgAAAAOAAAAeyJzdGF0ZSI6Ik5WIn0AAAYAAABsYWJlbHMAAAAAAADe/v//AAACAAAAAAAAAAAAfv///xQAAABoAAAAaAAAAAAAAANoAAAAAgAAACgAAAAEAAAATP///wgAAAAMAAAAAAAAAAAAAAAEAAAAbmFtZQAAAABs////CAAAABgAAAAOAAAAeyJzdGF0ZSI6Ik9SIn0AAAYAAABsYWJlbHMAAAAAAABi////AAACAAAAAAAAABIAGAAUAAAAEwAMAAAACAAEABIAAAAUAAAAcAAAAHgAAAAAAAADeAAAAAIAAAAwAAAABAAAAOD///8IAAAADAAAAAAAAAAAAAAABAAAAG5hbWUAAAAACAAMAAgABAAIAAAACAAAABgAAAAOAAAAeyJzdGF0ZSI6IkNBIn0AAAYAAABsYWJlbHMAAAAAAAAAAAYACAAGAAYAAAAAAAIAAAAAAAAAAABoAgAAQVJST1cx diff --git a/pkg/tsdb/testdatasource/testdata/usa-values-as-rows.txt b/pkg/tsdb/testdatasource/testdata/usa-values-as-rows.txt index e9fb0e991d5..29748c7bf0b 100644 --- a/pkg/tsdb/testdatasource/testdata/usa-values-as-rows.txt +++ b/pkg/tsdb/testdatasource/testdata/usa-values-as-rows.txt @@ -3,23 +3,23 @@ Frame[0] Name: Dimensions: 4 Fields by 51 Rows -+----------------+----------------------+----------------------+---------------------+ -| Name: state | Name: foo | Name: bar | Name: baz | -| Labels: | Labels: | Labels: | Labels: | -| Type: []string | Type: []float64 | Type: []float64 | Type: []float64 | -+----------------+----------------------+----------------------+---------------------+ -| AL | 0.6779842417778559 | 0.7350764367743711 | 0.9223316213929472 | -| AK | 0.9096030926893556 | -0.41547829518515106 | -2.1892914822036755 | -| AZ | -0.11168671678088725 | -0.9937434665418967 | 0.11238988787472795 | -| AR | -0.9791366197808846 | -0.2032030506760749 | 4.818513386109159 | -| CA | -0.4979007493043646 | 0.8672340190756773 | -0.5741250208738828 | -| CO | 0.6691553056325918 | 0.74312258540819 | 0.9004642286104536 | -| CT | 0.914501128595007 | -0.4045833483949364 | -2.260352859856979 | -| DE | -0.09980837850296802 | -0.9950066771537809 | 0.10030925499763493 | -| DC | -0.976639481217665 | -0.21488444272885437 | 4.544952016140177 | -| ... | ... | ... | ... | -+----------------+----------------------+----------------------+---------------------+ ++----------------+-----------------+-----------------+-----------------+ +| Name: state | Name: foo | Name: bar | Name: baz | +| Labels: | Labels: | Labels: | Labels: | +| Type: []string | Type: []float64 | Type: []float64 | Type: []float64 | ++----------------+-----------------+-----------------+-----------------+ +| AL | 0.6779842417 | 0.7350764367 | 0.9223316213 | +| AK | 0.9096030926 | -0.4154782951 | -2.1892914822 | +| AZ | -0.1116867167 | -0.9937434665 | 0.1123898878 | +| AR | -0.9791366197 | -0.2032030506 | 4.8185133861 | +| CA | -0.4979007493 | 0.867234019 | -0.5741250208 | +| CO | 0.6691553056 | 0.7431225854 | 0.9004642286 | +| CT | 0.9145011285 | -0.4045833483 | -2.2603528598 | +| DE | -0.0998083785 | -0.9950066771 | 0.1003092549 | +| DC | -0.9766394812 | -0.2148844427 | 4.5449520161 | +| ... | ... | ... | ... | ++----------------+-----------------+-----------------+-----------------+ ====== TEST DATA RESPONSE (arrow base64) ====== -FRAME=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 +FRAME=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 diff --git a/pkg/tsdb/testdatasource/usa_stats.go b/pkg/tsdb/testdatasource/usa_stats.go index 729479f665e..57dee9aed72 100644 --- a/pkg/tsdb/testdatasource/usa_stats.go +++ b/pkg/tsdb/testdatasource/usa_stats.go @@ -192,7 +192,10 @@ func getStateValues(t time.Time, field string, query usaQuery) []float64 { values := make([]float64, len(query.States)) for i := range query.States { tv += incr - values[i] = fn(float64(int64(tv) % int64(pn))) + value := fn(float64(int64(tv) % int64(pn))) + // We shall truncate float64 to a certain precision, because otherwise we might + // get different cos/tan results across different CPU architectures and compilers. + values[i] = float64(int(value*1e10)) / 1e10 } return values } diff --git a/public/app/features/alerting/unified/AmRoutes.test.tsx b/public/app/features/alerting/unified/AmRoutes.test.tsx index 0f103cc2964..91a379a106e 100644 --- a/public/app/features/alerting/unified/AmRoutes.test.tsx +++ b/public/app/features/alerting/unified/AmRoutes.test.tsx @@ -15,20 +15,6 @@ import { DataSourceType, GRAFANA_RULES_SOURCE_NAME } from './utils/datasource'; import userEvent from '@testing-library/user-event'; import { selectOptionInTest } from '@grafana/ui'; -Object.defineProperty(window, 'matchMedia', { - writable: true, - value: jest.fn().mockImplementation((query) => ({ - matches: false, - media: query, - onchange: null, - addListener: jest.fn(), // deprecated - removeListener: jest.fn(), // deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn(), - })), -}); - jest.mock('./api/alertmanager'); jest.mock('./utils/config'); diff --git a/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx b/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx new file mode 100644 index 00000000000..f584e1d80c0 --- /dev/null +++ b/public/app/features/alerting/unified/PanelAlertTabContent.test.tsx @@ -0,0 +1,273 @@ +import React from 'react'; +import { locationService, setDataSourceSrv } from '@grafana/runtime'; +import { configureStore } from 'app/store/configureStore'; +import { Provider } from 'react-redux'; +import { Router } from 'react-router-dom'; +import { render } from '@testing-library/react'; +import { PanelAlertTabContent } from './PanelAlertTabContent'; +import { DashboardModel, PanelModel } from 'app/features/dashboard/state'; +import { + mockDataSource, + MockDataSourceSrv, + mockPromAlertingRule, + mockPromRuleGroup, + mockPromRuleNamespace, + mockRulerGrafanaRule, +} from './mocks'; +import { DataSourceType } from './utils/datasource'; +import { typeAsJestMock } from 'test/helpers/typeAsJestMock'; +import { getAllDataSources } from './utils/config'; +import { fetchRules } from './api/prometheus'; +import { fetchRulerRules } from './api/ruler'; +import { Annotation } from './utils/constants'; +import { byTestId } from 'testing-library-selector'; +import { PrometheusDatasource } from 'app/plugins/datasource/prometheus/datasource'; +import { DataSourceApi } from '@grafana/data'; +import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; + +jest.mock('./api/prometheus'); +jest.mock('./api/ruler'); +jest.mock('./utils/config'); + +const dataSources = { + prometheus: mockDataSource({ + name: 'Prometheus', + type: DataSourceType.Prometheus, + }), +}; +dataSources.prometheus.meta.alerting = true; + +const mocks = { + getAllDataSources: typeAsJestMock(getAllDataSources), + api: { + fetchRules: typeAsJestMock(fetchRules), + fetchRulerRules: typeAsJestMock(fetchRulerRules), + }, +}; + +const renderAlertTabContent = (dashboard: DashboardModel, panel: PanelModel) => { + const store = configureStore(); + + return render( + + + + + + ); +}; + +const rules = [ + mockPromRuleNamespace({ + name: 'default', + groups: [ + mockPromRuleGroup({ + name: 'mygroup', + rules: [ + mockPromAlertingRule({ + name: 'dashboardrule1', + annotations: { + [Annotation.dashboardUID]: '12', + [Annotation.panelID]: '34', + }, + }), + ], + }), + mockPromRuleGroup({ + name: 'othergroup', + rules: [ + mockPromAlertingRule({ + name: 'dashboardrule2', + annotations: { + [Annotation.dashboardUID]: '121', + [Annotation.panelID]: '341', + }, + }), + ], + }), + ], + }), +]; + +const rulerRules = { + default: [ + { + name: 'mygroup', + rules: [ + mockRulerGrafanaRule( + { + annotations: { + [Annotation.dashboardUID]: '12', + [Annotation.panelID]: '34', + }, + }, + { + title: 'dashboardrule1', + } + ), + ], + }, + { + name: 'othergroup', + rules: [ + mockRulerGrafanaRule( + { + annotations: { + [Annotation.dashboardUID]: '121', + [Annotation.panelID]: '341', + }, + }, + { + title: 'dashboardrule2', + } + ), + ], + }, + ], +}; + +const dashboard = { + uid: '12', + time: { + from: 'now-6h', + to: 'now', + }, + meta: { + canSave: true, + folderId: 1, + folderTitle: 'super folder', + }, +} as DashboardModel; +const panel = ({ + datasource: dataSources.prometheus.uid, + title: 'mypanel', + editSourceId: 34, + targets: [ + { + expr: 'sum(some_metric [$__interval])) by (app)', + refId: 'A', + }, + ], +} as any) as PanelModel; + +const ui = { + row: byTestId('row'), + createButton: byTestId('create-alert-rule-button'), +}; + +describe('PanelAlertTabContent', () => { + beforeEach(() => { + jest.resetAllMocks(); + mocks.getAllDataSources.mockReturnValue(Object.values(dataSources)); + const dsService = new MockDataSourceSrv(dataSources); + dsService.datasources[dataSources.prometheus.name] = new PrometheusDatasource( + dataSources.prometheus + ) as DataSourceApi; + setDataSourceSrv(dsService); + }); + + it('Will take into account panel maxDataPoints', async () => { + await renderAlertTabContent(dashboard, ({ + ...panel, + maxDataPoints: 100, + interval: '10s', + } as any) as PanelModel); + const button = await ui.createButton.find(); + const href = button.href; + const match = href.match(/alerting\/new\?defaults=(.*)&returnTo=/); + expect(match).toHaveLength(2); + const defaults = JSON.parse(decodeURIComponent(match![1])); + expect(defaults.queries[0].model).toEqual({ + expr: 'sum(some_metric [5m])) by (app)', + refId: 'A', + datasource: 'Prometheus', + interval: '', + intervalMs: 300000, + maxDataPoints: 100, + }); + }); + + it('Will take into account datasource minInterval', async () => { + ((getDatasourceSrv() as any) as MockDataSourceSrv).datasources[dataSources.prometheus.name].interval = '7m'; + + await renderAlertTabContent(dashboard, ({ + ...panel, + maxDataPoints: 100, + } as any) as PanelModel); + const button = await ui.createButton.find(); + const href = button.href; + const match = href.match(/alerting\/new\?defaults=(.*)&returnTo=/); + expect(match).toHaveLength(2); + const defaults = JSON.parse(decodeURIComponent(match![1])); + expect(defaults.queries[0].model).toEqual({ + expr: 'sum(some_metric [7m])) by (app)', + refId: 'A', + datasource: 'Prometheus', + interval: '', + intervalMs: 420000, + maxDataPoints: 100, + }); + }); + + it('Will render alerts belonging to panel and a button to create alert from panel queries', async () => { + mocks.api.fetchRules.mockResolvedValue(rules); + mocks.api.fetchRulerRules.mockResolvedValue(rulerRules); + + await renderAlertTabContent(dashboard, panel); + + const rows = await ui.row.findAll(); + expect(rows).toHaveLength(1); + expect(rows[0]).toHaveTextContent(/dashboardrule1/); + expect(rows[0]).not.toHaveTextContent(/dashboardrule2/); + const button = await ui.createButton.find(); + const href = button.href; + const match = href.match(/alerting\/new\?defaults=(.*)&returnTo=/); + expect(match).toHaveLength(2); + const defaults = JSON.parse(decodeURIComponent(match![1])); + expect(defaults).toEqual({ + type: 'grafana', + folder: { id: 1, title: 'super folder' }, + queries: [ + { + refId: 'A', + queryType: '', + relativeTimeRange: { from: 21600, to: 0 }, + datasourceUid: 'mock-ds-2', + model: { + expr: 'sum(some_metric [15s])) by (app)', + refId: 'A', + datasource: 'Prometheus', + interval: '', + intervalMs: 15000, + }, + }, + { + refId: 'B', + datasourceUid: '-100', + queryType: '', + model: { + refId: 'B', + hide: false, + type: 'classic_conditions', + datasource: '__expr__', + conditions: [ + { + type: 'query', + evaluator: { params: [3], type: 'gt' }, + operator: { type: 'and' }, + query: { params: ['A'] }, + reducer: { params: [], type: 'last' }, + }, + ], + }, + }, + ], + name: 'mypanel', + condition: 'B', + annotations: [ + { key: '__dashboardUid__', value: '12' }, + { key: '__panelId__', value: '34' }, + ], + }); + }); +}); diff --git a/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.tsx b/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.tsx index fb11e355d08..234dc3c3175 100644 --- a/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.tsx +++ b/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.tsx @@ -1,9 +1,10 @@ import { DashboardModel, PanelModel } from 'app/features/dashboard/state'; import React, { FC } from 'react'; -import { Alert, LinkButton } from '@grafana/ui'; +import { Alert, LinkButton, Button } from '@grafana/ui'; import { panelToRuleFormValues } from '../../utils/rule-form'; import { useLocation } from 'react-router-dom'; import { urlUtil } from '@grafana/data'; +import { useAsync } from 'react-use'; interface Props { panel: PanelModel; @@ -12,8 +13,11 @@ interface Props { } export const NewRuleFromPanelButton: FC = ({ dashboard, panel, className }) => { - const formValues = panelToRuleFormValues(panel, dashboard); + const { loading, value: formValues } = useAsync(() => panelToRuleFormValues(panel, dashboard), [panel, dashboard]); const location = useLocation(); + if (loading) { + return ; + } if (!formValues) { return ( @@ -29,7 +33,7 @@ export const NewRuleFromPanelButton: FC = ({ dashboard, panel, className }); return ( - + Create alert rule from this panel ); diff --git a/public/app/features/alerting/unified/mocks.ts b/public/app/features/alerting/unified/mocks.ts index 70dc72ad90a..bd8c0f0bc20 100644 --- a/public/app/features/alerting/unified/mocks.ts +++ b/public/app/features/alerting/unified/mocks.ts @@ -1,5 +1,11 @@ import { DataSourceApi, DataSourceInstanceSettings, DataSourcePluginMeta, ScopedVars } from '@grafana/data'; -import { PromAlertingRuleState, PromRuleType } from 'app/types/unified-alerting-dto'; +import { + GrafanaAlertStateDecision, + GrafanaRuleDefinition, + PromAlertingRuleState, + PromRuleType, + RulerGrafanaRuleDTO, +} from 'app/types/unified-alerting-dto'; import { AlertingRule, Alert, RecordingRule, RuleGroup, RuleNamespace } from 'app/types/unified-alerting'; import DatasourceSrv from 'app/features/plugins/datasource_srv'; import { DataSourceSrv, GetDataSourceListFilters } from '@grafana/runtime'; @@ -17,7 +23,7 @@ let nextDataSourceId = 1; export const mockDataSource = ( partial: Partial = {}, meta: Partial = {} -): DataSourceInstanceSettings => { +): DataSourceInstanceSettings => { const id = partial.id ?? nextDataSourceId++; return { @@ -54,6 +60,40 @@ export const mockPromAlert = (partial: Partial = {}): Alert => ({ ...partial, }); +export const mockRulerGrafanaRule = ( + partial: Partial = {}, + partialDef: Partial = {} +): RulerGrafanaRuleDTO => { + return { + for: '1m', + grafana_alert: { + uid: '123', + title: 'myalert', + namespace_uid: '123', + namespace_id: 1, + condition: 'A', + no_data_state: GrafanaAlertStateDecision.Alerting, + exec_err_state: GrafanaAlertStateDecision.Alerting, + data: [ + { + datasourceUid: '123', + refId: 'A', + queryType: 'huh', + model: {} as any, + }, + ], + ...partialDef, + }, + annotations: { + message: 'alert with severity "{{.warning}}}"', + }, + labels: { + severity: 'warning', + }, + ...partial, + }; +}; + export const mockPromAlertingRule = (partial: Partial = {}): AlertingRule => { return { type: PromRuleType.Alerting, diff --git a/public/app/features/alerting/unified/utils/rule-form.ts b/public/app/features/alerting/unified/utils/rule-form.ts index e5006b801ea..5ce60e559b7 100644 --- a/public/app/features/alerting/unified/utils/rule-form.ts +++ b/public/app/features/alerting/unified/utils/rule-form.ts @@ -1,11 +1,18 @@ -import { DataQuery, rangeUtil, RelativeTimeRange } from '@grafana/data'; +import { + DataQuery, + rangeUtil, + RelativeTimeRange, + ScopedVars, + getDefaultRelativeTimeRange, + TimeRange, + IntervalValues, +} from '@grafana/data'; import { getDataSourceSrv } from '@grafana/runtime'; import { contextSrv } from 'app/core/services/context_srv'; import { getNextRefIdChar } from 'app/core/utils/query'; import { DashboardModel, PanelModel } from 'app/features/dashboard/state'; import { ExpressionDatasourceID, ExpressionDatasourceUID } from 'app/features/expressions/ExpressionDatasource'; import { ExpressionQuery, ExpressionQueryType } from 'app/features/expressions/types'; -import { getDatasourceSrv } from 'app/features/plugins/datasource_srv'; import { RuleWithLocation } from 'app/types/unified-alerting'; import { Annotations, @@ -22,7 +29,6 @@ import { isGrafanaRulesSource } from './datasource'; import { arrayToRecord, recordToArray } from './misc'; import { isAlertingRulerRule, isGrafanaRulerRule } from './rules'; import { parseInterval } from './time'; -import { getDefaultRelativeTimeRange } from '../../../../../../packages/grafana-data'; export const getDefaultFormValues = (): RuleFormValues => Object.freeze({ @@ -193,60 +199,81 @@ const getDefaultExpression = (refId: string): AlertQuery => { }; }; -const dataQueriesToGrafanaQueries = ( +const dataQueriesToGrafanaQueries = async ( queries: DataQuery[], relativeTimeRange: RelativeTimeRange, - datasourceName?: string -): AlertQuery[] => { - return queries.reduce((queries, target) => { + scopedVars: ScopedVars | {}, + datasourceName?: string, + maxDataPoints?: number, + minInterval?: string +): Promise => { + const result: AlertQuery[] = []; + for (const target of queries) { const dsName = target.datasource || datasourceName; + const datasource = await getDataSourceSrv().get(dsName); + + const range = rangeUtil.relativeToTimeRange(relativeTimeRange); + const { interval, intervalMs } = getIntervals(range, minInterval ?? datasource.interval, maxDataPoints); + const queryVariables = { + __interval: { text: interval, value: interval }, + __interval_ms: { text: intervalMs, value: intervalMs }, + ...scopedVars, + }; + const interpolatedTarget = datasource.interpolateVariablesInQueries + ? await datasource.interpolateVariablesInQueries([target], queryVariables)[0] + : target; if (dsName) { // expressions if (dsName === ExpressionDatasourceID) { const newQuery: AlertQuery = { - refId: target.refId, + refId: interpolatedTarget.refId, queryType: '', relativeTimeRange, datasourceUid: ExpressionDatasourceUID, - model: target, + model: interpolatedTarget, }; - return [...queries, newQuery]; + result.push(newQuery); // queries } else { - const datasource = getDataSourceSrv().getInstanceSettings(target.datasource || datasourceName); - if (datasource && datasource.meta.alerting) { + const datasourceSettings = getDataSourceSrv().getInstanceSettings(dsName); + if (datasourceSettings && datasourceSettings.meta.alerting) { const newQuery: AlertQuery = { - refId: target.refId, - queryType: target.queryType ?? '', + refId: interpolatedTarget.refId, + queryType: interpolatedTarget.queryType ?? '', relativeTimeRange, - datasourceUid: datasource.uid, - model: target, + datasourceUid: datasourceSettings.uid, + model: { + ...interpolatedTarget, + maxDataPoints, + intervalMs, + }, }; - return [...queries, newQuery]; + result.push(newQuery); } } } - return queries; - }, []); + } + return result; }; -export const panelToRuleFormValues = ( +export const panelToRuleFormValues = async ( panel: PanelModel, dashboard: DashboardModel -): Partial | undefined => { +): Promise | undefined> => { const { targets } = panel; - - // it seems if default datasource is selected, datasource=null, hah - const datasourceName = - panel.datasource === null ? getDatasourceSrv().getInstanceSettings('default')?.name : panel.datasource; - if (!panel.editSourceId || !dashboard.uid) { return undefined; } const relativeTimeRange = rangeUtil.timeRangeToRelative(rangeUtil.convertRawToRange(dashboard.time)); - const queries = dataQueriesToGrafanaQueries(targets, relativeTimeRange, datasourceName); - + const queries = await dataQueriesToGrafanaQueries( + targets, + relativeTimeRange, + panel.scopedVars || {}, + panel.datasource ?? undefined, + panel.maxDataPoints ?? undefined, + panel.interval ?? undefined + ); // if no alerting capable queries are found, can't create a rule if (!queries.length || !queries.find((query) => query.datasourceUid !== ExpressionDatasourceUID)) { return undefined; @@ -269,6 +296,7 @@ export const panelToRuleFormValues = ( : undefined, queries, name: panel.title, + condition: queries[queries.length - 1].refId, annotations: [ { key: Annotation.dashboardUID, @@ -282,3 +310,17 @@ export const panelToRuleFormValues = ( }; return formValues; }; + +export function getIntervals(range: TimeRange, lowLimit?: string, resolution?: number): IntervalValues { + if (!resolution) { + if (lowLimit && rangeUtil.intervalToMs(lowLimit) > 1000) { + return { + interval: lowLimit, + intervalMs: rangeUtil.intervalToMs(lowLimit), + }; + } + return { interval: '1s', intervalMs: 1000 }; + } + + return rangeUtil.calculateInterval(range, resolution, lowLimit); +} diff --git a/public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx b/public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx index b783570759b..203af35cf60 100644 --- a/public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx +++ b/public/app/features/dashboard/components/SubMenu/DashboardLinksDashboard.tsx @@ -1,5 +1,5 @@ import React, { useRef, useState, useLayoutEffect } from 'react'; -import { Icon, Tooltip } from '@grafana/ui'; +import { Icon, ToolbarButton, Tooltip, useStyles2 } from '@grafana/ui'; import { sanitize, sanitizeUrl } from '@grafana/data/src/text/sanitize'; import { getBackendSrv } from 'app/core/services/backend_srv'; import { getLinkSrv } from '../../../panel/panellinks/link_srv'; @@ -7,6 +7,7 @@ import { DashboardLink } from '../../state/DashboardModel'; import { DashboardSearchHit } from 'app/features/search/types'; import { selectors } from '@grafana/e2e-selectors'; import { useAsync } from 'react-use'; +import { css, cx } from '@emotion/css'; interface Props { link: DashboardLink; @@ -21,33 +22,45 @@ export const DashboardLinksDashboard: React.FC = (props) => { const [opened, setOpened] = useState(0); const resolvedLinks = useResolvedLinks(props, opened); + const buttonStyle = useStyles2( + (theme) => + css` + color: ${theme.colors.text.primary}; + ` + ); + useLayoutEffect(() => { setDropdownCssClass(getDropdownLocationCssClass(listRef.current)); }, [resolvedLinks]); if (link.asDropdown) { return ( - + <> - setOpened(Date.now())} - className="gf-form-label gf-form-label--dashlink" + className={cx('gf-form-label gf-form-label--dashlink', buttonStyle)} data-placement="bottom" data-toggle="dropdown" + aria-expanded={!!opened} + aria-controls="dropdown-list" + aria-haspopup="menu" > - + {linkInfo.title} - -
      + +