mirror of
https://github.com/grafana/grafana.git
synced 2025-07-30 12:32:43 +08:00
Chore: Update sqleng, elasticsearch, tempo and opentsdb plugins to support contextual logs. (#57777)
* make sql engine use pick log context for logs * update tempo to get log context * update opentsdb to use log context * update es client to use log context
This commit is contained in:
@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Masterminds/semver"
|
"github.com/Masterminds/semver"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
||||||
@ -36,10 +37,6 @@ type DatasourceInfo struct {
|
|||||||
|
|
||||||
const loggerName = "tsdb.elasticsearch.client"
|
const loggerName = "tsdb.elasticsearch.client"
|
||||||
|
|
||||||
var (
|
|
||||||
clientLog = log.New(loggerName)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Client represents a client which can interact with elasticsearch api
|
// Client represents a client which can interact with elasticsearch api
|
||||||
type Client interface {
|
type Client interface {
|
||||||
GetTimeField() string
|
GetTimeField() string
|
||||||
@ -61,9 +58,11 @@ var NewClient = func(ctx context.Context, ds *DatasourceInfo, timeRange backend.
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
clientLog.Debug("Creating new client", "version", ds.ESVersion, "timeField", ds.TimeField, "indices", strings.Join(indices, ", "))
|
logger := log.New(loggerName).FromContext(ctx)
|
||||||
|
logger.Debug("Creating new client", "version", ds.ESVersion, "timeField", ds.TimeField, "indices", strings.Join(indices, ", "))
|
||||||
|
|
||||||
return &baseClientImpl{
|
return &baseClientImpl{
|
||||||
|
logger: logger,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
ds: ds,
|
ds: ds,
|
||||||
timeField: ds.TimeField,
|
timeField: ds.TimeField,
|
||||||
@ -79,6 +78,7 @@ type baseClientImpl struct {
|
|||||||
indices []string
|
indices []string
|
||||||
timeRange backend.TimeRange
|
timeRange backend.TimeRange
|
||||||
debugEnabled bool
|
debugEnabled bool
|
||||||
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseClientImpl) GetTimeField() string {
|
func (c *baseClientImpl) GetTimeField() string {
|
||||||
@ -105,7 +105,7 @@ func (c *baseClientImpl) executeBatchRequest(uriPath, uriQuery string, requests
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseClientImpl) encodeBatchRequests(requests []*multiRequest) ([]byte, error) {
|
func (c *baseClientImpl) encodeBatchRequests(requests []*multiRequest) ([]byte, error) {
|
||||||
clientLog.Debug("Encoding batch requests to json", "batch requests", len(requests))
|
c.logger.Debug("Encoding batch requests to json", "batch requests", len(requests))
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
payload := bytes.Buffer{}
|
payload := bytes.Buffer{}
|
||||||
@ -129,7 +129,7 @@ func (c *baseClientImpl) encodeBatchRequests(requests []*multiRequest) ([]byte,
|
|||||||
}
|
}
|
||||||
|
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
clientLog.Debug("Encoded batch requests to json", "took", elapsed)
|
c.logger.Debug("Encoded batch requests to json", "took", elapsed)
|
||||||
|
|
||||||
return payload.Bytes(), nil
|
return payload.Bytes(), nil
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ func (c *baseClientImpl) executeRequest(method, uriPath, uriQuery string, body [
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
clientLog.Debug("Executing request", "url", req.URL.String(), "method", method)
|
c.logger.Debug("Executing request", "url", req.URL.String(), "method", method)
|
||||||
|
|
||||||
var reqInfo *SearchRequestInfo
|
var reqInfo *SearchRequestInfo
|
||||||
if c.debugEnabled {
|
if c.debugEnabled {
|
||||||
@ -168,7 +168,7 @@ func (c *baseClientImpl) executeRequest(method, uriPath, uriQuery string, body [
|
|||||||
start := time.Now()
|
start := time.Now()
|
||||||
defer func() {
|
defer func() {
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
clientLog.Debug("Executed request", "took", elapsed)
|
c.logger.Debug("Executed request", "took", elapsed)
|
||||||
}()
|
}()
|
||||||
//nolint:bodyclose
|
//nolint:bodyclose
|
||||||
resp, err := c.ds.HTTPClient.Do(req)
|
resp, err := c.ds.HTTPClient.Do(req)
|
||||||
@ -182,7 +182,7 @@ func (c *baseClientImpl) executeRequest(method, uriPath, uriQuery string, body [
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearchResponse, error) {
|
func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearchResponse, error) {
|
||||||
clientLog.Debug("Executing multisearch", "search requests", len(r.Requests))
|
c.logger.Debug("Executing multisearch", "search requests", len(r.Requests))
|
||||||
|
|
||||||
multiRequests := c.createMultiSearchRequests(r.Requests)
|
multiRequests := c.createMultiSearchRequests(r.Requests)
|
||||||
queryParams := c.getMultiSearchQueryParameters()
|
queryParams := c.getMultiSearchQueryParameters()
|
||||||
@ -193,20 +193,20 @@ func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearch
|
|||||||
res := clientRes.httpResponse
|
res := clientRes.httpResponse
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := res.Body.Close(); err != nil {
|
if err := res.Body.Close(); err != nil {
|
||||||
clientLog.Warn("Failed to close response body", "err", err)
|
c.logger.Warn("Failed to close response body", "err", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
clientLog.Debug("Received multisearch response", "code", res.StatusCode, "status", res.Status, "content-length", res.ContentLength)
|
c.logger.Debug("Received multisearch response", "code", res.StatusCode, "status", res.Status, "content-length", res.ContentLength)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
clientLog.Debug("Decoding multisearch json response")
|
c.logger.Debug("Decoding multisearch json response")
|
||||||
|
|
||||||
var bodyBytes []byte
|
var bodyBytes []byte
|
||||||
if c.debugEnabled {
|
if c.debugEnabled {
|
||||||
tmpBytes, err := io.ReadAll(res.Body)
|
tmpBytes, err := io.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
clientLog.Error("failed to read http response bytes", "error", err)
|
c.logger.Error("Failed to read http response bytes", "error", err)
|
||||||
} else {
|
} else {
|
||||||
bodyBytes = make([]byte, len(tmpBytes))
|
bodyBytes = make([]byte, len(tmpBytes))
|
||||||
copy(bodyBytes, tmpBytes)
|
copy(bodyBytes, tmpBytes)
|
||||||
@ -222,7 +222,7 @@ func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearch
|
|||||||
}
|
}
|
||||||
|
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
clientLog.Debug("Decoded multisearch json response", "took", elapsed)
|
c.logger.Debug("Decoded multisearch json response", "took", elapsed)
|
||||||
|
|
||||||
msr.Status = res.StatusCode
|
msr.Status = res.StatusCode
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearch
|
|||||||
bodyJSON, err := simplejson.NewFromReader(bytes.NewBuffer(bodyBytes))
|
bodyJSON, err := simplejson.NewFromReader(bytes.NewBuffer(bodyBytes))
|
||||||
var data *simplejson.Json
|
var data *simplejson.Json
|
||||||
if err != nil {
|
if err != nil {
|
||||||
clientLog.Error("failed to decode http response into json", "error", err)
|
c.logger.Error("Failed to decode http response into json", "error", err)
|
||||||
} else {
|
} else {
|
||||||
data = bodyJSON
|
data = bodyJSON
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
|
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
|
||||||
@ -26,7 +27,7 @@ type Service struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ProvideService(httpClientProvider httpclient.Provider) *Service {
|
func ProvideService(httpClientProvider httpclient.Provider) *Service {
|
||||||
eslog.Debug("initializing")
|
eslog.Debug("Initializing")
|
||||||
|
|
||||||
return &Service{
|
return &Service{
|
||||||
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
|
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
||||||
@ -80,7 +81,7 @@ func newInstanceSettings(cfg *setting.Cfg) datasource.InstanceFactoryFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Env == setting.Dev {
|
if cfg.Env == setting.Dev {
|
||||||
logger.Debug("getEngine", "connection", cnnstr)
|
logger.Debug("GetEngine", "connection", cnnstr)
|
||||||
}
|
}
|
||||||
config := sqleng.DataPluginConfiguration{
|
config := sqleng.DataPluginConfiguration{
|
||||||
DriverName: "mssql",
|
DriverName: "mssql",
|
||||||
@ -90,9 +91,7 @@ func newInstanceSettings(cfg *setting.Cfg) datasource.InstanceFactoryFunc {
|
|||||||
RowLimit: cfg.DataProxyRowLimit,
|
RowLimit: cfg.DataProxyRowLimit,
|
||||||
}
|
}
|
||||||
|
|
||||||
queryResultTransformer := mssqlQueryResultTransformer{
|
queryResultTransformer := mssqlQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
return sqleng.NewQueryDataHandler(config, &queryResultTransformer, newMssqlMacroEngine(), logger)
|
return sqleng.NewQueryDataHandler(config, &queryResultTransformer, newMssqlMacroEngine(), logger)
|
||||||
}
|
}
|
||||||
@ -175,15 +174,13 @@ func generateConnectionString(dsInfo sqleng.DataSourceInfo) (string, error) {
|
|||||||
return connStr, nil
|
return connStr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type mssqlQueryResultTransformer struct {
|
type mssqlQueryResultTransformer struct{}
|
||||||
log log.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *mssqlQueryResultTransformer) TransformQueryError(err error) error {
|
func (t *mssqlQueryResultTransformer) TransformQueryError(logger log.Logger, err error) error {
|
||||||
// go-mssql overrides source error, so we currently match on string
|
// go-mssql overrides source error, so we currently match on string
|
||||||
// ref https://github.com/denisenkom/go-mssqldb/blob/045585d74f9069afe2e115b6235eb043c8047043/tds.go#L904
|
// ref https://github.com/denisenkom/go-mssqldb/blob/045585d74f9069afe2e115b6235eb043c8047043/tds.go#L904
|
||||||
if strings.HasPrefix(strings.ToLower(err.Error()), "unable to open tcp connection with host") {
|
if strings.HasPrefix(strings.ToLower(err.Error()), "unable to open tcp connection with host") {
|
||||||
t.log.Error("query error", "err", err)
|
logger.Error("Query error", "error", err)
|
||||||
return sqleng.ErrConnectionFailed
|
return sqleng.ErrConnectionFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ import (
|
|||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
|
||||||
"github.com/grafana/grafana/pkg/services/sqlstore/sqlutil"
|
"github.com/grafana/grafana/pkg/services/sqlstore/sqlutil"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
||||||
)
|
)
|
||||||
@ -49,9 +48,7 @@ func TestMSSQL(t *testing.T) {
|
|||||||
return x, nil
|
return x, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
queryResultTransformer := mssqlQueryResultTransformer{
|
queryResultTransformer := mssqlQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
dsInfo := sqleng.DataSourceInfo{}
|
dsInfo := sqleng.DataSourceInfo{}
|
||||||
config := sqleng.DataPluginConfiguration{
|
config := sqleng.DataPluginConfiguration{
|
||||||
DriverName: "mssql",
|
DriverName: "mssql",
|
||||||
@ -787,9 +784,7 @@ func TestMSSQL(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("When doing a metric query using stored procedure should return correct result", func(t *testing.T) {
|
t.Run("When doing a metric query using stored procedure should return correct result", func(t *testing.T) {
|
||||||
queryResultTransformer := mssqlQueryResultTransformer{
|
queryResultTransformer := mssqlQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
dsInfo := sqleng.DataSourceInfo{}
|
dsInfo := sqleng.DataSourceInfo{}
|
||||||
config := sqleng.DataPluginConfiguration{
|
config := sqleng.DataPluginConfiguration{
|
||||||
DriverName: "mssql",
|
DriverName: "mssql",
|
||||||
@ -1194,9 +1189,7 @@ func TestMSSQL(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("When row limit set to 1", func(t *testing.T) {
|
t.Run("When row limit set to 1", func(t *testing.T) {
|
||||||
queryResultTransformer := mssqlQueryResultTransformer{
|
queryResultTransformer := mssqlQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
dsInfo := sqleng.DataSourceInfo{}
|
dsInfo := sqleng.DataSourceInfo{}
|
||||||
config := sqleng.DataPluginConfiguration{
|
config := sqleng.DataPluginConfiguration{
|
||||||
DriverName: "mssql",
|
DriverName: "mssql",
|
||||||
@ -1273,9 +1266,7 @@ func TestMSSQL(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTransformQueryError(t *testing.T) {
|
func TestTransformQueryError(t *testing.T) {
|
||||||
transformer := &mssqlQueryResultTransformer{
|
transformer := &mssqlQueryResultTransformer{}
|
||||||
log: log.New("test"),
|
|
||||||
}
|
|
||||||
|
|
||||||
randomErr := fmt.Errorf("random error")
|
randomErr := fmt.Errorf("random error")
|
||||||
|
|
||||||
@ -1289,7 +1280,7 @@ func TestTransformQueryError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
resultErr := transformer.TransformQueryError(tc.err)
|
resultErr := transformer.TransformQueryError(logger, tc.err)
|
||||||
assert.ErrorIs(t, resultErr, tc.expectedErr)
|
assert.ErrorIs(t, resultErr, tc.expectedErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
@ -106,7 +107,7 @@ func newInstanceSettings(cfg *setting.Cfg, httpClientProvider httpclient.Provide
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Env == setting.Dev {
|
if cfg.Env == setting.Dev {
|
||||||
logger.Debug("getEngine", "connection", cnnstr)
|
logger.Debug("GetEngine", "connection", cnnstr)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := sqleng.DataPluginConfiguration{
|
config := sqleng.DataPluginConfiguration{
|
||||||
@ -118,9 +119,7 @@ func newInstanceSettings(cfg *setting.Cfg, httpClientProvider httpclient.Provide
|
|||||||
RowLimit: cfg.DataProxyRowLimit,
|
RowLimit: cfg.DataProxyRowLimit,
|
||||||
}
|
}
|
||||||
|
|
||||||
rowTransformer := mysqlQueryResultTransformer{
|
rowTransformer := mysqlQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
return sqleng.NewQueryDataHandler(config, &rowTransformer, newMysqlMacroEngine(logger), logger)
|
return sqleng.NewQueryDataHandler(config, &rowTransformer, newMysqlMacroEngine(logger), logger)
|
||||||
}
|
}
|
||||||
@ -144,15 +143,14 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
type mysqlQueryResultTransformer struct {
|
type mysqlQueryResultTransformer struct {
|
||||||
log log.Logger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mysqlQueryResultTransformer) TransformQueryError(err error) error {
|
func (t *mysqlQueryResultTransformer) TransformQueryError(logger log.Logger, err error) error {
|
||||||
var driverErr *mysql.MySQLError
|
var driverErr *mysql.MySQLError
|
||||||
if errors.As(err, &driverErr) {
|
if errors.As(err, &driverErr) {
|
||||||
if driverErr.Number != mysqlerr.ER_PARSE_ERROR && driverErr.Number != mysqlerr.ER_BAD_FIELD_ERROR &&
|
if driverErr.Number != mysqlerr.ER_PARSE_ERROR && driverErr.Number != mysqlerr.ER_BAD_FIELD_ERROR &&
|
||||||
driverErr.Number != mysqlerr.ER_NO_SUCH_TABLE {
|
driverErr.Number != mysqlerr.ER_NO_SUCH_TABLE {
|
||||||
t.log.Error("query error", "err", err)
|
logger.Error("Query error", "error", err)
|
||||||
return errQueryFailed
|
return errQueryFailed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,9 +72,7 @@ func TestIntegrationMySQL(t *testing.T) {
|
|||||||
RowLimit: 1000000,
|
RowLimit: 1000000,
|
||||||
}
|
}
|
||||||
|
|
||||||
rowTransformer := mysqlQueryResultTransformer{
|
rowTransformer := mysqlQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
exe, err := sqleng.NewQueryDataHandler(config, &rowTransformer, newMysqlMacroEngine(logger), logger)
|
exe, err := sqleng.NewQueryDataHandler(config, &rowTransformer, newMysqlMacroEngine(logger), logger)
|
||||||
|
|
||||||
@ -1165,9 +1163,7 @@ func TestIntegrationMySQL(t *testing.T) {
|
|||||||
RowLimit: 1,
|
RowLimit: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
queryResultTransformer := mysqlQueryResultTransformer{
|
queryResultTransformer := mysqlQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
handler, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newMysqlMacroEngine(logger), logger)
|
handler, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newMysqlMacroEngine(logger), logger)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -23,15 +23,15 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var logger = log.New("tsdb.opentsdb")
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
logger log.Logger
|
im instancemgmt.InstanceManager
|
||||||
im instancemgmt.InstanceManager
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProvideService(httpClientProvider httpclient.Provider) *Service {
|
func ProvideService(httpClientProvider httpclient.Provider) *Service {
|
||||||
return &Service{
|
return &Service{
|
||||||
logger: log.New("tsdb.opentsdb"),
|
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
|
||||||
im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +66,8 @@ func newInstanceSettings(httpClientProvider httpclient.Provider) datasource.Inst
|
|||||||
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
var tsdbQuery OpenTsdbQuery
|
var tsdbQuery OpenTsdbQuery
|
||||||
|
|
||||||
|
logger := logger.FromContext(ctx)
|
||||||
|
|
||||||
q := req.Queries[0]
|
q := req.Queries[0]
|
||||||
|
|
||||||
tsdbQuery.Start = q.TimeRange.From.UnixNano() / int64(time.Millisecond)
|
tsdbQuery.Start = q.TimeRange.From.UnixNano() / int64(time.Millisecond)
|
||||||
@ -78,7 +80,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
|||||||
|
|
||||||
// TODO: Don't use global variable
|
// TODO: Don't use global variable
|
||||||
if setting.Env == setting.Dev {
|
if setting.Env == setting.Dev {
|
||||||
s.logger.Debug("OpenTsdb request", "params", tsdbQuery)
|
logger.Debug("OpenTsdb request", "params", tsdbQuery)
|
||||||
}
|
}
|
||||||
|
|
||||||
dsInfo, err := s.getDSInfo(req.PluginContext)
|
dsInfo, err := s.getDSInfo(req.PluginContext)
|
||||||
@ -86,7 +88,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
request, err := s.createRequest(ctx, dsInfo, tsdbQuery)
|
request, err := s.createRequest(ctx, logger, dsInfo, tsdbQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &backend.QueryDataResponse{}, err
|
return &backend.QueryDataResponse{}, err
|
||||||
}
|
}
|
||||||
@ -96,7 +98,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
|||||||
return &backend.QueryDataResponse{}, err
|
return &backend.QueryDataResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := s.parseResponse(res)
|
result, err := s.parseResponse(logger, res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &backend.QueryDataResponse{}, err
|
return &backend.QueryDataResponse{}, err
|
||||||
}
|
}
|
||||||
@ -104,7 +106,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) createRequest(ctx context.Context, dsInfo *datasourceInfo, data OpenTsdbQuery) (*http.Request, error) {
|
func (s *Service) createRequest(ctx context.Context, logger log.Logger, dsInfo *datasourceInfo, data OpenTsdbQuery) (*http.Request, error) {
|
||||||
u, err := url.Parse(dsInfo.URL)
|
u, err := url.Parse(dsInfo.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -113,13 +115,13 @@ func (s *Service) createRequest(ctx context.Context, dsInfo *datasourceInfo, dat
|
|||||||
|
|
||||||
postData, err := json.Marshal(data)
|
postData, err := json.Marshal(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Info("Failed marshaling data", "error", err)
|
logger.Info("Failed marshaling data", "error", err)
|
||||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u.String(), strings.NewReader(string(postData)))
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u.String(), strings.NewReader(string(postData)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Info("Failed to create request", "error", err)
|
logger.Info("Failed to create request", "error", err)
|
||||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +129,7 @@ func (s *Service) createRequest(ctx context.Context, dsInfo *datasourceInfo, dat
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) parseResponse(res *http.Response) (*backend.QueryDataResponse, error) {
|
func (s *Service) parseResponse(logger log.Logger, res *http.Response) (*backend.QueryDataResponse, error) {
|
||||||
resp := backend.NewQueryDataResponse()
|
resp := backend.NewQueryDataResponse()
|
||||||
|
|
||||||
body, err := io.ReadAll(res.Body)
|
body, err := io.ReadAll(res.Body)
|
||||||
@ -136,19 +138,19 @@ func (s *Service) parseResponse(res *http.Response) (*backend.QueryDataResponse,
|
|||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := res.Body.Close(); err != nil {
|
if err := res.Body.Close(); err != nil {
|
||||||
s.logger.Warn("Failed to close response body", "err", err)
|
logger.Warn("Failed to close response body", "err", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if res.StatusCode/100 != 2 {
|
if res.StatusCode/100 != 2 {
|
||||||
s.logger.Info("Request failed", "status", res.Status, "body", string(body))
|
logger.Info("Request failed", "status", res.Status, "body", string(body))
|
||||||
return nil, fmt.Errorf("request failed, status: %s", res.Status)
|
return nil, fmt.Errorf("request failed, status: %s", res.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
var responseData []OpenTsdbResponse
|
var responseData []OpenTsdbResponse
|
||||||
err = json.Unmarshal(body, &responseData)
|
err = json.Unmarshal(body, &responseData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Info("Failed to unmarshal opentsdb response", "error", err, "status", res.Status, "body", string(body))
|
logger.Info("Failed to unmarshal opentsdb response", "error", err, "status", res.Status, "body", string(body))
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +164,7 @@ func (s *Service) parseResponse(res *http.Response) (*backend.QueryDataResponse,
|
|||||||
for timeString, value := range val.DataPoints {
|
for timeString, value := range val.DataPoints {
|
||||||
timestamp, err := strconv.ParseInt(timeString, 10, 64)
|
timestamp, err := strconv.ParseInt(timeString, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Info("Failed to unmarshal opentsdb timestamp", "timestamp", timeString)
|
logger.Info("Failed to unmarshal opentsdb timestamp", "timestamp", timeString)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
timeVector = append(timeVector, time.Unix(timestamp, 0).UTC())
|
timeVector = append(timeVector, time.Unix(timestamp, 0).UTC())
|
||||||
|
@ -13,17 +13,13 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOpenTsdbExecutor(t *testing.T) {
|
func TestOpenTsdbExecutor(t *testing.T) {
|
||||||
service := &Service{
|
service := &Service{}
|
||||||
logger: log.New("test"),
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("create request", func(t *testing.T) {
|
t.Run("create request", func(t *testing.T) {
|
||||||
req, err := service.createRequest(context.Background(), &datasourceInfo{}, OpenTsdbQuery{})
|
req, err := service.createRequest(context.Background(), logger, &datasourceInfo{}, OpenTsdbQuery{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, "POST", req.Method)
|
assert.Equal(t, "POST", req.Method)
|
||||||
@ -37,7 +33,7 @@ func TestOpenTsdbExecutor(t *testing.T) {
|
|||||||
t.Run("Parse response should handle invalid JSON", func(t *testing.T) {
|
t.Run("Parse response should handle invalid JSON", func(t *testing.T) {
|
||||||
response := `{ invalid }`
|
response := `{ invalid }`
|
||||||
|
|
||||||
result, err := service.parseResponse(&http.Response{Body: io.NopCloser(strings.NewReader(response))})
|
result, err := service.parseResponse(logger, &http.Response{Body: io.NopCloser(strings.NewReader(response))})
|
||||||
require.Nil(t, result)
|
require.Nil(t, result)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
@ -67,7 +63,7 @@ func TestOpenTsdbExecutor(t *testing.T) {
|
|||||||
|
|
||||||
resp := http.Response{Body: io.NopCloser(strings.NewReader(response))}
|
resp := http.Response{Body: io.NopCloser(strings.NewReader(response))}
|
||||||
resp.StatusCode = 200
|
resp.StatusCode = 200
|
||||||
result, err := service.parseResponse(&resp)
|
result, err := service.parseResponse(logger, &resp)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
frame := result.Responses["A"]
|
frame := result.Responses["A"]
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
||||||
@ -82,7 +83,7 @@ func (s *Service) newInstanceSettings(cfg *setting.Cfg) datasource.InstanceFacto
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Env == setting.Dev {
|
if cfg.Env == setting.Dev {
|
||||||
logger.Debug("getEngine", "connection", cnnstr)
|
logger.Debug("GetEngine", "connection", cnnstr)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := sqleng.DataPluginConfiguration{
|
config := sqleng.DataPluginConfiguration{
|
||||||
@ -93,9 +94,7 @@ func (s *Service) newInstanceSettings(cfg *setting.Cfg) datasource.InstanceFacto
|
|||||||
RowLimit: cfg.DataProxyRowLimit,
|
RowLimit: cfg.DataProxyRowLimit,
|
||||||
}
|
}
|
||||||
|
|
||||||
queryResultTransformer := postgresQueryResultTransformer{
|
queryResultTransformer := postgresQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
handler, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newPostgresMacroEngine(dsInfo.JsonData.Timescaledb),
|
handler, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newPostgresMacroEngine(dsInfo.JsonData.Timescaledb),
|
||||||
logger)
|
logger)
|
||||||
@ -185,11 +184,9 @@ func (s *Service) generateConnectionString(dsInfo sqleng.DataSourceInfo) (string
|
|||||||
return connStr, nil
|
return connStr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type postgresQueryResultTransformer struct {
|
type postgresQueryResultTransformer struct{}
|
||||||
log log.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *postgresQueryResultTransformer) TransformQueryError(err error) error {
|
func (t *postgresQueryResultTransformer) TransformQueryError(_ log.Logger, err error) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,9 +223,7 @@ func TestIntegrationPostgres(t *testing.T) {
|
|||||||
RowLimit: 1000000,
|
RowLimit: 1000000,
|
||||||
}
|
}
|
||||||
|
|
||||||
queryResultTransformer := postgresQueryResultTransformer{
|
queryResultTransformer := postgresQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
exe, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newPostgresMacroEngine(dsInfo.JsonData.Timescaledb),
|
exe, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newPostgresMacroEngine(dsInfo.JsonData.Timescaledb),
|
||||||
logger)
|
logger)
|
||||||
@ -1267,9 +1265,7 @@ func TestIntegrationPostgres(t *testing.T) {
|
|||||||
RowLimit: 1,
|
RowLimit: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
queryResultTransformer := postgresQueryResultTransformer{
|
queryResultTransformer := postgresQueryResultTransformer{}
|
||||||
log: logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
handler, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newPostgresMacroEngine(false), logger)
|
handler, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newPostgresMacroEngine(false), logger)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -37,7 +37,7 @@ type SQLMacroEngine interface {
|
|||||||
// SqlQueryResultTransformer transforms a query result row to RowValues with proper types.
|
// SqlQueryResultTransformer transforms a query result row to RowValues with proper types.
|
||||||
type SqlQueryResultTransformer interface {
|
type SqlQueryResultTransformer interface {
|
||||||
// TransformQueryError transforms a query error.
|
// TransformQueryError transforms a query error.
|
||||||
TransformQueryError(err error) error
|
TransformQueryError(logger log.Logger, err error) error
|
||||||
GetConverterList() []sqlutil.StringConverter
|
GetConverterList() []sqlutil.StringConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,18 +105,18 @@ type QueryJson struct {
|
|||||||
Format string `json:"format"`
|
Format string `json:"format"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *DataSourceHandler) transformQueryError(err error) error {
|
func (e *DataSourceHandler) transformQueryError(logger log.Logger, err error) error {
|
||||||
// OpError is the error type usually returned by functions in the net
|
// OpError is the error type usually returned by functions in the net
|
||||||
// package. It describes the operation, network type, and address of
|
// package. It describes the operation, network type, and address of
|
||||||
// an error. We log this error rather than return it to the client
|
// an error. We log this error rather than return it to the client
|
||||||
// for security purposes.
|
// for security purposes.
|
||||||
var opErr *net.OpError
|
var opErr *net.OpError
|
||||||
if errors.As(err, &opErr) {
|
if errors.As(err, &opErr) {
|
||||||
e.log.Error("query error", "err", err)
|
logger.Error("Query error", "err", err)
|
||||||
return ErrConnectionFailed
|
return ErrConnectionFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
return e.queryResultTransformer.TransformQueryError(err)
|
return e.queryResultTransformer.TransformQueryError(logger, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewQueryDataHandler(config DataPluginConfiguration, queryResultTransformer SqlQueryResultTransformer,
|
func NewQueryDataHandler(config DataPluginConfiguration, queryResultTransformer SqlQueryResultTransformer,
|
||||||
@ -213,9 +213,11 @@ func (e *DataSourceHandler) executeQuery(query backend.DataQuery, wg *sync.WaitG
|
|||||||
refID: query.RefID,
|
refID: query.RefID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger := e.log.FromContext(queryContext)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
e.log.Error("executeQuery panic", "error", r, "stack", log.Stack(1))
|
logger.Error("ExecuteQuery panic", "error", r, "stack", log.Stack(1))
|
||||||
if theErr, ok := r.(error); ok {
|
if theErr, ok := r.(error); ok {
|
||||||
queryResult.dataResponse.Error = theErr
|
queryResult.dataResponse.Error = theErr
|
||||||
} else if theErrString, ok := r.(string); ok {
|
} else if theErrString, ok := r.(string); ok {
|
||||||
@ -246,14 +248,14 @@ func (e *DataSourceHandler) executeQuery(query backend.DataQuery, wg *sync.WaitG
|
|||||||
// global substitutions
|
// global substitutions
|
||||||
interpolatedQuery, err := Interpolate(query, timeRange, e.dsInfo.JsonData.TimeInterval, queryJson.RawSql)
|
interpolatedQuery, err := Interpolate(query, timeRange, e.dsInfo.JsonData.TimeInterval, queryJson.RawSql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errAppendDebug("interpolation failed", e.transformQueryError(err), interpolatedQuery)
|
errAppendDebug("interpolation failed", e.transformQueryError(logger, err), interpolatedQuery)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// data source specific substitutions
|
// data source specific substitutions
|
||||||
interpolatedQuery, err = e.macroEngine.Interpolate(&query, timeRange, interpolatedQuery)
|
interpolatedQuery, err = e.macroEngine.Interpolate(&query, timeRange, interpolatedQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errAppendDebug("interpolation failed", e.transformQueryError(err), interpolatedQuery)
|
errAppendDebug("interpolation failed", e.transformQueryError(logger, err), interpolatedQuery)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,12 +265,12 @@ func (e *DataSourceHandler) executeQuery(query backend.DataQuery, wg *sync.WaitG
|
|||||||
|
|
||||||
rows, err := db.QueryContext(queryContext, interpolatedQuery)
|
rows, err := db.QueryContext(queryContext, interpolatedQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errAppendDebug("db query error", e.transformQueryError(err), interpolatedQuery)
|
errAppendDebug("db query error", e.transformQueryError(logger, err), interpolatedQuery)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := rows.Close(); err != nil {
|
if err := rows.Close(); err != nil {
|
||||||
e.log.Warn("Failed to close rows", "err", err)
|
logger.Warn("Failed to close rows", "err", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -359,7 +361,7 @@ func (e *DataSourceHandler) executeQuery(query backend.DataQuery, wg *sync.WaitG
|
|||||||
var err error
|
var err error
|
||||||
frame, err = resample(frame, *qm)
|
frame, err = resample(frame, *qm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.log.Error("Failed to resample dataframe", "err", err)
|
logger.Error("Failed to resample dataframe", "err", err)
|
||||||
frame.AppendNotices(data.Notice{Text: "Failed to resample dataframe", Severity: data.NoticeSeverityWarning})
|
frame.AppendNotices(data.Notice{Text: "Failed to resample dataframe", Severity: data.NoticeSeverityWarning})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,11 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/xorcare/pointer"
|
"github.com/xorcare/pointer"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSQLEngine(t *testing.T) {
|
func TestSQLEngine(t *testing.T) {
|
||||||
@ -406,7 +407,7 @@ func TestSQLEngine(t *testing.T) {
|
|||||||
log: log.New("test"),
|
log: log.New("test"),
|
||||||
queryResultTransformer: transformer,
|
queryResultTransformer: transformer,
|
||||||
}
|
}
|
||||||
resultErr := dp.transformQueryError(tc.err)
|
resultErr := dp.transformQueryError(dp.log, tc.err)
|
||||||
assert.ErrorIs(t, resultErr, tc.expectedErr)
|
assert.ErrorIs(t, resultErr, tc.expectedErr)
|
||||||
assert.Equal(t, tc.expectQueryResultTransformerWasCalled, transformer.transformQueryErrorWasCalled)
|
assert.Equal(t, tc.expectQueryResultTransformerWasCalled, transformer.transformQueryErrorWasCalled)
|
||||||
}
|
}
|
||||||
@ -417,7 +418,7 @@ type testQueryResultTransformer struct {
|
|||||||
transformQueryErrorWasCalled bool
|
transformQueryErrorWasCalled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *testQueryResultTransformer) TransformQueryError(err error) error {
|
func (t *testQueryResultTransformer) TransformQueryError(_ log.Logger, err error) error {
|
||||||
t.transformQueryErrorWasCalled = true
|
t.transformQueryErrorWasCalled = true
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,10 @@ import (
|
|||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/datasource"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||||
|
"go.opentelemetry.io/collector/model/otlp"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"go.opentelemetry.io/collector/model/otlp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
@ -85,7 +86,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := resp.Body.Close(); err != nil {
|
if err := resp.Body.Close(); err != nil {
|
||||||
s.tlog.Warn("failed to close response body", "err", err)
|
s.tlog.FromContext(ctx).Warn("failed to close response body", "err", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -132,7 +133,7 @@ func (s *Service) createRequest(ctx context.Context, dsInfo *datasourceInfo, tra
|
|||||||
|
|
||||||
req.Header.Set("Accept", "application/protobuf")
|
req.Header.Set("Accept", "application/protobuf")
|
||||||
|
|
||||||
s.tlog.Debug("Tempo request", "url", req.URL.String(), "headers", req.Header)
|
s.tlog.FromContext(ctx).Debug("Tempo request", "url", req.URL.String(), "headers", req.Header)
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user