From ff9556229addd0e82c2b32f77b2ca52b76496048 Mon Sep 17 00:00:00 2001 From: Carl Bergquist Date: Tue, 18 Feb 2020 13:26:01 +0100 Subject: [PATCH] Data proxy: Log proxy errors using Grafana logger (#22174) Now any errors logged by http.ReverseProxy are forwarded to Grafana's logger and includes more contextual information like level (error), user id, org id, username, proxy path, referer and IP address. Co-authored-by: Marcus Efraimsson --- pkg/api/pluginproxy/ds_proxy.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/pkg/api/pluginproxy/ds_proxy.go b/pkg/api/pluginproxy/ds_proxy.go index a7da75386e2..8ff2cb060a2 100644 --- a/pkg/api/pluginproxy/ds_proxy.go +++ b/pkg/api/pluginproxy/ds_proxy.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io/ioutil" + "log" "net" "net/http" "net/http/httputil" @@ -17,7 +18,7 @@ import ( "golang.org/x/oauth2" "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/infra/log" + glog "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/login/social" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" @@ -26,7 +27,7 @@ import ( ) var ( - logger = log.New("data-proxy-log") + logger = glog.New("data-proxy-log") client = newHTTPClient() ) @@ -57,6 +58,18 @@ type httpClient interface { Do(req *http.Request) (*http.Response, error) } +type logWrapper struct { + logger glog.Logger +} + +// Write writes log messages as bytes from proxy +func (lw *logWrapper) Write(p []byte) (n int, err error) { + withoutNewline := strings.TrimSuffix(string(p), "\n") + lw.logger.Error("Data proxy error", "error", withoutNewline) + return len(p), nil +} + +// NewDataSourceProxy creates a new Datasource proxy func NewDataSourceProxy(ds *m.DataSource, plugin *plugins.DataSourcePlugin, ctx *m.ReqContext, proxyPath string, cfg *setting.Cfg) *DataSourceProxy { targetURL, _ := url.Parse(ds.Url) @@ -83,9 +96,12 @@ func (proxy *DataSourceProxy) HandleRequest() { return } + proxyErrorLogger := logger.New("userId", proxy.ctx.UserId, "orgId", proxy.ctx.OrgId, "uname", proxy.ctx.Login, "path", proxy.ctx.Req.URL.Path, "remote_addr", proxy.ctx.RemoteAddr(), "referer", proxy.ctx.Req.Referer()) + reverseProxy := &httputil.ReverseProxy{ Director: proxy.getDirector(), FlushInterval: time.Millisecond * 200, + ErrorLog: log.New(&logWrapper{logger: proxyErrorLogger}, "", 0), } transport, err := proxy.ds.GetHttpTransport()