|
|
@@ -23,6 +23,7 @@ import (
|
|
|
"tailscale.com/hostinfo"
|
|
|
"tailscale.com/syncs"
|
|
|
"tailscale.com/types/logger"
|
|
|
+ "tailscale.com/util/clientmetric"
|
|
|
"tailscale.com/util/cmpver"
|
|
|
)
|
|
|
|
|
|
@@ -43,6 +44,15 @@ var cachedProxy struct {
|
|
|
// forever. So for errors, we only log a bit.
|
|
|
var proxyErrorf = logger.RateLimitedFn(log.Printf, 10*time.Minute, 2 /* burst*/, 10 /* maxCache */)
|
|
|
|
|
|
+var (
|
|
|
+ metricSuccess = clientmetric.NewCounter("winhttp_proxy_success")
|
|
|
+ metricErrDetectionFailed = clientmetric.NewCounter("winhttp_proxy_err_detection_failed")
|
|
|
+ metricErrInvalidParameters = clientmetric.NewCounter("winhttp_proxy_err_invalid_param")
|
|
|
+ metricErrDownloadScript = clientmetric.NewCounter("winhttp_proxy_err_download_script")
|
|
|
+ metricErrTimeout = clientmetric.NewCounter("winhttp_proxy_err_timeout")
|
|
|
+ metricErrOther = clientmetric.NewCounter("winhttp_proxy_err_other")
|
|
|
+)
|
|
|
+
|
|
|
func proxyFromWinHTTPOrCache(req *http.Request) (*url.URL, error) {
|
|
|
if req.URL == nil {
|
|
|
return nil, nil
|
|
|
@@ -66,6 +76,7 @@ func proxyFromWinHTTPOrCache(req *http.Request) (*url.URL, error) {
|
|
|
case res := <-resc:
|
|
|
err := res.err
|
|
|
if err == nil {
|
|
|
+ metricSuccess.Add(1)
|
|
|
cachedProxy.Lock()
|
|
|
defer cachedProxy.Unlock()
|
|
|
if was, now := fmt.Sprint(cachedProxy.val), fmt.Sprint(res.proxy); was != now {
|
|
|
@@ -81,10 +92,12 @@ func proxyFromWinHTTPOrCache(req *http.Request) (*url.URL, error) {
|
|
|
ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = 12167
|
|
|
)
|
|
|
if err == syscall.Errno(ERROR_WINHTTP_AUTODETECTION_FAILED) {
|
|
|
+ metricErrDetectionFailed.Add(1)
|
|
|
setNoProxyUntil(10 * time.Second)
|
|
|
return nil, nil
|
|
|
}
|
|
|
if err == windows.ERROR_INVALID_PARAMETER {
|
|
|
+ metricErrInvalidParameters.Add(1)
|
|
|
// Seen on Windows 8.1. (https://github.com/tailscale/tailscale/issues/879)
|
|
|
// TODO(bradfitz): figure this out.
|
|
|
setNoProxyUntil(time.Hour)
|
|
|
@@ -93,11 +106,14 @@ func proxyFromWinHTTPOrCache(req *http.Request) (*url.URL, error) {
|
|
|
}
|
|
|
proxyErrorf("tshttpproxy: winhttp: GetProxyForURL(%q): %v/%#v", urlStr, err, err)
|
|
|
if err == syscall.Errno(ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT) {
|
|
|
+ metricErrDownloadScript.Add(1)
|
|
|
setNoProxyUntil(10 * time.Second)
|
|
|
return nil, nil
|
|
|
}
|
|
|
+ metricErrOther.Add(1)
|
|
|
return nil, err
|
|
|
case <-ctx.Done():
|
|
|
+ metricErrTimeout.Add(1)
|
|
|
cachedProxy.Lock()
|
|
|
defer cachedProxy.Unlock()
|
|
|
proxyErrorf("tshttpproxy: winhttp: GetProxyForURL(%q): timeout; using cached proxy %v", urlStr, cachedProxy.val)
|