diff --git a/devenv/dev-dashboards/datasource-mssql/mssql_fakedata.json b/devenv/dev-dashboards/datasource-mssql/mssql_fakedata.json index 5522b0d0e2d..19c5e1d0718 100644 --- a/devenv/dev-dashboards/datasource-mssql/mssql_fakedata.json +++ b/devenv/dev-dashboards/datasource-mssql/mssql_fakedata.json @@ -4,11 +4,37 @@ { "builtIn": 1, "datasource": "-- Grafana --", - "enable": true, + "enable": false, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, "name": "Annotations & Alerts", + "showIn": 0, "type": "dashboard" + }, + { + "datasource": "gdev-mssql", + "enable": false, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Single", + "rawQuery": "SELECT TOP 1\n createdAt as time,\n 'single' as text,\n hostname as tags\nFROM\n grafana_metric\nWHERE\n $__timeFilter(createdAt)\nORDER BY time\n", + "showIn": 0, + "tags": [], + "type": "tags" + }, + { + "datasource": "gdev-mssql", + "enable": false, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Region", + "rawQuery": "SELECT TOP 1\n DATEADD(MINUTE, 1, createdAt) as time,\n DATEADD(MINUTE, 6, createdAt) as timeend,\n 'region' as text,\n hostname as tags\nFROM\n grafana_metric\nWHERE\n $__timeFilter(createdAt)\nORDER BY time", + "showIn": 0, + "tags": [], + "type": "tags" } ] }, @@ -16,7 +42,7 @@ "editable": true, "gnetId": null, "graphTooltip": 0, - "iteration": 1532618661457, + "iteration": 1576251075020, "links": [], "panels": [ { @@ -28,12 +54,14 @@ "dashes": false, "datasource": "gdev-mssql", "fill": 2, + "fillGradient": 0, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 0 }, + "hiddenSeries": false, "id": 2, "legend": { "avg": false, @@ -48,6 +76,9 @@ "linewidth": 2, "links": [], "nullPointMode": "null", + "options": { + "dataLinks": [] + }, "percentage": false, "pointradius": 5, "points": false, @@ -79,6 +110,7 @@ ], "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Average logins / $summarize", "tooltip": { @@ -125,12 +157,14 @@ "dashes": false, "datasource": "gdev-mssql", "fill": 2, + "fillGradient": 0, "gridPos": { "h": 18, "w": 12, "x": 12, "y": 0 }, + "hiddenSeries": false, "id": 8, "legend": { "avg": false, @@ -145,6 +179,9 @@ "linewidth": 2, "links": [], "nullPointMode": "null", + "options": { + "dataLinks": [] + }, "percentage": false, "pointradius": 5, "points": false, @@ -169,6 +206,7 @@ ], "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Average payments started/ended / $summarize", "tooltip": { @@ -214,12 +252,14 @@ "dashes": false, "datasource": "gdev-mssql", "fill": 2, + "fillGradient": 0, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 9 }, + "hiddenSeries": false, "id": 6, "legend": { "avg": false, @@ -234,6 +274,9 @@ "linewidth": 2, "links": [], "nullPointMode": "null", + "options": { + "dataLinks": [] + }, "percentage": false, "pointradius": 5, "points": false, @@ -252,6 +295,7 @@ ], "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Max CPU / $summarize", "tooltip": { @@ -302,6 +346,7 @@ }, "id": 4, "links": [], + "options": {}, "pageSize": null, "scroll": true, "showHeader": true, @@ -340,15 +385,19 @@ "type": "table" } ], - "schemaVersion": 16, + "schemaVersion": 21, "style": "dark", "tags": ["gdev", "mssql", "datasource-test"], "templating": { "list": [ { "allValue": null, - "current": {}, + "current": { + "text": "Africa", + "value": "Africa" + }, "datasource": "gdev-mssql", + "definition": "", "hide": 0, "includeAll": false, "label": "Datacenter", @@ -368,8 +417,13 @@ }, { "allValue": null, - "current": {}, + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, "datasource": "gdev-mssql", + "definition": "", "hide": 0, "includeAll": true, "label": "Hostname", @@ -392,6 +446,7 @@ "auto_count": 30, "auto_min": "10s", "current": { + "selected": false, "text": "1m", "value": "1m" }, @@ -488,5 +543,5 @@ "timezone": "", "title": "Datasource tests - MSSQL", "uid": "86Js1xRmk", - "version": 1 + "version": 2 } diff --git a/devenv/dev-dashboards/datasource-mysql/mysql_fakedata.json b/devenv/dev-dashboards/datasource-mysql/mysql_fakedata.json index 31de0a81005..1bee8879782 100644 --- a/devenv/dev-dashboards/datasource-mysql/mysql_fakedata.json +++ b/devenv/dev-dashboards/datasource-mysql/mysql_fakedata.json @@ -4,11 +4,35 @@ { "builtIn": 1, "datasource": "-- Grafana --", - "enable": true, + "enable": false, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" + }, + { + "datasource": "gdev-mysql", + "enable": false, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Single", + "rawQuery": "SELECT\n createdAt as time,\n 'single' as text,\n hostname as tags\nFROM\n grafana_metric\nWHERE\n $__timeFilter(createdAt)\nORDER BY time\nLIMIT 1\n", + "showIn": 0, + "tags": [], + "type": "tags" + }, + { + "datasource": "gdev-mysql", + "enable": false, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Region", + "rawQuery": "SELECT\n ADDTIME(createdAt, '00:01:00') as time,\n ADDTIME(createdAt, '00:06:00') as timeend,\n 'region' as text,\n hostname as tags\nFROM\n grafana_metric\nWHERE\n $__timeFilter(createdAt)\nORDER BY time\nLIMIT 1\n", + "showIn": 0, + "tags": [], + "type": "tags" } ] }, @@ -16,7 +40,7 @@ "editable": true, "gnetId": null, "graphTooltip": 0, - "iteration": 1532620738041, + "iteration": 1576250298312, "links": [], "panels": [ { @@ -28,12 +52,14 @@ "dashes": false, "datasource": "gdev-mysql", "fill": 2, + "fillGradient": 0, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 0 }, + "hiddenSeries": false, "id": 2, "legend": { "avg": false, @@ -48,6 +74,9 @@ "linewidth": 2, "links": [], "nullPointMode": "null", + "options": { + "dataLinks": [] + }, "percentage": false, "pointradius": 5, "points": false, @@ -81,6 +110,7 @@ ], "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Average logins / $summarize", "tooltip": { @@ -126,12 +156,14 @@ "dashes": false, "datasource": "gdev-mysql", "fill": 2, + "fillGradient": 0, "gridPos": { "h": 18, "w": 12, "x": 12, "y": 0 }, + "hiddenSeries": false, "id": 4, "legend": { "avg": false, @@ -146,6 +178,9 @@ "linewidth": 2, "links": [], "nullPointMode": "null", + "options": { + "dataLinks": [] + }, "percentage": false, "pointradius": 5, "points": false, @@ -171,6 +206,7 @@ ], "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Average payments started/ended / $summarize", "tooltip": { @@ -216,12 +252,14 @@ "dashes": false, "datasource": "gdev-mysql", "fill": 2, + "fillGradient": 0, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 9 }, + "hiddenSeries": false, "id": 3, "legend": { "avg": false, @@ -236,6 +274,9 @@ "linewidth": 2, "links": [], "nullPointMode": "null", + "options": { + "dataLinks": [] + }, "percentage": false, "pointradius": 5, "points": false, @@ -255,6 +296,7 @@ ], "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Max CPU / $summarize", "tooltip": { @@ -305,6 +347,7 @@ }, "id": 6, "links": [], + "options": {}, "pageSize": null, "scroll": true, "showHeader": true, @@ -346,7 +389,8 @@ "type": "table" } ], - "schemaVersion": 16, + "refresh": false, + "schemaVersion": 21, "style": "dark", "tags": ["gdev", "mysql", "datasource-tags"], "templating": { @@ -358,6 +402,7 @@ "value": "America" }, "datasource": "gdev-mysql", + "definition": "", "hide": 0, "includeAll": false, "label": "Datacenter", @@ -378,10 +423,12 @@ { "allValue": null, "current": { + "selected": false, "text": "All", "value": "$__all" }, "datasource": "gdev-mysql", + "definition": "", "hide": 0, "includeAll": true, "label": "Hostname", @@ -404,6 +451,7 @@ "auto_count": 5, "auto_min": "10s", "current": { + "selected": false, "text": "1m", "value": "1m" }, @@ -500,5 +548,5 @@ "timezone": "", "title": "Datasource tests - MySQL", "uid": "DGsCac3kz", - "version": 8 + "version": 2 } diff --git a/devenv/dev-dashboards/datasource-postgres/postgres_fakedata.json b/devenv/dev-dashboards/datasource-postgres/postgres_fakedata.json index 5efa5536adf..aa49a9abf87 100644 --- a/devenv/dev-dashboards/datasource-postgres/postgres_fakedata.json +++ b/devenv/dev-dashboards/datasource-postgres/postgres_fakedata.json @@ -4,11 +4,35 @@ { "builtIn": 1, "datasource": "-- Grafana --", - "enable": true, + "enable": false, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" + }, + { + "datasource": "gdev-postgres", + "enable": false, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Single", + "rawQuery": "SELECT\n \"createdAt\" as time,\n 'single' as text,\n hostname as tags\nFROM\n grafana_metric\nWHERE\n $__timeFilter(\"createdAt\")\nORDER BY time\nLIMIT 1\n", + "showIn": 0, + "tags": [], + "type": "tags" + }, + { + "datasource": "gdev-postgres", + "enable": false, + "hide": false, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Region", + "rawQuery": "SELECT\n \"createdAt\" + (interval '1 minute') as time,\n \"createdAt\" + (6 * interval '1 minute') as timeend,\n 'region' as text,\n hostname as tags\nFROM\n grafana_metric\nWHERE\n $__timeFilter(\"createdAt\")\nORDER BY time\nLIMIT 1\n", + "showIn": 0, + "tags": [], + "type": "tags" } ] }, @@ -16,7 +40,7 @@ "editable": true, "gnetId": null, "graphTooltip": 0, - "iteration": 1532620601931, + "iteration": 1576249087264, "links": [], "panels": [ { @@ -28,12 +52,14 @@ "dashes": false, "datasource": "gdev-postgres", "fill": 2, + "fillGradient": 0, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 0 }, + "hiddenSeries": false, "id": 2, "legend": { "avg": false, @@ -48,6 +74,9 @@ "linewidth": 2, "links": [], "nullPointMode": "null", + "options": { + "dataLinks": [] + }, "percentage": false, "pointradius": 5, "points": false, @@ -67,20 +96,59 @@ { "alias": "", "format": "time_series", + "group": [], "hide": false, + "metricColumn": "none", + "rawQuery": true, "rawSql": "SELECT\n $__timeGroup(\"createdAt\",'$summarize'),\n avg(value) as \"value\",\n hostname as \"metric\"\nFROM \n grafana_metric\nWHERE\n $__timeFilter(\"createdAt\") AND\n measurement = 'logins.count' AND\n hostname IN($host)\nGROUP BY time, metric\nORDER BY time", "refId": "A", - "target": "" + "select": [ + [ + { + "params": ["value"], + "type": "column" + } + ] + ], + "target": "", + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] }, { "alias": "", "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, "rawSql": "SELECT\n $__timeGroup(\"createdAt\",'$summarize'),\n min(value) as \"value\",\n 'total avg' as \"metric\"\nFROM \n grafana_metric\nWHERE\n $__timeFilter(\"createdAt\") AND\n measurement = 'logins.count'\nGROUP BY time\nORDER BY time", - "refId": "B" + "refId": "B", + "select": [ + [ + { + "params": ["value"], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] } ], "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Average logins / $summarize", "tooltip": { @@ -126,12 +194,14 @@ "dashes": false, "datasource": "gdev-postgres", "fill": 2, + "fillGradient": 0, "gridPos": { "h": 18, "w": 12, "x": 12, "y": 0 }, + "hiddenSeries": false, "id": 4, "legend": { "avg": false, @@ -146,6 +216,9 @@ "linewidth": 2, "links": [], "nullPointMode": "null", + "options": { + "dataLinks": [] + }, "percentage": false, "pointradius": 5, "points": false, @@ -171,6 +244,7 @@ ], "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Average payments started/ended / $summarize", "tooltip": { @@ -216,12 +290,14 @@ "dashes": false, "datasource": "gdev-postgres", "fill": 2, + "fillGradient": 0, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 9 }, + "hiddenSeries": false, "id": 3, "legend": { "avg": false, @@ -236,6 +312,9 @@ "linewidth": 2, "links": [], "nullPointMode": "null", + "options": { + "dataLinks": [] + }, "percentage": false, "pointradius": 5, "points": false, @@ -255,6 +334,7 @@ ], "thresholds": [], "timeFrom": null, + "timeRegions": [], "timeShift": null, "title": "Max CPU / $summarize", "tooltip": { @@ -305,6 +385,7 @@ }, "id": 6, "links": [], + "options": {}, "pageSize": null, "scroll": true, "showHeader": true, @@ -345,7 +426,7 @@ "type": "table" } ], - "schemaVersion": 16, + "schemaVersion": 21, "style": "dark", "tags": ["gdev", "postgres", "datasource-test"], "templating": { @@ -357,6 +438,7 @@ "value": "America" }, "datasource": "gdev-postgres", + "definition": "", "hide": 0, "includeAll": false, "label": "Datacenter", @@ -377,10 +459,12 @@ { "allValue": null, "current": { + "selected": false, "text": "All", "value": "$__all" }, "datasource": "gdev-postgres", + "definition": "", "hide": 0, "includeAll": true, "label": "Hostname", @@ -403,6 +487,7 @@ "auto_count": 5, "auto_min": "10s", "current": { + "selected": false, "text": "1m", "value": "1m" }, @@ -499,5 +584,5 @@ "timezone": "", "title": "Datasource tests - Postgres", "uid": "JYola5qzz", - "version": 4 + "version": 5 } diff --git a/docs/sources/features/datasources/mssql.md b/docs/sources/features/datasources/mssql.md index 64796d0dd4b..1f10d6687fd 100644 --- a/docs/sources/features/datasources/mssql.md +++ b/docs/sources/features/datasources/mssql.md @@ -178,7 +178,7 @@ The resulting table panel: ## Time series queries -If you set `Format as` to `Time series`, for use in Graph panel for example, then the query must have a column named `time` that returns either a sql datetime or any numeric datatype representing Unix epoch in seconds. You may return a column named `metric` that is used as metric name for the value column. Any column except `time` and `metric` is treated as a value column. If you omit the `metric` column, the name of the value column will be the metric name. You may select multiple value columns, each will have its name as metric. +If you set `Format as` to `Time series`, for use in Graph panel for example, then the query must have a column named `time` that returns either a SQL datetime or any numeric datatype representing Unix epoch in seconds. You may return a column named `metric` that is used as metric name for the value column. Any column except `time` and `metric` is treated as a value column. If you omit the `metric` column, the name of the value column will be the metric name. You may select multiple value columns, each will have its name as metric. If you return multiple value columns and a column named `metric` then this column is used as prefix for the series name (only available in Grafana 5.3+). Resultsets of time series queries need to be sorted by time. @@ -380,7 +380,8 @@ Read more about variable formatting options in the [Variables]({{< relref "../.. Name | Description ------------ | ------------- -time | The name of the date/time field. Could be a column with a native sql date/time data type or epoch value. +time | The name of the date/time field. Could be a column with a native SQL date/time data type or epoch value. +timeend | Optional name of the end date/time field. Could be a column with a native SQL date/time data type or epoch value. text | Event description field. tags | Optional field name to use for event tags as a comma separated string. @@ -410,7 +411,7 @@ WHERE ORDER BY 1 ``` -**Example query using time column of native sql date/time data type:** +**Example query using time column of native SQL date/time data type:** ```sql SELECT diff --git a/docs/sources/features/datasources/mysql.md b/docs/sources/features/datasources/mysql.md index 89c3a3a0594..71ba037c613 100755 --- a/docs/sources/features/datasources/mysql.md +++ b/docs/sources/features/datasources/mysql.md @@ -182,7 +182,7 @@ The resulting table panel: ## Time series queries -If you set `Format as` to `Time series`, for use in Graph panel for example, then the query must return a column named `time` that returns either a sql datetime or any numeric datatype representing Unix epoch. +If you set `Format as` to `Time series`, for use in Graph panel for example, then the query must return a column named `time` that returns either a SQL datetime or any numeric datatype representing Unix epoch. Any column except `time` and `metric` is treated as a value column. You may return a column named `metric` that is used as metric name for the value column. If you return multiple value columns and a column named `metric` then this column is used as prefix for the series name (only available in Grafana 5.3+). @@ -350,7 +350,7 @@ WHERE $__unixEpochFilter(epoch_time) ``` -**Example query using time column of native sql date/time data type:** +**Example query using time column of native SQL date/time data type:** ```sql SELECT @@ -365,7 +365,8 @@ WHERE Name | Description ------------ | ------------- -time | The name of the date/time field. Could be a column with a native sql date/time data type or epoch value. +time | The name of the date/time field. Could be a column with a native SQL date/time data type or epoch value. +timeend | Optional name of the end date/time field. Could be a column with a native SQL date/time data type or epoch value. text | Event description field. tags | Optional field name to use for event tags as a comma separated string. diff --git a/docs/sources/features/datasources/postgres.md b/docs/sources/features/datasources/postgres.md index 956ac239dd4..6b7138a4fa0 100755 --- a/docs/sources/features/datasources/postgres.md +++ b/docs/sources/features/datasources/postgres.md @@ -354,7 +354,7 @@ WHERE $__unixEpochFilter(epoch_time) ``` -**Example query using time column of native sql date/time data type:** +**Example query using time column of native SQL date/time data type:** ```sql SELECT @@ -369,7 +369,8 @@ WHERE Name | Description ------------ | ------------- -time | The name of the date/time field. Could be a column with a native sql date/time data type or epoch value. +time | The name of the date/time field. Could be a column with a native SQL date/time data type or epoch value. +timeend | Optional name of the time end field, needs to be date/time data type. If set, then annotations are marked as regions between time and time-end. text | Event description field. tags | Optional field name to use for event tags as a comma separated string. diff --git a/pkg/tsdb/sqleng/sql_engine.go b/pkg/tsdb/sqleng/sql_engine.go index 9b3f17fdf78..0cfb1560e45 100644 --- a/pkg/tsdb/sqleng/sql_engine.go +++ b/pkg/tsdb/sqleng/sql_engine.go @@ -56,6 +56,8 @@ var NewXormEngine = func(driverName string, connectionString string) (*xorm.Engi return xorm.NewEngine(driverName, connectionString) } +const timeEndColumnName = "timeend" + type sqlQueryEndpoint struct { macroEngine SqlMacroEngine queryResultTransformer SqlQueryResultTransformer @@ -218,6 +220,7 @@ func (e *sqlQueryEndpoint) transformToTable(query *tsdb.Query, rows *core.Rows, rowCount := 0 timeIndex := -1 + timeEndIndex := -1 table := &tsdb.Table{ Columns: make([]tsdb.TableColumn, columnCount), @@ -232,6 +235,11 @@ func (e *sqlQueryEndpoint) transformToTable(query *tsdb.Query, rows *core.Rows, timeIndex = i break } + + if timeIndex >= 0 && name == timeEndColumnName { + timeEndIndex = i + break + } } } @@ -250,10 +258,11 @@ func (e *sqlQueryEndpoint) transformToTable(query *tsdb.Query, rows *core.Rows, return err } - // converts column named time to unix timestamp in milliseconds + // converts column named time and timeend to unix timestamp in milliseconds // to make native mssql datetime types and epoch dates work in // annotation and table queries. ConvertSqlTimeColumnToEpochMs(values, timeIndex) + ConvertSqlTimeColumnToEpochMs(values, timeEndIndex) table.Rows = append(table.Rows, values) } diff --git a/public/app/plugins/datasource/mssql/partials/annotations.editor.html b/public/app/plugins/datasource/mssql/partials/annotations.editor.html index f1c549cefa4..881741368f4 100644 --- a/public/app/plugins/datasource/mssql/partials/annotations.editor.html +++ b/public/app/plugins/datasource/mssql/partials/annotations.editor.html @@ -18,9 +18,10 @@
Annotation Query Format
-An annotation is an event that is overlaid on top of graphs. The query can have up to three columns per row, the time column is mandatory. Annotation rendering is expensive so it is important to limit the number of rows returned. +An annotation is an event that is overlaid on top of graphs. The query can have up to four columns per row, the time column is mandatory. Annotation rendering is expensive so it is important to limit the number of rows returned. - column with alias: time for the annotation event time. Use epoch time or any native date data type. +- column with alias: timeend for the annotation event end time. Use epoch time or any native date data type. - column with alias: text for the annotation text. - column with alias: tags for annotation tags. This is a comma separated string of tags e.g. 'tag1,tag2'. diff --git a/public/app/plugins/datasource/mssql/response_parser.ts b/public/app/plugins/datasource/mssql/response_parser.ts index 2a0ac5c6d52..d56ef88d0ff 100644 --- a/public/app/plugins/datasource/mssql/response_parser.ts +++ b/public/app/plugins/datasource/mssql/response_parser.ts @@ -104,12 +104,15 @@ export default class ResponseParser { const table = data.data.results[options.annotation.name].tables[0]; let timeColumnIndex = -1; + let timeEndColumnIndex = -1; let textColumnIndex = -1; let tagsColumnIndex = -1; for (let i = 0; i < table.columns.length; i++) { if (table.columns[i].text === 'time') { timeColumnIndex = i; + } else if (table.columns[i].text === 'timeend') { + timeEndColumnIndex = i; } else if (table.columns[i].text === 'text') { textColumnIndex = i; } else if (table.columns[i].text === 'tags') { @@ -124,9 +127,12 @@ export default class ResponseParser { const list = []; for (let i = 0; i < table.rows.length; i++) { const row = table.rows[i]; + const timeEnd = + timeEndColumnIndex !== -1 && row[timeEndColumnIndex] ? Math.floor(row[timeEndColumnIndex]) : undefined; list.push({ annotation: options.annotation, time: Math.floor(row[timeColumnIndex]), + timeEnd, text: row[textColumnIndex], tags: row[tagsColumnIndex] ? row[tagsColumnIndex].trim().split(/\s*,\s*/) : [], }); diff --git a/public/app/plugins/datasource/mysql/partials/annotations.editor.html b/public/app/plugins/datasource/mysql/partials/annotations.editor.html index 25d2f969cee..5dcd03e6517 100644 --- a/public/app/plugins/datasource/mysql/partials/annotations.editor.html +++ b/public/app/plugins/datasource/mysql/partials/annotations.editor.html @@ -18,9 +18,10 @@
Annotation Query Format
-An annotation is an event that is overlaid on top of graphs. The query can have up to three columns per row, the time or time_sec column is mandatory. Annotation rendering is expensive so it is important to limit the number of rows returned. +An annotation is an event that is overlaid on top of graphs. The query can have up to four columns per row, the time or time_sec column is mandatory. Annotation rendering is expensive so it is important to limit the number of rows returned. - column with alias: time or time_sec for the annotation event time. Use epoch time or any native date data type. +- column with alias: timeend for the annotation event end time. Use epoch time or any native date data type. - column with alias: text for the annotation text - column with alias: tags for annotation tags. This is a comma separated string of tags e.g. 'tag1,tag2' diff --git a/public/app/plugins/datasource/mysql/response_parser.ts b/public/app/plugins/datasource/mysql/response_parser.ts index c4e75c1f109..63574fc6647 100644 --- a/public/app/plugins/datasource/mysql/response_parser.ts +++ b/public/app/plugins/datasource/mysql/response_parser.ts @@ -107,12 +107,15 @@ export default class ResponseParser { const table = data.data.results[options.annotation.name].tables[0]; let timeColumnIndex = -1; + let timeEndColumnIndex = -1; let textColumnIndex = -1; let tagsColumnIndex = -1; for (let i = 0; i < table.columns.length; i++) { if (table.columns[i].text === 'time_sec' || table.columns[i].text === 'time') { timeColumnIndex = i; + } else if (table.columns[i].text === 'timeend') { + timeEndColumnIndex = i; } else if (table.columns[i].text === 'title') { return Promise.reject({ message: 'The title column for annotations is deprecated, now only a column named text is returned', @@ -133,9 +136,12 @@ export default class ResponseParser { const list = []; for (let i = 0; i < table.rows.length; i++) { const row = table.rows[i]; + const timeEnd = + timeEndColumnIndex !== -1 && row[timeEndColumnIndex] ? Math.floor(row[timeEndColumnIndex]) : undefined; list.push({ annotation: options.annotation, time: Math.floor(row[timeColumnIndex]), + timeEnd, text: row[textColumnIndex] ? row[textColumnIndex].toString() : '', tags: row[tagsColumnIndex] ? row[tagsColumnIndex].trim().split(/\s*,\s*/) : [], }); diff --git a/public/app/plugins/datasource/postgres/partials/annotations.editor.html b/public/app/plugins/datasource/postgres/partials/annotations.editor.html index 0b7180c0eaf..df4f9d53288 100644 --- a/public/app/plugins/datasource/postgres/partials/annotations.editor.html +++ b/public/app/plugins/datasource/postgres/partials/annotations.editor.html @@ -18,9 +18,10 @@
Annotation Query Format
-An annotation is an event that is overlaid on top of graphs. The query can have up to three columns per row, the time column is mandatory. Annotation rendering is expensive so it is important to limit the number of rows returned. +An annotation is an event that is overlaid on top of graphs. The query can have up to four columns per row, the time column is mandatory. Annotation rendering is expensive so it is important to limit the number of rows returned. - column with alias: time for the annotation event time. Use epoch time or any native date data type. +- column with alias: timeend for the annotation event time-end. Use epoch time or any native date data type. - column with alias: text for the annotation text - column with alias: tags for annotation tags. This is a comma separated string of tags e.g. 'tag1,tag2' diff --git a/public/app/plugins/datasource/postgres/response_parser.ts b/public/app/plugins/datasource/postgres/response_parser.ts index a7b86741d26..f4e3485a7ca 100644 --- a/public/app/plugins/datasource/postgres/response_parser.ts +++ b/public/app/plugins/datasource/postgres/response_parser.ts @@ -107,6 +107,7 @@ export default class ResponseParser { const table = data.data.results[options.annotation.name].tables[0]; let timeColumnIndex = -1; + let timeEndColumnIndex = -1; const titleColumnIndex = -1; let textColumnIndex = -1; let tagsColumnIndex = -1; @@ -114,6 +115,8 @@ export default class ResponseParser { for (let i = 0; i < table.columns.length; i++) { if (table.columns[i].text === 'time') { timeColumnIndex = i; + } else if (table.columns[i].text === 'timeend') { + timeEndColumnIndex = i; } else if (table.columns[i].text === 'text') { textColumnIndex = i; } else if (table.columns[i].text === 'tags') { @@ -130,9 +133,12 @@ export default class ResponseParser { const list = []; for (let i = 0; i < table.rows.length; i++) { const row = table.rows[i]; + const timeEnd = + timeEndColumnIndex !== -1 && row[timeEndColumnIndex] ? Math.floor(row[timeEndColumnIndex]) : undefined; list.push({ annotation: options.annotation, time: Math.floor(row[timeColumnIndex]), + timeEnd, title: row[titleColumnIndex], text: row[textColumnIndex], tags: row[tagsColumnIndex] ? row[tagsColumnIndex].trim().split(/\s*,\s*/) : [],