| 
									
										
										
										
											2015-01-06 16:11:00 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-10-03 15:38:03 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2016-06-03 22:15:36 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2016-06-03 21:06:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/api/dtos" | 
					
						
							| 
									
										
										
										
											2017-03-30 04:54:07 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/bus" | 
					
						
							| 
									
										
										
										
											2017-05-29 16:48:38 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/components/simplejson" | 
					
						
							| 
									
										
										
										
											2016-06-03 21:06:57 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/metrics" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/middleware" | 
					
						
							| 
									
										
										
										
											2016-12-07 18:10:42 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/models" | 
					
						
							| 
									
										
										
										
											2016-09-27 20:39:51 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/tsdb" | 
					
						
							| 
									
										
										
										
											2016-09-28 00:17:39 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/tsdb/testdata" | 
					
						
							| 
									
										
										
										
											2016-06-04 03:22:34 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/util" | 
					
						
							| 
									
										
										
										
											2015-01-06 16:11:00 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 00:17:39 +08:00
										 |  |  | // POST /api/tsdb/query
 | 
					
						
							|  |  |  | func QueryMetrics(c *middleware.Context, reqDto dtos.MetricRequest) Response { | 
					
						
							|  |  |  | 	timeRange := tsdb.NewTimeRange(reqDto.From, reqDto.To) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 04:54:07 +08:00
										 |  |  | 	if len(reqDto.Queries) == 0 { | 
					
						
							|  |  |  | 		return ApiError(400, "No queries found in query", nil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dsId, err := reqDto.Queries[0].Get("datasourceId").Int64() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return ApiError(400, "Query missing datasourceId", nil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dsQuery := models.GetDataSourceByIdQuery{Id: dsId} | 
					
						
							|  |  |  | 	if err := bus.Dispatch(&dsQuery); err != nil { | 
					
						
							|  |  |  | 		return ApiError(500, "failed to fetch data source", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 00:17:39 +08:00
										 |  |  | 	request := &tsdb.Request{TimeRange: timeRange} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, query := range reqDto.Queries { | 
					
						
							|  |  |  | 		request.Queries = append(request.Queries, &tsdb.Query{ | 
					
						
							|  |  |  | 			RefId:         query.Get("refId").MustString("A"), | 
					
						
							|  |  |  | 			MaxDataPoints: query.Get("maxDataPoints").MustInt64(100), | 
					
						
							|  |  |  | 			IntervalMs:    query.Get("intervalMs").MustInt64(1000), | 
					
						
							|  |  |  | 			Model:         query, | 
					
						
							| 
									
										
										
										
											2017-03-30 04:54:07 +08:00
										 |  |  | 			DataSource:    dsQuery.Result, | 
					
						
							| 
									
										
										
										
											2016-09-28 00:17:39 +08:00
										 |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2016-09-27 20:39:51 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-24 16:20:21 +08:00
										 |  |  | 	resp, err := tsdb.HandleRequest(context.Background(), request) | 
					
						
							| 
									
										
										
										
											2016-09-27 20:39:51 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return ApiError(500, "Metric request error", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-06 16:11:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-20 23:10:09 +08:00
										 |  |  | 	statusCode := 200 | 
					
						
							| 
									
										
										
										
											2017-03-31 17:45:25 +08:00
										 |  |  | 	for _, res := range resp.Results { | 
					
						
							|  |  |  | 		if res.Error != nil { | 
					
						
							|  |  |  | 			res.ErrorString = res.Error.Error() | 
					
						
							| 
									
										
										
										
											2017-04-20 23:10:09 +08:00
										 |  |  | 			resp.Message = res.ErrorString | 
					
						
							|  |  |  | 			statusCode = 500 | 
					
						
							| 
									
										
										
										
											2017-03-31 17:45:25 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-20 23:10:09 +08:00
										 |  |  | 	return Json(statusCode, &resp) | 
					
						
							| 
									
										
										
										
											2016-09-28 00:17:39 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-09-27 20:39:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 00:17:39 +08:00
										 |  |  | // GET /api/tsdb/testdata/scenarios
 | 
					
						
							|  |  |  | func GetTestDataScenarios(c *middleware.Context) Response { | 
					
						
							|  |  |  | 	result := make([]interface{}, 0) | 
					
						
							| 
									
										
										
										
											2015-01-06 16:11:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 00:17:39 +08:00
										 |  |  | 	for _, scenario := range testdata.ScenarioRegistry { | 
					
						
							|  |  |  | 		result = append(result, map[string]interface{}{ | 
					
						
							|  |  |  | 			"id":          scenario.Id, | 
					
						
							|  |  |  | 			"name":        scenario.Name, | 
					
						
							|  |  |  | 			"description": scenario.Description, | 
					
						
							| 
									
										
										
										
											2016-09-28 16:37:30 +08:00
										 |  |  | 			"stringInput": scenario.StringInput, | 
					
						
							| 
									
										
										
										
											2016-09-28 00:17:39 +08:00
										 |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2015-01-06 16:11:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 11:45:13 +08:00
										 |  |  | 	return Json(200, &result) | 
					
						
							| 
									
										
										
										
											2015-01-06 16:11:00 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-06-03 21:06:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 22:15:36 +08:00
										 |  |  | func GetInternalMetrics(c *middleware.Context) Response { | 
					
						
							| 
									
										
										
										
											2016-06-04 03:22:34 +08:00
										 |  |  | 	if metrics.UseNilMetrics { | 
					
						
							|  |  |  | 		return Json(200, util.DynMap{"message": "Metrics disabled"}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 21:06:57 +08:00
										 |  |  | 	snapshots := metrics.MetricStats.GetSnapshots() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resp := make(map[string]interface{}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, m := range snapshots { | 
					
						
							|  |  |  | 		metricName := m.Name() + m.StringifyTags() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch metric := m.(type) { | 
					
						
							| 
									
										
										
										
											2016-11-29 23:45:26 +08:00
										 |  |  | 		case metrics.Gauge: | 
					
						
							|  |  |  | 			resp[metricName] = map[string]interface{}{ | 
					
						
							|  |  |  | 				"value": metric.Value(), | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-06-03 21:06:57 +08:00
										 |  |  | 		case metrics.Counter: | 
					
						
							|  |  |  | 			resp[metricName] = map[string]interface{}{ | 
					
						
							|  |  |  | 				"count": metric.Count(), | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case metrics.Timer: | 
					
						
							|  |  |  | 			percentiles := metric.Percentiles([]float64{0.25, 0.75, 0.90, 0.99}) | 
					
						
							|  |  |  | 			resp[metricName] = map[string]interface{}{ | 
					
						
							|  |  |  | 				"count": metric.Count(), | 
					
						
							|  |  |  | 				"min":   metric.Min(), | 
					
						
							|  |  |  | 				"max":   metric.Max(), | 
					
						
							|  |  |  | 				"mean":  metric.Mean(), | 
					
						
							|  |  |  | 				"std":   metric.StdDev(), | 
					
						
							|  |  |  | 				"p25":   percentiles[0], | 
					
						
							|  |  |  | 				"p75":   percentiles[1], | 
					
						
							|  |  |  | 				"p90":   percentiles[2], | 
					
						
							|  |  |  | 				"p99":   percentiles[3], | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 22:15:36 +08:00
										 |  |  | 	var b []byte | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	if b, err = json.MarshalIndent(resp, "", " "); err != nil { | 
					
						
							|  |  |  | 		return ApiError(500, "body json marshal", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &NormalResponse{ | 
					
						
							|  |  |  | 		body:   b, | 
					
						
							|  |  |  | 		status: 200, | 
					
						
							|  |  |  | 		header: http.Header{ | 
					
						
							|  |  |  | 			"Content-Type": []string{"application/json"}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-06-03 21:06:57 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-06-07 16:05:10 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Genereates a index out of range error
 | 
					
						
							|  |  |  | func GenerateError(c *middleware.Context) Response { | 
					
						
							|  |  |  | 	var array []string | 
					
						
							|  |  |  | 	return Json(200, array[20]) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-31 02:23:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GET /api/tsdb/testdata/gensql
 | 
					
						
							|  |  |  | func GenerateSqlTestData(c *middleware.Context) Response { | 
					
						
							|  |  |  | 	if err := bus.Dispatch(&models.InsertSqlTestDataCommand{}); err != nil { | 
					
						
							|  |  |  | 		return ApiError(500, "Failed to insert test data", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Json(200, &util.DynMap{"message": "OK"}) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-05-29 16:48:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GET /api/tsdb/testdata/random-walk
 | 
					
						
							|  |  |  | func GetTestDataRandomWalk(c *middleware.Context) Response { | 
					
						
							|  |  |  | 	from := c.Query("from") | 
					
						
							|  |  |  | 	to := c.Query("to") | 
					
						
							|  |  |  | 	intervalMs := c.QueryInt64("intervalMs") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	timeRange := tsdb.NewTimeRange(from, to) | 
					
						
							|  |  |  | 	request := &tsdb.Request{TimeRange: timeRange} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	request.Queries = append(request.Queries, &tsdb.Query{ | 
					
						
							|  |  |  | 		RefId:      "A", | 
					
						
							|  |  |  | 		IntervalMs: intervalMs, | 
					
						
							|  |  |  | 		Model: simplejson.NewFromAny(&util.DynMap{ | 
					
						
							|  |  |  | 			"scenario": "random_walk", | 
					
						
							|  |  |  | 		}), | 
					
						
							|  |  |  | 		DataSource: &models.DataSource{Type: "grafana-testdata-datasource"}, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resp, err := tsdb.HandleRequest(context.Background(), request) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return ApiError(500, "Metric request error", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return Json(200, &resp) | 
					
						
							|  |  |  | } |