| 
									
										
										
										
											2015-01-06 16:11:00 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-07-24 18:34:56 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2021-02-04 03:47:45 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2016-06-03 21:06:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-31 23:35:03 +08:00
										 |  |  | 	"github.com/grafana/grafana-plugin-sdk-go/backend" | 
					
						
							| 
									
										
										
										
											2022-05-18 02:52:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 21:06:57 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/api/dtos" | 
					
						
							| 
									
										
										
										
											2021-01-15 21:43:20 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/api/response" | 
					
						
							| 
									
										
										
										
											2021-08-18 15:37:13 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/models" | 
					
						
							| 
									
										
										
										
											2022-04-29 18:08:40 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/plugins/backendplugin" | 
					
						
							| 
									
										
										
										
											2022-03-08 02:33:01 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/featuremgmt" | 
					
						
							| 
									
										
										
										
											2021-12-15 01:38:20 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/query" | 
					
						
							| 
									
										
										
										
											2021-11-10 18:52:16 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/tsdb/legacydata" | 
					
						
							| 
									
										
										
										
											2021-11-29 21:21:54 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/util" | 
					
						
							| 
									
										
										
										
											2021-11-29 17:18:01 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/web" | 
					
						
							| 
									
										
										
										
											2015-01-06 16:11:00 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-29 18:08:40 +08:00
										 |  |  | func (hs *HTTPServer) handleQueryMetricsError(err error) *response.NormalResponse { | 
					
						
							|  |  |  | 	if errors.Is(err, models.ErrDataSourceAccessDenied) { | 
					
						
							|  |  |  | 		return response.Error(http.StatusForbidden, "Access denied to data source", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if errors.Is(err, models.ErrDataSourceNotFound) { | 
					
						
							|  |  |  | 		return response.Error(http.StatusNotFound, "Data source not found", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var badQuery *query.ErrBadQuery | 
					
						
							|  |  |  | 	if errors.As(err, &badQuery) { | 
					
						
							|  |  |  | 		return response.Error(http.StatusBadRequest, util.Capitalize(badQuery.Message), err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if errors.Is(err, backendplugin.ErrPluginNotRegistered) { | 
					
						
							|  |  |  | 		return response.Error(http.StatusNotFound, "Plugin not found", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.Error(http.StatusInternalServerError, "Query data error", err) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-17 05:17:05 +08:00
										 |  |  | // QueryMetricsV2 returns query metrics.
 | 
					
						
							|  |  |  | // POST /api/ds/query   DataSource query w/ expressions
 | 
					
						
							|  |  |  | func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2022-03-08 02:33:01 +08:00
										 |  |  | 	reqDTO := dtos.MetricRequest{} | 
					
						
							|  |  |  | 	if err := web.Bind(c.Req, &reqDTO); err != nil { | 
					
						
							|  |  |  | 		return response.Error(http.StatusBadRequest, "bad request data", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	resp, err := hs.queryDataService.QueryData(c.Req.Context(), c.SignedInUser, c.SkipCache, reqDTO, true) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return hs.handleQueryMetricsError(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-05-04 00:02:20 +08:00
										 |  |  | 	return hs.toJsonStreamingResponse(resp) | 
					
						
							| 
									
										
										
										
											2022-03-08 02:33:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-29 21:21:54 +08:00
										 |  |  | // QueryMetrics returns query metrics
 | 
					
						
							|  |  |  | // POST /api/tsdb/query
 | 
					
						
							|  |  |  | //nolint: staticcheck // legacydata.DataResponse deprecated
 | 
					
						
							|  |  |  | //nolint: staticcheck // legacydata.DataQueryResult deprecated
 | 
					
						
							| 
									
										
										
										
											2022-03-30 23:46:06 +08:00
										 |  |  | // Deprecated: use QueryMetricsV2 instead.
 | 
					
						
							| 
									
										
										
										
											2021-11-29 21:21:54 +08:00
										 |  |  | func (hs *HTTPServer) QueryMetrics(c *models.ReqContext) response.Response { | 
					
						
							|  |  |  | 	reqDto := dtos.MetricRequest{} | 
					
						
							|  |  |  | 	if err := web.Bind(c.Req, &reqDto); err != nil { | 
					
						
							|  |  |  | 		return response.Error(http.StatusBadRequest, "bad request data", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-15 01:38:20 +08:00
										 |  |  | 	sdkResp, err := hs.queryDataService.QueryData(c.Req.Context(), c.SignedInUser, c.SkipCache, reqDto, false) | 
					
						
							| 
									
										
										
										
											2021-11-29 21:21:54 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return hs.handleQueryMetricsError(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	legacyResp := legacydata.DataResponse{ | 
					
						
							|  |  |  | 		Results: map[string]legacydata.DataQueryResult{}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for refID, res := range sdkResp.Responses { | 
					
						
							|  |  |  | 		dqr := legacydata.DataQueryResult{ | 
					
						
							|  |  |  | 			RefID: refID, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if res.Error != nil { | 
					
						
							|  |  |  | 			dqr.Error = res.Error | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if res.Frames != nil { | 
					
						
							|  |  |  | 			dqr.Dataframes = legacydata.NewDecodedDataFrames(res.Frames) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		legacyResp.Results[refID] = dqr | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	statusCode := http.StatusOK | 
					
						
							|  |  |  | 	for _, res := range legacyResp.Results { | 
					
						
							|  |  |  | 		if res.Error != nil { | 
					
						
							|  |  |  | 			res.ErrorString = res.Error.Error() | 
					
						
							|  |  |  | 			legacyResp.Message = res.ErrorString | 
					
						
							|  |  |  | 			statusCode = http.StatusBadRequest | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSON(statusCode, &legacyResp) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-04 00:02:20 +08:00
										 |  |  | func (hs *HTTPServer) toJsonStreamingResponse(qdr *backend.QueryDataResponse) response.Response { | 
					
						
							|  |  |  | 	statusWhenError := http.StatusBadRequest | 
					
						
							|  |  |  | 	if hs.Features.IsEnabled(featuremgmt.FlagDatasourceQueryMultiStatus) { | 
					
						
							|  |  |  | 		statusWhenError = http.StatusMultiStatus | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 23:12:55 +08:00
										 |  |  | 	statusCode := http.StatusOK | 
					
						
							|  |  |  | 	for _, res := range qdr.Responses { | 
					
						
							|  |  |  | 		if res.Error != nil { | 
					
						
							| 
									
										
										
										
											2022-05-04 00:02:20 +08:00
										 |  |  | 			statusCode = statusWhenError | 
					
						
							| 
									
										
										
										
											2021-11-05 23:12:55 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return response.JSONStreaming(statusCode, qdr) | 
					
						
							| 
									
										
										
										
											2019-10-25 21:28:26 +08:00
										 |  |  | } |