diff --git a/plugin/http.go b/plugin/http.go index 73904d198..88344c97c 100644 --- a/plugin/http.go +++ b/plugin/http.go @@ -101,37 +101,39 @@ func NewHTTP(log *util.Logger, method, uri string, insecure bool, cache time.Dur method: method, } - // override the transport to accept self-signed certificates + // build the cache stack without logging so the logging tripper + // can sit outside the cache and see cached responses too + var base http.RoundTripper = transport.Default() if insecure { - p.Client.Transport = request.NewTripper(log, transport.Insecure()) + base = transport.Insecure() } if cache > 0 { // remove no-cache response headers - p.Client.Transport = &transport.Modifier{ + base = &transport.Modifier{ Modifier: func(resp *http.Response) error { dropNoCache(resp, "Cache-Control") dropNoCache(resp, "Pragma") return nil }, - Base: p.Client.Transport, + Base: base, } } // http cache - p.Client.Transport = &httpcache.Transport{ + base = &httpcache.Transport{ Cache: mc, MarkCachedResponses: true, - Transport: p.Client.Transport, + Transport: base, } if cache > 0 { cacheHeader := fmt.Sprintf("max-age=%d, must-revalidate", int(cache.Seconds())) - p.Client.Transport = &transport.Decorator{ + base = &transport.Decorator{ Decorator: transport.DecorateHeaders(map[string]string{ "Cache-Control": cacheHeader, }), - Base: p.Client.Transport, + Base: base, } // for cached requests enforce single inflight GET @@ -140,6 +142,9 @@ func NewHTTP(log *util.Logger, method, uri string, insecure bool, cache time.Dur } } + // logging is outermost so cache hits are visible in the trace log + p.Client.Transport = request.NewTripper(log, base) + return p } diff --git a/util/request/roundtrip.go b/util/request/roundtrip.go index 7e0a1b975..63f12ad46 100644 --- a/util/request/roundtrip.go +++ b/util/request/roundtrip.go @@ -11,6 +11,7 @@ import ( "github.com/evcc-io/evcc/util" "github.com/prometheus/client_golang/prometheus" + "github.com/sandrolain/httpcache" ) type roundTripper struct { @@ -129,8 +130,6 @@ func dump(r io.ReadCloser, w *strings.Builder) error { } func (r *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { - r.log.TRACE.Printf("%s %s", req.Method, req.URL.String()) - // add evcc user agent if req.Header.Get("User-Agent") == "" { req = req.Clone(req.Context()) @@ -165,6 +164,12 @@ func (r *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { reqMetric.WithLabelValues(req.URL.Hostname()).Observe(time.Since(startTime).Seconds()) + var cached string + if err == nil && resp.Header.Get(httpcache.XFromCache) != "" { + cached = " CACHED" + } + r.log.TRACE.Printf("%s%s %s", req.Method, cached, req.URL.String()) + if err == nil { resMetric.WithLabelValues(req.URL.Hostname(), strconv.Itoa(resp.StatusCode)).Add(1)