Repository: VictoriaMetrics/VictoriaMetrics
Pull request #435 (2020-04-24 02:28:37)

fix: fix vmalert template label not complete bug
Ref https://github.com/VictoriaMetrics/VictoriaMetrics/issues/434


Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index c052d4602..4e848ffef 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -14,18 +14,19 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Setup Go
-        uses: actions/setup-go@v1
+        uses: actions/setup-go@master
         with:
-          go-version: 1.13
+          go-version: 1.14
         id: go
-      - name: Code checkout
-        uses: actions/checkout@v1
       - name: Dependencies
         env:
-          GO111MODULE: off
+          GO111MODULE: on
         run: |
-          go get -v golang.org/x/lint/golint
+          go get -u golang.org/x/lint/golint
           go get -u github.com/kisielk/errcheck
+          go get -u github.com/golangci/golangci-lint/cmd/golangci-lint
+      - name: Code checkout
+        uses: actions/checkout@master
       - name: Build
         env:
           GO111MODULE: on
diff --git a/README.md b/README.md
index ef5ebe021..eb5ef83e8 100644
--- a/README.md
+++ b/README.md
@@ -260,6 +260,7 @@ Currently the following [scrape_config](https://prometheus.io/docs/prometheus/la
 * [static_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config)
 * [file_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config)
 * [kubernetes_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config)
+* [gce_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config)
 
 In the future other `*_sd_config` types will be supported.
 
@@ -855,6 +856,7 @@ Consider setting the following command-line flags:
   with [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication).
 * `-deleteAuthKey` for protecting `/api/v1/admin/tsdb/delete_series` endpoint. See [how to delete time series](#how-to-delete-time-series).
 * `-snapshotAuthKey` for protecting `/snapshot*` endpoints. See [how to work with snapshots](#how-to-work-with-snapshots).
+* `-search.resetCacheAuthKey` for protecting `/internal/resetRollupResultCache` endpoint. See [backfilling](#backfilling) for more details.
 
 Explicitly set internal network interface for TCP and UDP ports for data ingestion with Graphite and OpenTSDB formats.
 For example, substitute `-graphiteListenAddr=:2003` with `-graphiteListenAddr=<internal_iface_ip>:2003`.
@@ -927,6 +929,10 @@ The most interesting metrics are:
   If the gaps are related to irregular intervals between samples, then try adjusting `-search.minStalenessInterval` command-line flag
   to value close to the maximum interval between samples.
 
+* If you are switching from InfluxDB or TimescaleDB, then take a look at `-search.maxStalenessInterval` command-line flag.
+  It may be needed in order to suppress default gap filling algorithm used by VictoriaMetrics - by default it assumes
+  each time series is continuous instead of discrete, so it fills gaps between real samples with regular intervals.
+
 * Metrics and labels leading to high cardinality or high churn rate can be determined at `/api/v1/status/tsdb` page.
   See [these docs](https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-stats) for details.
   VictoriaMetrics accepts optional `date=YYYY-MM-DD` and `topN=42` args on this page. By default `date` equals to the current date,
diff --git a/app/vmagent/README.md b/app/vmagent/README.md
index 3fa50e711..0ed7a0721 100644
--- a/app/vmagent/README.md
+++ b/app/vmagent/README.md
@@ -133,11 +133,12 @@ The following scrape types in [scrape_config](https://prometheus.io/docs/prometh
   See [these docs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config) for details.
 * `kubernetes_sd_configs` - for scraping targets in Kubernetes (k8s).
   See [kubernetes_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config) for details.
+* `gce_sd_configs` - for scraping targets in Google Compute Engine (GCE).
+  See [gce_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config) for details.
 
 The following service discovery mechanisms will be added to `vmagent` soon:
 
 * [ec2_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#ec2_sd_config)
-* [gce_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config)
 * [consul_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#consul_sd_config)
 * [dns_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dns_sd_config)
 
diff --git a/app/vmalert/rule.go b/app/vmalert/rule.go
index c51d4ce1c..b68538937 100644
--- a/app/vmalert/rule.go
+++ b/app/vmalert/rule.go
@@ -171,15 +171,31 @@ func (r *Rule) newAlert(m datasource.Metric) (*notifier.Alert, error) {
 		Start:  time.Now(),
 		// TODO: support End time
 	}
+
+	// 1. use data labels
 	for _, l := range m.Labels {
 		a.Labels[l.Name] = l.Value
 	}
+
+	// 2. template rule labels with data labels
+	rLabels, err := a.ExecTemplate(r.Labels)
+	if err != nil {
+		return a, err
+	}
+
+	// 3. merge data labels and rule labels
 	// metric labels may be overridden by
 	// rule labels
-	for k, v := range r.Labels {
+	for k, v := range rLabels {
 		a.Labels[k] = v
 	}
-	var err error
+
+	// 4. template merged labels
+	a.Labels, err = a.ExecTemplate(a.Labels)
+	if err != nil {
+		return a, err
+	}
+
 	a.Annotations, err = a.ExecTemplate(r.Annotations)
 	return a, err
 }
diff --git a/app/vmbackup/README.md b/app/vmbackup/README.md
index 227625205..39fc7994c 100644
--- a/app/vmbackup/README.md
+++ b/app/vmbackup/README.md
@@ -140,14 +140,28 @@ Run `vmbackup -help` in order to see all the available options:
   -dst string
     	Where to put the backup on the remote storage. Example: gcs://bucket/path/to/backup/dir, s3://bucket/path/to/backup/dir or fs:///path/to/local/backup/dir
     	-dst can point to the previous backup. In this case incremental backup is performed, i.e. only changed data is uploaded
+  -envflag.enable
+    	Whether to enable reading flags from environment variables additionally to command line. Command line flag values have priority over values from environment vars. Flags are read only from command line if this flag isn't set
+  -envflag.prefix string
+    	Prefix for environment variables if -envflag.enable is set
+  -fs.disableMmap
+    	Whether to use pread() instead of mmap() for reading data files
+  -loggerFormat string
+    	Format for logs. Possible values: default, json (default "default")
   -loggerLevel string
-    	Minimum level of errors to log. Possible values: INFO, ERROR, FATAL, PANIC (default "INFO")
+    	Minimum level of errors to log. Possible values: INFO, WARN, ERROR, FATAL, PANIC (default "INFO")
+  -loggerOutput string
+    	Output for the logs. Supported values: stderr, stdout (default "stderr")
   -maxBytesPerSecond int
     	The maximum upload speed. There is no limit if it is set to 0
   -memory.allowedPercent float
-    	Allowed percent of system memory VictoriaMetrics caches may occupy (default 60)
+    	Allowed percent of system memory VictoriaMetrics caches may occupy. Too low value may increase cache miss rate, which usually results in higher CPU and disk IO usage. Too high value may evict too much data from OS page cache, which will result in higher disk IO usage (default 60)
   -origin string
     	Optional origin directory on the remote storage with old backup for server-side copying when performing full backup. This speeds up full backups
+  -snapshot.createURL string
+    	VictoriaMetrics create snapshot url. When this is given a snapshot will automatically be created during backup.Example: http://victoriametrics:8428/snaphsot/create
+  -snapshot.deleteURL string
+    	VictoriaMetrics delete snapshot url. Optional. Will be generated from snapshotCreateURL if not provided. All created snaphosts will be automatically deleted.Example: http://victoriametrics:8428/snaphsot/delete
   -snapshotName string
     	Name for the snapshot to backup. See https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md#how-to-work-with-snapshots
   -storageDataPath string
diff --git a/app/vmbackup/main.go b/app/vmbackup/main.go
index eb5f08297..ed24bc38c 100644
--- a/app/vmbackup/main.go
+++ b/app/vmbackup/main.go
@@ -4,7 +4,9 @@ import (
 	"flag"
 	"fmt"
 	"os"
+	"strings"
 
+	"github.com/VictoriaMetrics/VictoriaMetrics/app/vmbackup/snapshot"
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/backup/actions"
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/backup/common"
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/backup/fslocal"
@@ -14,9 +16,13 @@ import (
 )
 
 var (
-	storageDataPath = flag.String("storageDataPath", "victoria-metrics-data", "Path to VictoriaMetrics data. Must match -storageDataPath from VictoriaMetrics or vmstorage")
-	snapshotName    = flag.String("snapshotName", "", "Name for the snapshot to backup. See https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md#how-to-work-with-snapshots")
-	dst             = flag.String("dst", "", "Where to put the backup on the remote storage. "+
+	storageDataPath   = flag.String("storageDataPath", "victoria-metrics-data", "Path to VictoriaMetrics data. Must match -storageDataPath from VictoriaMetrics or vmstorage")
+	snapshotName      = flag.String("snapshotName", "", "Name for the snapshot to backup. See https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md#how-to-work-with-snapshots")
+	snapshotCreateURL = flag.String("snapshot.createURL", "", "VictoriaMetrics create snapshot url. When this is given a snapshot will automatically be created during backup."+
+		"Example: http://victoriametrics:8428/snaphsot/create")
+	snapshotDeleteURL = flag.String("snapshot.deleteURL", "", "VictoriaMetrics delete snapshot url. Optional. Will be generated from snapshotCreateURL if not provided. All created snaphosts will be automatically deleted."+
+		"Example: http://victoriametrics:8428/snaphsot/delete")
+	dst = flag.String("dst", "", "Where to put the backup on the remote storage. "+
 		"Example: gcs://bucket/path/to/backup/dir, s3://bucket/path/to/backup/dir or fs:///path/to/local/backup/dir\n"+
 		"-dst can point to the previous backup. In this case incremental backup is performed, i.e. only changed data is uploaded")
 	origin            = flag.String("origin", "", "Optional origin directory on the remote storage with old backup for server-side copying when performing full backup. This speeds up full backups")
@@ -29,6 +35,34 @@ func main() {
 	envflag.Parse()
 	buildinfo.Init()
 
+	if len(*snapshotCreateURL) > 0 {
+		logger.Infof("%s", "Snapshots enabled")
+		logger.Infof("Snapshot create url %s", *snapshotCreateURL)
+		if len(*snapshotDeleteURL) <= 0 {
+			err := flag.Set("snapshot.deleteURL", strings.Replace(*snapshotCreateURL, "/create", "/delete", 1))
+			if err != nil {
+				logger.Fatalf("Failed to set snapshot.deleteURL flag: %v", err)
+			}
+		}
+		logger.Infof("Snapshot delete url %s", *snapshotDeleteURL)
+
+		name, err := snapshot.Create(*snapshotCreateURL)
+		if err != nil {
+			logger.Fatalf("%s", err)
+		}
+		err = flag.Set("snapshotName", name)
+		if err != nil {
+			logger.Fatalf("Failed to set snapshotName flag: %v", err)
+		}
+
+		defer func() {
+			err := snapshot.Delete(*snapshotDeleteURL, name)
+			if err != nil {
+				logger.Fatalf("%s", err)
+			}
+		}()
+	}
+
 	srcFS, err := newSrcFS()
 	if err != nil {
 		logger.Fatalf("%s", err)
@@ -67,7 +101,7 @@ See the docs at https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/a
 
 func newSrcFS() (*fslocal.FS, error) {
 	if len(*snapshotName) == 0 {
-		return nil, fmt.Errorf("`-snapshotName` cannot be empty")
+		return nil, fmt.Errorf("`-snapshotName` or `-snapshot.createURL` must be provided")
 	}
 	snapshotPath := *storageDataPath + "/snapshots/" + *snapshotName
 
diff --git a/app/vmbackup/snapshot/snapshot.go b/app/vmbackup/snapshot/snapshot.go
new file mode 100644
index 000000000..852c0b3b4
--- /dev/null
+++ b/app/vmbackup/snapshot/snapshot.go
@@ -0,0 +1,91 @@
+package snapshot
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
+)
+
+type snapshot struct {
+	Status   string `json:"status"`
+	Snapshot string `json:"snapshot"`
+	Msg      string `json:"msg"`
+}
+
+// Create creates a snapshot and the provided api endpoint and returns
+// the snapshot name
+func Create(createSnapshotURL string) (string, error) {
+	logger.Infof("%s", "Creating snapshot")
+	u, err := url.Parse(createSnapshotURL)
+	if err != nil {
+		return "", err
+	}
+
+	resp, err := http.Get(u.String())
+	if err != nil {
+		return "", err
+	}
+
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return "", err
+	}
+
+	snap := snapshot{}
+	err = json.Unmarshal(body, &snap)
+	if err != nil {
+		return "", err
+	}
+
+	if snap.Status == "ok" {
+		logger.Infof("Snapshot %s created", snap.Snapshot)
+		return snap.Snapshot, nil
+	} else if snap.Status == "error" {
+		return "", errors.New(snap.Msg)
+	} else {
+		return "", fmt.Errorf("Unkown status: %v", snap.Status)
+	}
+}
+
+// Delete deletes a snapshot and the provided api endpoint returns any failure
+func Delete(deleteSnapshotURL string, snapshotName string) error {
+	logger.Infof("Deleting snapshot %s", snapshotName)
+	formData := url.Values{
+		"snapshot": {snapshotName},
+	}
+
+	u, err := url.Parse(deleteSnapshotURL)
+	if err != nil {
+		return err
+	}
+
+	resp, err := http.PostForm(u.String(), formData)
+	if err != nil {
+		return err
+	}
+
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return err
+	}
+
+	snap := snapshot{}
+	err = json.Unmarshal(body, &snap)
+	if err != nil {
+		return err
+	}
+
+	if snap.Status == "ok" {
+		logger.Infof("Snapshot %s deleted", snapshotName)
+		return nil
+	} else if snap.Status == "error" {
+		return errors.New(snap.Msg)
+	} else {
+		return fmt.Errorf("Unkown status: %v", snap.Status)
+	}
+}
diff --git a/app/vmrestore/README.md b/app/vmrestore/README.md
index f81e42d70..d7523bcf1 100644
--- a/app/vmrestore/README.md
+++ b/app/vmrestore/README.md
@@ -47,12 +47,24 @@ Run `vmrestore -help` in order to see all the available options:
     	See https://cloud.google.com/iam/docs/creating-managing-service-account-keys and https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html
   -customS3Endpoint string
     	Custom S3 endpoint for use with S3-compatible storages (e.g. MinIO). S3 is used if not set
+  -envflag.enable
+    	Whether to enable reading flags from environment variables additionally to command line. Command line flag values have priority over values from environment vars. Flags are read only from command line if this flag isn't set
+  -envflag.prefix string
+    	Prefix for environment variables if -envflag.enable is set
+  -fs.disableMmap
+    	Whether to use pread() instead of mmap() for reading data files
+  -loggerFormat string
+    	Format for logs. Possible values: default, json (default "default")
   -loggerLevel string
-    	Minimum level of errors to log. Possible values: INFO, ERROR, FATAL, PANIC (default "INFO")
+    	Minimum level of errors to log. Possible values: INFO, WARN, ERROR, FATAL, PANIC (default "INFO")
+  -loggerOutput string
+    	Output for the logs. Supported values: stderr, stdout (default "stderr")
   -maxBytesPerSecond int
     	The maximum download speed. There is no limit if it is set to 0
   -memory.allowedPercent float
-    	Allowed percent of system memory VictoriaMetrics caches may occupy (default 60)
+    	Allowed percent of system memory VictoriaMetrics caches may occupy. Too low value may increase cache miss rate, which usually results in higher CPU and disk IO usage. Too high value may evict too much data from OS page cache, which will result in higher disk IO usage (default 60)
+  -skipBackupCompleteCheck
+    	Whether to skip checking for 'backup complete' file in -src. This may be useful for restoring from old backups, which were created without 'backup complete' file
   -src string
     	Source path with backup on the remote storage. Example: gcs://bucket/path/to/backup/dir, s3://bucket/path/to/backup/dir or fs:///path/to/local/backup/dir
   -storageDataPath string
diff --git a/app/vmselect/main.go b/app/vmselect/main.go
index 1f00c6255..8a3d174f3 100644
--- a/app/vmselect/main.go
+++ b/app/vmselect/main.go
@@ -24,7 +24,7 @@ var (
 	maxConcurrentRequests = flag.Int("search.maxConcurrentRequests", getDefaultMaxConcurrentRequests(), "The maximum number of concurrent search requests. "+
 		"It shouldn't be high, since a single request can saturate all the CPU cores. See also -search.maxQueueDuration")
 	maxQueueDuration  = flag.Duration("search.maxQueueDuration", 10*time.Second, "The maximum time the request waits for execution when -search.maxConcurrentRequests limit is reached")
-	resetCacheAuthKey = flag.String("search.resetCacheAuthKey", "", "Optional authKey for resetting rollup cache via /internal/resetCache call")
+	resetCacheAuthKey = flag.String("search.resetCacheAuthKey", "", "Optional authKey for resetting rollup cache via /internal/resetRollupResultCache call")
 )
 
 func getDefaultMaxConcurrentRequests() int {
diff --git a/docs/Single-server-VictoriaMetrics.md b/docs/Single-server-VictoriaMetrics.md
index ef5ebe021..eb5ef83e8 100644
--- a/docs/Single-server-VictoriaMetrics.md
+++ b/docs/Single-server-VictoriaMetrics.md
@@ -260,6 +260,7 @@ Currently the following [scrape_config](https://prometheus.io/docs/prometheus/la
 * [static_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config)
 * [file_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config)
 * [kubernetes_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config)
+* [gce_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config)
 
 In the future other `*_sd_config` types will be supported.
 
@@ -855,6 +856,7 @@ Consider setting the following command-line flags:
   with [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication).
 * `-deleteAuthKey` for protecting `/api/v1/admin/tsdb/delete_series` endpoint. See [how to delete time series](#how-to-delete-time-series).
 * `-snapshotAuthKey` for protecting `/snapshot*` endpoints. See [how to work with snapshots](#how-to-work-with-snapshots).
+* `-search.resetCacheAuthKey` for protecting `/internal/resetRollupResultCache` endpoint. See [backfilling](#backfilling) for more details.
 
 Explicitly set internal network interface for TCP and UDP ports for data ingestion with Graphite and OpenTSDB formats.
 For example, substitute `-graphiteListenAddr=:2003` with `-graphiteListenAddr=<internal_iface_ip>:2003`.
@@ -927,6 +929,10 @@ The most interesting metrics are:
   If the gaps are related to irregular intervals between samples, then try adjusting `-search.minStalenessInterval` command-line flag
   to value close to the maximum interval between samples.
 
+* If you are switching from InfluxDB or TimescaleDB, then take a look at `-search.maxStalenessInterval` command-line flag.
+  It may be needed in order to suppress default gap filling algorithm used by VictoriaMetrics - by default it assumes
+  each time series is continuous instead of discrete, so it fills gaps between real samples with regular intervals.
+
 * Metrics and labels leading to high cardinality or high churn rate can be determined at `/api/v1/status/tsdb` page.
   See [these docs](https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-stats) for details.
   VictoriaMetrics accepts optional `date=YYYY-MM-DD` and `topN=42` args on this page. By default `date` equals to the current date,
diff --git a/docs/vmagent.md b/docs/vmagent.md
index 3fa50e711..0ed7a0721 100644
--- a/docs/vmagent.md
+++ b/docs/vmagent.md
@@ -133,11 +133,12 @@ The following scrape types in [scrape_config](https://prometheus.io/docs/prometh
   See [these docs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config) for details.
 * `kubernetes_sd_configs` - for scraping targets in Kubernetes (k8s).
   See [kubernetes_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config) for details.
+* `gce_sd_configs` - for scraping targets in Google Compute Engine (GCE).
+  See [gce_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config) for details.
 
 The following service discovery mechanisms will be added to `vmagent` soon:
 
 * [ec2_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#ec2_sd_config)
-* [gce_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config)
 * [consul_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#consul_sd_config)
 * [dns_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#dns_sd_config)
 
diff --git a/docs/vmbackup.md b/docs/vmbackup.md
index 227625205..39fc7994c 100644
--- a/docs/vmbackup.md
+++ b/docs/vmbackup.md
@@ -140,14 +140,28 @@ Run `vmbackup -help` in order to see all the available options:
   -dst string
     	Where to put the backup on the remote storage. Example: gcs://bucket/path/to/backup/dir, s3://bucket/path/to/backup/dir or fs:///path/to/local/backup/dir
     	-dst can point to the previous backup. In this case incremental backup is performed, i.e. only changed data is uploaded
+  -envflag.enable
+    	Whether to enable reading flags from environment variables additionally to command line. Command line flag values have priority over values from environment vars. Flags are read only from command line if this flag isn't set
+  -envflag.prefix string
+    	Prefix for environment variables if -envflag.enable is set
+  -fs.disableMmap
+    	Whether to use pread() instead of mmap() for reading data files
+  -loggerFormat string
+    	Format for logs. Possible values: default, json (default "default")
   -loggerLevel string
-    	Minimum level of errors to log. Possible values: INFO, ERROR, FATAL, PANIC (default "INFO")
+    	Minimum level of errors to log. Possible values: INFO, WARN, ERROR, FATAL, PANIC (default "INFO")
+  -loggerOutput string
+    	Output for the logs. Supported values: stderr, stdout (default "stderr")
   -maxBytesPerSecond int
     	The maximum upload speed. There is no limit if it is set to 0
   -memory.allowedPercent float
-    	Allowed percent of system memory VictoriaMetrics caches may occupy (default 60)
+    	Allowed percent of system memory VictoriaMetrics caches may occupy. Too low value may increase cache miss rate, which usually results in higher CPU and disk IO usage. Too high value may evict too much data from OS page cache, which will result in higher disk IO usage (default 60)
   -origin string
     	Optional origin directory on the remote storage with old backup for server-side copying when performing full backup. This speeds up full backups
+  -snapshot.createURL string
+    	VictoriaMetrics create snapshot url. When this is given a snapshot will automatically be created during backup.Example: http://victoriametrics:8428/snaphsot/create
+  -snapshot.deleteURL string
+    	VictoriaMetrics delete snapshot url. Optional. Will be generated from snapshotCreateURL if not provided. All created snaphosts will be automatically deleted.Example: http://victoriametrics:8428/snaphsot/delete
   -snapshotName string
     	Name for the snapshot to backup. See https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/README.md#how-to-work-with-snapshots
   -storageDataPath string
diff --git a/docs/vmrestore.md b/docs/vmrestore.md
index f81e42d70..d7523bcf1 100644
--- a/docs/vmrestore.md
+++ b/docs/vmrestore.md
@@ -47,12 +47,24 @@ Run `vmrestore -help` in order to see all the available options:
     	See https://cloud.google.com/iam/docs/creating-managing-service-account-keys and https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html
   -customS3Endpoint string
     	Custom S3 endpoint for use with S3-compatible storages (e.g. MinIO). S3 is used if not set
+  -envflag.enable
+    	Whether to enable reading flags from environment variables additionally to command line. Command line flag values have priority over values from environment vars. Flags are read only from command line if this flag isn't set
+  -envflag.prefix string
+    	Prefix for environment variables if -envflag.enable is set
+  -fs.disableMmap
+    	Whether to use pread() instead of mmap() for reading data files
+  -loggerFormat string
+    	Format for logs. Possible values: default, json (default "default")
   -loggerLevel string
-    	Minimum level of errors to log. Possible values: INFO, ERROR, FATAL, PANIC (default "INFO")
+    	Minimum level of errors to log. Possible values: INFO, WARN, ERROR, FATAL, PANIC (default "INFO")
+  -loggerOutput string
+    	Output for the logs. Supported values: stderr, stdout (default "stderr")
   -maxBytesPerSecond int
     	The maximum download speed. There is no limit if it is set to 0
   -memory.allowedPercent float
-    	Allowed percent of system memory VictoriaMetrics caches may occupy (default 60)
+    	Allowed percent of system memory VictoriaMetrics caches may occupy. Too low value may increase cache miss rate, which usually results in higher CPU and disk IO usage. Too high value may evict too much data from OS page cache, which will result in higher disk IO usage (default 60)
+  -skipBackupCompleteCheck
+    	Whether to skip checking for 'backup complete' file in -src. This may be useful for restoring from old backups, which were created without 'backup complete' file
   -src string
     	Source path with backup on the remote storage. Example: gcs://bucket/path/to/backup/dir, s3://bucket/path/to/backup/dir or fs:///path/to/local/backup/dir
   -storageDataPath string
diff --git a/go.mod b/go.mod
index 3893add82..2c4bf9f14 100644
--- a/go.mod
+++ b/go.mod
@@ -5,22 +5,25 @@ require (
 	cloud.google.com/go/storage v1.6.0
 	github.com/VictoriaMetrics/fastcache v1.5.7
 	github.com/VictoriaMetrics/metrics v1.11.2
-	github.com/aws/aws-sdk-go v1.30.12
+	github.com/aws/aws-sdk-go v1.30.13
 	github.com/cespare/xxhash/v2 v2.1.1
 	github.com/golang/protobuf v1.4.0 // indirect
 	github.com/golang/snappy v0.0.1
-	github.com/klauspost/compress v1.10.4
-	github.com/valyala/fasthttp v1.10.0
+	github.com/klauspost/compress v1.10.5
+	github.com/valyala/fasthttp v1.12.0
 	github.com/valyala/fastjson v1.5.1
 	github.com/valyala/fastrand v1.0.0
 	github.com/valyala/gozstd v1.7.0
 	github.com/valyala/histogram v1.0.1
 	github.com/valyala/quicktemplate v1.4.1
-	golang.org/x/sys v0.0.0-20200413165638-669c56c373c4
-	golang.org/x/tools v0.0.0-20200416214402-fc959738d646 // indirect
+	golang.org/x/net v0.0.0-20200421231249-e086a090c8fd // indirect
+	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
+	golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f
+	golang.org/x/tools v0.0.0-20200423205358-59e73619c742 // indirect
 	google.golang.org/api v0.22.0
-	google.golang.org/genproto v0.0.0-20200416231807-8751e049a2a0 // indirect
-	google.golang.org/grpc v1.28.1 // indirect
+	google.golang.org/appengine v1.6.6 // indirect
+	google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215 // indirect
+	google.golang.org/grpc v1.29.1 // indirect
 	gopkg.in/yaml.v2 v2.2.8
 )
 
diff --git a/go.sum b/go.sum
index 240bf0b19..9e24292d3 100644
--- a/go.sum
+++ b/go.sum
@@ -40,8 +40,8 @@ github.com/VictoriaMetrics/metrics v1.11.2 h1:t/ceLP6SvagUqypCKU7cI7+tQn54+TIV/t
 github.com/VictoriaMetrics/metrics v1.11.2/go.mod h1:LU2j9qq7xqZYXz8tF3/RQnB2z2MbZms5TDiIg9/NHiQ=
 github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
 github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
-github.com/aws/aws-sdk-go v1.30.12 h1:KrjyosZvkpJjcwMk0RNxMZewQ47v7+ZkbQDXjWsJMs8=
-github.com/aws/aws-sdk-go v1.30.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/aws/aws-sdk-go v1.30.13 h1:fBDYaJzInlOHpoKFaTEze5MvZ/pw7mhYkzDE8HAmD74=
+github.com/aws/aws-sdk-go v1.30.13/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -119,12 +119,12 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.10.4 h1:jFzIFaf586tquEB5EhzQG0HwGNSlgAJpG53G6Ss11wc=
 github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.10.5 h1:7q6vHIqubShURwQz8cQK6yIe/xC3IF0Vm7TGfqjewrc=
+github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
 github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
-github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
 github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -144,8 +144,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
-github.com/valyala/fasthttp v1.10.0 h1:OcUaVkFSir/TK5oHYpsxBDzCgUcwCm+Ns8GnouOmcGw=
-github.com/valyala/fasthttp v1.10.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
+github.com/valyala/fasthttp v1.12.0 h1:TsB9qkSeiMXB40ELWWSRMjlsE+8IkqXHcs01y2d9aw0=
+github.com/valyala/fasthttp v1.12.0/go.mod h1:229t1eWu9UXTPmoUkbpN/fctKPBY4IJoFXQnxHGXy6E=
 github.com/valyala/fastjson v1.5.1 h1:SXaQZVSwLjZOVhDEhjiCcDtnX0Feu7Z7A1+C5atpoHM=
 github.com/valyala/fastjson v1.5.1/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
 github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI=
@@ -217,7 +217,6 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
@@ -227,6 +226,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZ
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200421231249-e086a090c8fd h1:QPwSajcTUrFriMF1nJ3XzgoqakqQEsnZf9LdXdi2nkI=
+golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -263,8 +264,8 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepx
 golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
-golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8=
+golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -303,8 +304,8 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
 golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200416214402-fc959738d646 h1:7CEkhBsBejkW845gR1AmglqMfc1yGzn42FBmtM4jxyM=
-golang.org/x/tools v0.0.0-20200416214402-fc959738d646/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200423205358-59e73619c742 h1:9OGWpORUXvk8AsaBJlpzzDx7Srv/rSK6rvjcsJq4rJo=
+golang.org/x/tools v0.0.0-20200423205358-59e73619c742/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
@@ -330,6 +331,8 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
 google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
 google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -349,8 +352,8 @@ google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce h1:1mbrb1tUU+Zmt5C
 google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200416231807-8751e049a2a0 h1:N5O9PpTbQrkvH0IQ1q+mmGyg8Gt6iKcu6b6+gmz3jnA=
-google.golang.org/genproto v0.0.0-20200416231807-8751e049a2a0/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215 h1:0Uz5jLJQioKgVozXa1gzGbzYxbb/rhQEVvSWxzw5oUs=
+google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -363,8 +366,8 @@ google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
 google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
-google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k=
-google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/lib/promscrape/config.go b/lib/promscrape/config.go
index 28ceda4d5..1a7939c58 100644
--- a/lib/promscrape/config.go
+++ b/lib/promscrape/config.go
@@ -14,6 +14,7 @@ import (
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/gce"
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discovery/kubernetes"
 	"gopkg.in/yaml.v2"
 )
@@ -60,6 +61,7 @@ type ScrapeConfig struct {
 	StaticConfigs        []StaticConfig              `yaml:"static_configs"`
 	FileSDConfigs        []FileSDConfig              `yaml:"file_sd_configs"`
 	KubernetesSDConfigs  []kubernetes.SDConfig       `yaml:"kubernetes_sd_configs"`
+	GCESDConfigs         []gce.SDConfig              `yaml:"gce_sd_configs"`
 	RelabelConfigs       []promrelabel.RelabelConfig `yaml:"relabel_configs"`
 	MetricRelabelConfigs []promrelabel.RelabelConfig `yaml:"metric_relabel_configs"`
 	SampleLimit          int                         `yaml:"sample_limit"`
@@ -147,6 +149,14 @@ func (cfg *Config) kubernetesSDConfigsCount() int {
 	return n
 }
 
+func (cfg *Config) gceSDConfigsCount() int {
+	n := 0
+	for i := range cfg.ScrapeConfigs {
+		n += len(cfg.ScrapeConfigs[i].GCESDConfigs)
+	}
+	return n
+}
+
 func (cfg *Config) fileSDConfigsCount() int {
 	n := 0
 	for i := range cfg.ScrapeConfigs {
@@ -168,6 +178,19 @@ func (cfg *Config) getKubernetesSDScrapeWork() []ScrapeWork {
 	return dst
 }
 
+// getGCESDScrapeWork returns `gce_sd_configs` ScrapeWork from cfg.
+func (cfg *Config) getGCESDScrapeWork() []ScrapeWork {
+	var dst []ScrapeWork
+	for i := range cfg.ScrapeConfigs {
+		sc := &cfg.ScrapeConfigs[i]
+		for j := range sc.GCESDConfigs {
+			sdc := &sc.GCESDConfigs[j]
+			dst = appendGCEScrapeWork(dst, sdc, sc.swc)
+		}
+	}
+	return dst
+}
+
 // getFileSDScrapeWork returns `file_sd_configs` ScrapeWork from cfg.
 func (cfg *Config) getFileSDScrapeWork(prev []ScrapeWork) []ScrapeWork {
 	// Create a map for the previous scrape work.
@@ -297,13 +320,25 @@ func appendKubernetesScrapeWork(dst []ScrapeWork, sdc *kubernetes.SDConfig, base
 		logger.Errorf("error when discovering kubernetes nodes for `job_name` %q: %s; skipping it", swc.jobName, err)
 		return dst
 	}
+	return appendScrapeWorkForTargetLabels(dst, swc, targetLabels, "kubernetes_sd_config")
+}
+
+func appendGCEScrapeWork(dst []ScrapeWork, sdc *gce.SDConfig, swc *scrapeWorkConfig) []ScrapeWork {
+	targetLabels, err := gce.GetLabels(sdc)
+	if err != nil {
+		logger.Errorf("error when discovering gce nodes for `job_name` %q: %s; skippint it", swc.jobName, err)
+		return dst
+	}
+	return appendScrapeWorkForTargetLabels(dst, swc, targetLabels, "gce_sd_config")
+}
+
+func appendScrapeWorkForTargetLabels(dst []ScrapeWork, swc *scrapeWorkConfig, targetLabels []map[string]string, sectionName string) []ScrapeWork {
 	for _, metaLabels := range targetLabels {
 		target := metaLabels["__address__"]
 		var err error
 		dst, err = appendScrapeWork(dst, swc, target, nil, metaLabels)
 		if err != nil {
-			logger.Errorf("error when parsing `kubernetes_sd_config` target %q with role %q for `job_name` %q: %s; skipping it",
-				target, sdc.Role, swc.jobName, err)
+			logger.Errorf("error when parsing `%s` target %q for `job_name` %q: %s; skipping it", sectionName, target, swc.jobName, err)
 			continue
 		}
 	}
diff --git a/lib/promscrape/discovery/gce/api.go b/lib/promscrape/discovery/gce/api.go
new file mode 100644
index 000000000..96da0e011
--- /dev/null
+++ b/lib/promscrape/discovery/gce/api.go
@@ -0,0 +1,97 @@
+package gce
+
+import (
+	"context"
+	"fmt"
+	"net/http"
+	"net/url"
+	"sync"
+	"time"
+
+	"golang.org/x/oauth2/google"
+)
+
+type apiConfig struct {
+	client       *http.Client
+	apiURL       string
+	project      string
+	tagSeparator string
+	port         int
+}
+
+func getAPIConfig(sdc *SDConfig) (*apiConfig, error) {
+	apiConfigMapLock.Lock()
+	defer apiConfigMapLock.Unlock()
+
+	if !hasAPIConfigMapCleaner {
+		hasAPIConfigMapCleaner = true
+		go apiConfigMapCleaner()
+	}
+
+	e := apiConfigMap[sdc]
+	if e != nil {
+		e.lastAccessTime = time.Now()
+		return e.cfg, nil
+	}
+	cfg, err := newAPIConfig(sdc)
+	if err != nil {
+		return nil, err
+	}
+	apiConfigMap[sdc] = &apiConfigMapEntry{
+		cfg:            cfg,
+		lastAccessTime: time.Now(),
+	}
+	return cfg, nil
+}
+
+func apiConfigMapCleaner() {
+	tc := time.NewTicker(15 * time.Minute)
+	for currentTime := range tc.C {
+		apiConfigMapLock.Lock()
+		for k, e := range apiConfigMap {
+			if currentTime.Sub(e.lastAccessTime) > 10*time.Minute {
+				delete(apiConfigMap, k)
+			}
+		}
+		apiConfigMapLock.Unlock()
+	}
+}
+
+type apiConfigMapEntry struct {
+	cfg            *apiConfig
+	lastAccessTime time.Time
+}
+
+var (
+	apiConfigMap           = make(map[*SDConfig]*apiConfigMapEntry)
+	apiConfigMapLock       sync.Mutex
+	hasAPIConfigMapCleaner bool
+)
+
+func newAPIConfig(sdc *SDConfig) (*apiConfig, error) {
+	ctx := context.Background()
+	client, err := google.DefaultClient(ctx, "https://www.googleapis.com/auth/compute.readonly")
+	if err != nil {
+		return nil, fmt.Errorf("cannot create oauth2 client for gce: %s", err)
+	}
+	// See https://cloud.google.com/compute/docs/reference/rest/v1/instances/list
+	apiURL := fmt.Sprintf("https://compute.googleapis.com/compute/v1/projects/%s/zones/%s/instances", sdc.Project, sdc.Zone)
+	if len(sdc.Filter) > 0 {
+		apiURL += fmt.Sprintf("?filter=%s", url.QueryEscape(sdc.Filter))
+	}
+	tagSeparator := ","
+	if sdc.TagSeparator != nil {
+		tagSeparator = *sdc.TagSeparator
+	}
+	port := 80
+	if sdc.Port != nil {
+		port = *sdc.Port
+	}
+	return &apiConfig{
+		client:       client,
+		apiURL:       apiURL,
+		project:      sdc.Project,
+		tagSeparator: tagSeparator,
+		port:         port,
+	}, nil
+}
diff --git a/lib/promscrape/discovery/gce/gce.go b/lib/promscrape/discovery/gce/gce.go
new file mode 100644
index 000000000..ea68627f6
--- /dev/null
+++ b/lib/promscrape/discovery/gce/gce.go
@@ -0,0 +1,31 @@
+package gce
+
+import (
+	"fmt"
+)
+
+// SDConfig represents service discovery config for gce.
+//
+// See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config
+type SDConfig struct {
+	Project string `yaml:"project"`
+	Zone    string `yaml:"zone"`
+	Filter  string `yaml:"filter"`
+	// RefreshInterval time.Duration `yaml:"refresh_interval"`
+	// refresh_interval is obtained from `-promscrape.gceSDCheckInterval` command-line option.
+	Port         *int    `yaml:"port"`
+	TagSeparator *string `yaml:"tag_separator"`
+}
+
+// GetLabels returns gce labels according to sdc.
+func GetLabels(sdc *SDConfig) ([]map[string]string, error) {
+	cfg, err := getAPIConfig(sdc)
+	if err != nil {
+		return nil, fmt.Errorf("cannot get API config: %s", err)
+	}
+	ms, err := getInstancesLabels(cfg)
+	if err != nil {
+		return nil, fmt.Errorf("error when fetching instances data from GCE: %s", err)
+	}
+	return ms, nil
+}
diff --git a/lib/promscrape/discovery/gce/instance.go b/lib/promscrape/discovery/gce/instance.go
new file mode 100644
index 000000000..392646665
--- /dev/null
+++ b/lib/promscrape/discovery/gce/instance.go
@@ -0,0 +1,172 @@
+package gce
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"strings"
+
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
+)
+
+// getInstancesLabels returns labels for gce instances obtained from the given cfg
+func getInstancesLabels(cfg *apiConfig) ([]map[string]string, error) {
+	insts, err := getInstances(cfg)
+	if err != nil {
+		return nil, err
+	}
+	var ms []map[string]string
+	for _, inst := range insts {
+		ms = inst.appendTargetLabels(ms, cfg.project, cfg.tagSeparator, cfg.port)
+	}
+	return ms, nil
+}
+
+func getInstances(cfg *apiConfig) ([]Instance, error) {
+	var result []Instance
+	pageToken := ""
+	for {
+		insts, nextPageToken, err := getInstancesPage(cfg, pageToken)
+		if err != nil {
+			return nil, err
+		}
+		result = append(result, insts...)
+		if len(nextPageToken) == 0 {
+			return result, nil
+		}
+		pageToken = nextPageToken
+	}
+}
+
+func getInstancesPage(cfg *apiConfig, pageToken string) ([]Instance, string, error) {
+	apiURL := cfg.apiURL
+	if len(pageToken) > 0 {
+		// See https://cloud.google.com/compute/docs/reference/rest/v1/instances/list about pageToken
+		prefix := "?"
+		if strings.Contains(apiURL, "?") {
+			prefix = "&"
+		}
+		apiURL += fmt.Sprintf("%spageToken=%s", prefix, url.QueryEscape(pageToken))
+	}
+	resp, err := cfg.client.Get(apiURL)
+	if err != nil {
+		return nil, "", fmt.Errorf("cannot obtain instances data from API server: %s", err)
+	}
+	defer func() {
+		_ = resp.Body.Close()
+	}()
+	data, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, "", fmt.Errorf("cannot read instances data from API server: %s", err)
+	}
+	if resp.StatusCode != http.StatusOK {
+		return nil, "", fmt.Errorf("unexpected status code when reading instances data from API server; got %d; want %d; response body: %q",
+			resp.StatusCode, http.StatusOK, data)
+	}
+	il, err := parseInstanceList(data)
+	if err != nil {
+		return nil, "", fmt.Errorf("cannot parse instances response from API server: %s", err)
+	}
+	return il.Items, il.NextPageToken, nil
+}
+
+// InstanceList is response to https://cloud.google.com/compute/docs/reference/rest/v1/instances/list
+type InstanceList struct {
+	Items         []Instance
+	NextPageToken string
+}
+
+// Instance is instance from https://cloud.google.com/compute/docs/reference/rest/v1/instances/list
+type Instance struct {
+	ID                string `json:"id"`
+	Name              string
+	Status            string
+	MachineType       string
+	Zone              string
+	NetworkInterfaces []NetworkInterface
+	Tags              TagList
+	Metadata          MetadataList
+	Labels            discoveryutils.SortedLabels
+}
+
+// NetworkInterface is network interface from https://cloud.google.com/compute/docs/reference/rest/v1/instances/list
+type NetworkInterface struct {
+	Network       string
+	Subnetwork    string
+	NetworkIP     string
+	AccessConfigs []AccessConfig
+}
+
+// AccessConfig is access config from https://cloud.google.com/compute/docs/reference/rest/v1/instances/list
+type AccessConfig struct {
+	Type  string
+	NatIP string
+}
+
+// TagList is tag list from https://cloud.google.com/compute/docs/reference/rest/v1/instances/list
+type TagList struct {
+	Items []string
+}
+
+// MetadataList is metadataList from https://cloud.google.com/compute/docs/reference/rest/v1/instances/list
+type MetadataList struct {
+	Items []MetadataEntry
+}
+
+// MetadataEntry is a single entry from metadata
+type MetadataEntry struct {
+	Key   string
+	Value string
+}
+
+// parseInstanceList parses InstanceList from data.
+func parseInstanceList(data []byte) (*InstanceList, error) {
+	var il InstanceList
+	if err := json.Unmarshal(data, &il); err != nil {
+		return nil, fmt.Errorf("cannot unmarshal InstanceList from %q: %s", data, err)
+	}
+	return &il, nil
+}
+
+func (inst *Instance) appendTargetLabels(ms []map[string]string, project, tagSeparator string, port int) []map[string]string {
+	if len(inst.NetworkInterfaces) == 0 {
+		return ms
+	}
+	iface := inst.NetworkInterfaces[0]
+	addr := discoveryutils.JoinHostPort(iface.NetworkIP, port)
+	m := map[string]string{
+		"__address__":                addr,
+		"__meta_gce_instance_id":     inst.ID,
+		"__meta_gce_instance_status": inst.Status,
+		"__meta_gce_instance_name":   inst.Name,
+		"__meta_gce_machine_type":    inst.MachineType,
+		"__meta_gce_network":         iface.Network,
+		"__meta_gce_private_ip":      iface.NetworkIP,
+		"__meta_gce_project":         project,
+		"__meta_gce_subnetwork":      iface.Subnetwork,
+		"__meta_gce_zone":            inst.Zone,
+	}
+	if len(inst.Tags.Items) > 0 {
+		// We surround the separated list with the separator as well. This way regular expressions
+		// in relabeling rules don't have to consider tag positions.
+		m["__meta_gce_tags"] = tagSeparator + strings.Join(inst.Tags.Items, tagSeparator) + tagSeparator
+	}
+	for _, item := range inst.Metadata.Items {
+		key := discoveryutils.SanitizeLabelName(item.Key)
+		m["__meta_gce_metadata_"+key] = item.Value
+	}
+	for _, label := range inst.Labels {
+		name := discoveryutils.SanitizeLabelName(label.Name)
+		m["__meta_gce_label_"+name] = label.Value
+	}
+	if len(iface.AccessConfigs) > 0 {
+		ac := iface.AccessConfigs[0]
+		if ac.Type == "ONE_TO_ONE_NAT" {
+			m["__meta_gce_public_ip"] = ac.NatIP
+		}
+	}
+	ms = append(ms, m)
+	return ms
+}
diff --git a/lib/promscrape/discovery/kubernetes/common_types.go b/lib/promscrape/discovery/kubernetes/common_types.go
index 38c483312..039fce6a9 100644
--- a/lib/promscrape/discovery/kubernetes/common_types.go
+++ b/lib/promscrape/discovery/kubernetes/common_types.go
@@ -1,13 +1,10 @@
 package kubernetes
 
 import (
-	"encoding/json"
 	"fmt"
 	"net/url"
-	"sort"
 	"strings"
 
-	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
 )
 
@@ -18,8 +15,8 @@ type ObjectMeta struct {
 	Name            string
 	Namespace       string
 	UID             string
-	Labels          SortedLabels
-	Annotations     SortedLabels
+	Labels          discoveryutils.SortedLabels
+	Annotations     discoveryutils.SortedLabels
 	OwnerReferences []OwnerReference
 }
 
@@ -36,33 +33,6 @@ func (om *ObjectMeta) registerLabelsAndAnnotations(prefix string, m map[string]s
 	}
 }
 
-// SortedLabels represents sorted labels.
-type SortedLabels []prompbmarshal.Label
-
-// UnmarshalJSON unmarshals JSON from data.
-func (sls *SortedLabels) UnmarshalJSON(data []byte) error {
-	var m map[string]string
-	if err := json.Unmarshal(data, &m); err != nil {
-		return err
-	}
-	*sls = getSortedLabels(m)
-	return nil
-}
-
-func getSortedLabels(m map[string]string) SortedLabels {
-	a := make([]prompbmarshal.Label, 0, len(m))
-	for k, v := range m {
-		a = append(a, prompbmarshal.Label{
-			Name:  k,
-			Value: v,
-		})
-	}
-	sort.Slice(a, func(i, j int) bool {
-		return a[i].Name < a[j].Name
-	})
-	return a
-}
-
 // OwnerReference represents OwnerReferense from k8s API.
 //
 // See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#ownerreference-v1-meta
diff --git a/lib/promscrape/discovery/kubernetes/endpoints.go b/lib/promscrape/discovery/kubernetes/endpoints.go
index 7a7e0d6b7..9d48b7e09 100644
--- a/lib/promscrape/discovery/kubernetes/endpoints.go
+++ b/lib/promscrape/discovery/kubernetes/endpoints.go
@@ -9,13 +9,9 @@ import (
 
 // getEndpointsLabels returns labels for k8s endpoints obtained from the given cfg.
 func getEndpointsLabels(cfg *apiConfig) ([]map[string]string, error) {
-	data, err := getAPIResponse(cfg, "endpoints", "/api/v1/endpoints")
+	eps, err := getEndpoints(cfg)
 	if err != nil {
-		return nil, fmt.Errorf("cannot obtain endpoints data from API server: %s", err)
-	}
-	epl, err := parseEndpointsList(data)
-	if err != nil {
-		return nil, fmt.Errorf("cannot parse endpoints response from API server: %s", err)
+		return nil, err
 	}
 	pods, err := getPods(cfg)
 	if err != nil {
@@ -26,12 +22,46 @@ func getEndpointsLabels(cfg *apiConfig) ([]map[string]string, error) {
 		return nil, err
 	}
 	var ms []map[string]string
-	for _, ep := range epl.Items {
+	for _, ep := range eps {
 		ms = ep.appendTargetLabels(ms, pods, svcs)
 	}
 	return ms, nil
 }
 
+func getEndpoints(cfg *apiConfig) ([]Endpoints, error) {
+	if len(cfg.Namespaces) == 0 {
+		return getEndpointsByPath(cfg, "/api/v1/endpoints")
+	}
+	// Query /api/v1/namespaces/* for each namespace.
+	// This fixes authorization issue at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/432
+	cfgCopy := *cfg
+	namespaces := cfgCopy.Namespaces
+	cfgCopy.Namespaces = nil
+	cfg = &cfgCopy
+	var result []Endpoints
+	for _, ns := range namespaces {
+		path := fmt.Sprintf("/api/v1/namespaces/%s/endpoints", ns)
+		eps, err := getEndpointsByPath(cfg, path)
+		if err != nil {
+			return nil, err
+		}
+		result = append(result, eps...)
+	}
+	return result, nil
+}
+
+func getEndpointsByPath(cfg *apiConfig, path string) ([]Endpoints, error) {
+	data, err := getAPIResponse(cfg, "endpoints", path)
+	if err != nil {
+		return nil, fmt.Errorf("cannot obtain endpoints data from API server: %s", err)
+	}
+	epl, err := parseEndpointsList(data)
+	if err != nil {
+		return nil, fmt.Errorf("cannot parse endpoints response from API server: %s", err)
+	}
+	return epl.Items, nil
+}
+
 // EndpointsList implements k8s endpoints list.
 //
 // See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#endpointslist-v1-core
diff --git a/lib/promscrape/discovery/kubernetes/ingress.go b/lib/promscrape/discovery/kubernetes/ingress.go
index 322e19e90..c90035913 100644
--- a/lib/promscrape/discovery/kubernetes/ingress.go
+++ b/lib/promscrape/discovery/kubernetes/ingress.go
@@ -7,7 +7,41 @@ import (
 
 // getIngressesLabels returns labels for k8s ingresses obtained from the given cfg.
 func getIngressesLabels(cfg *apiConfig) ([]map[string]string, error) {
-	data, err := getAPIResponse(cfg, "ingress", "/apis/extensions/v1beta1/ingresses")
+	igs, err := getIngresses(cfg)
+	if err != nil {
+		return nil, err
+	}
+	var ms []map[string]string
+	for _, ig := range igs {
+		ms = ig.appendTargetLabels(ms)
+	}
+	return ms, nil
+}
+
+func getIngresses(cfg *apiConfig) ([]Ingress, error) {
+	if len(cfg.Namespaces) == 0 {
+		return getIngressesByPath(cfg, "/apis/extensions/v1beta1/ingresses")
+	}
+	// Query /api/v1/namespaces/* for each namespace.
+	// This fixes authorization issue at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/432
+	cfgCopy := *cfg
+	namespaces := cfgCopy.Namespaces
+	cfgCopy.Namespaces = nil
+	cfg = &cfgCopy
+	var result []Ingress
+	for _, ns := range namespaces {
+		path := fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/ingresses", ns)
+		igs, err := getIngressesByPath(cfg, path)
+		if err != nil {
+			return nil, err
+		}
+		result = append(result, igs...)
+	}
+	return result, nil
+}
+
+func getIngressesByPath(cfg *apiConfig, path string) ([]Ingress, error) {
+	data, err := getAPIResponse(cfg, "ingress", path)
 	if err != nil {
 		return nil, fmt.Errorf("cannot obtain ingresses data from API server: %s", err)
 	}
@@ -15,11 +49,7 @@ func getIngressesLabels(cfg *apiConfig) ([]map[string]string, error) {
 	if err != nil {
 		return nil, fmt.Errorf("cannot parse ingresses response from API server: %s", err)
 	}
-	var ms []map[string]string
-	for _, ig := range igl.Items {
-		ms = ig.appendTargetLabels(ms)
-	}
-	return ms, nil
+	return igl.Items, nil
 }
 
 // IngressList represents ingress list in k8s.
diff --git a/lib/promscrape/discovery/kubernetes/kubernetes.go b/lib/promscrape/discovery/kubernetes/kubernetes.go
index 1c1b212be..fd1af2a3e 100644
--- a/lib/promscrape/discovery/kubernetes/kubernetes.go
+++ b/lib/promscrape/discovery/kubernetes/kubernetes.go
@@ -6,30 +6,6 @@ import (
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promauth"
 )
 
-// GetLabels returns labels for the given k8s role and the given cfg.
-func GetLabels(ac *promauth.Config, sdc *SDConfig) ([]map[string]string, error) {
-	cfg := &apiConfig{
-		Server:     sdc.APIServer,
-		AuthConfig: ac,
-		Namespaces: sdc.Namespaces.Names,
-		Selectors:  sdc.Selectors,
-	}
-	switch sdc.Role {
-	case "node":
-		return getNodesLabels(cfg)
-	case "service":
-		return getServicesLabels(cfg)
-	case "pod":
-		return getPodsLabels(cfg)
-	case "endpoints":
-		return getEndpointsLabels(cfg)
-	case "ingress":
-		return getIngressesLabels(cfg)
-	default:
-		return nil, fmt.Errorf("unexpected `role`: %q; must be one of `node`, `service`, `pod`, `endpoints` or `ingress`; skipping it", sdc.Role)
-	}
-}
-
 // SDConfig represents kubernetes-based service discovery config.
 //
 // See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
@@ -58,3 +34,27 @@ type Selector struct {
 	Label string `yaml:"label"`
 	Field string `yaml:"field"`
 }
+
+// GetLabels returns labels for the given k8s role and the given ac and sdc.
+func GetLabels(ac *promauth.Config, sdc *SDConfig) ([]map[string]string, error) {
+	cfg := &apiConfig{
+		Server:     sdc.APIServer,
+		AuthConfig: ac,
+		Namespaces: sdc.Namespaces.Names,
+		Selectors:  sdc.Selectors,
+	}
+	switch sdc.Role {
+	case "node":
+		return getNodesLabels(cfg)
+	case "service":
+		return getServicesLabels(cfg)
+	case "pod":
+		return getPodsLabels(cfg)
+	case "endpoints":
+		return getEndpointsLabels(cfg)
+	case "ingress":
+		return getIngressesLabels(cfg)
+	default:
+		return nil, fmt.Errorf("unexpected `role`: %q; must be one of `node`, `service`, `pod`, `endpoints` or `ingress`; skipping it", sdc.Role)
+	}
+}
diff --git a/lib/promscrape/discovery/kubernetes/pod.go b/lib/promscrape/discovery/kubernetes/pod.go
index 3602ff154..3220faab3 100644
--- a/lib/promscrape/discovery/kubernetes/pod.go
+++ b/lib/promscrape/discovery/kubernetes/pod.go
@@ -23,7 +23,29 @@ func getPodsLabels(cfg *apiConfig) ([]map[string]string, error) {
 }
 
 func getPods(cfg *apiConfig) ([]Pod, error) {
-	data, err := getAPIResponse(cfg, "pod", "/api/v1/pods")
+	if len(cfg.Namespaces) == 0 {
+		return getPodsByPath(cfg, "/api/v1/pods")
+	}
+	// Query /api/v1/namespaces/* for each namespace.
+	// This fixes authorization issue at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/432
+	cfgCopy := *cfg
+	namespaces := cfgCopy.Namespaces
+	cfgCopy.Namespaces = nil
+	cfg = &cfgCopy
+	var result []Pod
+	for _, ns := range namespaces {
+		path := fmt.Sprintf("/api/v1/namespaces/%s/pods", ns)
+		pods, err := getPodsByPath(cfg, path)
+		if err != nil {
+			return nil, err
+		}
+		result = append(result, pods...)
+	}
+	return result, nil
+}
+
+func getPodsByPath(cfg *apiConfig, path string) ([]Pod, error) {
+	data, err := getAPIResponse(cfg, "pod", path)
 	if err != nil {
 		return nil, fmt.Errorf("cannot obtain pods data from API server: %s", err)
 	}
diff --git a/lib/promscrape/discovery/kubernetes/service.go b/lib/promscrape/discovery/kubernetes/service.go
index ec4f02064..53c69172b 100644
--- a/lib/promscrape/discovery/kubernetes/service.go
+++ b/lib/promscrape/discovery/kubernetes/service.go
@@ -21,7 +21,29 @@ func getServicesLabels(cfg *apiConfig) ([]map[string]string, error) {
 }
 
 func getServices(cfg *apiConfig) ([]Service, error) {
-	data, err := getAPIResponse(cfg, "service", "/api/v1/services")
+	if len(cfg.Namespaces) == 0 {
+		return getServicesByPath(cfg, "/api/v1/services")
+	}
+	// Query /api/v1/namespaces/* for each namespace.
+	// This fixes authorization issue at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/432
+	cfgCopy := *cfg
+	namespaces := cfgCopy.Namespaces
+	cfgCopy.Namespaces = nil
+	cfg = &cfgCopy
+	var result []Service
+	for _, ns := range namespaces {
+		path := fmt.Sprintf("/api/v1/namespaces/%s/services", ns)
+		svcs, err := getServicesByPath(cfg, path)
+		if err != nil {
+			return nil, err
+		}
+		result = append(result, svcs...)
+	}
+	return result, nil
+}
+
+func getServicesByPath(cfg *apiConfig, path string) ([]Service, error) {
+	data, err := getAPIResponse(cfg, "service", path)
 	if err != nil {
 		return nil, fmt.Errorf("cannot obtain services data from API server: %s", err)
 	}
diff --git a/lib/promscrape/discoveryutils/utils.go b/lib/promscrape/discoveryutils/utils.go
index 58b21e306..18c7d00e0 100644
--- a/lib/promscrape/discoveryutils/utils.go
+++ b/lib/promscrape/discoveryutils/utils.go
@@ -1,9 +1,13 @@
 package discoveryutils
 
 import (
+	"encoding/json"
 	"net"
 	"regexp"
+	"sort"
 	"strconv"
+
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
 )
 
 // SanitizeLabelName replaces anything that doesn't match
@@ -25,3 +29,31 @@ func JoinHostPort(host string, port int) string {
 	portStr := strconv.Itoa(port)
 	return net.JoinHostPort(host, portStr)
 }
+
+// SortedLabels represents sorted labels.
+type SortedLabels []prompbmarshal.Label
+
+// UnmarshalJSON unmarshals JSON from data.
+func (sls *SortedLabels) UnmarshalJSON(data []byte) error {
+	var m map[string]string
+	if err := json.Unmarshal(data, &m); err != nil {
+		return err
+	}
+	*sls = GetSortedLabels(m)
+	return nil
+}
+
+// GetSortedLabels returns SortedLabels built from m.
+func GetSortedLabels(m map[string]string) SortedLabels {
+	a := make([]prompbmarshal.Label, 0, len(m))
+	for k, v := range m {
+		a = append(a, prompbmarshal.Label{
+			Name:  k,
+			Value: v,
+		})
+	}
+	sort.Slice(a, func(i, j int) bool {
+		return a[i].Name < a[j].Name
+	})
+	return a
+}
diff --git a/lib/promscrape/scraper.go b/lib/promscrape/scraper.go
index 643d55d74..32d96fbb0 100644
--- a/lib/promscrape/scraper.go
+++ b/lib/promscrape/scraper.go
@@ -18,10 +18,13 @@ var (
 	configCheckInterval = flag.Duration("promscrape.configCheckInterval", 0, "Interval for checking for changes in '-promscrape.config' file. "+
 		"By default the checking is disabled. Send SIGHUP signal in order to force config check for changes")
 	fileSDCheckInterval = flag.Duration("promscrape.fileSDCheckInterval", 30*time.Second, "Interval for checking for changes in 'file_sd_config'. "+
-		"See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config")
+		"See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#file_sd_config for details")
 	kubernetesSDCheckInterval = flag.Duration("promscrape.kubernetesSDCheckInterval", 30*time.Second, "Interval for checking for changes in Kubernetes API server. "+
 		"This works only if `kubernetes_sd_configs` is configured in '-promscrape.config' file. "+
 		"See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config for details")
+	gceSDCheckInterval = flag.Duration("promscrape.gceSDCheckInterval", time.Minute, "Interval for checking for changes in gce. "+
+		"This works only if `gce_sd_configs` is configured in '-promscrape.config' file. "+
+		"See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#gce_sd_config for details")
 	promscrapeConfigFile = flag.String("promscrape.config", "", "Optional path to Prometheus config file with 'scrape_configs' section containing targets to scrape. "+
 		"See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config for details")
 )
@@ -89,6 +92,11 @@ func runScraper(configFile string, pushData func(wr *prompbmarshal.WriteRequest)
 			defer wg.Done()
 			runKubernetesSDScrapers(cfg, pushData, stopCh)
 		}()
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			runGCESDScrapers(cfg, pushData, stopCh)
+		}()
 
 	waitForChans:
 		select {
@@ -194,6 +202,51 @@ var (
 	kubernetesSDReloads = metrics.NewCounter(`vm_promscrape_reloads_total{type="kubernetes_sd"}`)
 )
 
+func runGCESDScrapers(cfg *Config, pushData func(wr *prompbmarshal.WriteRequest), stopCh <-chan struct{}) {
+	if cfg.gceSDConfigsCount() == 0 {
+		return
+	}
+	sws := cfg.getGCESDScrapeWork()
+	ticker := time.NewTicker(*gceSDCheckInterval)
+	defer ticker.Stop()
+	mustStop := false
+	for !mustStop {
+		localStopCh := make(chan struct{})
+		var wg sync.WaitGroup
+		wg.Add(1)
+		go func(sws []ScrapeWork) {
+			defer wg.Done()
+			logger.Infof("starting %d scrapers for `gce_sd_config` targets", len(sws))
+			gceSDTargets.Set(uint64(len(sws)))
+			runScrapeWorkers(sws, pushData, localStopCh)
+			gceSDTargets.Set(0)
+			logger.Infof("stopped all the %d scrapers for `gce_sd_config` targets", len(sws))
+		}(sws)
+	waitForChans:
+		select {
+		case <-ticker.C:
+			swsNew := cfg.getGCESDScrapeWork()
+			if equalStaticConfigForScrapeWorks(swsNew, sws) {
+				// Nothing changed, continue waiting for updated scrape work
+				goto waitForChans
+			}
+			logger.Infof("restarting scrapers for changed `gce_sd_config` targets")
+			sws = swsNew
+		case <-stopCh:
+			mustStop = true
+		}
+
+		close(localStopCh)
+		wg.Wait()
+		gceSDReloads.Inc()
+	}
+}
+
+var (
+	gceSDTargets = metrics.NewCounter(`vm_promscrape_targets{type="gce_sd"}`)
+	gceSDReloads = metrics.NewCounter(`vm_promscrape_reloads_total{type="gce_sd"}`)
+)
+
 func runFileSDScrapers(cfg *Config, pushData func(wr *prompbmarshal.WriteRequest), stopCh <-chan struct{}) {
 	if cfg.fileSDConfigsCount() == 0 {
 		return
diff --git a/lib/storage/dedup.go b/lib/storage/dedup.go
index 70f060ac1..96cd1daef 100644
--- a/lib/storage/dedup.go
+++ b/lib/storage/dedup.go
@@ -1,7 +1,6 @@
 package storage
 
 import (
-	"math"
 	"time"
 )
 
@@ -11,53 +10,39 @@ import (
 //
 // This function must be called before initializing the storage.
 func SetMinScrapeIntervalForDeduplication(interval time.Duration) {
-	minScrapeInterval = interval
+	minScrapeInterval = interval.Milliseconds()
 }
 
-var minScrapeInterval = time.Duration(0)
-
-func getMinDelta() int64 {
-	// Use 7/8 of minScrapeInterval in order to preserve proper data points.
-	// For instance, if minScrapeInterval=10, the following time series:
-	//    10 15 19 25 30 34 41
-	// Would be unexpectedly converted to if using 100% of minScrapeInterval:
-	//    10 25 41
-	// When using 7/8 of minScrapeInterval, it will be converted to the expected:
-	//    10 19 30 41
-	ms := minScrapeInterval.Milliseconds()
-
-	// Try calculating scrape interval via integer arithmetic.
-	d := (ms / 8) * 7
-	if d > 0 {
-		return d
-	}
-	// Too small scrape interval for integer arithmetic. Calculate d using floating-point arithmetic.
-	return int64(math.Round(float64(ms) / 8 * 7))
-}
+var minScrapeInterval = int64(0)
 
 // DeduplicateSamples removes samples from src* if they are closer to each other than minScrapeInterval.
 func DeduplicateSamples(srcTimestamps []int64, srcValues []float64) ([]int64, []float64) {
 	if minScrapeInterval <= 0 {
 		return srcTimestamps, srcValues
 	}
-	minDelta := getMinDelta()
-	if !needsDedup(srcTimestamps, minDelta) {
+	if !needsDedup(srcTimestamps, minScrapeInterval) {
 		// Fast path - nothing to deduplicate
 		return srcTimestamps, srcValues
 	}
 
 	// Slow path - dedup data points.
-	prevTimestamp := srcTimestamps[0]
+	tsNext := (srcTimestamps[0] - srcTimestamps[0] % minScrapeInterval) + minScrapeInterval
 	dstTimestamps := srcTimestamps[:1]
 	dstValues := srcValues[:1]
 	for i := 1; i < len(srcTimestamps); i++ {
 		ts := srcTimestamps[i]
-		if ts-prevTimestamp < minDelta {
+		if ts < tsNext {
 			continue
 		}
 		dstTimestamps = append(dstTimestamps, ts)
 		dstValues = append(dstValues, srcValues[i])
-		prevTimestamp = ts
+
+		// Update tsNext
+		tsNext += minScrapeInterval
+		if ts >= tsNext {
+			// Slow path for updating ts.
+			tsNext = (ts - ts % minScrapeInterval) + minScrapeInterval
+		}
 	}
 	return dstTimestamps, dstValues
 }
@@ -66,29 +51,29 @@ func deduplicateSamplesDuringMerge(srcTimestamps, srcValues []int64) ([]int64, [
 	if minScrapeInterval <= 0 {
 		return srcTimestamps, srcValues
 	}
-	if len(srcTimestamps) < 32 {
-		// Do not de-duplicate small number of samples during merge
-		// in order to improve deduplication accuracy on later stages.
-		return srcTimestamps, srcValues
-	}
-	minDelta := getMinDelta()
-	if !needsDedup(srcTimestamps, minDelta) {
+	if !needsDedup(srcTimestamps, minScrapeInterval) {
 		// Fast path - nothing to deduplicate
 		return srcTimestamps, srcValues
 	}
 
 	// Slow path - dedup data points.
-	prevTimestamp := srcTimestamps[0]
+	tsNext := (srcTimestamps[0] - srcTimestamps[0] % minScrapeInterval) + minScrapeInterval
 	dstTimestamps := srcTimestamps[:1]
 	dstValues := srcValues[:1]
 	for i := 1; i < len(srcTimestamps); i++ {
 		ts := srcTimestamps[i]
-		if ts-prevTimestamp < minDelta {
+		if ts < tsNext {
 			continue
 		}
 		dstTimestamps = append(dstTimestamps, ts)
 		dstValues = append(dstValues, srcValues[i])
-		prevTimestamp = ts
+
+		// Update tsNext
+		tsNext += minScrapeInterval
+		if ts >= tsNext {
+			// Slow path for updating ts.
+			tsNext = (ts - ts % minScrapeInterval) + minScrapeInterval
+		}
 	}
 	return dstTimestamps, dstValues
 }
diff --git a/lib/storage/index_db.go b/lib/storage/index_db.go
index 36a0d3dd8..808137351 100644
--- a/lib/storage/index_db.go
+++ b/lib/storage/index_db.go
@@ -2398,19 +2398,36 @@ func (is *indexSearch) getMetricIDsForDateAndFilters(date uint64, tfs *TagFilter
 	})
 
 	// Populate metricIDs with the first non-negative filter.
-	var tfFirst *tagFilter
+	var tfsPostponed []*tagFilter
+	var metricIDs *uint64set.Set
+	maxDateMetrics := maxMetrics * 50
+	tfsRemainingWithCount := tfsWithCount[:0]
 	for i := range tfsWithCount {
 		tf := tfsWithCount[i].tf
 		if tf.isNegative {
+			tfsRemainingWithCount = append(tfsRemainingWithCount, tfsWithCount[i])
+			continue
+		}
+		m, err := is.getMetricIDsForDateTagFilter(tf, date, tfs.commonPrefix, maxDateMetrics)
+		if err != nil {
+			return nil, err
+		}
+		if m.Len() >= maxDateMetrics {
+			// Too many time series found by a single tag filter. Postpone applying this filter via metricName match.
+			tfsPostponed = append(tfsPostponed, tf)
 			continue
 		}
-		tfFirst = tf
+		metricIDs = m
+		i++
+		for i < len(tfsWithCount) {
+			tfsRemainingWithCount = append(tfsRemainingWithCount, tfsWithCount[i])
+			i++
+		}
 		break
 	}
-	var metricIDs *uint64set.Set
-	maxDateMetrics := maxMetrics * 50
-	if tfFirst == nil {
-		// All the filters in tfs are negative. Populate all the metricIDs for the given (date),
+	if metricIDs == nil {
+		// All the filters in tfs are negative or match too many time series.
+		// Populate all the metricIDs for the given (date),
 		// so later they can be filtered out with negative filters.
 		m, err := is.getMetricIDsForDate(date, maxDateMetrics)
 		if err != nil {
@@ -2422,52 +2439,34 @@ func (is *indexSearch) getMetricIDsForDateAndFilters(date uint64, tfs *TagFilter
 			}
 			return nil, fmt.Errorf("cannot obtain all the metricIDs: %s", err)
 		}
-		metricIDs = m
-	} else {
-		// Populate metricIDs for the given tfFirst on the given (date)
-		m, err := is.getMetricIDsForDateTagFilter(tfFirst, date, tfs.commonPrefix, maxDateMetrics)
-		if err != nil {
-			return nil, err
+		if m.Len() >= maxDateMetrics {
+			// Too many time series found for the given (date). Fall back to global search.
+			return nil, errFallbackToMetricNameMatch
 		}
 		metricIDs = m
 	}
-	if metricIDs.Len() >= maxDateMetrics {
-		// Too many time series found by a single tag filter. Fall back to global search.
-		return nil, errFallbackToMetricNameMatch
-	}
 
 	// Intersect metricIDs with the rest of filters.
-	for i := range tfsWithCount {
-		tfWithCount := &tfsWithCount[i]
-		tf := tfWithCount.tf
-		if tf == tfFirst {
-			continue
-		}
-		if n := uint64(metricIDs.Len()); n < 1000 || n < tfWithCount.count/maxIndexScanLoopsPerMetric {
+	for i := range tfsRemainingWithCount {
+		tfWithCount := tfsRemainingWithCount[i]
+		if n := uint64(metricIDs.Len()); n < 1000 || (n < tfWithCount.count/maxIndexScanLoopsPerMetric && n < uint64(maxMetrics)/10) {
 			// It should be faster performing metricName match on the remaining filters
 			// instead of scanning big number of entries in the inverted index for these filters.
-			tfsRemaining := tfsWithCount[i:]
-			tfsPostponed := make([]*tagFilter, 0, len(tfsRemaining))
-			for j := range tfsRemaining {
-				tf := tfsRemaining[j].tf
-				if tf == tfFirst {
-					continue
-				}
-				tfsPostponed = append(tfsPostponed, tf)
-			}
-			var m uint64set.Set
-			if err := is.updateMetricIDsByMetricNameMatch(&m, metricIDs, tfsPostponed); err != nil {
-				return nil, err
+			for i < len(tfsRemainingWithCount) {
+				tfsPostponed = append(tfsPostponed, tfsRemainingWithCount[i].tf)
+				i++
 			}
-			return &m, nil
+			break
 		}
+		tf := tfWithCount.tf
 		m, err := is.getMetricIDsForDateTagFilter(tf, date, tfs.commonPrefix, maxDateMetrics)
 		if err != nil {
 			return nil, err
 		}
 		if m.Len() >= maxDateMetrics {
-			// Too many time series found by a single tag filter. Fall back to global search.
-			return nil, errFallbackToMetricNameMatch
+			// Too many time series found by a single tag filter. Postpone applying this filter via metricName match.
+			tfsPostponed = append(tfsPostponed, tf)
+			continue
 		}
 		if tf.isNegative {
 			metricIDs.Subtract(m)
@@ -2479,6 +2478,19 @@ func (is *indexSearch) getMetricIDsForDateAndFilters(date uint64, tfs *TagFilter
 			return nil, nil
 		}
 	}
+	if len(tfsPostponed) > 0 {
+		if n := metricIDs.Len(); n > 50000 && n > maxMetrics/10 {
+			// It will be slow to perform metricName match on this number of time series.
+			// Fall back to global search.
+			return nil, errFallbackToMetricNameMatch
+		}
+		// Apply the postponed filters via metricName match.
+		var m uint64set.Set
+		if err := is.updateMetricIDsByMetricNameMatch(&m, metricIDs, tfsPostponed); err != nil {
+			return nil, err
+		}
+		return &m, nil
+	}
 	return metricIDs, nil
 }
 
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
index 73d9763c9..6846ef6f8 100644
--- a/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
+++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
@@ -169,6 +169,29 @@ type AssumeRoleProvider struct {
 	// size.
 	Policy *string
 
+	// The ARNs of IAM managed policies you want to use as managed session policies.
+	// The policies must exist in the same account as the role.
+	//
+	// This parameter is optional. You can provide up to 10 managed policy ARNs.
+	// However, the plain text that you use for both inline and managed session
+	// policies can't exceed 2,048 characters.
+	//
+	// An AWS conversion compresses the passed session policies and session tags
+	// into a packed binary format that has a separate limit. Your request can fail
+	// for this limit even if your plain text meets the other requirements. The
+	// PackedPolicySize response element indicates by percentage how close the policies
+	// and tags for your request are to the upper size limit.
+	//
+	// Passing policies to this operation returns new temporary credentials. The
+	// resulting session's permissions are the intersection of the role's identity-based
+	// policy and the session policies. You can use the role's temporary credentials
+	// in subsequent AWS API calls to access resources in the account that owns
+	// the role. You cannot use session policies to grant more permissions than
+	// those allowed by the identity-based policy of the role that is being assumed.
+	// For more information, see Session Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
+	// in the IAM User Guide.
+	PolicyArns []*sts.PolicyDescriptorType
+
 	// The identification number of the MFA device that is associated with the user
 	// who is making the AssumeRole call. Specify this value if the trust policy
 	// of the role being assumed includes a condition that requires MFA authentication.
@@ -291,6 +314,7 @@ func (p *AssumeRoleProvider) RetrieveWithContext(ctx credentials.Context) (crede
 		RoleSessionName:   aws.String(p.RoleSessionName),
 		ExternalId:        p.ExternalID,
 		Tags:              p.Tags,
+		PolicyArns:        p.PolicyArns,
 		TransitiveTagKeys: p.TransitiveTagKeys,
 	}
 	if p.Policy != nil {
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/web_identity_provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/web_identity_provider.go
index fda495194..6feb262b2 100644
--- a/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/web_identity_provider.go
+++ b/vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/web_identity_provider.go
@@ -50,6 +50,7 @@ func (f FetchTokenPath) FetchToken(ctx credentials.Context) ([]byte, error) {
 // an OIDC token.
 type WebIdentityRoleProvider struct {
 	credentials.Expiry
+	PolicyArns []*sts.PolicyDescriptorType
 
 	client       stsiface.STSAPI
 	ExpiryWindow time.Duration
@@ -107,6 +108,7 @@ func (p *WebIdentityRoleProvider) RetrieveWithContext(ctx credentials.Context) (
 		sessionName = strconv.FormatInt(now().UnixNano(), 10)
 	}
 	req, resp := p.client.AssumeRoleWithWebIdentityRequest(&sts.AssumeRoleWithWebIdentityInput{
+		PolicyArns:       p.PolicyArns,
 		RoleArn:          &p.roleARN,
 		RoleSessionName:  &sessionName,
 		WebIdentityToken: aws.String(string(b)),
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
index 4173d38bc..2bf2f01ec 100644
--- a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
+++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
@@ -2729,6 +2729,7 @@ var awsPartition = partition{
 			Endpoints: endpoints{
 				"ap-southeast-2": endpoint{},
 				"eu-north-1":     endpoint{},
+				"eu-west-1":      endpoint{},
 				"me-south-1":     endpoint{},
 				"us-east-2":      endpoint{},
 				"us-west-2":      endpoint{},
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/version.go b/vendor/github.com/aws/aws-sdk-go/aws/version.go
index 64b91ae74..a22e6787a 100644
--- a/vendor/github.com/aws/aws-sdk-go/aws/version.go
+++ b/vendor/github.com/aws/aws-sdk-go/aws/version.go
@@ -5,4 +5,4 @@ package aws
 const SDKName = "aws-sdk-go"
 
 // SDKVersion is the version of this SDK
-const SDKVersion = "1.30.12"
+const SDKVersion = "1.30.13"
diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go
index 63062ffa6..c2f855e75 100644
--- a/vendor/github.com/klauspost/compress/zstd/blockdec.go
+++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go
@@ -131,17 +131,25 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error {
 	b.Type = blockType((bh >> 1) & 3)
 	// find size.
 	cSize := int(bh >> 3)
+	maxSize := maxBlockSize
 	switch b.Type {
 	case blockTypeReserved:
 		return ErrReservedBlockType
 	case blockTypeRLE:
 		b.RLESize = uint32(cSize)
+		if b.lowMem {
+			maxSize = cSize
+		}
 		cSize = 1
 	case blockTypeCompressed:
 		if debug {
 			println("Data size on stream:", cSize)
 		}
 		b.RLESize = 0
+		maxSize = maxCompressedBlockSize
+		if windowSize < maxCompressedBlockSize && b.lowMem {
+			maxSize = int(windowSize)
+		}
 		if cSize > maxCompressedBlockSize || uint64(cSize) > b.WindowSize {
 			if debug {
 				printf("compressed block too big: csize:%d block: %+v\n", uint64(cSize), b)
@@ -160,8 +168,8 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error {
 			b.dataStorage = make([]byte, 0, maxBlockSize)
 		}
 	}
-	if cap(b.dst) <= maxBlockSize {
-		b.dst = make([]byte, 0, maxBlockSize+1)
+	if cap(b.dst) <= maxSize {
+		b.dst = make([]byte, 0, maxSize+1)
 	}
 	var err error
 	b.data, err = br.readBig(cSize, b.dataStorage)
@@ -679,8 +687,11 @@ func (b *blockDec) decodeCompressed(hist *history) error {
 		println("initializing sequences:", err)
 		return err
 	}
-
-	err = seqs.decode(nSeqs, br, hist.b)
+	hbytes := hist.b
+	if len(hbytes) > hist.windowSize {
+		hbytes = hbytes[len(hbytes)-hist.windowSize:]
+	}
+	err = seqs.decode(nSeqs, br, hbytes)
 	if err != nil {
 		return err
 	}
diff --git a/vendor/github.com/klauspost/compress/zstd/framedec.go b/vendor/github.com/klauspost/compress/zstd/framedec.go
index e38f34a9b..780880ebe 100644
--- a/vendor/github.com/klauspost/compress/zstd/framedec.go
+++ b/vendor/github.com/klauspost/compress/zstd/framedec.go
@@ -233,7 +233,11 @@ func (d *frameDec) reset(br byteBuffer) error {
 		return ErrWindowSizeTooSmall
 	}
 	d.history.windowSize = int(d.WindowSize)
-	d.history.maxSize = d.history.windowSize + maxBlockSize
+	if d.o.lowMem && d.history.windowSize < maxBlockSize {
+		d.history.maxSize = d.history.windowSize * 2
+	} else {
+		d.history.maxSize = d.history.windowSize + maxBlockSize
+	}
 	// history contains input - maybe we do something
 	d.rawInput = br
 	return nil
@@ -320,8 +324,8 @@ func (d *frameDec) checkCRC() error {
 
 func (d *frameDec) initAsync() {
 	if !d.o.lowMem && !d.SingleSegment {
-		// set max extra size history to 20MB.
-		d.history.maxSize = d.history.windowSize + maxBlockSize*10
+		// set max extra size history to 10MB.
+		d.history.maxSize = d.history.windowSize + maxBlockSize*5
 	}
 	// re-alloc if more than one extra block size.
 	if d.o.lowMem && cap(d.history.b) > d.history.maxSize+maxBlockSize {
diff --git a/vendor/github.com/valyala/fasthttp/SECURITY.md b/vendor/github.com/valyala/fasthttp/SECURITY.md
index 2beab1714..642bbb988 100644
--- a/vendor/github.com/valyala/fasthttp/SECURITY.md
+++ b/vendor/github.com/valyala/fasthttp/SECURITY.md
@@ -54,7 +54,7 @@ Any GitHub issues pertaining to a security issue will be prefixed with [security
 ### Comments on This Policy
 If you have any suggestions to improve this policy, please send an email to oss-security@highload.solutions for discussion.
 
-### PGP Key for oss-security@highload.solutions
+### PGP Key for oss-security@highload.ltd
 
 We accept PGP-encrypted email, but the majority of the security team are not regular PGP users
 so it's somewhat inconvenient. Please only use PGP for critical security reports.
diff --git a/vendor/github.com/valyala/fasthttp/go.mod b/vendor/github.com/valyala/fasthttp/go.mod
index 3e1c929b5..ba38c2780 100644
--- a/vendor/github.com/valyala/fasthttp/go.mod
+++ b/vendor/github.com/valyala/fasthttp/go.mod
@@ -3,9 +3,8 @@ module github.com/valyala/fasthttp
 go 1.11
 
 require (
-	github.com/klauspost/compress v1.8.2
-	github.com/klauspost/cpuid v1.2.1 // indirect
+	github.com/klauspost/compress v1.10.4
 	github.com/valyala/bytebufferpool v1.0.0
 	github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a
-	golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
+	golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
 )
diff --git a/vendor/github.com/valyala/fasthttp/go.sum b/vendor/github.com/valyala/fasthttp/go.sum
index 52407f3f4..96298ae16 100644
--- a/vendor/github.com/valyala/fasthttp/go.sum
+++ b/vendor/github.com/valyala/fasthttp/go.sum
@@ -1,13 +1,12 @@
-github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs=
-github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
-github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/compress v1.10.4 h1:jFzIFaf586tquEB5EhzQG0HwGNSlgAJpG53G6Ss11wc=
+github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc=
 github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
-golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/vendor/github.com/valyala/fasthttp/server.go b/vendor/github.com/valyala/fasthttp/server.go
index 43a450733..29ce90940 100644
--- a/vendor/github.com/valyala/fasthttp/server.go
+++ b/vendor/github.com/valyala/fasthttp/server.go
@@ -180,6 +180,9 @@ type Server struct {
 	// The maximum number of concurrent connections the server may serve.
 	//
 	// DefaultConcurrency is used if not set.
+	//
+	// Concurrency only works if you either call Serve once, or only ServeConn multiple times.
+	// It works with ListenAndServe as well.
 	Concurrency int
 
 	// Whether to disable keep-alive connections.
@@ -1888,8 +1891,14 @@ func (s *Server) idleTimeout() time.Duration {
 	return s.ReadTimeout
 }
 
+func (s *Server) serveConnCleanup() {
+	atomic.AddInt32(&s.open, -1)
+	atomic.AddUint32(&s.concurrency, ^uint32(0))
+}
+
 func (s *Server) serveConn(c net.Conn) (err error) {
-	defer atomic.AddInt32(&s.open, -1)
+	defer s.serveConnCleanup()
+	atomic.AddUint32(&s.concurrency, 1)
 
 	var proto string
 	if proto, err = s.getNextProto(c); err != nil {
diff --git a/vendor/golang.org/x/tools/cmd/goimports/goimports.go b/vendor/golang.org/x/tools/cmd/goimports/goimports.go
index a5680d8d6..c195caaf8 100644
--- a/vendor/golang.org/x/tools/cmd/goimports/goimports.go
+++ b/vendor/golang.org/x/tools/cmd/goimports/goimports.go
@@ -160,7 +160,12 @@ func processFile(filename string, in io.Reader, out io.Writer, argType argumentT
 				// filename is "<standard input>"
 				return errors.New("can't use -w on stdin")
 			}
-			err = ioutil.WriteFile(filename, res, 0)
+			// On Windows, we need to re-set the permissions from the file. See golang/go#38225.
+			var perms os.FileMode
+			if fi, err := os.Stat(filename); err == nil {
+				perms = fi.Mode() & os.ModePerm
+			}
+			err = ioutil.WriteFile(filename, res, perms)
 			if err != nil {
 				return err
 			}
diff --git a/vendor/golang.org/x/tools/internal/event/core/event.go b/vendor/golang.org/x/tools/internal/event/core/event.go
new file mode 100644
index 000000000..29f293e62
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/event/core/event.go
@@ -0,0 +1,106 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package core provides support for event based telemetry.
+package core
+
+import (
+	"fmt"
+	"time"
+
+	"golang.org/x/tools/internal/event/label"
+)
+
+type eventType uint8
+
+const (
+	invalidType   = eventType(iota)
+	LogType       // an event that should be recorded in a log
+	StartSpanType // the start of a span of time
+	EndSpanType   // the end of a span of time
+	LabelType     // some values that should be noted for later events
+	DetachType    // an event that causes a context to detach
+	RecordType    // a value that should be tracked
+)
+
+// Event holds the information about an event of note that ocurred.
+type Event struct {
+	at time.Time
+
+	typ eventType
+
+	// As events are often on the stack, storing the first few labels directly
+	// in the event can avoid an allocation at all for the very common cases of
+	// simple events.
+	// The length needs to be large enough to cope with the majority of events
+	// but no so large as to cause undue stack pressure.
+	// A log message with two values will use 3 labels (one for each value and
+	// one for the message itself).
+
+	static  [3]label.Label // inline storage for the first few labels
+	dynamic []label.Label  // dynamically sized storage for remaining labels
+}
+
+// eventLabelMap implements label.Map for a the labels of an Event.
+type eventLabelMap struct {
+	event Event
+}
+
+func (ev Event) At() time.Time { return ev.at }
+
+func (ev Event) IsLog() bool       { return ev.typ == LogType }
+func (ev Event) IsEndSpan() bool   { return ev.typ == EndSpanType }
+func (ev Event) IsStartSpan() bool { return ev.typ == StartSpanType }
+func (ev Event) IsLabel() bool     { return ev.typ == LabelType }
+func (ev Event) IsDetach() bool    { return ev.typ == DetachType }
+func (ev Event) IsRecord() bool    { return ev.typ == RecordType }
+
+func (ev Event) Format(f fmt.State, r rune) {
+	if !ev.at.IsZero() {
+		fmt.Fprint(f, ev.at.Format("2006/01/02 15:04:05 "))
+	}
+	for index := 0; ev.Valid(index); index++ {
+		l := ev.Label(index)
+		fmt.Fprintf(f, "\n\t%v", l)
+	}
+}
+
+func (ev Event) Valid(index int) bool {
+	return index >= 0 && index < len(ev.static)+len(ev.dynamic)
+}
+
+func (ev Event) Label(index int) label.Label {
+	if index < len(ev.static) {
+		return ev.static[index]
+	}
+	return ev.dynamic[index-len(ev.static)]
+}
+
+func (ev Event) Find(key label.Key) label.Label {
+	for _, l := range ev.static {
+		if l.Key() == key {
+			return l
+		}
+	}
+	for _, l := range ev.dynamic {
+		if l.Key() == key {
+			return l
+		}
+	}
+	return label.Label{}
+}
+
+func MakeEvent(typ eventType, static [3]label.Label, labels []label.Label) Event {
+	return Event{
+		typ:     typ,
+		static:  static,
+		dynamic: labels,
+	}
+}
+
+// CloneEvent event returns a copy of the event with the time adjusted to at.
+func CloneEvent(ev Event, at time.Time) Event {
+	ev.at = at
+	return ev
+}
diff --git a/vendor/golang.org/x/tools/internal/telemetry/event/export.go b/vendor/golang.org/x/tools/internal/event/core/export.go
similarity index 76%
rename from vendor/golang.org/x/tools/internal/telemetry/event/export.go
rename to vendor/golang.org/x/tools/internal/event/core/export.go
index a2633b602..05f3a9a57 100644
--- a/vendor/golang.org/x/tools/internal/telemetry/event/export.go
+++ b/vendor/golang.org/x/tools/internal/event/core/export.go
@@ -2,18 +2,20 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package event
+package core
 
 import (
 	"context"
 	"sync/atomic"
 	"time"
 	"unsafe"
+
+	"golang.org/x/tools/internal/event/label"
 )
 
 // Exporter is a function that handles events.
 // It may return a modified context and event.
-type Exporter func(context.Context, Event, TagMap) context.Context
+type Exporter func(context.Context, Event, label.Map) context.Context
 
 var (
 	exporter unsafe.Pointer
@@ -35,16 +37,16 @@ func SetExporter(e Exporter) {
 }
 
 // deliver is called to deliver an event to the supplied exporter.
-// it will fill in the time and generate the basic tag source.
+// it will fill in the time.
 func deliver(ctx context.Context, exporter Exporter, ev Event) context.Context {
 	// add the current time to the event
-	ev.At = time.Now()
+	ev.at = time.Now()
 	// hand the event off to the current exporter
 	return exporter(ctx, ev, ev)
 }
 
-// dispatch is called to deliver an event to the global exporter if set.
-func dispatch(ctx context.Context, ev Event) context.Context {
+// Export is called to deliver an event to the global exporter if set.
+func Export(ctx context.Context, ev Event) context.Context {
 	// get the global exporter and abort early if there is not one
 	exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
 	if exporterPtr == nil {
@@ -53,11 +55,11 @@ func dispatch(ctx context.Context, ev Event) context.Context {
 	return deliver(ctx, *exporterPtr, ev)
 }
 
-// dispatchPair is called to deliver a start event to the supplied exporter.
+// ExportPair is called to deliver a start event to the supplied exporter.
 // It also returns a function that will deliver the end event to the same
 // exporter.
-// it will fill in the time and generate the basic tag source.
-func dispatchPair(ctx context.Context, begin, end Event) (context.Context, func()) {
+// It will fill in the time.
+func ExportPair(ctx context.Context, begin, end Event) (context.Context, func()) {
 	// get the global exporter and abort early if there is not one
 	exporterPtr := (*Exporter)(atomic.LoadPointer(&exporter))
 	if exporterPtr == nil {
diff --git a/vendor/golang.org/x/tools/internal/event/core/fast.go b/vendor/golang.org/x/tools/internal/event/core/fast.go
new file mode 100644
index 000000000..e61f2cf79
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/event/core/fast.go
@@ -0,0 +1,57 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package core
+
+import (
+	"context"
+
+	"golang.org/x/tools/internal/event/keys"
+	"golang.org/x/tools/internal/event/label"
+)
+
+// Log1 takes a message and one label delivers a log event to the exporter.
+// It is a customized version of Print that is faster and does no allocation.
+func Log1(ctx context.Context, message string, t1 label.Label) {
+	Export(ctx, MakeEvent(LogType, [3]label.Label{keys.Msg.Of(message), t1}, nil))
+}
+
+// Log2 takes a message and two labels and delivers a log event to the exporter.
+// It is a customized version of Print that is faster and does no allocation.
+func Log2(ctx context.Context, message string, t1 label.Label, t2 label.Label) {
+	Export(ctx, MakeEvent(LogType, [3]label.Label{keys.Msg.Of(message), t1, t2}, nil))
+}
+
+// Metric1 sends a label event to the exporter with the supplied labels.
+func Metric1(ctx context.Context, t1 label.Label) context.Context {
+	return Export(ctx, MakeEvent(RecordType, [3]label.Label{t1}, nil))
+}
+
+// Metric2 sends a label event to the exporter with the supplied labels.
+func Metric2(ctx context.Context, t1, t2 label.Label) context.Context {
+	return Export(ctx, MakeEvent(RecordType, [3]label.Label{t1, t2}, nil))
+}
+
+// Metric3 sends a label event to the exporter with the supplied labels.
+func Metric3(ctx context.Context, t1, t2, t3 label.Label) context.Context {
+	return Export(ctx, MakeEvent(RecordType, [3]label.Label{t1, t2, t3}, nil))
+}
+
+// Start1 sends a span start event with the supplied label list to the exporter.
+// It also returns a function that will end the span, which should normally be
+// deferred.
+func Start1(ctx context.Context, name string, t1 label.Label) (context.Context, func()) {
+	return ExportPair(ctx,
+		MakeEvent(StartSpanType, [3]label.Label{keys.Name.Of(name), t1}, nil),
+		MakeEvent(EndSpanType, [3]label.Label{}, nil))
+}
+
+// Start2 sends a span start event with the supplied label list to the exporter.
+// It also returns a function that will end the span, which should normally be
+// deferred.
+func Start2(ctx context.Context, name string, t1, t2 label.Label) (context.Context, func()) {
+	return ExportPair(ctx,
+		MakeEvent(StartSpanType, [3]label.Label{keys.Name.Of(name), t1, t2}, nil),
+		MakeEvent(EndSpanType, [3]label.Label{}, nil))
+}
diff --git a/vendor/golang.org/x/tools/internal/event/doc.go b/vendor/golang.org/x/tools/internal/event/doc.go
new file mode 100644
index 000000000..5dc6e6bab
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/event/doc.go
@@ -0,0 +1,7 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package event provides a set of packages that cover the main
+// concepts of telemetry in an implementation agnostic way.
+package event
diff --git a/vendor/golang.org/x/tools/internal/event/event.go b/vendor/golang.org/x/tools/internal/event/event.go
new file mode 100644
index 000000000..730313b8b
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/event/event.go
@@ -0,0 +1,69 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package event
+
+import (
+	"context"
+
+	"golang.org/x/tools/internal/event/core"
+	"golang.org/x/tools/internal/event/keys"
+	"golang.org/x/tools/internal/event/label"
+)
+
+// Exporter is a function that handles events.
+// It may return a modified context and event.
+type Exporter func(context.Context, core.Event, label.Map) context.Context
+
+// SetExporter sets the global exporter function that handles all events.
+// The exporter is called synchronously from the event call site, so it should
+// return quickly so as not to hold up user code.
+func SetExporter(e Exporter) {
+	core.SetExporter(core.Exporter(e))
+}
+
+// Log takes a message and a label list and combines them into a single event
+// before delivering them to the exporter.
+func Log(ctx context.Context, message string, labels ...label.Label) {
+	core.Export(ctx, core.MakeEvent(core.LogType, [3]label.Label{
+		keys.Msg.Of(message),
+	}, labels))
+}
+
+// Error takes a message and a label list and combines them into a single event
+// before delivering them to the exporter. It captures the error in the
+// delivered event.
+func Error(ctx context.Context, message string, err error, labels ...label.Label) {
+	core.Export(ctx, core.MakeEvent(core.LogType, [3]label.Label{
+		keys.Msg.Of(message),
+		keys.Err.Of(err),
+	}, labels))
+}
+
+// Metric sends a label event to the exporter with the supplied labels.
+func Metric(ctx context.Context, labels ...label.Label) {
+	core.Export(ctx, core.MakeEvent(core.RecordType, [3]label.Label{}, labels))
+}
+
+// Label sends a label event to the exporter with the supplied labels.
+func Label(ctx context.Context, labels ...label.Label) context.Context {
+	return core.Export(ctx, core.MakeEvent(core.LabelType, [3]label.Label{}, labels))
+}
+
+// Start sends a span start event with the supplied label list to the exporter.
+// It also returns a function that will end the span, which should normally be
+// deferred.
+func Start(ctx context.Context, name string, labels ...label.Label) (context.Context, func()) {
+	return core.ExportPair(ctx,
+		core.MakeEvent(core.StartSpanType, [3]label.Label{
+			keys.Name.Of(name),
+		}, labels),
+		core.MakeEvent(core.EndSpanType, [3]label.Label{}, nil))
+}
+
+// Detach returns a context without an associated span.
+// This allows the creation of spans that are not children of the current span.
+func Detach(ctx context.Context) context.Context {
+	return core.Export(ctx, core.MakeEvent(core.DetachType, [3]label.Label{}, nil))
+}
diff --git a/vendor/golang.org/x/tools/internal/event/keys/keys.go b/vendor/golang.org/x/tools/internal/event/keys/keys.go
new file mode 100644
index 000000000..5814f71a0
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/event/keys/keys.go
@@ -0,0 +1,542 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package keys
+
+import (
+	"fmt"
+	"io"
+	"math"
+	"strconv"
+
+	"golang.org/x/tools/internal/event/label"
+)
+
+// Value represents a key for untyped values.
+type Value struct {
+	name        string
+	description string
+}
+
+// New creates a new Key for untyped values.
+func New(name, description string) *Value {
+	return &Value{name: name, description: description}
+}
+
+func (k *Value) Name() string        { return k.name }
+func (k *Value) Description() string { return k.description }
+
+func (k *Value) Format(w io.Writer, buf []byte, l label.Label) {
+	fmt.Fprint(w, k.From(l))
+}
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Value) Get(lm label.Map) interface{} {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return nil
+}
+
+// From can be used to get a value from a Label.
+func (k *Value) From(t label.Label) interface{} { return t.UnpackValue() }
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Value) Of(value interface{}) label.Label { return label.OfValue(k, value) }
+
+// Int represents a key
+type Int struct {
+	name        string
+	description string
+}
+
+// NewInt creates a new Key for int values.
+func NewInt(name, description string) *Int {
+	return &Int{name: name, description: description}
+}
+
+func (k *Int) Name() string        { return k.name }
+func (k *Int) Description() string { return k.description }
+
+func (k *Int) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Int) Of(v int) label.Label { return label.Of64(k, uint64(v)) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Int) Get(lm label.Map) int {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *Int) From(t label.Label) int { return int(t.Unpack64()) }
+
+// Int8 represents a key
+type Int8 struct {
+	name        string
+	description string
+}
+
+// NewInt8 creates a new Key for int8 values.
+func NewInt8(name, description string) *Int8 {
+	return &Int8{name: name, description: description}
+}
+
+func (k *Int8) Name() string        { return k.name }
+func (k *Int8) Description() string { return k.description }
+
+func (k *Int8) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Int8) Of(v int8) label.Label { return label.Of64(k, uint64(v)) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Int8) Get(lm label.Map) int8 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *Int8) From(t label.Label) int8 { return int8(t.Unpack64()) }
+
+// Int16 represents a key
+type Int16 struct {
+	name        string
+	description string
+}
+
+// NewInt16 creates a new Key for int16 values.
+func NewInt16(name, description string) *Int16 {
+	return &Int16{name: name, description: description}
+}
+
+func (k *Int16) Name() string        { return k.name }
+func (k *Int16) Description() string { return k.description }
+
+func (k *Int16) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Int16) Of(v int16) label.Label { return label.Of64(k, uint64(v)) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Int16) Get(lm label.Map) int16 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *Int16) From(t label.Label) int16 { return int16(t.Unpack64()) }
+
+// Int32 represents a key
+type Int32 struct {
+	name        string
+	description string
+}
+
+// NewInt32 creates a new Key for int32 values.
+func NewInt32(name, description string) *Int32 {
+	return &Int32{name: name, description: description}
+}
+
+func (k *Int32) Name() string        { return k.name }
+func (k *Int32) Description() string { return k.description }
+
+func (k *Int32) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendInt(buf, int64(k.From(l)), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Int32) Of(v int32) label.Label { return label.Of64(k, uint64(v)) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Int32) Get(lm label.Map) int32 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *Int32) From(t label.Label) int32 { return int32(t.Unpack64()) }
+
+// Int64 represents a key
+type Int64 struct {
+	name        string
+	description string
+}
+
+// NewInt64 creates a new Key for int64 values.
+func NewInt64(name, description string) *Int64 {
+	return &Int64{name: name, description: description}
+}
+
+func (k *Int64) Name() string        { return k.name }
+func (k *Int64) Description() string { return k.description }
+
+func (k *Int64) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendInt(buf, k.From(l), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Int64) Of(v int64) label.Label { return label.Of64(k, uint64(v)) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Int64) Get(lm label.Map) int64 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *Int64) From(t label.Label) int64 { return int64(t.Unpack64()) }
+
+// UInt represents a key
+type UInt struct {
+	name        string
+	description string
+}
+
+// NewUInt creates a new Key for uint values.
+func NewUInt(name, description string) *UInt {
+	return &UInt{name: name, description: description}
+}
+
+func (k *UInt) Name() string        { return k.name }
+func (k *UInt) Description() string { return k.description }
+
+func (k *UInt) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *UInt) Of(v uint) label.Label { return label.Of64(k, uint64(v)) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *UInt) Get(lm label.Map) uint {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *UInt) From(t label.Label) uint { return uint(t.Unpack64()) }
+
+// UInt8 represents a key
+type UInt8 struct {
+	name        string
+	description string
+}
+
+// NewUInt8 creates a new Key for uint8 values.
+func NewUInt8(name, description string) *UInt8 {
+	return &UInt8{name: name, description: description}
+}
+
+func (k *UInt8) Name() string        { return k.name }
+func (k *UInt8) Description() string { return k.description }
+
+func (k *UInt8) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *UInt8) Of(v uint8) label.Label { return label.Of64(k, uint64(v)) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *UInt8) Get(lm label.Map) uint8 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *UInt8) From(t label.Label) uint8 { return uint8(t.Unpack64()) }
+
+// UInt16 represents a key
+type UInt16 struct {
+	name        string
+	description string
+}
+
+// NewUInt16 creates a new Key for uint16 values.
+func NewUInt16(name, description string) *UInt16 {
+	return &UInt16{name: name, description: description}
+}
+
+func (k *UInt16) Name() string        { return k.name }
+func (k *UInt16) Description() string { return k.description }
+
+func (k *UInt16) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *UInt16) Of(v uint16) label.Label { return label.Of64(k, uint64(v)) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *UInt16) Get(lm label.Map) uint16 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *UInt16) From(t label.Label) uint16 { return uint16(t.Unpack64()) }
+
+// UInt32 represents a key
+type UInt32 struct {
+	name        string
+	description string
+}
+
+// NewUInt32 creates a new Key for uint32 values.
+func NewUInt32(name, description string) *UInt32 {
+	return &UInt32{name: name, description: description}
+}
+
+func (k *UInt32) Name() string        { return k.name }
+func (k *UInt32) Description() string { return k.description }
+
+func (k *UInt32) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendUint(buf, uint64(k.From(l)), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *UInt32) Of(v uint32) label.Label { return label.Of64(k, uint64(v)) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *UInt32) Get(lm label.Map) uint32 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *UInt32) From(t label.Label) uint32 { return uint32(t.Unpack64()) }
+
+// UInt64 represents a key
+type UInt64 struct {
+	name        string
+	description string
+}
+
+// NewUInt64 creates a new Key for uint64 values.
+func NewUInt64(name, description string) *UInt64 {
+	return &UInt64{name: name, description: description}
+}
+
+func (k *UInt64) Name() string        { return k.name }
+func (k *UInt64) Description() string { return k.description }
+
+func (k *UInt64) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendUint(buf, k.From(l), 10))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *UInt64) Of(v uint64) label.Label { return label.Of64(k, v) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *UInt64) Get(lm label.Map) uint64 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *UInt64) From(t label.Label) uint64 { return t.Unpack64() }
+
+// Float32 represents a key
+type Float32 struct {
+	name        string
+	description string
+}
+
+// NewFloat32 creates a new Key for float32 values.
+func NewFloat32(name, description string) *Float32 {
+	return &Float32{name: name, description: description}
+}
+
+func (k *Float32) Name() string        { return k.name }
+func (k *Float32) Description() string { return k.description }
+
+func (k *Float32) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendFloat(buf, float64(k.From(l)), 'E', -1, 32))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Float32) Of(v float32) label.Label {
+	return label.Of64(k, uint64(math.Float32bits(v)))
+}
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Float32) Get(lm label.Map) float32 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *Float32) From(t label.Label) float32 {
+	return math.Float32frombits(uint32(t.Unpack64()))
+}
+
+// Float64 represents a key
+type Float64 struct {
+	name        string
+	description string
+}
+
+// NewFloat64 creates a new Key for int64 values.
+func NewFloat64(name, description string) *Float64 {
+	return &Float64{name: name, description: description}
+}
+
+func (k *Float64) Name() string        { return k.name }
+func (k *Float64) Description() string { return k.description }
+
+func (k *Float64) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendFloat(buf, k.From(l), 'E', -1, 64))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Float64) Of(v float64) label.Label {
+	return label.Of64(k, math.Float64bits(v))
+}
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Float64) Get(lm label.Map) float64 {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return 0
+}
+
+// From can be used to get a value from a Label.
+func (k *Float64) From(t label.Label) float64 {
+	return math.Float64frombits(t.Unpack64())
+}
+
+// String represents a key
+type String struct {
+	name        string
+	description string
+}
+
+// NewString creates a new Key for int64 values.
+func NewString(name, description string) *String {
+	return &String{name: name, description: description}
+}
+
+func (k *String) Name() string        { return k.name }
+func (k *String) Description() string { return k.description }
+
+func (k *String) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendQuote(buf, k.From(l)))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *String) Of(v string) label.Label { return label.OfString(k, v) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *String) Get(lm label.Map) string {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return ""
+}
+
+// From can be used to get a value from a Label.
+func (k *String) From(t label.Label) string { return t.UnpackString() }
+
+// Boolean represents a key
+type Boolean struct {
+	name        string
+	description string
+}
+
+// NewBoolean creates a new Key for bool values.
+func NewBoolean(name, description string) *Boolean {
+	return &Boolean{name: name, description: description}
+}
+
+func (k *Boolean) Name() string        { return k.name }
+func (k *Boolean) Description() string { return k.description }
+
+func (k *Boolean) Format(w io.Writer, buf []byte, l label.Label) {
+	w.Write(strconv.AppendBool(buf, k.From(l)))
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Boolean) Of(v bool) label.Label {
+	if v {
+		return label.Of64(k, 1)
+	}
+	return label.Of64(k, 0)
+}
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Boolean) Get(lm label.Map) bool {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return false
+}
+
+// From can be used to get a value from a Label.
+func (k *Boolean) From(t label.Label) bool { return t.Unpack64() > 0 }
+
+// Error represents a key
+type Error struct {
+	name        string
+	description string
+}
+
+// NewError creates a new Key for int64 values.
+func NewError(name, description string) *Error {
+	return &Error{name: name, description: description}
+}
+
+func (k *Error) Name() string        { return k.name }
+func (k *Error) Description() string { return k.description }
+
+func (k *Error) Format(w io.Writer, buf []byte, l label.Label) {
+	io.WriteString(w, k.From(l).Error())
+}
+
+// Of creates a new Label with this key and the supplied value.
+func (k *Error) Of(v error) label.Label { return label.OfValue(k, v) }
+
+// Get can be used to get a label for the key from a label.Map.
+func (k *Error) Get(lm label.Map) error {
+	if t := lm.Find(k); t.Valid() {
+		return k.From(t)
+	}
+	return nil
+}
+
+// From can be used to get a value from a Label.
+func (k *Error) From(t label.Label) error {
+	err, _ := t.UnpackValue().(error)
+	return err
+}
diff --git a/vendor/golang.org/x/tools/internal/event/keys/standard.go b/vendor/golang.org/x/tools/internal/event/keys/standard.go
new file mode 100644
index 000000000..59516c256
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/event/keys/standard.go
@@ -0,0 +1,14 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package keys
+
+var (
+	// Msg is a key used to add message strings to label lists.
+	Msg = NewString("message", "a readable message")
+	// Name is used for things like traces that have a name.
+	Name = NewString("name", "an entity name")
+	// Err is a key used to add error values to label lists.
+	Err = NewError("error", "an error that occurred")
+)
diff --git a/vendor/golang.org/x/tools/internal/event/label/label.go b/vendor/golang.org/x/tools/internal/event/label/label.go
new file mode 100644
index 000000000..b55c12eb2
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/event/label/label.go
@@ -0,0 +1,213 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package label
+
+import (
+	"fmt"
+	"io"
+	"reflect"
+	"unsafe"
+)
+
+// Key is used as the identity of a Label.
+// Keys are intended to be compared by pointer only, the name should be unique
+// for communicating with external systems, but it is not required or enforced.
+type Key interface {
+	// Name returns the key name.
+	Name() string
+	// Description returns a string that can be used to describe the value.
+	Description() string
+
+	// Format is used in formatting to append the value of the label to the
+	// supplied buffer.
+	// The formatter may use the supplied buf as a scratch area to avoid
+	// allocations.
+	Format(w io.Writer, buf []byte, l Label)
+}
+
+// Label holds a key and value pair.
+// It is normally used when passing around lists of labels.
+type Label struct {
+	key     Key
+	packed  uint64
+	untyped interface{}
+}
+
+// Map is the interface to a collection of Labels indexed by key.
+type Map interface {
+	// Find returns the label that matches the supplied key.
+	Find(key Key) Label
+}
+
+// List is the interface to something that provides an iterable
+// list of labels.
+// Iteration should start from 0 and continue until Valid returns false.
+type List interface {
+	// Valid returns true if the index is within range for the list.
+	// It does not imply the label at that index will itself be valid.
+	Valid(index int) bool
+	// Label returns the label at the given index.
+	Label(index int) Label
+}
+
+// list implements LabelList for a list of Labels.
+type list struct {
+	labels []Label
+}
+
+// filter wraps a LabelList filtering out specific labels.
+type filter struct {
+	keys       []Key
+	underlying List
+}
+
+// listMap implements LabelMap for a simple list of labels.
+type listMap struct {
+	labels []Label
+}
+
+// mapChain implements LabelMap for a list of underlying LabelMap.
+type mapChain struct {
+	maps []Map
+}
+
+// OfValue creates a new label from the key and value.
+// This method is for implementing new key types, label creation should
+// normally be done with the Of method of the key.
+func OfValue(k Key, value interface{}) Label { return Label{key: k, untyped: value} }
+
+// UnpackValue assumes the label was built using LabelOfValue and returns the value
+// that was passed to that constructor.
+// This method is for implementing new key types, for type safety normal
+// access should be done with the From method of the key.
+func (t Label) UnpackValue() interface{} { return t.untyped }
+
+// Of64 creates a new label from a key and a uint64. This is often
+// used for non uint64 values that can be packed into a uint64.
+// This method is for implementing new key types, label creation should
+// normally be done with the Of method of the key.
+func Of64(k Key, v uint64) Label { return Label{key: k, packed: v} }
+
+// Unpack64 assumes the label was built using LabelOf64 and returns the value that
+// was passed to that constructor.
+// This method is for implementing new key types, for type safety normal
+// access should be done with the From method of the key.
+func (t Label) Unpack64() uint64 { return t.packed }
+
+// OfString creates a new label from a key and a string.
+// This method is for implementing new key types, label creation should
+// normally be done with the Of method of the key.
+func OfString(k Key, v string) Label {
+	hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
+	return Label{
+		key:     k,
+		packed:  uint64(hdr.Len),
+		untyped: unsafe.Pointer(hdr.Data),
+	}
+}
+
+// UnpackString assumes the label was built using LabelOfString and returns the
+// value that was passed to that constructor.
+// This method is for implementing new key types, for type safety normal
+// access should be done with the From method of the key.
+func (t Label) UnpackString() string {
+	var v string
+	hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
+	hdr.Data = uintptr(t.untyped.(unsafe.Pointer))
+	hdr.Len = int(t.packed)
+	return *(*string)(unsafe.Pointer(hdr))
+}
+
+// Valid returns true if the Label is a valid one (it has a key).
+func (t Label) Valid() bool { return t.key != nil }
+
+// Key returns the key of this Label.
+func (t Label) Key() Key { return t.key }
+
+// Format is used for debug printing of labels.
+func (t Label) Format(f fmt.State, r rune) {
+	if !t.Valid() {
+		io.WriteString(f, `nil`)
+		return
+	}
+	io.WriteString(f, t.Key().Name())
+	io.WriteString(f, "=")
+	var buf [128]byte
+	t.Key().Format(f, buf[:0], t)
+}
+
+func (l *list) Valid(index int) bool {
+	return index >= 0 && index < len(l.labels)
+}
+
+func (l *list) Label(index int) Label {
+	return l.labels[index]
+}
+
+func (f *filter) Valid(index int) bool {
+	return f.underlying.Valid(index)
+}
+
+func (f *filter) Label(index int) Label {
+	l := f.underlying.Label(index)
+	for _, f := range f.keys {
+		if l.Key() == f {
+			return Label{}
+		}
+	}
+	return l
+}
+
+func (lm listMap) Find(key Key) Label {
+	for _, l := range lm.labels {
+		if l.Key() == key {
+			return l
+		}
+	}
+	return Label{}
+}
+
+func (c mapChain) Find(key Key) Label {
+	for _, src := range c.maps {
+		l := src.Find(key)
+		if l.Valid() {
+			return l
+		}
+	}
+	return Label{}
+}
+
+var emptyList = &list{}
+
+func NewList(labels ...Label) List {
+	if len(labels) == 0 {
+		return emptyList
+	}
+	return &list{labels: labels}
+}
+
+func Filter(l List, keys ...Key) List {
+	if len(keys) == 0 {
+		return l
+	}
+	return &filter{keys: keys, underlying: l}
+}
+
+func NewMap(labels ...Label) Map {
+	return listMap{labels: labels}
+}
+
+func MergeMaps(srcs ...Map) Map {
+	var nonNil []Map
+	for _, src := range srcs {
+		if src != nil {
+			nonNil = append(nonNil, src)
+		}
+	}
+	if len(nonNil) == 1 {
+		return nonNil[0]
+	}
+	return mapChain{maps: nonNil}
+}
diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
index 5b1341270..9aa798456 100644
--- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go
+++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
@@ -17,7 +17,7 @@ import (
 	"sync"
 	"time"
 
-	"golang.org/x/tools/internal/telemetry/event"
+	"golang.org/x/tools/internal/event"
 )
 
 // An Runner will run go command invocations and serialize
@@ -39,7 +39,7 @@ func (runner *Runner) Run(ctx context.Context, inv Invocation) (*bytes.Buffer, e
 	return stdout, friendly
 }
 
-// Run calls Innvocation.RunRaw, serializing requests if they fight over
+// RunRaw calls Invocation.runRaw, serializing requests if they fight over
 // go.mod changes.
 func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {
 	// We want to run invocations concurrently as much as possible. However,
@@ -93,6 +93,7 @@ func (i *Invocation) runRaw(ctx context.Context) (stdout *bytes.Buffer, stderr *
 	stderr = &bytes.Buffer{}
 	rawError = i.RunPiped(ctx, stdout, stderr)
 	if rawError != nil {
+		friendlyError = rawError
 		// Check for 'go' executable not being found.
 		if ee, ok := rawError.(*exec.Error); ok && ee.Err == exec.ErrNotFound {
 			friendlyError = fmt.Errorf("go command required, not found: %v", ee)
@@ -100,7 +101,7 @@ func (i *Invocation) runRaw(ctx context.Context) (stdout *bytes.Buffer, stderr *
 		if ctx.Err() != nil {
 			friendlyError = ctx.Err()
 		}
-		friendlyError = fmt.Errorf("err: %v: stderr: %s", rawError, stderr)
+		friendlyError = fmt.Errorf("err: %v: stderr: %s", friendlyError, stderr)
 	}
 	return
 }
diff --git a/vendor/golang.org/x/tools/internal/imports/zstdlib.go b/vendor/golang.org/x/tools/internal/imports/zstdlib.go
index 7e60eb04e..16252111f 100644
--- a/vendor/golang.org/x/tools/internal/imports/zstdlib.go
+++ b/vendor/golang.org/x/tools/internal/imports/zstdlib.go
@@ -415,6 +415,9 @@ var stdlib = map[string][]string{
 	"crypto/tls": []string{
 		"Certificate",
 		"CertificateRequestInfo",
+		"CipherSuite",
+		"CipherSuiteName",
+		"CipherSuites",
 		"Client",
 		"ClientAuthType",
 		"ClientHelloInfo",
@@ -434,6 +437,7 @@ var stdlib = map[string][]string{
 		"ECDSAWithP521AndSHA512",
 		"ECDSAWithSHA1",
 		"Ed25519",
+		"InsecureCipherSuites",
 		"Listen",
 		"LoadX509KeyPair",
 		"NewLRUClientSessionCache",
@@ -465,6 +469,7 @@ var stdlib = map[string][]string{
 		"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
 		"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
 		"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
+		"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
 		"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
 		"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
 		"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
@@ -473,6 +478,7 @@ var stdlib = map[string][]string{
 		"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
 		"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
 		"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
+		"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
 		"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
 		"TLS_FALLBACK_SCSV",
 		"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
@@ -698,36 +704,65 @@ var stdlib = map[string][]string{
 		"Attr",
 		"AttrAbstractOrigin",
 		"AttrAccessibility",
+		"AttrAddrBase",
 		"AttrAddrClass",
+		"AttrAlignment",
 		"AttrAllocated",
 		"AttrArtificial",
 		"AttrAssociated",
 		"AttrBaseTypes",
+		"AttrBinaryScale",
 		"AttrBitOffset",
 		"AttrBitSize",
 		"AttrByteSize",
+		"AttrCallAllCalls",
+		"AttrCallAllSourceCalls",
+		"AttrCallAllTailCalls",
 		"AttrCallColumn",
+		"AttrCallDataLocation",
+		"AttrCallDataValue",
 		"AttrCallFile",
 		"AttrCallLine",
+		"AttrCallOrigin",
+		"AttrCallPC",
+		"AttrCallParameter",
+		"AttrCallReturnPC",
+		"AttrCallTailCall",
+		"AttrCallTarget",
+		"AttrCallTargetClobbered",
+		"AttrCallValue",
 		"AttrCalling",
 		"AttrCommonRef",
 		"AttrCompDir",
+		"AttrConstExpr",
 		"AttrConstValue",
 		"AttrContainingType",
 		"AttrCount",
+		"AttrDataBitOffset",
 		"AttrDataLocation",
 		"AttrDataMemberLoc",
+		"AttrDecimalScale",
+		"AttrDecimalSign",
 		"AttrDeclColumn",
 		"AttrDeclFile",
 		"AttrDeclLine",
 		"AttrDeclaration",
 		"AttrDefaultValue",
+		"AttrDefaulted",
+		"AttrDeleted",
 		"AttrDescription",
+		"AttrDigitCount",
 		"AttrDiscr",
 		"AttrDiscrList",
 		"AttrDiscrValue",
+		"AttrDwoName",
+		"AttrElemental",
 		"AttrEncoding",
+		"AttrEndianity",
 		"AttrEntrypc",
+		"AttrEnumClass",
+		"AttrExplicit",
+		"AttrExportSymbols",
 		"AttrExtension",
 		"AttrExternal",
 		"AttrFrameBase",
@@ -738,27 +773,47 @@ var stdlib = map[string][]string{
 		"AttrInline",
 		"AttrIsOptional",
 		"AttrLanguage",
+		"AttrLinkageName",
 		"AttrLocation",
+		"AttrLoclistsBase",
 		"AttrLowerBound",
 		"AttrLowpc",
 		"AttrMacroInfo",
+		"AttrMacros",
+		"AttrMainSubprogram",
+		"AttrMutable",
 		"AttrName",
 		"AttrNamelistItem",
+		"AttrNoreturn",
+		"AttrObjectPointer",
 		"AttrOrdering",
+		"AttrPictureString",
 		"AttrPriority",
 		"AttrProducer",
 		"AttrPrototyped",
+		"AttrPure",
 		"AttrRanges",
+		"AttrRank",
+		"AttrRecursive",
+		"AttrReference",
 		"AttrReturnAddr",
+		"AttrRnglistsBase",
+		"AttrRvalueReference",
 		"AttrSegment",
 		"AttrSibling",
+		"AttrSignature",
+		"AttrSmall",
 		"AttrSpecification",
 		"AttrStartScope",
 		"AttrStaticLink",
 		"AttrStmtList",
+		"AttrStrOffsetsBase",
 		"AttrStride",
 		"AttrStrideSize",
 		"AttrStringLength",
+		"AttrStringLengthBitSize",
+		"AttrStringLengthByteSize",
+		"AttrThreadsScaled",
 		"AttrTrampoline",
 		"AttrType",
 		"AttrUpperBound",
@@ -772,18 +827,23 @@ var stdlib = map[string][]string{
 		"BoolType",
 		"CharType",
 		"Class",
+		"ClassAddrPtr",
 		"ClassAddress",
 		"ClassBlock",
 		"ClassConstant",
 		"ClassExprLoc",
 		"ClassFlag",
 		"ClassLinePtr",
+		"ClassLocList",
 		"ClassLocListPtr",
 		"ClassMacPtr",
 		"ClassRangeListPtr",
 		"ClassReference",
 		"ClassReferenceAlt",
 		"ClassReferenceSig",
+		"ClassRngList",
+		"ClassRngListsPtr",
+		"ClassStrOffsetsPtr",
 		"ClassString",
 		"ClassStringAlt",
 		"ClassUnknown",
@@ -814,9 +874,13 @@ var stdlib = map[string][]string{
 		"Tag",
 		"TagAccessDeclaration",
 		"TagArrayType",
+		"TagAtomicType",
 		"TagBaseType",
+		"TagCallSite",
+		"TagCallSiteParameter",
 		"TagCatchDwarfBlock",
 		"TagClassType",
+		"TagCoarrayType",
 		"TagCommonDwarfBlock",
 		"TagCommonInclusion",
 		"TagCompileUnit",
@@ -824,12 +888,15 @@ var stdlib = map[string][]string{
 		"TagConstType",
 		"TagConstant",
 		"TagDwarfProcedure",
+		"TagDynamicType",
 		"TagEntryPoint",
 		"TagEnumerationType",
 		"TagEnumerator",
 		"TagFileType",
 		"TagFormalParameter",
 		"TagFriend",
+		"TagGenericSubrange",
+		"TagImmutableType",
 		"TagImportedDeclaration",
 		"TagImportedModule",
 		"TagImportedUnit",
@@ -853,6 +920,7 @@ var stdlib = map[string][]string{
 		"TagRvalueReferenceType",
 		"TagSetType",
 		"TagSharedType",
+		"TagSkeletonUnit",
 		"TagStringType",
 		"TagStructType",
 		"TagSubprogram",
@@ -2359,6 +2427,7 @@ var stdlib = map[string][]string{
 		"RawValue",
 		"StructuralError",
 		"SyntaxError",
+		"TagBMPString",
 		"TagBitString",
 		"TagBoolean",
 		"TagEnum",
@@ -2787,6 +2856,7 @@ var stdlib = map[string][]string{
 		"IsPredeclared",
 		"Mode",
 		"New",
+		"NewFromFiles",
 		"Note",
 		"Package",
 		"PreserveAST",
@@ -3115,6 +3185,11 @@ var stdlib = map[string][]string{
 		"New64",
 		"New64a",
 	},
+	"hash/maphash": []string{
+		"Hash",
+		"MakeSeed",
+		"Seed",
+	},
 	"html": []string{
 		"EscapeString",
 		"UnescapeString",
@@ -3367,6 +3442,7 @@ var stdlib = map[string][]string{
 		"Ldate",
 		"Llongfile",
 		"Lmicroseconds",
+		"Lmsgprefix",
 		"Logger",
 		"Lshortfile",
 		"LstdFlags",
@@ -3443,6 +3519,7 @@ var stdlib = map[string][]string{
 		"Exp",
 		"Exp2",
 		"Expm1",
+		"FMA",
 		"Float32bits",
 		"Float32frombits",
 		"Float64bits",
@@ -3567,6 +3644,9 @@ var stdlib = map[string][]string{
 		"OnesCount32",
 		"OnesCount64",
 		"OnesCount8",
+		"Rem",
+		"Rem32",
+		"Rem64",
 		"Reverse",
 		"Reverse16",
 		"Reverse32",
@@ -5140,7 +5220,10 @@ var stdlib = map[string][]string{
 		"CTL_NET",
 		"CTL_QUERY",
 		"CTRL_BREAK_EVENT",
+		"CTRL_CLOSE_EVENT",
 		"CTRL_C_EVENT",
+		"CTRL_LOGOFF_EVENT",
+		"CTRL_SHUTDOWN_EVENT",
 		"CancelIo",
 		"CancelIoEx",
 		"CertAddCertificateContextToStore",
@@ -10112,6 +10195,7 @@ var stdlib = map[string][]string{
 		"Duployan",
 		"Egyptian_Hieroglyphs",
 		"Elbasan",
+		"Elymaic",
 		"Ethiopic",
 		"Extender",
 		"FoldCategory",
@@ -10215,6 +10299,7 @@ var stdlib = map[string][]string{
 		"Myanmar",
 		"N",
 		"Nabataean",
+		"Nandinagari",
 		"Nd",
 		"New_Tai_Lue",
 		"Newa",
@@ -10224,6 +10309,7 @@ var stdlib = map[string][]string{
 		"Noncharacter_Code_Point",
 		"Number",
 		"Nushu",
+		"Nyiakeng_Puachue_Hmong",
 		"Ogham",
 		"Ol_Chiki",
 		"Old_Hungarian",
@@ -10331,6 +10417,7 @@ var stdlib = map[string][]string{
 		"Vai",
 		"Variation_Selector",
 		"Version",
+		"Wancho",
 		"Warang_Citi",
 		"White_Space",
 		"Yi",
diff --git a/vendor/golang.org/x/tools/internal/telemetry/event/event.go b/vendor/golang.org/x/tools/internal/telemetry/event/event.go
deleted file mode 100644
index 2b990c5c1..000000000
--- a/vendor/golang.org/x/tools/internal/telemetry/event/event.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package event provides support for event based telemetry.
-package event
-
-import (
-	"fmt"
-	"time"
-)
-
-type eventType uint8
-
-const (
-	invalidType   = eventType(iota)
-	LogType       // an event that should be recorded in a log
-	StartSpanType // the start of a span of time
-	EndSpanType   // the end of a span of time
-	LabelType     // some values that should be noted for later events
-	DetachType    // an event that causes a context to detach
-	RecordType    // a value that should be tracked
-)
-
-// sTags is used to hold a small number of tags inside an event whichout
-// requiring a separate allocation.
-// As tags are often on the stack, this avoids an allocation at all for
-// the very common cases of simple events.
-// The length needs to be large enough to cope with the majority of events
-// but no so large as to cause undue stack pressure.
-// A log message with two values will use 3 tags (one for each value and
-// one for the message itself).
-type sTags [3]Tag
-
-// Event holds the information about an event of note that ocurred.
-type Event struct {
-	At time.Time
-
-	typ     eventType
-	static  sTags // inline storage for the first few tags
-	dynamic []Tag // dynamically sized storage for remaining tags
-}
-
-// eventTagMap implements TagMap for a the tags of an Event.
-type eventTagMap struct {
-	event Event
-}
-
-func (ev Event) IsLog() bool       { return ev.typ == LogType }
-func (ev Event) IsEndSpan() bool   { return ev.typ == EndSpanType }
-func (ev Event) IsStartSpan() bool { return ev.typ == StartSpanType }
-func (ev Event) IsLabel() bool     { return ev.typ == LabelType }
-func (ev Event) IsDetach() bool    { return ev.typ == DetachType }
-func (ev Event) IsRecord() bool    { return ev.typ == RecordType }
-
-func (ev Event) Format(f fmt.State, r rune) {
-	tagMap := TagMap(ev)
-	if !ev.At.IsZero() {
-		fmt.Fprint(f, ev.At.Format("2006/01/02 15:04:05 "))
-	}
-	msg := Msg.Get(tagMap)
-	err := Err.Get(tagMap)
-	fmt.Fprint(f, msg)
-	if err != nil {
-		if f.Flag('+') {
-			fmt.Fprintf(f, ": %+v", err)
-		} else {
-			fmt.Fprintf(f, ": %v", err)
-		}
-	}
-	for index := 0; ev.Valid(index); index++ {
-		tag := ev.Tag(index)
-		// msg and err were both already printed above, so we skip them to avoid
-		// double printing
-		if !tag.Valid() || tag.Key() == Msg || tag.Key() == Err {
-			continue
-		}
-		fmt.Fprintf(f, "\n\t%v", tag)
-	}
-}
-
-func (ev Event) Valid(index int) bool {
-	return index >= 0 && index < len(ev.static)+len(ev.dynamic)
-}
-
-func (ev Event) Tag(index int) Tag {
-	if index < len(ev.static) {
-		return ev.static[index]
-	}
-	return ev.dynamic[index-len(ev.static)]
-}
-
-func (ev Event) Find(key Key) Tag {
-	for _, tag := range ev.static {
-		if tag.Key() == key {
-			return tag
-		}
-	}
-	for _, tag := range ev.dynamic {
-		if tag.Key() == key {
-			return tag
-		}
-	}
-	return Tag{}
-}
-
-func makeEvent(typ eventType, static sTags, tags []Tag) Event {
-	return Event{
-		typ:     typ,
-		static:  static,
-		dynamic: tags,
-	}
-}
diff --git a/vendor/golang.org/x/tools/internal/telemetry/event/key.go b/vendor/golang.org/x/tools/internal/telemetry/event/key.go
deleted file mode 100644
index acde7511e..000000000
--- a/vendor/golang.org/x/tools/internal/telemetry/event/key.go
+++ /dev/null
@@ -1,565 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package event
-
-import (
-	"fmt"
-	"io"
-	"math"
-	"strconv"
-)
-
-var (
-	// Msg is a key used to add message strings to tag lists.
-	Msg = NewStringKey("message", "a readable message")
-	// Name is used for things like traces that have a name.
-	Name = NewStringKey("name", "an entity name")
-	// Err is a key used to add error values to tag lists.
-	Err = NewErrorKey("error", "an error that occurred")
-)
-
-// Key is used as the identity of a Tag.
-// Keys are intended to be compared by pointer only, the name should be unique
-// for communicating with external systems, but it is not required or enforced.
-type Key interface {
-	// Name returns the key name.
-	Name() string
-	// Description returns a string that can be used to describe the value.
-	Description() string
-
-	// Format is used in formatting to append the value of the tag to the
-	// supplied buffer.
-	// The formatter may use the supplied buf as a scratch area to avoid
-	// allocations.
-	Format(w io.Writer, buf []byte, tag Tag)
-}
-
-// ValueKey represents a key for untyped values.
-type ValueKey struct {
-	name        string
-	description string
-}
-
-// NewKey creates a new Key for untyped values.
-func NewKey(name, description string) *ValueKey {
-	return &ValueKey{name: name, description: description}
-}
-
-func (k *ValueKey) Name() string        { return k.name }
-func (k *ValueKey) Description() string { return k.description }
-
-func (k *ValueKey) Format(w io.Writer, buf []byte, tag Tag) {
-	fmt.Fprint(w, k.From(tag))
-}
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *ValueKey) Get(tags TagMap) interface{} {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return nil
-}
-
-// From can be used to get a value from a Tag.
-func (k *ValueKey) From(t Tag) interface{} { return t.UnpackValue() }
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *ValueKey) Of(value interface{}) Tag { return TagOfValue(k, value) }
-
-// IntKey represents a key
-type IntKey struct {
-	name        string
-	description string
-}
-
-// NewIntKey creates a new Key for int values.
-func NewIntKey(name, description string) *IntKey {
-	return &IntKey{name: name, description: description}
-}
-
-func (k *IntKey) Name() string        { return k.name }
-func (k *IntKey) Description() string { return k.description }
-
-func (k *IntKey) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendInt(buf, int64(k.From(tag)), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *IntKey) Of(v int) Tag { return TagOf64(k, uint64(v)) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *IntKey) Get(tags TagMap) int {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *IntKey) From(t Tag) int { return int(t.Unpack64()) }
-
-// Int8Key represents a key
-type Int8Key struct {
-	name        string
-	description string
-}
-
-// NewInt8Key creates a new Key for int8 values.
-func NewInt8Key(name, description string) *Int8Key {
-	return &Int8Key{name: name, description: description}
-}
-
-func (k *Int8Key) Name() string        { return k.name }
-func (k *Int8Key) Description() string { return k.description }
-
-func (k *Int8Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendInt(buf, int64(k.From(tag)), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *Int8Key) Of(v int8) Tag { return TagOf64(k, uint64(v)) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *Int8Key) Get(tags TagMap) int8 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *Int8Key) From(t Tag) int8 { return int8(t.Unpack64()) }
-
-// Int16Key represents a key
-type Int16Key struct {
-	name        string
-	description string
-}
-
-// NewInt16Key creates a new Key for int16 values.
-func NewInt16Key(name, description string) *Int16Key {
-	return &Int16Key{name: name, description: description}
-}
-
-func (k *Int16Key) Name() string        { return k.name }
-func (k *Int16Key) Description() string { return k.description }
-
-func (k *Int16Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendInt(buf, int64(k.From(tag)), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *Int16Key) Of(v int16) Tag { return TagOf64(k, uint64(v)) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *Int16Key) Get(tags TagMap) int16 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *Int16Key) From(t Tag) int16 { return int16(t.Unpack64()) }
-
-// Int32Key represents a key
-type Int32Key struct {
-	name        string
-	description string
-}
-
-// NewInt32Key creates a new Key for int32 values.
-func NewInt32Key(name, description string) *Int32Key {
-	return &Int32Key{name: name, description: description}
-}
-
-func (k *Int32Key) Name() string        { return k.name }
-func (k *Int32Key) Description() string { return k.description }
-
-func (k *Int32Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendInt(buf, int64(k.From(tag)), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *Int32Key) Of(v int32) Tag { return TagOf64(k, uint64(v)) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *Int32Key) Get(tags TagMap) int32 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *Int32Key) From(t Tag) int32 { return int32(t.Unpack64()) }
-
-// Int64Key represents a key
-type Int64Key struct {
-	name        string
-	description string
-}
-
-// NewInt64Key creates a new Key for int64 values.
-func NewInt64Key(name, description string) *Int64Key {
-	return &Int64Key{name: name, description: description}
-}
-
-func (k *Int64Key) Name() string        { return k.name }
-func (k *Int64Key) Description() string { return k.description }
-
-func (k *Int64Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendInt(buf, k.From(tag), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *Int64Key) Of(v int64) Tag { return TagOf64(k, uint64(v)) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *Int64Key) Get(tags TagMap) int64 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *Int64Key) From(t Tag) int64 { return int64(t.Unpack64()) }
-
-// UIntKey represents a key
-type UIntKey struct {
-	name        string
-	description string
-}
-
-// NewUIntKey creates a new Key for uint values.
-func NewUIntKey(name, description string) *UIntKey {
-	return &UIntKey{name: name, description: description}
-}
-
-func (k *UIntKey) Name() string        { return k.name }
-func (k *UIntKey) Description() string { return k.description }
-
-func (k *UIntKey) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendUint(buf, uint64(k.From(tag)), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *UIntKey) Of(v uint) Tag { return TagOf64(k, uint64(v)) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *UIntKey) Get(tags TagMap) uint {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *UIntKey) From(t Tag) uint { return uint(t.Unpack64()) }
-
-// UInt8Key represents a key
-type UInt8Key struct {
-	name        string
-	description string
-}
-
-// NewUInt8Key creates a new Key for uint8 values.
-func NewUInt8Key(name, description string) *UInt8Key {
-	return &UInt8Key{name: name, description: description}
-}
-
-func (k *UInt8Key) Name() string        { return k.name }
-func (k *UInt8Key) Description() string { return k.description }
-
-func (k *UInt8Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendUint(buf, uint64(k.From(tag)), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *UInt8Key) Of(v uint8) Tag { return TagOf64(k, uint64(v)) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *UInt8Key) Get(tags TagMap) uint8 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *UInt8Key) From(t Tag) uint8 { return uint8(t.Unpack64()) }
-
-// UInt16Key represents a key
-type UInt16Key struct {
-	name        string
-	description string
-}
-
-// NewUInt16Key creates a new Key for uint16 values.
-func NewUInt16Key(name, description string) *UInt16Key {
-	return &UInt16Key{name: name, description: description}
-}
-
-func (k *UInt16Key) Name() string        { return k.name }
-func (k *UInt16Key) Description() string { return k.description }
-
-func (k *UInt16Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendUint(buf, uint64(k.From(tag)), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *UInt16Key) Of(v uint16) Tag { return TagOf64(k, uint64(v)) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *UInt16Key) Get(tags TagMap) uint16 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *UInt16Key) From(t Tag) uint16 { return uint16(t.Unpack64()) }
-
-// UInt32Key represents a key
-type UInt32Key struct {
-	name        string
-	description string
-}
-
-// NewUInt32Key creates a new Key for uint32 values.
-func NewUInt32Key(name, description string) *UInt32Key {
-	return &UInt32Key{name: name, description: description}
-}
-
-func (k *UInt32Key) Name() string        { return k.name }
-func (k *UInt32Key) Description() string { return k.description }
-
-func (k *UInt32Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendUint(buf, uint64(k.From(tag)), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *UInt32Key) Of(v uint32) Tag { return TagOf64(k, uint64(v)) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *UInt32Key) Get(tags TagMap) uint32 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *UInt32Key) From(t Tag) uint32 { return uint32(t.Unpack64()) }
-
-// UInt64Key represents a key
-type UInt64Key struct {
-	name        string
-	description string
-}
-
-// NewUInt64Key creates a new Key for uint64 values.
-func NewUInt64Key(name, description string) *UInt64Key {
-	return &UInt64Key{name: name, description: description}
-}
-
-func (k *UInt64Key) Name() string        { return k.name }
-func (k *UInt64Key) Description() string { return k.description }
-
-func (k *UInt64Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendUint(buf, k.From(tag), 10))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *UInt64Key) Of(v uint64) Tag { return TagOf64(k, v) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *UInt64Key) Get(tags TagMap) uint64 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *UInt64Key) From(t Tag) uint64 { return t.Unpack64() }
-
-// Float32Key represents a key
-type Float32Key struct {
-	name        string
-	description string
-}
-
-// NewFloat32Key creates a new Key for float32 values.
-func NewFloat32Key(name, description string) *Float32Key {
-	return &Float32Key{name: name, description: description}
-}
-
-func (k *Float32Key) Name() string        { return k.name }
-func (k *Float32Key) Description() string { return k.description }
-
-func (k *Float32Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendFloat(buf, float64(k.From(tag)), 'E', -1, 32))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *Float32Key) Of(v float32) Tag {
-	return TagOf64(k, uint64(math.Float32bits(v)))
-}
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *Float32Key) Get(tags TagMap) float32 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *Float32Key) From(t Tag) float32 {
-	return math.Float32frombits(uint32(t.Unpack64()))
-}
-
-// Float64Key represents a key
-type Float64Key struct {
-	name        string
-	description string
-}
-
-// NewFloat64Key creates a new Key for int64 values.
-func NewFloat64Key(name, description string) *Float64Key {
-	return &Float64Key{name: name, description: description}
-}
-
-func (k *Float64Key) Name() string        { return k.name }
-func (k *Float64Key) Description() string { return k.description }
-
-func (k *Float64Key) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendFloat(buf, k.From(tag), 'E', -1, 64))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *Float64Key) Of(v float64) Tag {
-	return TagOf64(k, math.Float64bits(v))
-}
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *Float64Key) Get(tags TagMap) float64 {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return 0
-}
-
-// From can be used to get a value from a Tag.
-func (k *Float64Key) From(t Tag) float64 {
-	return math.Float64frombits(t.Unpack64())
-}
-
-// StringKey represents a key
-type StringKey struct {
-	name        string
-	description string
-}
-
-// NewStringKey creates a new Key for int64 values.
-func NewStringKey(name, description string) *StringKey {
-	return &StringKey{name: name, description: description}
-}
-
-func (k *StringKey) Name() string        { return k.name }
-func (k *StringKey) Description() string { return k.description }
-
-func (k *StringKey) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendQuote(buf, k.From(tag)))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *StringKey) Of(v string) Tag { return TagOfString(k, v) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *StringKey) Get(tags TagMap) string {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return ""
-}
-
-// From can be used to get a value from a Tag.
-func (k *StringKey) From(t Tag) string { return t.UnpackString() }
-
-// BooleanKey represents a key
-type BooleanKey struct {
-	name        string
-	description string
-}
-
-// NewBooleanKey creates a new Key for bool values.
-func NewBooleanKey(name, description string) *BooleanKey {
-	return &BooleanKey{name: name, description: description}
-}
-
-func (k *BooleanKey) Name() string        { return k.name }
-func (k *BooleanKey) Description() string { return k.description }
-
-func (k *BooleanKey) Format(w io.Writer, buf []byte, tag Tag) {
-	w.Write(strconv.AppendBool(buf, k.From(tag)))
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *BooleanKey) Of(v bool) Tag {
-	if v {
-		return TagOf64(k, 1)
-	}
-	return TagOf64(k, 0)
-}
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *BooleanKey) Get(tags TagMap) bool {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return false
-}
-
-// From can be used to get a value from a Tag.
-func (k *BooleanKey) From(t Tag) bool { return t.Unpack64() > 0 }
-
-// ErrorKey represents a key
-type ErrorKey struct {
-	name        string
-	description string
-}
-
-// NewErrorKey creates a new Key for int64 values.
-func NewErrorKey(name, description string) *ErrorKey {
-	return &ErrorKey{name: name, description: description}
-}
-
-func (k *ErrorKey) Name() string        { return k.name }
-func (k *ErrorKey) Description() string { return k.description }
-
-func (k *ErrorKey) Format(w io.Writer, buf []byte, tag Tag) {
-	io.WriteString(w, k.From(tag).Error())
-}
-
-// Of creates a new Tag with this key and the supplied value.
-func (k *ErrorKey) Of(v error) Tag { return TagOfValue(k, v) }
-
-// Get can be used to get a tag for the key from a TagMap.
-func (k *ErrorKey) Get(tags TagMap) error {
-	if t := tags.Find(k); t.Valid() {
-		return k.From(t)
-	}
-	return nil
-}
-
-// From can be used to get a value from a Tag.
-func (k *ErrorKey) From(t Tag) error {
-	err, _ := t.UnpackValue().(error)
-	return err
-}
diff --git a/vendor/golang.org/x/tools/internal/telemetry/event/label.go b/vendor/golang.org/x/tools/internal/telemetry/event/label.go
deleted file mode 100644
index edd34bb08..000000000
--- a/vendor/golang.org/x/tools/internal/telemetry/event/label.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package event
-
-import (
-	"context"
-)
-
-// Label sends a label event to the exporter with the supplied tags.
-func Label(ctx context.Context, tags ...Tag) context.Context {
-	return dispatch(ctx, makeEvent(LabelType, sTags{}, tags))
-}
-
-// Label1 sends a label event to the exporter with the supplied tags.
-func Label1(ctx context.Context, t1 Tag) context.Context {
-	return dispatch(ctx, makeEvent(LabelType, sTags{t1}, nil))
-}
-
-// Label2 sends a label event to the exporter with the supplied tags.
-func Label2(ctx context.Context, t1, t2 Tag) context.Context {
-	return dispatch(ctx, makeEvent(LabelType, sTags{t1, t2}, nil))
-}
-
-// Label3 sends a label event to the exporter with the supplied tags.
-func Label3(ctx context.Context, t1, t2, t3 Tag) context.Context {
-	return dispatch(ctx, makeEvent(LabelType, sTags{t1, t2, t3}, nil))
-}
diff --git a/vendor/golang.org/x/tools/internal/telemetry/event/log.go b/vendor/golang.org/x/tools/internal/telemetry/event/log.go
deleted file mode 100644
index 568aa1b92..000000000
--- a/vendor/golang.org/x/tools/internal/telemetry/event/log.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package event
-
-import (
-	"context"
-	"errors"
-)
-
-// Log sends a log event with the supplied tag list to the exporter.
-func Log(ctx context.Context, tags ...Tag) {
-	dispatch(ctx, makeEvent(LogType, sTags{}, tags))
-}
-
-// Log1 sends a label event to the exporter with the supplied tags.
-func Log1(ctx context.Context, t1 Tag) context.Context {
-	return dispatch(ctx, makeEvent(LogType, sTags{t1}, nil))
-}
-
-// Log2 sends a label event to the exporter with the supplied tags.
-func Log2(ctx context.Context, t1, t2 Tag) context.Context {
-	return dispatch(ctx, makeEvent(LogType, sTags{t1, t2}, nil))
-}
-
-// Log3 sends a label event to the exporter with the supplied tags.
-func Log3(ctx context.Context, t1, t2, t3 Tag) context.Context {
-	return dispatch(ctx, makeEvent(LogType, sTags{t1, t2, t3}, nil))
-}
-
-// Print takes a message and a tag list and combines them into a single event
-// before delivering them to the exporter.
-func Print(ctx context.Context, message string, tags ...Tag) {
-	dispatch(ctx, makeEvent(LogType, sTags{Msg.Of(message)}, tags))
-}
-
-// Print1 takes a message and one tag delivers a log event to the exporter.
-// It is a customized version of Print that is faster and does no allocation.
-func Print1(ctx context.Context, message string, t1 Tag) {
-	dispatch(ctx, makeEvent(LogType, sTags{Msg.Of(message), t1}, nil))
-}
-
-// Print2 takes a message and two tags and delivers a log event to the exporter.
-// It is a customized version of Print that is faster and does no allocation.
-func Print2(ctx context.Context, message string, t1 Tag, t2 Tag) {
-	dispatch(ctx, makeEvent(LogType, sTags{Msg.Of(message), t1, t2}, nil))
-}
-
-// Error takes a message and a tag list and combines them into a single event
-// before delivering them to the exporter. It captures the error in the
-// delivered event.
-func Error(ctx context.Context, message string, err error, tags ...Tag) {
-	if err == nil {
-		err = errors.New(message)
-		message = ""
-	}
-	dispatch(ctx, makeEvent(LogType, sTags{Msg.Of(message), Err.Of(err)}, tags))
-}
diff --git a/vendor/golang.org/x/tools/internal/telemetry/event/metric.go b/vendor/golang.org/x/tools/internal/telemetry/event/metric.go
deleted file mode 100644
index e4092bb0d..000000000
--- a/vendor/golang.org/x/tools/internal/telemetry/event/metric.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package event
-
-import (
-	"context"
-)
-
-// Record sends a label event to the exporter with the supplied tags.
-func Record(ctx context.Context, tags ...Tag) context.Context {
-	return dispatch(ctx, makeEvent(RecordType, sTags{}, tags))
-}
-
-// Record1 sends a label event to the exporter with the supplied tags.
-func Record1(ctx context.Context, t1 Tag) context.Context {
-	return dispatch(ctx, makeEvent(RecordType, sTags{t1}, nil))
-}
-
-// Record2 sends a label event to the exporter with the supplied tags.
-func Record2(ctx context.Context, t1, t2 Tag) context.Context {
-	return dispatch(ctx, makeEvent(RecordType, sTags{t1, t2}, nil))
-}
-
-// Record3 sends a label event to the exporter with the supplied tags.
-func Record3(ctx context.Context, t1, t2, t3 Tag) context.Context {
-	return dispatch(ctx, makeEvent(RecordType, sTags{t1, t2, t3}, nil))
-}
diff --git a/vendor/golang.org/x/tools/internal/telemetry/event/tag.go b/vendor/golang.org/x/tools/internal/telemetry/event/tag.go
deleted file mode 100644
index 8476bc967..000000000
--- a/vendor/golang.org/x/tools/internal/telemetry/event/tag.go
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package event
-
-import (
-	"fmt"
-	"io"
-	"reflect"
-	"unsafe"
-)
-
-// Tag holds a key and value pair.
-// It is normally used when passing around lists of tags.
-type Tag struct {
-	key     Key
-	packed  uint64
-	untyped interface{}
-}
-
-// TagMap is the interface to a collection of Tags indexed by key.
-type TagMap interface {
-	// Find returns the tag that matches the supplied key.
-	Find(key Key) Tag
-}
-
-// TagList is the interface to something that provides an iterable
-// list of tags.
-// Iteration should start from 0 and continue until Valid returns false.
-type TagList interface {
-	// Valid returns true if the index is within range for the list.
-	// It does not imply the tag at that index will itself be valid.
-	Valid(index int) bool
-	// Tag returns the tag at the given index.
-	Tag(index int) Tag
-}
-
-// tagList implements TagList for a list of Tags.
-type tagList struct {
-	tags []Tag
-}
-
-// tagFilter wraps a TagList filtering out specific tags.
-type tagFilter struct {
-	keys       []Key
-	underlying TagList
-}
-
-// tagMap implements TagMap for a simple list of tags.
-type tagMap struct {
-	tags []Tag
-}
-
-// tagMapChain implements TagMap for a list of underlying TagMap.
-type tagMapChain struct {
-	maps []TagMap
-}
-
-// TagOfValue creates a new tag from the key and value.
-// This method is for implementing new key types, tag creation should
-// normally be done with the Of method of the key.
-func TagOfValue(k Key, value interface{}) Tag { return Tag{key: k, untyped: value} }
-
-// UnpackValue assumes the tag was built using TagOfValue and returns the value
-// that was passed to that constructor.
-// This method is for implementing new key types, for type safety normal
-// access should be done with the From method of the key.
-func (t Tag) UnpackValue() interface{} { return t.untyped }
-
-// TagOf64 creates a new tag from a key and a uint64. This is often
-// used for non uint64 values that can be packed into a uint64.
-// This method is for implementing new key types, tag creation should
-// normally be done with the Of method of the key.
-func TagOf64(k Key, v uint64) Tag { return Tag{key: k, packed: v} }
-
-// Unpack64 assumes the tag was built using TagOf64 and returns the value that
-// was passed to that constructor.
-// This method is for implementing new key types, for type safety normal
-// access should be done with the From method of the key.
-func (t Tag) Unpack64() uint64 { return t.packed }
-
-// TagOfString creates a new tag from a key and a string.
-// This method is for implementing new key types, tag creation should
-// normally be done with the Of method of the key.
-func TagOfString(k Key, v string) Tag {
-	hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
-	return Tag{
-		key:     k,
-		packed:  uint64(hdr.Len),
-		untyped: unsafe.Pointer(hdr.Data),
-	}
-}
-
-// UnpackString assumes the tag was built using TagOfString and returns the
-// value that was passed to that constructor.
-// This method is for implementing new key types, for type safety normal
-// access should be done with the From method of the key.
-func (t Tag) UnpackString() string {
-	var v string
-	hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
-	hdr.Data = uintptr(t.untyped.(unsafe.Pointer))
-	hdr.Len = int(t.packed)
-	return *(*string)(unsafe.Pointer(hdr))
-}
-
-// Valid returns true if the Tag is a valid one (it has a key).
-func (t Tag) Valid() bool { return t.key != nil }
-
-// Key returns the key of this Tag.
-func (t Tag) Key() Key { return t.key }
-
-// Format is used for debug printing of tags.
-func (t Tag) Format(f fmt.State, r rune) {
-	if !t.Valid() {
-		io.WriteString(f, `nil`)
-		return
-	}
-	io.WriteString(f, t.Key().Name())
-	io.WriteString(f, "=")
-	var buf [128]byte
-	t.Key().Format(f, buf[:0], t)
-}
-
-func (l *tagList) Valid(index int) bool {
-	return index >= 0 && index < len(l.tags)
-}
-
-func (l *tagList) Tag(index int) Tag {
-	return l.tags[index]
-}
-
-func (f *tagFilter) Valid(index int) bool {
-	return f.underlying.Valid(index)
-}
-
-func (f *tagFilter) Tag(index int) Tag {
-	tag := f.underlying.Tag(index)
-	for _, f := range f.keys {
-		if tag.Key() == f {
-			return Tag{}
-		}
-	}
-	return tag
-}
-
-func (l tagMap) Find(key Key) Tag {
-	for _, tag := range l.tags {
-		if tag.Key() == key {
-			return tag
-		}
-	}
-	return Tag{}
-}
-
-func (c tagMapChain) Find(key Key) Tag {
-	for _, src := range c.maps {
-		tag := src.Find(key)
-		if tag.Valid() {
-			return tag
-		}
-	}
-	return Tag{}
-}
-
-var emptyList = &tagList{}
-
-func NewTagList(tags ...Tag) TagList {
-	if len(tags) == 0 {
-		return emptyList
-	}
-	return &tagList{tags: tags}
-}
-
-func Filter(l TagList, keys ...Key) TagList {
-	if len(keys) == 0 {
-		return l
-	}
-	return &tagFilter{keys: keys, underlying: l}
-}
-
-func NewTagMap(tags ...Tag) TagMap {
-	return tagMap{tags: tags}
-}
-
-func MergeTagMaps(srcs ...TagMap) TagMap {
-	return tagMapChain{maps: srcs}
-}
diff --git a/vendor/golang.org/x/tools/internal/telemetry/event/trace.go b/vendor/golang.org/x/tools/internal/telemetry/event/trace.go
deleted file mode 100644
index 2c40341ff..000000000
--- a/vendor/golang.org/x/tools/internal/telemetry/event/trace.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package event
-
-import (
-	"context"
-)
-
-// StartSpan sends a span start event with the supplied tag list to the exporter.
-// It also returns a function that will end the span, which should normally be
-// deferred.
-func StartSpan(ctx context.Context, name string, tags ...Tag) (context.Context, func()) {
-	return dispatchPair(ctx,
-		makeEvent(StartSpanType, sTags{Name.Of(name)}, tags),
-		makeEvent(EndSpanType, sTags{}, nil))
-}
-
-// StartSpan1 sends a span start event with the supplied tag list to the exporter.
-// It also returns a function that will end the span, which should normally be
-// deferred.
-func StartSpan1(ctx context.Context, name string, t1 Tag) (context.Context, func()) {
-	return dispatchPair(ctx,
-		makeEvent(StartSpanType, sTags{Name.Of(name), t1}, nil),
-		makeEvent(EndSpanType, sTags{}, nil))
-}
-
-// StartSpan2 sends a span start event with the supplied tag list to the exporter.
-// It also returns a function that will end the span, which should normally be
-// deferred.
-func StartSpan2(ctx context.Context, name string, t1, t2 Tag) (context.Context, func()) {
-	return dispatchPair(ctx,
-		makeEvent(StartSpanType, sTags{Name.Of(name), t1, t2}, nil),
-		makeEvent(EndSpanType, sTags{}, nil))
-}
-
-// Detach returns a context without an associated span.
-// This allows the creation of spans that are not children of the current span.
-func Detach(ctx context.Context) context.Context {
-	return dispatch(ctx, makeEvent(DetachType, sTags{}, nil))
-}
diff --git a/vendor/google.golang.org/appengine/.travis.yml b/vendor/google.golang.org/appengine/.travis.yml
index 70ffe89d5..6d03f4d36 100644
--- a/vendor/google.golang.org/appengine/.travis.yml
+++ b/vendor/google.golang.org/appengine/.travis.yml
@@ -10,8 +10,6 @@ script:
 
 matrix:
   include:
-    - go: 1.8.x
-      env: GOAPP=true
     - go: 1.9.x
       env: GOAPP=true
     - go: 1.10.x
diff --git a/vendor/google.golang.org/appengine/internal/api.go b/vendor/google.golang.org/appengine/internal/api.go
index a6ec19e14..721053c20 100644
--- a/vendor/google.golang.org/appengine/internal/api.go
+++ b/vendor/google.golang.org/appengine/internal/api.go
@@ -58,8 +58,11 @@ var (
 
 	apiHTTPClient = &http.Client{
 		Transport: &http.Transport{
-			Proxy: http.ProxyFromEnvironment,
-			Dial:  limitDial,
+			Proxy:               http.ProxyFromEnvironment,
+			Dial:                limitDial,
+			MaxIdleConns:        1000,
+			MaxIdleConnsPerHost: 10000,
+			IdleConnTimeout:     90 * time.Second,
 		},
 	}
 
diff --git a/vendor/google.golang.org/grpc/README.md b/vendor/google.golang.org/grpc/README.md
index a54b6f560..800e7bd4c 100644
--- a/vendor/google.golang.org/grpc/README.md
+++ b/vendor/google.golang.org/grpc/README.md
@@ -130,6 +130,10 @@ possible reasons, including:
  1. mis-configured transport credentials, connection failed on handshaking
  1. bytes disrupted, possibly by a proxy in between
  1. server shutdown
+ 1. Keepalive parameters caused connection shutdown, for example if you have configured
+    your server to terminate connections regularly to [trigger DNS lookups](https://github.com/grpc/grpc-go/issues/3170#issuecomment-552517779).
+    If this is the case, you may want to increase your [MaxConnectionAgeGrace](https://pkg.go.dev/google.golang.org/grpc/keepalive?tab=doc#ServerParameters),
+    to allow longer RPC calls to finish.
 
 It can be tricky to debug this because the error happens on the client side but
 the root cause of the connection being closed is on the server side. Turn on
diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go
index 293d2f62f..0740693b7 100644
--- a/vendor/google.golang.org/grpc/clientconn.go
+++ b/vendor/google.golang.org/grpc/clientconn.go
@@ -194,12 +194,13 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
 	cc.mkp = cc.dopts.copts.KeepaliveParams
 
 	if cc.dopts.copts.Dialer == nil {
-		cc.dopts.copts.Dialer = newProxyDialer(
-			func(ctx context.Context, addr string) (net.Conn, error) {
-				network, addr := parseDialTarget(addr)
-				return (&net.Dialer{}).DialContext(ctx, network, addr)
-			},
-		)
+		cc.dopts.copts.Dialer = func(ctx context.Context, addr string) (net.Conn, error) {
+			network, addr := parseDialTarget(addr)
+			return (&net.Dialer{}).DialContext(ctx, network, addr)
+		}
+		if cc.dopts.withProxy {
+			cc.dopts.copts.Dialer = newProxyDialer(cc.dopts.copts.Dialer)
+		}
 	}
 
 	if cc.dopts.copts.UserAgent != "" {
@@ -1525,9 +1526,9 @@ var ErrClientConnTimeout = errors.New("grpc: timed out when dialing")
 
 func (cc *ClientConn) getResolver(scheme string) resolver.Builder {
 	for _, rb := range cc.dopts.resolvers {
-		if cc.parsedTarget.Scheme == rb.Scheme() {
+		if scheme == rb.Scheme() {
 			return rb
 		}
 	}
-	return resolver.Get(cc.parsedTarget.Scheme)
+	return resolver.Get(scheme)
 }
diff --git a/vendor/google.golang.org/grpc/credentials/tls.go b/vendor/google.golang.org/grpc/credentials/tls.go
index 28b4f6232..86e956bc8 100644
--- a/vendor/google.golang.org/grpc/credentials/tls.go
+++ b/vendor/google.golang.org/grpc/credentials/tls.go
@@ -135,16 +135,26 @@ func NewTLS(c *tls.Config) TransportCredentials {
 	return tc
 }
 
-// NewClientTLSFromCert constructs TLS credentials from the input certificate for client.
+// NewClientTLSFromCert constructs TLS credentials from the provided root
+// certificate authority certificate(s) to validate server connections. If
+// certificates to establish the identity of the client need to be included in
+// the credentials (eg: for mTLS), use NewTLS instead, where a complete
+// tls.Config can be specified.
 // serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header field) in requests.
+// it will override the virtual host name of authority (e.g. :authority header
+// field) in requests.
 func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
 	return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
 }
 
-// NewClientTLSFromFile constructs TLS credentials from the input certificate file for client.
+// NewClientTLSFromFile constructs TLS credentials from the provided root
+// certificate authority certificate file(s) to validate server connections. If
+// certificates to establish the identity of the client need to be included in
+// the credentials (eg: for mTLS), use NewTLS instead, where a complete
+// tls.Config can be specified.
 // serverNameOverride is for testing only. If set to a non empty string,
-// it will override the virtual host name of authority (e.g. :authority header field) in requests.
+// it will override the virtual host name of authority (e.g. :authority header
+// field) in requests.
 func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
 	b, err := ioutil.ReadFile(certFile)
 	if err != nil {
diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go
index 63f5ae21d..35bde1033 100644
--- a/vendor/google.golang.org/grpc/dialoptions.go
+++ b/vendor/google.golang.org/grpc/dialoptions.go
@@ -72,6 +72,7 @@ type dialOptions struct {
 	// we need to be able to configure this in tests.
 	resolveNowBackoff func(int) time.Duration
 	resolvers         []resolver.Builder
+	withProxy         bool
 }
 
 // DialOption configures how we set up the connection.
@@ -307,6 +308,16 @@ func WithInsecure() DialOption {
 	})
 }
 
+// WithNoProxy returns a DialOption which disables the use of proxies for this
+// ClientConn. This is ignored if WithDialer or WithContextDialer are used.
+//
+// This API is EXPERIMENTAL.
+func WithNoProxy() DialOption {
+	return newFuncDialOption(func(o *dialOptions) {
+		o.withProxy = false
+	})
+}
+
 // WithTransportCredentials returns a DialOption which configures a connection
 // level security credentials (e.g., TLS/SSL). This should not be used together
 // with WithCredentialsBundle.
@@ -557,6 +568,7 @@ func defaultDialOptions() dialOptions {
 			ReadBufferSize:  defaultReadBufSize,
 		},
 		resolveNowBackoff: internalbackoff.DefaultExponential.Backoff,
+		withProxy:         true,
 	}
 }
 
diff --git a/vendor/google.golang.org/grpc/go.mod b/vendor/google.golang.org/grpc/go.mod
index 84c98c29f..ecef1ab0c 100644
--- a/vendor/google.golang.org/grpc/go.mod
+++ b/vendor/google.golang.org/grpc/go.mod
@@ -3,8 +3,8 @@ module google.golang.org/grpc
 go 1.11
 
 require (
+	github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f
 	github.com/envoyproxy/go-control-plane v0.9.4
-	github.com/envoyproxy/protoc-gen-validate v0.1.0
 	github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
 	github.com/golang/mock v1.1.1
 	github.com/golang/protobuf v1.3.3
diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go
index 0912f0bf4..c6fbe8bb1 100644
--- a/vendor/google.golang.org/grpc/internal/internal.go
+++ b/vendor/google.golang.org/grpc/internal/internal.go
@@ -37,11 +37,6 @@ var (
 	// KeepaliveMinPingTime is the minimum ping interval.  This must be 10s by
 	// default, but tests may wish to set it lower for convenience.
 	KeepaliveMinPingTime = 10 * time.Second
-	// StatusRawProto is exported by status/status.go. This func returns a
-	// pointer to the wrapped Status proto for a given status.Status without a
-	// call to proto.Clone(). The returned Status proto should not be mutated by
-	// the caller.
-	StatusRawProto interface{} // func (*status.Status) *spb.Status
 	// NewRequestInfoContext creates a new context based on the argument context attaching
 	// the passed in RequestInfo to the new context.
 	NewRequestInfoContext interface{} // func(context.Context, credentials.RequestInfo) context.Context
diff --git a/vendor/google.golang.org/grpc/internal/status/status.go b/vendor/google.golang.org/grpc/internal/status/status.go
new file mode 100644
index 000000000..681260692
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/status/status.go
@@ -0,0 +1,161 @@
+/*
+ *
+ * Copyright 2020 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package status implements errors returned by gRPC.  These errors are
+// serialized and transmitted on the wire between server and client, and allow
+// for additional data to be transmitted via the Details field in the status
+// proto.  gRPC service handlers should return an error created by this
+// package, and gRPC clients should expect a corresponding error to be
+// returned from the RPC call.
+//
+// This package upholds the invariants that a non-nil error may not
+// contain an OK code, and an OK code must result in a nil error.
+package status
+
+import (
+	"errors"
+	"fmt"
+
+	"github.com/golang/protobuf/proto"
+	"github.com/golang/protobuf/ptypes"
+	spb "google.golang.org/genproto/googleapis/rpc/status"
+	"google.golang.org/grpc/codes"
+)
+
+// Status represents an RPC status code, message, and details.  It is immutable
+// and should be created with New, Newf, or FromProto.
+type Status struct {
+	s *spb.Status
+}
+
+// New returns a Status representing c and msg.
+func New(c codes.Code, msg string) *Status {
+	return &Status{s: &spb.Status{Code: int32(c), Message: msg}}
+}
+
+// Newf returns New(c, fmt.Sprintf(format, a...)).
+func Newf(c codes.Code, format string, a ...interface{}) *Status {
+	return New(c, fmt.Sprintf(format, a...))
+}
+
+// FromProto returns a Status representing s.
+func FromProto(s *spb.Status) *Status {
+	return &Status{s: proto.Clone(s).(*spb.Status)}
+}
+
+// Err returns an error representing c and msg.  If c is OK, returns nil.
+func Err(c codes.Code, msg string) error {
+	return New(c, msg).Err()
+}
+
+// Errorf returns Error(c, fmt.Sprintf(format, a...)).
+func Errorf(c codes.Code, format string, a ...interface{}) error {
+	return Err(c, fmt.Sprintf(format, a...))
+}
+
+// Code returns the status code contained in s.
+func (s *Status) Code() codes.Code {
+	if s == nil || s.s == nil {
+		return codes.OK
+	}
+	return codes.Code(s.s.Code)
+}
+
+// Message returns the message contained in s.
+func (s *Status) Message() string {
+	if s == nil || s.s == nil {
+		return ""
+	}
+	return s.s.Message
+}
+
+// Proto returns s's status as an spb.Status proto message.
+func (s *Status) Proto() *spb.Status {
+	if s == nil {
+		return nil
+	}
+	return proto.Clone(s.s).(*spb.Status)
+}
+
+// Err returns an immutable error representing s; returns nil if s.Code() is OK.
+func (s *Status) Err() error {
+	if s.Code() == codes.OK {
+		return nil
+	}
+	return (*Error)(s.Proto())
+}
+
+// WithDetails returns a new status with the provided details messages appended to the status.
+// If any errors are encountered, it returns nil and the first error encountered.
+func (s *Status) WithDetails(details ...proto.Message) (*Status, error) {
+	if s.Code() == codes.OK {
+		return nil, errors.New("no error details for status with code OK")
+	}
+	// s.Code() != OK implies that s.Proto() != nil.
+	p := s.Proto()
+	for _, detail := range details {
+		any, err := ptypes.MarshalAny(detail)
+		if err != nil {
+			return nil, err
+		}
+		p.Details = append(p.Details, any)
+	}
+	return &Status{s: p}, nil
+}
+
+// Details returns a slice of details messages attached to the status.
+// If a detail cannot be decoded, the error is returned in place of the detail.
+func (s *Status) Details() []interface{} {
+	if s == nil || s.s == nil {
+		return nil
+	}
+	details := make([]interface{}, 0, len(s.s.Details))
+	for _, any := range s.s.Details {
+		detail := &ptypes.DynamicAny{}
+		if err := ptypes.UnmarshalAny(any, detail); err != nil {
+			details = append(details, err)
+			continue
+		}
+		details = append(details, detail.Message)
+	}
+	return details
+}
+
+// Error is an alias of a status proto. It implements error and Status,
+// and a nil Error should never be returned by this package.
+type Error spb.Status
+
+func (se *Error) Error() string {
+	p := (*spb.Status)(se)
+	return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage())
+}
+
+// GRPCStatus returns the Status represented by se.
+func (se *Error) GRPCStatus() *Status {
+	return FromProto((*spb.Status)(se))
+}
+
+// Is implements future error.Is functionality.
+// A Error is equivalent if the code and message are identical.
+func (se *Error) Is(target error) bool {
+	tse, ok := target.(*Error)
+	if !ok {
+		return false
+	}
+	return proto.Equal((*spb.Status)(se), (*spb.Status)(tse))
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go
index 228b82184..fc44e9761 100644
--- a/vendor/google.golang.org/grpc/internal/transport/handler_server.go
+++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go
@@ -112,11 +112,10 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats sta
 // at this point to be speaking over HTTP/2, so it's able to speak valid
 // gRPC.
 type serverHandlerTransport struct {
-	rw               http.ResponseWriter
-	req              *http.Request
-	timeoutSet       bool
-	timeout          time.Duration
-	didCommonHeaders bool
+	rw         http.ResponseWriter
+	req        *http.Request
+	timeoutSet bool
+	timeout    time.Duration
 
 	headerMD metadata.MD
 
@@ -186,8 +185,11 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro
 	ht.writeStatusMu.Lock()
 	defer ht.writeStatusMu.Unlock()
 
+	headersWritten := s.updateHeaderSent()
 	err := ht.do(func() {
-		ht.writeCommonHeaders(s)
+		if !headersWritten {
+			ht.writePendingHeaders(s)
+		}
 
 		// And flush, in case no header or body has been sent yet.
 		// This forces a separation of headers and trailers if this is the
@@ -227,6 +229,8 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro
 
 	if err == nil { // transport has not been closed
 		if ht.stats != nil {
+			// Note: The trailer fields are compressed with hpack after this call returns.
+			// No WireLength field is set here.
 			ht.stats.HandleRPC(s.Context(), &stats.OutTrailer{
 				Trailer: s.trailer.Copy(),
 			})
@@ -236,14 +240,16 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro
 	return err
 }
 
+// writePendingHeaders sets common and custom headers on the first
+// write call (Write, WriteHeader, or WriteStatus)
+func (ht *serverHandlerTransport) writePendingHeaders(s *Stream) {
+	ht.writeCommonHeaders(s)
+	ht.writeCustomHeaders(s)
+}
+
 // writeCommonHeaders sets common headers on the first write
 // call (Write, WriteHeader, or WriteStatus).
 func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) {
-	if ht.didCommonHeaders {
-		return
-	}
-	ht.didCommonHeaders = true
-
 	h := ht.rw.Header()
 	h["Date"] = nil // suppress Date to make tests happy; TODO: restore
 	h.Set("Content-Type", ht.contentType)
@@ -262,9 +268,30 @@ func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) {
 	}
 }
 
+// writeCustomHeaders sets custom headers set on the stream via SetHeader
+// on the first write call (Write, WriteHeader, or WriteStatus).
+func (ht *serverHandlerTransport) writeCustomHeaders(s *Stream) {
+	h := ht.rw.Header()
+
+	s.hdrMu.Lock()
+	for k, vv := range s.header {
+		if isReservedHeader(k) {
+			continue
+		}
+		for _, v := range vv {
+			h.Add(k, encodeMetadataHeader(k, v))
+		}
+	}
+
+	s.hdrMu.Unlock()
+}
+
 func (ht *serverHandlerTransport) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
+	headersWritten := s.updateHeaderSent()
 	return ht.do(func() {
-		ht.writeCommonHeaders(s)
+		if !headersWritten {
+			ht.writePendingHeaders(s)
+		}
 		ht.rw.Write(hdr)
 		ht.rw.Write(data)
 		ht.rw.(http.Flusher).Flush()
@@ -272,27 +299,27 @@ func (ht *serverHandlerTransport) Write(s *Stream, hdr []byte, data []byte, opts
 }
 
 func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
+	if err := s.SetHeader(md); err != nil {
+		return err
+	}
+
+	headersWritten := s.updateHeaderSent()
 	err := ht.do(func() {
-		ht.writeCommonHeaders(s)
-		h := ht.rw.Header()
-		for k, vv := range md {
-			// Clients don't tolerate reading restricted headers after some non restricted ones were sent.
-			if isReservedHeader(k) {
-				continue
-			}
-			for _, v := range vv {
-				v = encodeMetadataHeader(k, v)
-				h.Add(k, v)
-			}
+		if !headersWritten {
+			ht.writePendingHeaders(s)
 		}
+
 		ht.rw.WriteHeader(200)
 		ht.rw.(http.Flusher).Flush()
 	})
 
 	if err == nil {
 		if ht.stats != nil {
+			// Note: The header fields are compressed with hpack after this call returns.
+			// No WireLength field is set here.
 			ht.stats.HandleRPC(s.Context(), &stats.OutHeader{
-				Header: md.Copy(),
+				Header:      md.Copy(),
+				Compression: s.sendCompress,
 			})
 		}
 	}
diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go
index b1b82ec95..1cc586f73 100644
--- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go
+++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go
@@ -686,6 +686,8 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Strea
 		} else {
 			header = metadata.Pairs("user-agent", t.userAgent)
 		}
+		// Note: The header fields are compressed with hpack after this call returns.
+		// No WireLength field is set here.
 		outHeader := &stats.OutHeader{
 			Client:      true,
 			FullMethod:  callHdr.Method,
@@ -1193,9 +1195,10 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
 		if t.statsHandler != nil {
 			if isHeader {
 				inHeader := &stats.InHeader{
-					Client:     true,
-					WireLength: int(frame.Header().Length),
-					Header:     s.header.Copy(),
+					Client:      true,
+					WireLength:  int(frame.Header().Length),
+					Header:      s.header.Copy(),
+					Compression: s.recvCompress,
 				}
 				t.statsHandler.HandleRPC(s.ctx, inHeader)
 			} else {
diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
index 8b04b0392..fa33ffb18 100644
--- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go
+++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
@@ -35,11 +35,9 @@ import (
 	"golang.org/x/net/http2"
 	"golang.org/x/net/http2/hpack"
 
-	spb "google.golang.org/genproto/googleapis/rpc/status"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/grpclog"
-	"google.golang.org/grpc/internal"
 	"google.golang.org/grpc/internal/channelz"
 	"google.golang.org/grpc/internal/grpcrand"
 	"google.golang.org/grpc/keepalive"
@@ -57,9 +55,6 @@ var (
 	// ErrHeaderListSizeLimitViolation indicates that the header list size is larger
 	// than the limit set by peer.
 	ErrHeaderListSizeLimitViolation = errors.New("transport: trying to send header list size larger than the limit set by peer")
-	// statusRawProto is a function to get to the raw status proto wrapped in a
-	// status.Status without a proto.Clone().
-	statusRawProto = internal.StatusRawProto.(func(*status.Status) *spb.Status)
 )
 
 // serverConnectionCounter counts the number of connections a server has seen
@@ -813,10 +808,11 @@ func (t *http2Server) writeHeaderLocked(s *Stream) error {
 		return ErrHeaderListSizeLimitViolation
 	}
 	if t.stats != nil {
-		// Note: WireLength is not set in outHeader.
-		// TODO(mmukhi): Revisit this later, if needed.
+		// Note: Headers are compressed with hpack after this call returns.
+		// No WireLength field is set here.
 		outHeader := &stats.OutHeader{
-			Header: s.header.Copy(),
+			Header:      s.header.Copy(),
+			Compression: s.sendCompress,
 		}
 		t.stats.HandleRPC(s.Context(), outHeader)
 	}
@@ -849,7 +845,7 @@ func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error {
 	headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-status", Value: strconv.Itoa(int(st.Code()))})
 	headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-message", Value: encodeGrpcMessage(st.Message())})
 
-	if p := statusRawProto(st); p != nil && len(p.Details) > 0 {
+	if p := st.Proto(); p != nil && len(p.Details) > 0 {
 		stBytes, err := proto.Marshal(p)
 		if err != nil {
 			// TODO: return error instead, when callers are able to handle it.
@@ -880,6 +876,8 @@ func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error {
 	rst := s.getState() == streamActive
 	t.finishStream(s, rst, http2.ErrCodeNo, trailingHeader, true)
 	if t.stats != nil {
+		// Note: The trailer fields are compressed with hpack after this call returns.
+		// No WireLength field is set here.
 		t.stats.HandleRPC(s.Context(), &stats.OutTrailer{
 			Trailer: s.trailer.Copy(),
 		})
diff --git a/vendor/google.golang.org/grpc/stats/stats.go b/vendor/google.golang.org/grpc/stats/stats.go
index 9e22c393f..a7970c79a 100644
--- a/vendor/google.golang.org/grpc/stats/stats.go
+++ b/vendor/google.golang.org/grpc/stats/stats.go
@@ -81,6 +81,10 @@ type InHeader struct {
 	Client bool
 	// WireLength is the wire length of header.
 	WireLength int
+	// Compression is the compression algorithm used for the RPC.
+	Compression string
+	// Header contains the header metadata received.
+	Header metadata.MD
 
 	// The following fields are valid only if Client is false.
 	// FullMethod is the full RPC method string, i.e., /package.service/method.
@@ -89,10 +93,6 @@ type InHeader struct {
 	RemoteAddr net.Addr
 	// LocalAddr is the local address of the corresponding connection.
 	LocalAddr net.Addr
-	// Compression is the compression algorithm used for the RPC.
-	Compression string
-	// Header contains the header metadata received.
-	Header metadata.MD
 }
 
 // IsClient indicates if the stats information is from client side.
@@ -141,6 +141,10 @@ func (s *OutPayload) isRPCStats() {}
 type OutHeader struct {
 	// Client is true if this OutHeader is from client side.
 	Client bool
+	// Compression is the compression algorithm used for the RPC.
+	Compression string
+	// Header contains the header metadata sent.
+	Header metadata.MD
 
 	// The following fields are valid only if Client is true.
 	// FullMethod is the full RPC method string, i.e., /package.service/method.
@@ -149,10 +153,6 @@ type OutHeader struct {
 	RemoteAddr net.Addr
 	// LocalAddr is the local address of the corresponding connection.
 	LocalAddr net.Addr
-	// Compression is the compression algorithm used for the RPC.
-	Compression string
-	// Header contains the header metadata sent.
-	Header metadata.MD
 }
 
 // IsClient indicates if this stats information is from client side.
@@ -165,6 +165,9 @@ type OutTrailer struct {
 	// Client is true if this OutTrailer is from client side.
 	Client bool
 	// WireLength is the wire length of trailer.
+	//
+	// Deprecated: This field is never set. The length is not known when this message is
+	// emitted because the trailer fields are compressed with hpack after that.
 	WireLength int
 	// Trailer contains the trailer metadata sent to the client. This
 	// field is only valid if this OutTrailer is from the server side.
diff --git a/vendor/google.golang.org/grpc/status/status.go b/vendor/google.golang.org/grpc/status/status.go
index a1348e9b1..01e182c30 100644
--- a/vendor/google.golang.org/grpc/status/status.go
+++ b/vendor/google.golang.org/grpc/status/status.go
@@ -29,88 +29,23 @@ package status
 
 import (
 	"context"
-	"errors"
 	"fmt"
 
-	"github.com/golang/protobuf/proto"
-	"github.com/golang/protobuf/ptypes"
 	spb "google.golang.org/genproto/googleapis/rpc/status"
+
 	"google.golang.org/grpc/codes"
-	"google.golang.org/grpc/internal"
+	"google.golang.org/grpc/internal/status"
 )
 
-func init() {
-	internal.StatusRawProto = statusRawProto
-}
-
-func statusRawProto(s *Status) *spb.Status { return s.s }
-
-// statusError is an alias of a status proto.  It implements error and Status,
-// and a nil statusError should never be returned by this package.
-type statusError spb.Status
-
-func (se *statusError) Error() string {
-	p := (*spb.Status)(se)
-	return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage())
-}
-
-func (se *statusError) GRPCStatus() *Status {
-	return &Status{s: (*spb.Status)(se)}
-}
-
-// Is implements future error.Is functionality.
-// A statusError is equivalent if the code and message are identical.
-func (se *statusError) Is(target error) bool {
-	tse, ok := target.(*statusError)
-	if !ok {
-		return false
-	}
-
-	return proto.Equal((*spb.Status)(se), (*spb.Status)(tse))
-}
-
-// Status represents an RPC status code, message, and details.  It is immutable
-// and should be created with New, Newf, or FromProto.
-type Status struct {
-	s *spb.Status
-}
-
-// Code returns the status code contained in s.
-func (s *Status) Code() codes.Code {
-	if s == nil || s.s == nil {
-		return codes.OK
-	}
-	return codes.Code(s.s.Code)
-}
-
-// Message returns the message contained in s.
-func (s *Status) Message() string {
-	if s == nil || s.s == nil {
-		return ""
-	}
-	return s.s.Message
-}
-
-// Proto returns s's status as an spb.Status proto message.
-func (s *Status) Proto() *spb.Status {
-	if s == nil {
-		return nil
-	}
-	return proto.Clone(s.s).(*spb.Status)
-}
-
-// Err returns an immutable error representing s; returns nil if s.Code() is
-// OK.
-func (s *Status) Err() error {
-	if s.Code() == codes.OK {
-		return nil
-	}
-	return (*statusError)(s.s)
-}
+// Status references google.golang.org/grpc/internal/status. It represents an
+// RPC status code, message, and details.  It is immutable and should be
+// created with New, Newf, or FromProto.
+// https://godoc.org/google.golang.org/grpc/internal/status
+type Status = status.Status
 
 // New returns a Status representing c and msg.
 func New(c codes.Code, msg string) *Status {
-	return &Status{s: &spb.Status{Code: int32(c), Message: msg}}
+	return status.New(c, msg)
 }
 
 // Newf returns New(c, fmt.Sprintf(format, a...)).
@@ -135,7 +70,7 @@ func ErrorProto(s *spb.Status) error {
 
 // FromProto returns a Status representing s.
 func FromProto(s *spb.Status) *Status {
-	return &Status{s: proto.Clone(s).(*spb.Status)}
+	return status.FromProto(s)
 }
 
 // FromError returns a Status representing err if it was produced from this
@@ -160,42 +95,6 @@ func Convert(err error) *Status {
 	return s
 }
 
-// WithDetails returns a new status with the provided details messages appended to the status.
-// If any errors are encountered, it returns nil and the first error encountered.
-func (s *Status) WithDetails(details ...proto.Message) (*Status, error) {
-	if s.Code() == codes.OK {
-		return nil, errors.New("no error details for status with code OK")
-	}
-	// s.Code() != OK implies that s.Proto() != nil.
-	p := s.Proto()
-	for _, detail := range details {
-		any, err := ptypes.MarshalAny(detail)
-		if err != nil {
-			return nil, err
-		}
-		p.Details = append(p.Details, any)
-	}
-	return &Status{s: p}, nil
-}
-
-// Details returns a slice of details messages attached to the status.
-// If a detail cannot be decoded, the error is returned in place of the detail.
-func (s *Status) Details() []interface{} {
-	if s == nil || s.s == nil {
-		return nil
-	}
-	details := make([]interface{}, 0, len(s.s.Details))
-	for _, any := range s.s.Details {
-		detail := &ptypes.DynamicAny{}
-		if err := ptypes.UnmarshalAny(any, detail); err != nil {
-			details = append(details, err)
-			continue
-		}
-		details = append(details, detail.Message)
-	}
-	return details
-}
-
 // Code returns the Code of the error if it is a Status error, codes.OK if err
 // is nil, or codes.Unknown otherwise.
 func Code(err error) codes.Code {
diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go
index 66d09b4ab..ca5d55fdd 100644
--- a/vendor/google.golang.org/grpc/version.go
+++ b/vendor/google.golang.org/grpc/version.go
@@ -19,4 +19,4 @@
 package grpc
 
 // Version is the current grpc version.
-const Version = "1.28.1"
+const Version = "1.29.1"
diff --git a/vendor/google.golang.org/grpc/vet.sh b/vendor/google.golang.org/grpc/vet.sh
index f077fe775..e12024fb8 100644
--- a/vendor/google.golang.org/grpc/vet.sh
+++ b/vendor/google.golang.org/grpc/vet.sh
@@ -1,20 +1,22 @@
 #!/bin/bash
 
-if [[ `uname -a` = *"Darwin"* ]]; then
-  echo "It seems you are running on Mac. This script does not work on Mac. See https://github.com/grpc/grpc-go/issues/2047"
-  exit 1
-fi
-
 set -ex  # Exit on error; debugging enabled.
 set -o pipefail  # Fail a pipe if any sub-command fails.
 
+# not makes sure the command passed to it does not exit with a return code of 0.
+not() {
+  # This is required instead of the earlier (! $COMMAND) because subshells and
+  # pipefail don't work the same on Darwin as in Linux.
+  ! "$@"
+}
+
 die() {
   echo "$@" >&2
   exit 1
 }
 
 fail_on_output() {
-  tee /dev/stderr | (! read)
+  tee /dev/stderr | not read
 }
 
 # Check to make sure it's safe to modify the user's git repo.
@@ -60,7 +62,7 @@ if [[ "$1" = "-install" ]]; then
       unzip ${PROTOC_FILENAME}
       bin/protoc --version
       popd
-    elif ! which protoc > /dev/null; then
+    elif not which protoc > /dev/null; then
       die "Please install protoc into your path"
     fi
   fi
@@ -70,21 +72,21 @@ elif [[ "$#" -ne 0 ]]; then
 fi
 
 # - Ensure all source files contain a copyright message.
-(! git grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)\|DO NOT EDIT" -- '*.go')
+not git grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)\|DO NOT EDIT" -- '*.go'
 
 # - Make sure all tests in grpc and grpc/test use leakcheck via Teardown.
-(! grep 'func Test[^(]' *_test.go)
-(! grep 'func Test[^(]' test/*.go)
+not grep 'func Test[^(]' *_test.go
+not grep 'func Test[^(]' test/*.go
 
 # - Do not import x/net/context.
-(! git grep -l 'x/net/context' -- "*.go")
+not git grep -l 'x/net/context' -- "*.go"
 
 # - Do not import math/rand for real library code.  Use internal/grpcrand for
 #   thread safety.
-git grep -l '"math/rand"' -- "*.go" 2>&1 | (! grep -v '^examples\|^stress\|grpcrand\|^benchmark\|wrr_test')
+git grep -l '"math/rand"' -- "*.go" 2>&1 | not grep -v '^examples\|^stress\|grpcrand\|^benchmark\|wrr_test'
 
 # - Ensure all ptypes proto packages are renamed when importing.
-(! git grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/" -- "*.go")
+not git grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/" -- "*.go"
 
 # - Check imports that are illegal in appengine (until Go 1.11).
 # TODO: Remove when we drop Go 1.10 support
@@ -92,8 +94,8 @@ go list -f {{.Dir}} ./... | xargs go run test/go_vet/vet.go
 
 # - gofmt, goimports, golint (with exceptions for generated code), go vet.
 gofmt -s -d -l . 2>&1 | fail_on_output
-goimports -l . 2>&1 | (! grep -vE "(_mock|\.pb)\.go")
-golint ./... 2>&1 | (! grep -vE "(_mock|\.pb)\.go:")
+goimports -l . 2>&1 | not grep -vE "(_mock|\.pb)\.go"
+golint ./... 2>&1 | not grep -vE "(_mock|\.pb)\.go:"
 go vet -all ./...
 
 misspell -error .
@@ -119,9 +121,9 @@ fi
 SC_OUT="$(mktemp)"
 staticcheck -go 1.9 -checks 'inherit,-ST1015' ./... > "${SC_OUT}" || true
 # Error if anything other than deprecation warnings are printed.
-(! grep -v "is deprecated:.*SA1019" "${SC_OUT}")
+not grep -v "is deprecated:.*SA1019" "${SC_OUT}"
 # Only ignore the following deprecated types/fields/functions.
-(! grep -Fv '.HandleResolvedAddrs
+not grep -Fv '.HandleResolvedAddrs
 .HandleSubConnStateChange
 .HeaderMap
 .NewAddress
@@ -157,4 +159,5 @@ naming.Update
 naming.Watcher
 resolver.Backend
 resolver.GRPCLB' "${SC_OUT}"
-)
+
+echo SUCCESS
diff --git a/vendor/modules.txt b/vendor/modules.txt
index fcf6a8c47..0d8884ca3 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -14,7 +14,7 @@ github.com/BurntSushi/toml
 github.com/VictoriaMetrics/fastcache
 # github.com/VictoriaMetrics/metrics v1.11.2
 github.com/VictoriaMetrics/metrics
-# github.com/aws/aws-sdk-go v1.30.12
+# github.com/aws/aws-sdk-go v1.30.13
 github.com/aws/aws-sdk-go/aws
 github.com/aws/aws-sdk-go/aws/arn
 github.com/aws/aws-sdk-go/aws/awserr
@@ -82,7 +82,7 @@ github.com/jmespath/go-jmespath
 github.com/jstemmer/go-junit-report
 github.com/jstemmer/go-junit-report/formatter
 github.com/jstemmer/go-junit-report/parser
-# github.com/klauspost/compress v1.10.4
+# github.com/klauspost/compress v1.10.5
 github.com/klauspost/compress/flate
 github.com/klauspost/compress/fse
 github.com/klauspost/compress/gzip
@@ -93,7 +93,7 @@ github.com/klauspost/compress/zstd
 github.com/klauspost/compress/zstd/internal/xxhash
 # github.com/valyala/bytebufferpool v1.0.0
 github.com/valyala/bytebufferpool
-# github.com/valyala/fasthttp v1.10.0
+# github.com/valyala/fasthttp v1.12.0
 github.com/valyala/fasthttp
 github.com/valyala/fasthttp/fasthttputil
 github.com/valyala/fasthttp/stackless
@@ -131,7 +131,7 @@ golang.org/x/lint/golint
 # golang.org/x/mod v0.2.0
 golang.org/x/mod/module
 golang.org/x/mod/semver
-# golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
+# golang.org/x/net v0.0.0-20200421231249-e086a090c8fd
 golang.org/x/net/context
 golang.org/x/net/context/ctxhttp
 golang.org/x/net/http/httpguts
@@ -146,14 +146,14 @@ golang.org/x/oauth2/google
 golang.org/x/oauth2/internal
 golang.org/x/oauth2/jws
 golang.org/x/oauth2/jwt
-# golang.org/x/sys v0.0.0-20200413165638-669c56c373c4
+# golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f
 golang.org/x/sys/unix
 # golang.org/x/text v0.3.2
 golang.org/x/text/secure/bidirule
 golang.org/x/text/transform
 golang.org/x/text/unicode/bidi
 golang.org/x/text/unicode/norm
-# golang.org/x/tools v0.0.0-20200416214402-fc959738d646
+# golang.org/x/tools v0.0.0-20200423205358-59e73619c742
 golang.org/x/tools/cmd/goimports
 golang.org/x/tools/go/analysis
 golang.org/x/tools/go/analysis/passes/inspect
@@ -169,12 +169,15 @@ golang.org/x/tools/go/packages
 golang.org/x/tools/go/types/objectpath
 golang.org/x/tools/go/types/typeutil
 golang.org/x/tools/internal/analysisinternal
+golang.org/x/tools/internal/event
+golang.org/x/tools/internal/event/core
+golang.org/x/tools/internal/event/keys
+golang.org/x/tools/internal/event/label
 golang.org/x/tools/internal/fastwalk
 golang.org/x/tools/internal/gocommand
 golang.org/x/tools/internal/gopathwalk
 golang.org/x/tools/internal/imports
 golang.org/x/tools/internal/packagesinternal
-golang.org/x/tools/internal/telemetry/event
 # golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
 golang.org/x/xerrors
 golang.org/x/xerrors/internal
@@ -191,7 +194,7 @@ google.golang.org/api/storage/v1
 google.golang.org/api/transport/cert
 google.golang.org/api/transport/http
 google.golang.org/api/transport/http/internal/propagation
-# google.golang.org/appengine v1.6.5
+# google.golang.org/appengine v1.6.6
 google.golang.org/appengine
 google.golang.org/appengine/internal
 google.golang.org/appengine/internal/app_identity
@@ -202,13 +205,13 @@ google.golang.org/appengine/internal/modules
 google.golang.org/appengine/internal/remote_api
 google.golang.org/appengine/internal/urlfetch
 google.golang.org/appengine/urlfetch
-# google.golang.org/genproto v0.0.0-20200416231807-8751e049a2a0
+# google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215
 google.golang.org/genproto/googleapis/api/annotations
 google.golang.org/genproto/googleapis/iam/v1
 google.golang.org/genproto/googleapis/rpc/code
 google.golang.org/genproto/googleapis/rpc/status
 google.golang.org/genproto/googleapis/type/expr
-# google.golang.org/grpc v1.28.1
+# google.golang.org/grpc v1.29.1
 google.golang.org/grpc
 google.golang.org/grpc/attributes
 google.golang.org/grpc/backoff
@@ -236,6 +239,7 @@ google.golang.org/grpc/internal/grpcsync
 google.golang.org/grpc/internal/grpcutil
 google.golang.org/grpc/internal/resolver/dns
 google.golang.org/grpc/internal/resolver/passthrough
+google.golang.org/grpc/internal/status
 google.golang.org/grpc/internal/syscall
 google.golang.org/grpc/internal/transport
 google.golang.org/grpc/keepalive


Test patch:
diff --git a/app/vmbackup/snapshot/snapshot_test.go b/app/vmbackup/snapshot/snapshot_test.go
new file mode 100644
index 000000000..6d4266de6
--- /dev/null
+++ b/app/vmbackup/snapshot/snapshot_test.go
@@ -0,0 +1,106 @@
+package snapshot
+
+import (
+	"io"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+)
+
+func TestCreateSnapshot(t *testing.T) {
+	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.Path == "/snapshot/create" {
+			_, err := io.WriteString(w, `{"status":"ok","snapshot":"mysnapshot"}`)
+			if err != nil {
+				t.Fatalf("Failed to write response output: %v", err)
+			}
+		} else {
+			t.Fatalf("Invalid path, got %v", r.URL.Path)
+		}
+	})
+
+	server := httptest.NewServer(http.HandlerFunc(handler))
+	defer server.Close()
+
+	snapshotName, err := Create(server.URL + "/snapshot/create")
+	if err != nil {
+		t.Fatalf("Failed taking snapshot: %v", err)
+	}
+
+	if snapshotName != "mysnapshot" {
+		t.Fatalf("Snapshot name is not correct, got %v", snapshotName)
+	}
+}
+
+func TestCreateSnapshotFailed(t *testing.T) {
+	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.Path == "/snapshot/create" {
+			_, err := io.WriteString(w, `{"status":"error","msg":"I am unwell"}`)
+			if err != nil {
+				t.Fatalf("Failed to write response output: %v", err)
+			}
+		} else {
+			t.Fatalf("Invalid path, got %v", r.URL.Path)
+		}
+	})
+
+	server := httptest.NewServer(http.HandlerFunc(handler))
+	defer server.Close()
+
+	snapshotName, err := Create(server.URL + "/snapshot/create")
+	if err == nil {
+		t.Fatalf("Snapshot did not fail, got snapshot: %v", snapshotName)
+	}
+}
+
+func TestDeleteSnapshot(t *testing.T) {
+	snapshotName := "mysnapshot"
+
+	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.Path == "/snapshot/delete" {
+			_, err := io.WriteString(w, `{"status":"ok"}`)
+			if err != nil {
+				t.Fatalf("Failed to write response output: %v", err)
+			}
+		} else {
+			t.Fatalf("Invalid path, got %v", r.URL.Path)
+		}
+		if r.FormValue("snapshot") != snapshotName {
+			t.Fatalf("Invalid snapshot name, got %v", snapshotName)
+		}
+	})
+
+	server := httptest.NewServer(http.HandlerFunc(handler))
+	defer server.Close()
+
+	err := Delete(server.URL+"/snapshot/delete", snapshotName)
+	if err != nil {
+		t.Fatalf("Failed to delete snapshot: %v", err)
+	}
+}
+
+func TestDeleteSnapshotFailed(t *testing.T) {
+	snapshotName := "mysnapshot"
+
+	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.URL.Path == "/snapshot/delete" {
+			_, err := io.WriteString(w, `{"status":"error", "msg":"failed to delete"}`)
+			if err != nil {
+				t.Fatalf("Failed to write response output: %v", err)
+			}
+		} else {
+			t.Fatalf("Invalid path, got %v", r.URL.Path)
+		}
+		if r.FormValue("snapshot") != snapshotName {
+			t.Fatalf("Invalid snapshot name, got %v", snapshotName)
+		}
+	})
+
+	server := httptest.NewServer(http.HandlerFunc(handler))
+	defer server.Close()
+
+	err := Delete(server.URL+"/snapshot/delete", snapshotName)
+	if err == nil {
+		t.Fatalf("Snapshot should have failed, got: %v", err)
+	}
+}
diff --git a/lib/promscrape/discovery/gce/instance_test.go b/lib/promscrape/discovery/gce/instance_test.go
new file mode 100644
index 000000000..a5426d81e
--- /dev/null
+++ b/lib/promscrape/discovery/gce/instance_test.go
@@ -0,0 +1,179 @@
+package gce
+
+import (
+	"reflect"
+	"testing"
+
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
+)
+
+func TestParseInstanceListFailure(t *testing.T) {
+	f := func(s string) {
+		t.Helper()
+		il, err := parseInstanceList([]byte(s))
+		if err == nil {
+			t.Fatalf("expecting non-nil error")
+		}
+		if il != nil {
+			t.Fatalf("unexpected non-nil InstanceList: %v", il)
+		}
+	}
+	f(``)
+	f(`[1,23]`)
+	f(`{"items":[{"metadata":1}]}`)
+}
+
+func TestParseInstanceListSuccess(t *testing.T) {
+	data := `
+{
+  "id": "projects/victoriametrics-test/zones/us-east1-b/instances",
+  "items": [
+    {
+      "id": "7897352091592122",
+      "creationTimestamp": "2020-02-16T07:10:14.357-08:00",
+      "name": "play-1m-1-vmagent",
+      "tags": {
+        "items": [
+          "play",
+          "play-1m-1",
+          "vmagent"
+        ],
+        "fingerprint": "O44NvJ36CCo="
+      },
+      "machineType": "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/zones/us-east1-b/machineTypes/f1-micro",
+      "status": "RUNNING",
+      "zone": "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/zones/us-east1-b",
+      "networkInterfaces": [
+        {
+          "network": "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/global/networks/default",
+          "subnetwork": "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/regions/us-east1/subnetworks/play-1m-1-snw",
+          "networkIP": "10.11.2.7",
+          "name": "nic0",
+          "fingerprint": "O4eNOfaplJ4=",
+          "kind": "compute#networkInterface"
+        }
+      ],
+      "disks": [
+        {
+          "type": "PERSISTENT",
+          "mode": "READ_WRITE",
+          "source": "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/zones/us-east1-b/disks/play-1m-1-vmagent",
+          "deviceName": "boot",
+          "index": 0,
+          "boot": true,
+          "autoDelete": true,
+          "licenses": [
+            "https://www.googleapis.com/compute/v1/projects/cos-cloud-shielded/global/licenses/shielded-cos",
+            "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/licenses/cos",
+            "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/licenses/cos-pcid"
+          ],
+          "interface": "SCSI",
+          "guestOsFeatures": [
+            {
+              "type": "VIRTIO_SCSI_MULTIQUEUE"
+            },
+            {
+              "type": "UEFI_COMPATIBLE"
+            }
+          ],
+          "diskSizeGb": "10",
+          "kind": "compute#attachedDisk"
+        }
+      ],
+      "metadata": {
+        "fingerprint": "BAFZwTyaAxQ=",
+        "items": [
+          {
+            "key": "gce-container-declaration",
+            "value": "foobar"
+	  }
+        ],
+        "kind": "compute#metadata"
+      },
+      "serviceAccounts": [
+        {
+          "email": "12-compute@developer.gserviceaccount.com",
+          "scopes": [
+            "https://www.googleapis.com/auth/devstorage.read_write",
+            "https://www.googleapis.com/auth/logging.write",
+            "https://www.googleapis.com/auth/monitoring.write",
+            "https://www.googleapis.com/auth/servicecontrol",
+            "https://www.googleapis.com/auth/service.management.readonly"
+          ]
+        }
+      ],
+      "selfLink": "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/zones/us-east1-b/instances/play-1m-1-vmagent",
+      "scheduling": {
+        "onHostMaintenance": "MIGRATE",
+        "automaticRestart": true,
+        "preemptible": false
+      },
+      "cpuPlatform": "Intel Haswell",
+      "labels": {
+        "goog-dm": "play-deployment",
+        "cluster_num": "1",
+        "cluster_retention": "1m",
+        "env": "play",
+        "type": "vmagent"
+      },
+      "labelFingerprint": "-CXeRXMQiVc=",
+      "startRestricted": false,
+      "deletionProtection": false,
+      "shieldedInstanceConfig": {
+        "enableSecureBoot": false,
+        "enableVtpm": true,
+        "enableIntegrityMonitoring": true
+      },
+      "shieldedInstanceIntegrityPolicy": {
+        "updateAutoLearnPolicy": true
+      },
+      "fingerprint": "hd3NB2-9QIg=",
+      "kind": "compute#instance"
+    }
+  ]
+}
+`
+	il, err := parseInstanceList([]byte(data))
+	if err != nil {
+		t.Fatalf("unexpected error: %s", err)
+	}
+	if len(il.Items) != 1 {
+		t.Fatalf("unexpected length of InstanceList.Items; got %d; want %d", len(il.Items), 1)
+	}
+	inst := il.Items[0]
+
+	// Check inst.appendTargetLabels()
+	project := "proj-1"
+	tagSeparator := ","
+	port := 80
+	labelss := inst.appendTargetLabels(nil, project, tagSeparator, port)
+	var sortedLabelss [][]prompbmarshal.Label
+	for _, labels := range labelss {
+		sortedLabelss = append(sortedLabelss, discoveryutils.GetSortedLabels(labels))
+	}
+	expectedLabelss := [][]prompbmarshal.Label{
+		discoveryutils.GetSortedLabels(map[string]string{
+			"__address__":                                   "10.11.2.7:80",
+			"__meta_gce_instance_id":                        "7897352091592122",
+			"__meta_gce_instance_name":                      "play-1m-1-vmagent",
+			"__meta_gce_instance_status":                    "RUNNING",
+			"__meta_gce_label_cluster_num":                  "1",
+			"__meta_gce_label_cluster_retention":            "1m",
+			"__meta_gce_label_env":                          "play",
+			"__meta_gce_label_goog_dm":                      "play-deployment",
+			"__meta_gce_label_type":                         "vmagent",
+			"__meta_gce_machine_type":                       "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/zones/us-east1-b/machineTypes/f1-micro",
+			"__meta_gce_metadata_gce_container_declaration": "foobar",
+			"__meta_gce_network":                            "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/global/networks/default",
+			"__meta_gce_private_ip":                         "10.11.2.7",
+			"__meta_gce_project":                            "proj-1",
+			"__meta_gce_subnetwork":                         "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/regions/us-east1/subnetworks/play-1m-1-snw",
+			"__meta_gce_tags":                               ",play,play-1m-1,vmagent,",
+			"__meta_gce_zone":                               "https://www.googleapis.com/compute/v1/projects/victoriametrics-test/zones/us-east1-b",
+		}),
+	}
+	if !reflect.DeepEqual(sortedLabelss, expectedLabelss) {
+		t.Fatalf("unexpected labels:\ngot\n%v\nwant\n%v", sortedLabelss, expectedLabelss)
+	}
+}
diff --git a/lib/promscrape/discovery/kubernetes/endpoints_test.go b/lib/promscrape/discovery/kubernetes/endpoints_test.go
index cb8bb698e..0decc0800 100644
--- a/lib/promscrape/discovery/kubernetes/endpoints_test.go
+++ b/lib/promscrape/discovery/kubernetes/endpoints_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
 )
 
 func TestParseEndpointsListFailure(t *testing.T) {
@@ -85,10 +86,10 @@ func TestParseEndpointsListSuccess(t *testing.T) {
 	labelss := endpoint.appendTargetLabels(nil, nil, nil)
 	var sortedLabelss [][]prompbmarshal.Label
 	for _, labels := range labelss {
-		sortedLabelss = append(sortedLabelss, getSortedLabels(labels))
+		sortedLabelss = append(sortedLabelss, discoveryutils.GetSortedLabels(labels))
 	}
 	expectedLabelss := [][]prompbmarshal.Label{
-		getSortedLabels(map[string]string{
+		discoveryutils.GetSortedLabels(map[string]string{
 			"__address__": "172.17.0.2:8443",
 			"__meta_kubernetes_endpoint_address_target_kind": "Pod",
 			"__meta_kubernetes_endpoint_address_target_name": "coredns-6955765f44-lnp6t",
diff --git a/lib/promscrape/discovery/kubernetes/ingress_test.go b/lib/promscrape/discovery/kubernetes/ingress_test.go
index 8a1fbae75..575abb5f8 100644
--- a/lib/promscrape/discovery/kubernetes/ingress_test.go
+++ b/lib/promscrape/discovery/kubernetes/ingress_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
 )
 
 func TestParseIngressListFailure(t *testing.T) {
@@ -83,10 +84,10 @@ func TestParseIngressListSuccess(t *testing.T) {
 	labelss := ig.appendTargetLabels(nil)
 	var sortedLabelss [][]prompbmarshal.Label
 	for _, labels := range labelss {
-		sortedLabelss = append(sortedLabelss, getSortedLabels(labels))
+		sortedLabelss = append(sortedLabelss, discoveryutils.GetSortedLabels(labels))
 	}
 	expectedLabelss := [][]prompbmarshal.Label{
-		getSortedLabels(map[string]string{
+		discoveryutils.GetSortedLabels(map[string]string{
 			"__address__": "foobar",
 			"__meta_kubernetes_ingress_annotation_kubectl_kubernetes_io_last_applied_configuration":        `{"apiVersion":"networking.k8s.io/v1beta1","kind":"Ingress","metadata":{"annotations":{},"name":"test-ingress","namespace":"default"},"spec":{"backend":{"serviceName":"testsvc","servicePort":80}}}` + "\n",
 			"__meta_kubernetes_ingress_annotationpresent_kubectl_kubernetes_io_last_applied_configuration": "true",
diff --git a/lib/promscrape/discovery/kubernetes/node_test.go b/lib/promscrape/discovery/kubernetes/node_test.go
index 00ce2c89e..c632b8123 100644
--- a/lib/promscrape/discovery/kubernetes/node_test.go
+++ b/lib/promscrape/discovery/kubernetes/node_test.go
@@ -3,6 +3,8 @@ package kubernetes
 import (
 	"reflect"
 	"testing"
+
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
 )
 
 func TestParseNodeListFailure(t *testing.T) {
@@ -236,7 +238,7 @@ func TestParseNodeListSuccess(t *testing.T) {
 	if meta.Name != "m01" {
 		t.Fatalf("unexpected ObjectMeta.Name; got %q; want %q", meta.Name, "m01")
 	}
-	expectedLabels := getSortedLabels(map[string]string{
+	expectedLabels := discoveryutils.GetSortedLabels(map[string]string{
 		"beta.kubernetes.io/arch":        "amd64",
 		"beta.kubernetes.io/os":          "linux",
 		"kubernetes.io/arch":             "amd64",
@@ -251,7 +253,7 @@ func TestParseNodeListSuccess(t *testing.T) {
 	if !reflect.DeepEqual(meta.Labels, expectedLabels) {
 		t.Fatalf("unexpected ObjectMeta.Labels\ngot\n%v\nwant\n%v", meta.Labels, expectedLabels)
 	}
-	expectedAnnotations := getSortedLabels(map[string]string{
+	expectedAnnotations := discoveryutils.GetSortedLabels(map[string]string{
 		"kubeadm.alpha.kubernetes.io/cri-socket":                 "/var/run/dockershim.sock",
 		"node.alpha.kubernetes.io/ttl":                           "0",
 		"volumes.kubernetes.io/controller-managed-attach-detach": "true",
@@ -275,8 +277,8 @@ func TestParseNodeListSuccess(t *testing.T) {
 	}
 
 	// Check node.appendTargetLabels()
-	labels := getSortedLabels(node.appendTargetLabels(nil)[0])
-	expectedLabels = getSortedLabels(map[string]string{
+	labels := discoveryutils.GetSortedLabels(node.appendTargetLabels(nil)[0])
+	expectedLabels = discoveryutils.GetSortedLabels(map[string]string{
 		"instance":                    "m01",
 		"__address__":                 "172.17.0.2:10250",
 		"__meta_kubernetes_node_name": "m01",
diff --git a/lib/promscrape/discovery/kubernetes/pod_test.go b/lib/promscrape/discovery/kubernetes/pod_test.go
index fb3842828..7462f0014 100644
--- a/lib/promscrape/discovery/kubernetes/pod_test.go
+++ b/lib/promscrape/discovery/kubernetes/pod_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
 )
 
 func TestParsePodListFailure(t *testing.T) {
@@ -240,10 +241,10 @@ func TestParsePodListSuccess(t *testing.T) {
 	labelss := pod.appendTargetLabels(nil)
 	var sortedLabelss [][]prompbmarshal.Label
 	for _, labels := range labelss {
-		sortedLabelss = append(sortedLabelss, getSortedLabels(labels))
+		sortedLabelss = append(sortedLabelss, discoveryutils.GetSortedLabels(labels))
 	}
 	expectedLabels := [][]prompbmarshal.Label{
-		getSortedLabels(map[string]string{
+		discoveryutils.GetSortedLabels(map[string]string{
 			"__address__": "172.17.0.2:1234",
 
 			"__meta_kubernetes_namespace":                   "kube-system",
diff --git a/lib/promscrape/discovery/kubernetes/service_test.go b/lib/promscrape/discovery/kubernetes/service_test.go
index caf7215e3..2f3c1f7e7 100644
--- a/lib/promscrape/discovery/kubernetes/service_test.go
+++ b/lib/promscrape/discovery/kubernetes/service_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
+	"github.com/VictoriaMetrics/VictoriaMetrics/lib/promscrape/discoveryutils"
 )
 
 func TestParseServiceListFailure(t *testing.T) {
@@ -100,7 +101,7 @@ func TestParseServiceListSuccess(t *testing.T) {
 	if meta.Name != "kube-dns" {
 		t.Fatalf("unexpected ObjectMeta.Name; got %q; want %q", meta.Name, "kube-dns")
 	}
-	expectedLabels := getSortedLabels(map[string]string{
+	expectedLabels := discoveryutils.GetSortedLabels(map[string]string{
 		"k8s-app":                       "kube-dns",
 		"kubernetes.io/cluster-service": "true",
 		"kubernetes.io/name":            "KubeDNS",
@@ -108,7 +109,7 @@ func TestParseServiceListSuccess(t *testing.T) {
 	if !reflect.DeepEqual(meta.Labels, expectedLabels) {
 		t.Fatalf("unexpected ObjectMeta.Labels\ngot\n%v\nwant\n%v", meta.Labels, expectedLabels)
 	}
-	expectedAnnotations := getSortedLabels(map[string]string{
+	expectedAnnotations := discoveryutils.GetSortedLabels(map[string]string{
 		"prometheus.io/port":   "9153",
 		"prometheus.io/scrape": "true",
 	})
@@ -148,10 +149,10 @@ func TestParseServiceListSuccess(t *testing.T) {
 	labelss := service.appendTargetLabels(nil)
 	var sortedLabelss [][]prompbmarshal.Label
 	for _, labels := range labelss {
-		sortedLabelss = append(sortedLabelss, getSortedLabels(labels))
+		sortedLabelss = append(sortedLabelss, discoveryutils.GetSortedLabels(labels))
 	}
 	expectedLabelss := [][]prompbmarshal.Label{
-		getSortedLabels(map[string]string{
+		discoveryutils.GetSortedLabels(map[string]string{
 			"__address__":                             "kube-dns.kube-system.svc:53",
 			"__meta_kubernetes_namespace":             "kube-system",
 			"__meta_kubernetes_service_name":          "kube-dns",
@@ -174,7 +175,7 @@ func TestParseServiceListSuccess(t *testing.T) {
 			"__meta_kubernetes_service_annotationpresent_prometheus_io_port":   "true",
 			"__meta_kubernetes_service_annotationpresent_prometheus_io_scrape": "true",
 		}),
-		getSortedLabels(map[string]string{
+		discoveryutils.GetSortedLabels(map[string]string{
 			"__address__":                             "kube-dns.kube-system.svc:53",
 			"__meta_kubernetes_namespace":             "kube-system",
 			"__meta_kubernetes_service_name":          "kube-dns",
@@ -197,7 +198,7 @@ func TestParseServiceListSuccess(t *testing.T) {
 			"__meta_kubernetes_service_annotationpresent_prometheus_io_port":   "true",
 			"__meta_kubernetes_service_annotationpresent_prometheus_io_scrape": "true",
 		}),
-		getSortedLabels(map[string]string{
+		discoveryutils.GetSortedLabels(map[string]string{
 			"__address__":                             "kube-dns.kube-system.svc:9153",
 			"__meta_kubernetes_namespace":             "kube-system",
 			"__meta_kubernetes_service_name":          "kube-dns",
diff --git a/lib/storage/dedup_test.go b/lib/storage/dedup_test.go
index b33d5b5d0..9ac7ba0d5 100644
--- a/lib/storage/dedup_test.go
+++ b/lib/storage/dedup_test.go
@@ -6,27 +6,6 @@ import (
 	"time"
 )
 
-func TestGetMinDelta(t *testing.T) {
-	// Disable deduplication before exit, since the rest of tests expect disabled dedup.
-	defer SetMinScrapeIntervalForDeduplication(0)
-
-	f := func(scrapeInterval time.Duration, dExpected int64) {
-		t.Helper()
-		SetMinScrapeIntervalForDeduplication(scrapeInterval)
-		d := getMinDelta()
-		if d != dExpected {
-			t.Fatalf("unexpected getMinDelta(%s); got %d; want %d", scrapeInterval, d, dExpected)
-		}
-	}
-	f(0, 0)
-	f(time.Millisecond, 1)
-	f(5*time.Millisecond, 4)
-	f(8*time.Millisecond, 7)
-	f(100*time.Millisecond, 84)
-	f(time.Second, 875)
-	f(10*time.Second, 8750)
-}
-
 func TestDeduplicateSamples(t *testing.T) {
 	// Disable deduplication before exit, since the rest of tests expect disabled dedup.
 	defer SetMinScrapeIntervalForDeduplication(0)
@@ -73,8 +52,8 @@ func TestDeduplicateSamples(t *testing.T) {
 	f(time.Millisecond, []int64{123, 456}, []int64{123, 456})
 	f(time.Millisecond, []int64{0, 0, 0, 1, 1, 2, 3, 3, 3, 4}, []int64{0, 1, 2, 3, 4})
 	f(0, []int64{0, 0, 0, 1, 1, 2, 3, 3, 3, 4}, []int64{0, 0, 0, 1, 1, 2, 3, 3, 3, 4})
-	f(100*time.Millisecond, []int64{0, 100, 100, 101, 150, 180, 200, 300, 1000}, []int64{0, 100, 200, 300, 1000})
-	f(10*time.Second, []int64{10e3, 13e3, 21e3, 22e3, 30e3, 33e3, 39e3, 45e3}, []int64{10e3, 21e3, 30e3, 39e3})
+	f(100*time.Millisecond, []int64{0, 100, 100, 101, 150, 180, 205, 300, 1000}, []int64{0, 100, 205, 300, 1000})
+	f(10*time.Second, []int64{10e3, 13e3, 21e3, 22e3, 30e3, 33e3, 39e3, 45e3}, []int64{10e3, 21e3, 30e3, 45e3})
 }
 
 func TestDeduplicateSamplesDuringMerge(t *testing.T) {
@@ -121,9 +100,9 @@ func TestDeduplicateSamplesDuringMerge(t *testing.T) {
 	f(time.Millisecond, nil, []int64{})
 	f(time.Millisecond, []int64{123}, []int64{123})
 	f(time.Millisecond, []int64{123, 456}, []int64{123, 456})
-	f(time.Millisecond, []int64{0, 0, 0, 1, 1, 2, 3, 3, 3, 4}, []int64{0, 0, 0, 1, 1, 2, 3, 3, 3, 4})
-	f(100*time.Millisecond, []int64{0, 100, 100, 101, 150, 180, 200, 300, 1000}, []int64{0, 100, 100, 101, 150, 180, 200, 300, 1000})
-	f(10*time.Second, []int64{10e3, 13e3, 21e3, 22e3, 30e3, 33e3, 39e3, 45e3}, []int64{10e3, 13e3, 21e3, 22e3, 30e3, 33e3, 39e3, 45e3})
+	f(time.Millisecond, []int64{0, 0, 0, 1, 1, 2, 3, 3, 3, 4}, []int64{0, 1, 2, 3, 4})
+	f(100*time.Millisecond, []int64{0, 100, 100, 101, 150, 180, 200, 300, 1000}, []int64{0, 100, 200, 300, 1000})
+	f(10*time.Second, []int64{10e3, 13e3, 21e3, 22e3, 30e3, 33e3, 39e3, 45e3}, []int64{10e3, 21e3, 30e3, 45e3})
 
 	var timestamps, timestampsExpected []int64
 	for i := 0; i < 40; i++ {
diff --git a/lib/storage/dedup_timing_test.go b/lib/storage/dedup_timing_test.go
new file mode 100644
index 000000000..9be079403
--- /dev/null
+++ b/lib/storage/dedup_timing_test.go
@@ -0,0 +1,36 @@
+package storage
+
+import (
+	"fmt"
+	"testing"
+	"time"
+)
+
+func BenchmarkDeduplicateSamples(b *testing.B) {
+	const blockSize = 8192
+	timestamps := make([]int64, blockSize)
+	values := make([]float64, blockSize)
+	for i := 0; i < len(timestamps); i++ {
+		timestamps[i] = int64(i) * 1e3
+	}
+	for _, minScrapeInterval := range []time.Duration{time.Second, 2 * time.Second, 5 * time.Second, 10 * time.Second} {
+		b.Run(fmt.Sprintf("minScrapeInterval=%s", minScrapeInterval), func(b *testing.B) {
+			SetMinScrapeIntervalForDeduplication(minScrapeInterval)
+			defer SetMinScrapeIntervalForDeduplication(0)
+			b.ReportAllocs()
+			b.SetBytes(blockSize)
+			b.RunParallel(func(pb *testing.PB) {
+				timestampsCopy := make([]int64, 0, blockSize)
+				valuesCopy := make([]float64, 0, blockSize)
+				for pb.Next() {
+					timestampsCopy := append(timestampsCopy[:0], timestamps...)
+					valuesCopy := append(valuesCopy[:0], values...)
+					ts, vs := DeduplicateSamples(timestampsCopy, valuesCopy)
+					if len(ts) == 0 || len(vs) == 0 {
+						panic(fmt.Errorf("expecting non-empty results; got\nts=%v\nvs=%v", ts, vs))
+					}
+				}
+			})
+		})
+	}
+}