mirror of
https://github.com/grafana/grafana.git
synced 2024-12-28 01:41:24 -06: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:
parent
17ebeab02c
commit
d9c40ca41e
@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/Masterminds/semver"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
||||
@ -36,10 +37,6 @@ type DatasourceInfo struct {
|
||||
|
||||
const loggerName = "tsdb.elasticsearch.client"
|
||||
|
||||
var (
|
||||
clientLog = log.New(loggerName)
|
||||
)
|
||||
|
||||
// Client represents a client which can interact with elasticsearch api
|
||||
type Client interface {
|
||||
GetTimeField() string
|
||||
@ -61,9 +58,11 @@ var NewClient = func(ctx context.Context, ds *DatasourceInfo, timeRange backend.
|
||||
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{
|
||||
logger: logger,
|
||||
ctx: ctx,
|
||||
ds: ds,
|
||||
timeField: ds.TimeField,
|
||||
@ -79,6 +78,7 @@ type baseClientImpl struct {
|
||||
indices []string
|
||||
timeRange backend.TimeRange
|
||||
debugEnabled bool
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
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) {
|
||||
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()
|
||||
|
||||
payload := bytes.Buffer{}
|
||||
@ -129,7 +129,7 @@ func (c *baseClientImpl) encodeBatchRequests(requests []*multiRequest) ([]byte,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@ -152,7 +152,7 @@ func (c *baseClientImpl) executeRequest(method, uriPath, uriQuery string, body [
|
||||
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
|
||||
if c.debugEnabled {
|
||||
@ -168,7 +168,7 @@ func (c *baseClientImpl) executeRequest(method, uriPath, uriQuery string, body [
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
elapsed := time.Since(start)
|
||||
clientLog.Debug("Executed request", "took", elapsed)
|
||||
c.logger.Debug("Executed request", "took", elapsed)
|
||||
}()
|
||||
//nolint:bodyclose
|
||||
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) {
|
||||
clientLog.Debug("Executing multisearch", "search requests", len(r.Requests))
|
||||
c.logger.Debug("Executing multisearch", "search requests", len(r.Requests))
|
||||
|
||||
multiRequests := c.createMultiSearchRequests(r.Requests)
|
||||
queryParams := c.getMultiSearchQueryParameters()
|
||||
@ -193,20 +193,20 @@ func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearch
|
||||
res := clientRes.httpResponse
|
||||
defer func() {
|
||||
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()
|
||||
clientLog.Debug("Decoding multisearch json response")
|
||||
c.logger.Debug("Decoding multisearch json response")
|
||||
|
||||
var bodyBytes []byte
|
||||
if c.debugEnabled {
|
||||
tmpBytes, err := io.ReadAll(res.Body)
|
||||
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 {
|
||||
bodyBytes = make([]byte, len(tmpBytes))
|
||||
copy(bodyBytes, tmpBytes)
|
||||
@ -222,7 +222,7 @@ func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearch
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@ -230,7 +230,7 @@ func (c *baseClientImpl) ExecuteMultisearch(r *MultiSearchRequest) (*MultiSearch
|
||||
bodyJSON, err := simplejson.NewFromReader(bytes.NewBuffer(bodyBytes))
|
||||
var data *simplejson.Json
|
||||
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 {
|
||||
data = bodyJSON
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"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/instancemgmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
es "github.com/grafana/grafana/pkg/tsdb/elasticsearch/client"
|
||||
@ -26,7 +27,7 @@ type Service struct {
|
||||
}
|
||||
|
||||
func ProvideService(httpClientProvider httpclient.Provider) *Service {
|
||||
eslog.Debug("initializing")
|
||||
eslog.Debug("Initializing")
|
||||
|
||||
return &Service{
|
||||
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/data"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
||||
@ -80,7 +81,7 @@ func newInstanceSettings(cfg *setting.Cfg) datasource.InstanceFactoryFunc {
|
||||
}
|
||||
|
||||
if cfg.Env == setting.Dev {
|
||||
logger.Debug("getEngine", "connection", cnnstr)
|
||||
logger.Debug("GetEngine", "connection", cnnstr)
|
||||
}
|
||||
config := sqleng.DataPluginConfiguration{
|
||||
DriverName: "mssql",
|
||||
@ -90,9 +91,7 @@ func newInstanceSettings(cfg *setting.Cfg) datasource.InstanceFactoryFunc {
|
||||
RowLimit: cfg.DataProxyRowLimit,
|
||||
}
|
||||
|
||||
queryResultTransformer := mssqlQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
queryResultTransformer := mssqlQueryResultTransformer{}
|
||||
|
||||
return sqleng.NewQueryDataHandler(config, &queryResultTransformer, newMssqlMacroEngine(), logger)
|
||||
}
|
||||
@ -175,15 +174,13 @@ func generateConnectionString(dsInfo sqleng.DataSourceInfo) (string, error) {
|
||||
return connStr, nil
|
||||
}
|
||||
|
||||
type mssqlQueryResultTransformer struct {
|
||||
log log.Logger
|
||||
}
|
||||
type mssqlQueryResultTransformer struct{}
|
||||
|
||||
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
|
||||
// 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") {
|
||||
t.log.Error("query error", "err", err)
|
||||
logger.Error("Query error", "error", err)
|
||||
return sqleng.ErrConnectionFailed
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@ import (
|
||||
"xorm.io/xorm"
|
||||
|
||||
"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/tsdb/sqleng"
|
||||
)
|
||||
@ -49,9 +48,7 @@ func TestMSSQL(t *testing.T) {
|
||||
return x, nil
|
||||
}
|
||||
|
||||
queryResultTransformer := mssqlQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
queryResultTransformer := mssqlQueryResultTransformer{}
|
||||
dsInfo := sqleng.DataSourceInfo{}
|
||||
config := sqleng.DataPluginConfiguration{
|
||||
DriverName: "mssql",
|
||||
@ -787,9 +784,7 @@ func TestMSSQL(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("When doing a metric query using stored procedure should return correct result", func(t *testing.T) {
|
||||
queryResultTransformer := mssqlQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
queryResultTransformer := mssqlQueryResultTransformer{}
|
||||
dsInfo := sqleng.DataSourceInfo{}
|
||||
config := sqleng.DataPluginConfiguration{
|
||||
DriverName: "mssql",
|
||||
@ -1194,9 +1189,7 @@ func TestMSSQL(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("When row limit set to 1", func(t *testing.T) {
|
||||
queryResultTransformer := mssqlQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
queryResultTransformer := mssqlQueryResultTransformer{}
|
||||
dsInfo := sqleng.DataSourceInfo{}
|
||||
config := sqleng.DataPluginConfiguration{
|
||||
DriverName: "mssql",
|
||||
@ -1273,9 +1266,7 @@ func TestMSSQL(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTransformQueryError(t *testing.T) {
|
||||
transformer := &mssqlQueryResultTransformer{
|
||||
log: log.New("test"),
|
||||
}
|
||||
transformer := &mssqlQueryResultTransformer{}
|
||||
|
||||
randomErr := fmt.Errorf("random error")
|
||||
|
||||
@ -1289,7 +1280,7 @@ func TestTransformQueryError(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
resultErr := transformer.TransformQueryError(tc.err)
|
||||
resultErr := transformer.TransformQueryError(logger, tc.err)
|
||||
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/data"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@ -106,7 +107,7 @@ func newInstanceSettings(cfg *setting.Cfg, httpClientProvider httpclient.Provide
|
||||
}
|
||||
|
||||
if cfg.Env == setting.Dev {
|
||||
logger.Debug("getEngine", "connection", cnnstr)
|
||||
logger.Debug("GetEngine", "connection", cnnstr)
|
||||
}
|
||||
|
||||
config := sqleng.DataPluginConfiguration{
|
||||
@ -118,9 +119,7 @@ func newInstanceSettings(cfg *setting.Cfg, httpClientProvider httpclient.Provide
|
||||
RowLimit: cfg.DataProxyRowLimit,
|
||||
}
|
||||
|
||||
rowTransformer := mysqlQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
rowTransformer := mysqlQueryResultTransformer{}
|
||||
|
||||
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 {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func (t *mysqlQueryResultTransformer) TransformQueryError(err error) error {
|
||||
func (t *mysqlQueryResultTransformer) TransformQueryError(logger log.Logger, err error) error {
|
||||
var driverErr *mysql.MySQLError
|
||||
if errors.As(err, &driverErr) {
|
||||
if driverErr.Number != mysqlerr.ER_PARSE_ERROR && driverErr.Number != mysqlerr.ER_BAD_FIELD_ERROR &&
|
||||
driverErr.Number != mysqlerr.ER_NO_SUCH_TABLE {
|
||||
t.log.Error("query error", "err", err)
|
||||
logger.Error("Query error", "error", err)
|
||||
return errQueryFailed
|
||||
}
|
||||
}
|
||||
|
@ -72,9 +72,7 @@ func TestIntegrationMySQL(t *testing.T) {
|
||||
RowLimit: 1000000,
|
||||
}
|
||||
|
||||
rowTransformer := mysqlQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
rowTransformer := mysqlQueryResultTransformer{}
|
||||
|
||||
exe, err := sqleng.NewQueryDataHandler(config, &rowTransformer, newMysqlMacroEngine(logger), logger)
|
||||
|
||||
@ -1165,9 +1163,7 @@ func TestIntegrationMySQL(t *testing.T) {
|
||||
RowLimit: 1,
|
||||
}
|
||||
|
||||
queryResultTransformer := mysqlQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
queryResultTransformer := mysqlQueryResultTransformer{}
|
||||
|
||||
handler, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newMysqlMacroEngine(logger), logger)
|
||||
require.NoError(t, err)
|
||||
|
@ -23,15 +23,15 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var logger = log.New("tsdb.opentsdb")
|
||||
|
||||
type Service struct {
|
||||
logger log.Logger
|
||||
im instancemgmt.InstanceManager
|
||||
im instancemgmt.InstanceManager
|
||||
}
|
||||
|
||||
func ProvideService(httpClientProvider httpclient.Provider) *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) {
|
||||
var tsdbQuery OpenTsdbQuery
|
||||
|
||||
logger := logger.FromContext(ctx)
|
||||
|
||||
q := req.Queries[0]
|
||||
|
||||
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
|
||||
if setting.Env == setting.Dev {
|
||||
s.logger.Debug("OpenTsdb request", "params", tsdbQuery)
|
||||
logger.Debug("OpenTsdb request", "params", tsdbQuery)
|
||||
}
|
||||
|
||||
dsInfo, err := s.getDSInfo(req.PluginContext)
|
||||
@ -86,7 +88,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
request, err := s.createRequest(ctx, dsInfo, tsdbQuery)
|
||||
request, err := s.createRequest(ctx, logger, dsInfo, tsdbQuery)
|
||||
if err != nil {
|
||||
return &backend.QueryDataResponse{}, err
|
||||
}
|
||||
@ -96,7 +98,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
||||
return &backend.QueryDataResponse{}, err
|
||||
}
|
||||
|
||||
result, err := s.parseResponse(res)
|
||||
result, err := s.parseResponse(logger, res)
|
||||
if err != nil {
|
||||
return &backend.QueryDataResponse{}, err
|
||||
}
|
||||
@ -104,7 +106,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -113,13 +115,13 @@ func (s *Service) createRequest(ctx context.Context, dsInfo *datasourceInfo, dat
|
||||
|
||||
postData, err := json.Marshal(data)
|
||||
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)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u.String(), strings.NewReader(string(postData)))
|
||||
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)
|
||||
}
|
||||
|
||||
@ -127,7 +129,7 @@ func (s *Service) createRequest(ctx context.Context, dsInfo *datasourceInfo, dat
|
||||
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()
|
||||
|
||||
body, err := io.ReadAll(res.Body)
|
||||
@ -136,19 +138,19 @@ func (s *Service) parseResponse(res *http.Response) (*backend.QueryDataResponse,
|
||||
}
|
||||
defer func() {
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
var responseData []OpenTsdbResponse
|
||||
err = json.Unmarshal(body, &responseData)
|
||||
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
|
||||
}
|
||||
|
||||
@ -162,7 +164,7 @@ func (s *Service) parseResponse(res *http.Response) (*backend.QueryDataResponse,
|
||||
for timeString, value := range val.DataPoints {
|
||||
timestamp, err := strconv.ParseInt(timeString, 10, 64)
|
||||
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
|
||||
}
|
||||
timeVector = append(timeVector, time.Unix(timestamp, 0).UTC())
|
||||
|
@ -13,17 +13,13 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
)
|
||||
|
||||
func TestOpenTsdbExecutor(t *testing.T) {
|
||||
service := &Service{
|
||||
logger: log.New("test"),
|
||||
}
|
||||
service := &Service{}
|
||||
|
||||
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)
|
||||
|
||||
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) {
|
||||
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.Error(t, err)
|
||||
})
|
||||
@ -67,7 +63,7 @@ func TestOpenTsdbExecutor(t *testing.T) {
|
||||
|
||||
resp := http.Response{Body: io.NopCloser(strings.NewReader(response))}
|
||||
resp.StatusCode = 200
|
||||
result, err := service.parseResponse(&resp)
|
||||
result, err := service.parseResponse(logger, &resp)
|
||||
require.NoError(t, err)
|
||||
|
||||
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/data"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data/sqlutil"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"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 {
|
||||
logger.Debug("getEngine", "connection", cnnstr)
|
||||
logger.Debug("GetEngine", "connection", cnnstr)
|
||||
}
|
||||
|
||||
config := sqleng.DataPluginConfiguration{
|
||||
@ -93,9 +94,7 @@ func (s *Service) newInstanceSettings(cfg *setting.Cfg) datasource.InstanceFacto
|
||||
RowLimit: cfg.DataProxyRowLimit,
|
||||
}
|
||||
|
||||
queryResultTransformer := postgresQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
queryResultTransformer := postgresQueryResultTransformer{}
|
||||
|
||||
handler, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newPostgresMacroEngine(dsInfo.JsonData.Timescaledb),
|
||||
logger)
|
||||
@ -185,11 +184,9 @@ func (s *Service) generateConnectionString(dsInfo sqleng.DataSourceInfo) (string
|
||||
return connStr, nil
|
||||
}
|
||||
|
||||
type postgresQueryResultTransformer struct {
|
||||
log log.Logger
|
||||
}
|
||||
type postgresQueryResultTransformer struct{}
|
||||
|
||||
func (t *postgresQueryResultTransformer) TransformQueryError(err error) error {
|
||||
func (t *postgresQueryResultTransformer) TransformQueryError(_ log.Logger, err error) error {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -223,9 +223,7 @@ func TestIntegrationPostgres(t *testing.T) {
|
||||
RowLimit: 1000000,
|
||||
}
|
||||
|
||||
queryResultTransformer := postgresQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
queryResultTransformer := postgresQueryResultTransformer{}
|
||||
|
||||
exe, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newPostgresMacroEngine(dsInfo.JsonData.Timescaledb),
|
||||
logger)
|
||||
@ -1267,9 +1265,7 @@ func TestIntegrationPostgres(t *testing.T) {
|
||||
RowLimit: 1,
|
||||
}
|
||||
|
||||
queryResultTransformer := postgresQueryResultTransformer{
|
||||
log: logger,
|
||||
}
|
||||
queryResultTransformer := postgresQueryResultTransformer{}
|
||||
|
||||
handler, err := sqleng.NewQueryDataHandler(config, &queryResultTransformer, newPostgresMacroEngine(false), logger)
|
||||
require.NoError(t, err)
|
||||
|
@ -37,7 +37,7 @@ type SQLMacroEngine interface {
|
||||
// SqlQueryResultTransformer transforms a query result row to RowValues with proper types.
|
||||
type SqlQueryResultTransformer interface {
|
||||
// TransformQueryError transforms a query error.
|
||||
TransformQueryError(err error) error
|
||||
TransformQueryError(logger log.Logger, err error) error
|
||||
GetConverterList() []sqlutil.StringConverter
|
||||
}
|
||||
|
||||
@ -105,18 +105,18 @@ type QueryJson struct {
|
||||
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
|
||||
// package. It describes the operation, network type, and address of
|
||||
// an error. We log this error rather than return it to the client
|
||||
// for security purposes.
|
||||
var opErr *net.OpError
|
||||
if errors.As(err, &opErr) {
|
||||
e.log.Error("query error", "err", err)
|
||||
logger.Error("Query error", "err", err)
|
||||
return ErrConnectionFailed
|
||||
}
|
||||
|
||||
return e.queryResultTransformer.TransformQueryError(err)
|
||||
return e.queryResultTransformer.TransformQueryError(logger, err)
|
||||
}
|
||||
|
||||
func NewQueryDataHandler(config DataPluginConfiguration, queryResultTransformer SqlQueryResultTransformer,
|
||||
@ -213,9 +213,11 @@ func (e *DataSourceHandler) executeQuery(query backend.DataQuery, wg *sync.WaitG
|
||||
refID: query.RefID,
|
||||
}
|
||||
|
||||
logger := e.log.FromContext(queryContext)
|
||||
|
||||
defer func() {
|
||||
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 {
|
||||
queryResult.dataResponse.Error = theErr
|
||||
} else if theErrString, ok := r.(string); ok {
|
||||
@ -246,14 +248,14 @@ func (e *DataSourceHandler) executeQuery(query backend.DataQuery, wg *sync.WaitG
|
||||
// global substitutions
|
||||
interpolatedQuery, err := Interpolate(query, timeRange, e.dsInfo.JsonData.TimeInterval, queryJson.RawSql)
|
||||
if err != nil {
|
||||
errAppendDebug("interpolation failed", e.transformQueryError(err), interpolatedQuery)
|
||||
errAppendDebug("interpolation failed", e.transformQueryError(logger, err), interpolatedQuery)
|
||||
return
|
||||
}
|
||||
|
||||
// data source specific substitutions
|
||||
interpolatedQuery, err = e.macroEngine.Interpolate(&query, timeRange, interpolatedQuery)
|
||||
if err != nil {
|
||||
errAppendDebug("interpolation failed", e.transformQueryError(err), interpolatedQuery)
|
||||
errAppendDebug("interpolation failed", e.transformQueryError(logger, err), interpolatedQuery)
|
||||
return
|
||||
}
|
||||
|
||||
@ -263,12 +265,12 @@ func (e *DataSourceHandler) executeQuery(query backend.DataQuery, wg *sync.WaitG
|
||||
|
||||
rows, err := db.QueryContext(queryContext, interpolatedQuery)
|
||||
if err != nil {
|
||||
errAppendDebug("db query error", e.transformQueryError(err), interpolatedQuery)
|
||||
errAppendDebug("db query error", e.transformQueryError(logger, err), interpolatedQuery)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
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
|
||||
frame, err = resample(frame, *qm)
|
||||
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})
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,11 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"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/require"
|
||||
"github.com/xorcare/pointer"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
)
|
||||
|
||||
func TestSQLEngine(t *testing.T) {
|
||||
@ -406,7 +407,7 @@ func TestSQLEngine(t *testing.T) {
|
||||
log: log.New("test"),
|
||||
queryResultTransformer: transformer,
|
||||
}
|
||||
resultErr := dp.transformQueryError(tc.err)
|
||||
resultErr := dp.transformQueryError(dp.log, tc.err)
|
||||
assert.ErrorIs(t, resultErr, tc.expectedErr)
|
||||
assert.Equal(t, tc.expectQueryResultTransformerWasCalled, transformer.transformQueryErrorWasCalled)
|
||||
}
|
||||
@ -417,7 +418,7 @@ type testQueryResultTransformer struct {
|
||||
transformQueryErrorWasCalled bool
|
||||
}
|
||||
|
||||
func (t *testQueryResultTransformer) TransformQueryError(err error) error {
|
||||
func (t *testQueryResultTransformer) TransformQueryError(_ log.Logger, err error) error {
|
||||
t.transformQueryErrorWasCalled = true
|
||||
return err
|
||||
}
|
||||
|
@ -11,9 +11,10 @@ import (
|
||||
"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/data"
|
||||
"go.opentelemetry.io/collector/model/otlp"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"go.opentelemetry.io/collector/model/otlp"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
@ -85,7 +86,7 @@ func (s *Service) QueryData(ctx context.Context, req *backend.QueryDataRequest)
|
||||
|
||||
defer func() {
|
||||
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")
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user