mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
mysql: worked on mysql data soruce
This commit is contained in:
parent
1bbc149089
commit
c78c460f79
@ -10,3 +10,5 @@ mysql:
|
|||||||
volumes:
|
volumes:
|
||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
- /etc/timezone:/etc/timezone:ro
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
command: [mysqld, --character-set-server=utf8mb4, --collation-server=utf8mb4_unicode_ci, --innodb_monitor_enable=all]
|
||||||
|
|
||||||
|
@ -50,13 +50,16 @@ func QueryMetrics(c *middleware.Context, reqDto dtos.MetricRequest) Response {
|
|||||||
return ApiError(500, "Metric request error", err)
|
return ApiError(500, "Metric request error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statusCode := 200
|
||||||
for _, res := range resp.Results {
|
for _, res := range resp.Results {
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
res.ErrorString = res.Error.Error()
|
res.ErrorString = res.Error.Error()
|
||||||
|
resp.Message = res.ErrorString
|
||||||
|
statusCode = 500
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Json(200, &resp)
|
return Json(statusCode, &resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET /api/tsdb/testdata/scenarios
|
// GET /api/tsdb/testdata/scenarios
|
||||||
|
@ -27,6 +27,7 @@ type Request struct {
|
|||||||
type Response struct {
|
type Response struct {
|
||||||
BatchTimings []*BatchTiming `json:"timings"`
|
BatchTimings []*BatchTiming `json:"timings"`
|
||||||
Results map[string]*QueryResult `json:"results"`
|
Results map[string]*QueryResult `json:"results"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BatchTiming struct {
|
type BatchTiming struct {
|
||||||
|
@ -112,14 +112,18 @@ func (e *MysqlExecutor) Execute(ctx context.Context, queries tsdb.QuerySlice, co
|
|||||||
|
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
res, err := e.TransformToTimeSeries(query, rows)
|
format := query.Model.Get("format").MustString("time_series")
|
||||||
if err != nil {
|
|
||||||
queryResult.Error = err
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
queryResult.Series = res
|
if format == "time_series" {
|
||||||
queryResult.Meta.Set("rowCount", countPointsInAllSeries(res))
|
res, err := e.TransformToTimeSeries(query, rows)
|
||||||
|
if err != nil {
|
||||||
|
queryResult.Error = err
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
queryResult.Series = res
|
||||||
|
queryResult.Meta.Set("rowCount", countPointsInAllSeries(res))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -184,8 +184,8 @@ class TimeSrv {
|
|||||||
timeRangeForUrl() {
|
timeRangeForUrl() {
|
||||||
var range = this.timeRange().raw;
|
var range = this.timeRange().raw;
|
||||||
|
|
||||||
if (moment.isMoment(range.from)) { range.from = range.from.valueOf(); }
|
if (moment.isMoment(range.from)) { range.from = range.from.valueOf().toString(); }
|
||||||
if (moment.isMoment(range.to)) { range.to = range.to.valueOf(); }
|
if (moment.isMoment(range.to)) { range.to = range.to.valueOf().toString(); }
|
||||||
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,16 @@ class MetricsPanelCtrl extends PanelCtrl {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.error = err.message || "Request Error";
|
this.error = err.message || "Request Error";
|
||||||
this.inspector = {error: err};
|
this.inspector = {error: err};
|
||||||
|
|
||||||
|
if (err.data) {
|
||||||
|
if (err.data.message) {
|
||||||
|
this.error = err.data.message;
|
||||||
|
}
|
||||||
|
if (err.data.error) {
|
||||||
|
this.error = err.data.error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.events.emit('data-error', err);
|
this.events.emit('data-error', err);
|
||||||
console.log('Panel data error:', err);
|
console.log('Panel data error:', err);
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
<div class="gf-form-query">
|
<div class="gf-form-query">
|
||||||
<div class="gf-form">
|
<div class="gf-form gf-form-query-letter-cell">
|
||||||
<label class="gf-form-label gf-form-query-letter-cell">
|
<label class="gf-form-label">
|
||||||
<a class="pointer" tabindex="1" ng-click="ctrl.toggleCollapse()">
|
<a class="pointer" tabindex="1" ng-click="ctrl.toggleCollapse()">
|
||||||
<span ng-class="{muted: !ctrl.canCollapse}" class="gf-form-query-letter-cell-carret">
|
<span ng-class="{muted: !ctrl.canCollapse}" class="gf-form-query-letter-cell-carret">
|
||||||
<i class="fa fa-caret-down" ng-hide="ctrl.collapsed"></i>
|
<i class="fa fa-caret-down" ng-hide="ctrl.collapsed"></i>
|
||||||
|
@ -22,6 +22,7 @@ export class MysqlDatasource {
|
|||||||
maxDataPoints: options.maxDataPoints,
|
maxDataPoints: options.maxDataPoints,
|
||||||
datasourceId: this.id,
|
datasourceId: this.id,
|
||||||
rawSql: item.rawSql,
|
rawSql: item.rawSql,
|
||||||
|
format: item.format,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -29,29 +30,31 @@ export class MysqlDatasource {
|
|||||||
return this.$q.when({data: []});
|
return this.$q.when({data: []});
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.backendSrv.post('/api/tsdb/query', {
|
return this.backendSrv.datasourceRequest({
|
||||||
from: options.range.from.valueOf().toString(),
|
url: '/api/tsdb/query',
|
||||||
to: options.range.to.valueOf().toString(),
|
method: 'POST',
|
||||||
queries: queries,
|
data: {
|
||||||
}).then(res => {
|
from: options.range.from.valueOf().toString(),
|
||||||
console.log('mysql response', res);
|
to: options.range.to.valueOf().toString(),
|
||||||
|
queries: queries,
|
||||||
var data = [];
|
|
||||||
if (res.results) {
|
|
||||||
_.forEach(res.results, queryRes => {
|
|
||||||
|
|
||||||
if (queryRes.error) {
|
|
||||||
throw {error: queryRes.error, message: queryRes.error};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let series of queryRes.series) {
|
|
||||||
data.push({
|
|
||||||
target: series.name,
|
|
||||||
datapoints: series.points
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}).then(res => {
|
||||||
|
var data = [];
|
||||||
|
|
||||||
|
if (!res.data.results) {
|
||||||
|
return {data: data};
|
||||||
|
}
|
||||||
|
|
||||||
|
_.forEach(res.data.results, queryRes => {
|
||||||
|
for (let series of queryRes.series) {
|
||||||
|
data.push({
|
||||||
|
target: series.name,
|
||||||
|
datapoints: series.points,
|
||||||
|
refId: queryRes.refId,
|
||||||
|
meta: queryRes.meta,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return {data: data};
|
return {data: data};
|
||||||
});
|
});
|
||||||
|
@ -1,25 +1,61 @@
|
|||||||
///<reference path="../../../headers/common.d.ts" />
|
///<reference path="../../../headers/common.d.ts" />
|
||||||
|
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
|
import _ from 'lodash';
|
||||||
import {MysqlDatasource} from './datasource';
|
import {MysqlDatasource} from './datasource';
|
||||||
import {QueryCtrl} from 'app/plugins/sdk';
|
import {QueryCtrl} from 'app/plugins/sdk';
|
||||||
|
|
||||||
|
export interface MysqlQuery {
|
||||||
|
refId: string;
|
||||||
|
format: string;
|
||||||
|
alias: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QueryMeta {
|
||||||
|
sql: string;
|
||||||
|
}
|
||||||
|
|
||||||
class MysqlQueryCtrl extends QueryCtrl {
|
class MysqlQueryCtrl extends QueryCtrl {
|
||||||
static templateUrl = 'partials/query.editor.html';
|
static templateUrl = 'partials/query.editor.html';
|
||||||
|
|
||||||
resultFormats: any;
|
showLastQuerySQL: boolean;
|
||||||
target: any;
|
formats: any[];
|
||||||
|
target: MysqlQuery;
|
||||||
|
lastQueryMeta: QueryMeta;
|
||||||
|
lastQueryError: string;
|
||||||
|
|
||||||
constructor($scope, $injector) {
|
constructor($scope, $injector) {
|
||||||
super($scope, $injector);
|
super($scope, $injector);
|
||||||
|
|
||||||
this.target.resultFormat = 'time_series';
|
this.target.format = 'time_series';
|
||||||
this.target.alias = "";
|
this.target.alias = "";
|
||||||
this.resultFormats = [
|
this.formats = [
|
||||||
{text: 'Time series', value: 'time_series'},
|
{text: 'Time series', value: 'time_series'},
|
||||||
{text: 'Table', value: 'table'},
|
{text: 'Table', value: 'table'},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
|
||||||
|
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDataReceived(dataList) {
|
||||||
|
this.lastQueryMeta = null;
|
||||||
|
this.lastQueryError = null;
|
||||||
|
|
||||||
|
let anySeriesFromQuery = _.find(dataList, {refId: this.target.refId});
|
||||||
|
if (anySeriesFromQuery) {
|
||||||
|
this.lastQueryMeta = anySeriesFromQuery.meta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDataError(err) {
|
||||||
|
if (err.data && err.data.results) {
|
||||||
|
let queryRes = err.data.results[this.target.refId];
|
||||||
|
if (queryRes) {
|
||||||
|
this.lastQueryMeta = queryRes.meta;
|
||||||
|
this.lastQueryError = queryRes.error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label query-keyword">Format as</label>
|
<label class="gf-form-label query-keyword">Format as</label>
|
||||||
<div class="gf-form-select-wrapper">
|
<div class="gf-form-select-wrapper">
|
||||||
<select class="gf-form-input gf-size-auto" ng-model="ctrl.target.resultFormat" ng-options="f.value as f.text for f in ctrl.resultFormats" ng-change="ctrl.refresh()"></select>
|
<select class="gf-form-input gf-size-auto" ng-model="ctrl.target.format" ng-options="f.value as f.text for f in ctrl.formats" ng-change="ctrl.refresh()"></select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form max-width-30">
|
<div class="gf-form max-width-30">
|
||||||
@ -22,4 +22,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-inline" ng-show="ctrl.lastQueryMeta">
|
||||||
|
<div class="gf-form">
|
||||||
|
<label class="gf-form-label query-keyword" ng-click="ctrl.showLastQuerySQL = !ctrl.showLastQuerySQL">
|
||||||
|
Generated SQL
|
||||||
|
<i class="fa fa-caret-down" ng-show="ctrl.showLastQuerySQL"></i>
|
||||||
|
<i class="fa fa-caret-right" ng-hide="ctrl.showLastQuerySQL"></i>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form gf-form--grow">
|
||||||
|
<div class="gf-form-label gf-form-label--grow"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<pre class="small" ng-show="ctrl.showLastQuerySQL">{{ctrl.lastQueryMeta.sql}}</pre>
|
||||||
|
<pre class="small alert alert-error" ng-show="ctrl.lastQueryError">{{ctrl.lastQueryError}}</pre>
|
||||||
|
|
||||||
</query-editor-row>
|
</query-editor-row>
|
||||||
|
Loading…
Reference in New Issue
Block a user