Repository: linkerd/linkerd2
Pull request #6335 (2021-06-21 20:52:53)

Bump history from 4.10.1 to 5.0.0 in /web/app
Bumps [history](https://github.com/ReactTraining/history) from 4.10.1 to 5.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/ReactTraining/history/releases">history's releases</a>.</em></p>
<blockquote>
<h2>v5.0.0</h2>
<p>Today we are very pleased to announce the stable release of history version 5!</p>
<h2>Overview</h2>
<p>This version includes many enhancements and fixes a few important issues with the library.</p>
<h3>New Features</h3>
<ul>
<li>Hash history now has support for <code>location.state</code></li>
<li>Better <code>history.block</code> API, with support for retrying transitions</li>
<li>Full TypeScript declarations and IntelliSense docs</li>
<li>Adds development and production builds for <code>&lt;script type=module&gt;</code> users</li>
<li>Both browser and hash history have support for iframes (custom <code>window</code> objects)</li>
<li>About 50% smaller than v4 (and no dependencies)</li>
</ul>
<h3>Bugfixes</h3>
<ul>
<li>Fixed some long-standing encoding issues with <code>location.pathname</code></li>
<li>Removed unfixable warnings about pushing the same path in hash history</li>
<li>Renamed browser global to <code>HistoryLibrary</code> so it doesn't conflict with <code>window.History</code></li>
</ul>
<h3>Breaking Changes</h3>
<ul>
<li>Removed support for browsers that do not support the HTML5 history API (no <code>pushState</code>)</li>
<li>Removed relative pathname support in hash history and memory history</li>
<li>Removed <code>getUserConfirmation</code>, <code>keyLength</code>, and <code>hashType</code> APIs</li>
</ul>
<h2>Usage</h2>
<p>Please refer to <a href="https://github.com/ReactTraining/history/blob/master/docs/installation.md">our installation guide</a> for instructions about how to install the library.</p>
<p>There is also <a href="https://github.com/ReactTraining/history/blob/master/docs/getting-started.md">a getting started guide</a> as well as <a href="https://github.com/ReactTraining/history/blob/master/docs/api-reference.md">a complete API reference</a> in the <code>docs</code> folder.</p>
<p>We are very excited about this release, especially because it will serve as the foundation for the upcoming release of <a href="https://reactrouter.com">React Router</a> version 6.</p>
<p>Thank you for your support. Enjoy! 😀</p>
<h2>v5.0.0-beta.8</h2>
<p>[You can track v5 beta progress in <a href="https://github-redirect.dependabot.com/ReactTraining/history/issues/751">#751</a>](<a href="https://github-redirect.dependabot.com/ReactTraining/history/pull/751">ReactTraining/history#751</a>)</p>
<p>You can install the v5 beta using the <code>next</code> tag: <code>npm add history@next</code></p>
<p><strong>Changes</strong></p>
<p>In this release the core library was converted to TypeScript, and the type declaration files that are published with the npm package are derived from the source instead of being written by hand. This should make them both more accurate and more useful.</p>
<p>A migration guide will be available soon. For now, you can either browse around <a href="https://github.com/ReactTraining/history/tree/dev/docs">the docs on the <code>dev</code> branch</a> or <a href="https://github.com/ReactTraining/history/tree/dev/modules/__tests__">the tests</a>.</p>
<p>Enjoy!</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/ReactTraining/history/commit/026d9e56bdee4e05341b70bae1fb6261fdb80bf0"><code>026d9e5</code></a> Version 5.0.0</li>
<li><a href="https://github.com/ReactTraining/history/commit/ef40006b921c57ef03ae5e5ec6376072095485b1"><code>ef40006</code></a> Remove api doc generation script</li>
<li><a href="https://github.com/ReactTraining/history/commit/9930845d298be5d3bd55b0542d1f670ecf1a4141"><code>9930845</code></a> Update doc links to master branch</li>
<li><a href="https://github.com/ReactTraining/history/commit/987ff43e4489c84c62d1758706d09a38ed100030"><code>987ff43</code></a> Add some more type declarations</li>
<li><a href="https://github.com/ReactTraining/history/commit/4ab6a42082e768b4eafb2b0692220595b8f4feba"><code>4ab6a42</code></a> Restore syntax highlights in declaration blocks</li>
<li><a href="https://github.com/ReactTraining/history/commit/41bacf07dfc317f08c2a7b6222cbd6de7736e9f9"><code>41bacf0</code></a> Add more links to doc comments</li>
<li><a href="https://github.com/ReactTraining/history/commit/a7ae54c646c8f8cf067359ba28b0dcd5fbf5a254"><code>a7ae54c</code></a> More docs + IntelliSense doc comments</li>
<li><a href="https://github.com/ReactTraining/history/commit/1babffe4082c76ed414d5ada7b2c41b3e074d15a"><code>1babffe</code></a> Update API docs</li>
<li><a href="https://github.com/ReactTraining/history/commit/0f95d29539cc6c7b30d4540852d3821ccaf09bd5"><code>0f95d29</code></a> More tweaks to API docs</li>
<li><a href="https://github.com/ReactTraining/history/commit/f88b17451df20db28d92222537bed0f327952834"><code>f88b174</code></a> Small tweaks to api reference</li>
<li>Additional commits viewable in <a href="https://github.com/ReactTraining/history/compare/v4.10.1...v5.0.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=history&package-manager=npm_and_yarn&previous-version=4.10.1&new-version=5.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index a5270fe33..76338f386 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -13,10 +13,10 @@ The Linkerd maintainers are:
 
 The Linkerd Steering Committee members are:
 
-* Chris Campbell @campbel
-* Christian Hüning @christianhuening
-* Justin Turner @justin-turner-heb
-* William King @quentusrex
+* Chris Campbell @campbel (HP)
+* Christian Hüning @christianhuening (finleap connect)
+* Justin Turner @justin-turner-heb (HEB)
+* William King @quentusrex (Subspace)
 
 ## Emeriti
 
diff --git a/bin/protoc b/bin/protoc
index 0939a3f55..184d796ec 100755
--- a/bin/protoc
+++ b/bin/protoc
@@ -11,7 +11,7 @@ arch=$(uname -m)
 
 bindir=$( cd "${0%/*}" && pwd )
 targetbin=$( cd "$bindir"/.. && pwd )/target/bin
-protocversion=3.6.0
+protocversion=3.15.7
 protocbin=$targetbin/protoc-$protocversion
 protocurl=https://github.com/google/protobuf/releases/download/v$protocversion/protoc-$protocversion-$os-$arch.zip
 
diff --git a/bin/protoc-go.sh b/bin/protoc-go.sh
index 16bdde589..48a62cf5d 100755
--- a/bin/protoc-go.sh
+++ b/bin/protoc-go.sh
@@ -5,14 +5,17 @@ set -eu
 bindir=$( cd "${0%/*}" && pwd )
 
 go install -mod=readonly github.com/golang/protobuf/protoc-gen-go
+go install -mod=readonly google.golang.org/grpc/cmd/protoc-gen-go-grpc
 
 rm -rf controller/gen/common controller/gen/config viz/metrics-api/gen viz/tap/gen
 mkdir -p controller/gen/common/net viz/metrics-api/gen/viz viz/tap/gen/tap
 
-"$bindir"/protoc -I proto --go_out=plugins=grpc,paths=source_relative:controller/gen proto/common/net.proto
-"$bindir"/protoc -I proto --go_out=plugins=grpc,paths=source_relative:controller/gen proto/config/config.proto
-"$bindir"/protoc -I proto -I viz/metrics-api/proto --go_out=plugins=grpc,paths=source_relative:viz/metrics-api/gen viz/metrics-api/proto/viz.proto
-"$bindir"/protoc -I proto -I viz/tap/proto -I viz/metrics-api/proto --go_out=plugins=grpc,paths=source_relative:viz/tap/gen viz/tap/proto/viz_tap.proto
+"$bindir"/protoc -I proto --go_out=paths=source_relative:controller/gen proto/common/net.proto
+"$bindir"/protoc -I proto --go_out=paths=source_relative:controller/gen proto/config/config.proto
+"$bindir"/protoc -I proto -I viz/metrics-api/proto --go_out=paths=source_relative:viz/metrics-api/gen viz/metrics-api/proto/viz.proto
+"$bindir"/protoc -I proto -I viz/metrics-api/proto --go-grpc_out=paths=source_relative:viz/metrics-api/gen/viz viz/metrics-api/proto/viz.proto
+"$bindir"/protoc -I proto -I viz/tap/proto -I viz/metrics-api/proto --go_out=paths=source_relative:viz/tap/gen viz/tap/proto/viz_tap.proto
+"$bindir"/protoc -I proto -I viz/tap/proto -I viz/metrics-api/proto --go-grpc_out=paths=source_relative:viz/tap/gen/tap viz/tap/proto/viz_tap.proto
 
 mv controller/gen/common/net.pb.go   controller/gen/common/net/
 mv viz/metrics-api/gen/viz.pb.go viz/metrics-api/gen/viz/viz.pb.go
diff --git a/controller/gen/common/net/net.pb.go b/controller/gen/common/net/net.pb.go
index ceeeba61b..fc5f5979c 100644
--- a/controller/gen/common/net/net.pb.go
+++ b/controller/gen/common/net/net.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.6.0
+// 	protoc        v3.15.7
 // source: common/net.proto
 
 package net
diff --git a/controller/gen/config/config.pb.go b/controller/gen/config/config.pb.go
index efbb46fcf..88675c9ef 100644
--- a/controller/gen/config/config.pb.go
+++ b/controller/gen/config/config.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.6.0
+// 	protoc        v3.15.7
 // source: config/config.proto
 
 package config
diff --git a/go.mod b/go.mod
index b7174e078..3002b354f 100644
--- a/go.mod
+++ b/go.mod
@@ -19,7 +19,7 @@ require (
 	github.com/grantae/certinfo v0.0.0-20170412194111-59d56a35515b
 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
 	github.com/imdario/mergo v0.3.11
-	github.com/julienschmidt/httprouter v1.2.0
+	github.com/julienschmidt/httprouter v1.3.0
 	github.com/linkerd/linkerd2-proxy-api v0.1.18
 	github.com/linkerd/linkerd2-proxy-init v1.3.12
 	github.com/mattn/go-isatty v0.0.12
@@ -28,8 +28,8 @@ require (
 	github.com/onsi/gomega v1.8.1 // indirect
 	github.com/patrickmn/go-cache v2.1.0+incompatible
 	github.com/pkg/browser v0.0.0-20170505125900-c90ca0c84f15
-	github.com/prometheus/client_golang v1.7.1
-	github.com/prometheus/common v0.10.0
+	github.com/prometheus/client_golang v1.11.0
+	github.com/prometheus/common v0.26.0
 	github.com/sergi/go-diff v1.2.0
 	github.com/servicemeshinterface/smi-sdk-go v0.5.0
 	github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect
@@ -41,6 +41,7 @@ require (
 	golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
 	golang.org/x/tools v0.1.3
 	google.golang.org/grpc v1.38.0
+	google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0
 	google.golang.org/protobuf v1.26.0
 	helm.sh/helm/v3 v3.6.1
 	k8s.io/api v0.21.2
diff --git a/go.sum b/go.sum
index 078a56a79..11f0a30b2 100644
--- a/go.sum
+++ b/go.sum
@@ -92,8 +92,9 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
@@ -273,6 +274,7 @@ github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
+github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
@@ -488,16 +490,20 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
 github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
+github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@@ -592,6 +598,8 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P
 github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
 github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
 github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
@@ -672,8 +680,9 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod
 github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
-github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA=
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
+github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
 github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -688,8 +697,9 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
 github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
-github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
+github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
 github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@@ -697,8 +707,9 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
 github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
@@ -924,6 +935,7 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -994,6 +1006,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1003,8 +1016,9 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=
+golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
@@ -1146,6 +1160,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
 google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
 google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
 google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE=
+google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 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/tools.go b/tools.go
index 5692c18b5..5dc96771e 100644
--- a/tools.go
+++ b/tools.go
@@ -6,4 +6,5 @@ import (
 	_ "github.com/shurcooL/vfsgen"
 	_ "golang.org/x/tools/cmd/goimports"
 	_ "k8s.io/code-generator"
+	_ "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
 )
diff --git a/viz/metrics-api/gen/viz/viz.pb.go b/viz/metrics-api/gen/viz/viz.pb.go
index 99924ebb6..b2a4972af 100644
--- a/viz/metrics-api/gen/viz/viz.pb.go
+++ b/viz/metrics-api/gen/viz/viz.pb.go
@@ -1,17 +1,13 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.6.0
+// 	protoc        v3.15.7
 // source: viz.proto
 
 package viz
 
 import (
-	context "context"
 	duration "github.com/golang/protobuf/ptypes/duration"
-	grpc "google.golang.org/grpc"
-	codes "google.golang.org/grpc/codes"
-	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
@@ -4513,299 +4509,3 @@ func file_viz_proto_init() {
 	file_viz_proto_goTypes = nil
 	file_viz_proto_depIdxs = nil
 }
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ context.Context
-var _ grpc.ClientConnInterface
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion6
-
-// ApiClient is the client API for Api service.
-//
-// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
-type ApiClient interface {
-	StatSummary(ctx context.Context, in *StatSummaryRequest, opts ...grpc.CallOption) (*StatSummaryResponse, error)
-	Edges(ctx context.Context, in *EdgesRequest, opts ...grpc.CallOption) (*EdgesResponse, error)
-	Gateways(ctx context.Context, in *GatewaysRequest, opts ...grpc.CallOption) (*GatewaysResponse, error)
-	TopRoutes(ctx context.Context, in *TopRoutesRequest, opts ...grpc.CallOption) (*TopRoutesResponse, error)
-	ListPods(ctx context.Context, in *ListPodsRequest, opts ...grpc.CallOption) (*ListPodsResponse, error)
-	ListServices(ctx context.Context, in *ListServicesRequest, opts ...grpc.CallOption) (*ListServicesResponse, error)
-	SelfCheck(ctx context.Context, in *SelfCheckRequest, opts ...grpc.CallOption) (*SelfCheckResponse, error)
-}
-
-type apiClient struct {
-	cc grpc.ClientConnInterface
-}
-
-func NewApiClient(cc grpc.ClientConnInterface) ApiClient {
-	return &apiClient{cc}
-}
-
-func (c *apiClient) StatSummary(ctx context.Context, in *StatSummaryRequest, opts ...grpc.CallOption) (*StatSummaryResponse, error) {
-	out := new(StatSummaryResponse)
-	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/StatSummary", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *apiClient) Edges(ctx context.Context, in *EdgesRequest, opts ...grpc.CallOption) (*EdgesResponse, error) {
-	out := new(EdgesResponse)
-	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/Edges", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *apiClient) Gateways(ctx context.Context, in *GatewaysRequest, opts ...grpc.CallOption) (*GatewaysResponse, error) {
-	out := new(GatewaysResponse)
-	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/Gateways", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *apiClient) TopRoutes(ctx context.Context, in *TopRoutesRequest, opts ...grpc.CallOption) (*TopRoutesResponse, error) {
-	out := new(TopRoutesResponse)
-	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/TopRoutes", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *apiClient) ListPods(ctx context.Context, in *ListPodsRequest, opts ...grpc.CallOption) (*ListPodsResponse, error) {
-	out := new(ListPodsResponse)
-	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/ListPods", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *apiClient) ListServices(ctx context.Context, in *ListServicesRequest, opts ...grpc.CallOption) (*ListServicesResponse, error) {
-	out := new(ListServicesResponse)
-	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/ListServices", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *apiClient) SelfCheck(ctx context.Context, in *SelfCheckRequest, opts ...grpc.CallOption) (*SelfCheckResponse, error) {
-	out := new(SelfCheckResponse)
-	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/SelfCheck", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-// ApiServer is the server API for Api service.
-type ApiServer interface {
-	StatSummary(context.Context, *StatSummaryRequest) (*StatSummaryResponse, error)
-	Edges(context.Context, *EdgesRequest) (*EdgesResponse, error)
-	Gateways(context.Context, *GatewaysRequest) (*GatewaysResponse, error)
-	TopRoutes(context.Context, *TopRoutesRequest) (*TopRoutesResponse, error)
-	ListPods(context.Context, *ListPodsRequest) (*ListPodsResponse, error)
-	ListServices(context.Context, *ListServicesRequest) (*ListServicesResponse, error)
-	SelfCheck(context.Context, *SelfCheckRequest) (*SelfCheckResponse, error)
-}
-
-// UnimplementedApiServer can be embedded to have forward compatible implementations.
-type UnimplementedApiServer struct {
-}
-
-func (*UnimplementedApiServer) StatSummary(context.Context, *StatSummaryRequest) (*StatSummaryResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method StatSummary not implemented")
-}
-func (*UnimplementedApiServer) Edges(context.Context, *EdgesRequest) (*EdgesResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method Edges not implemented")
-}
-func (*UnimplementedApiServer) Gateways(context.Context, *GatewaysRequest) (*GatewaysResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method Gateways not implemented")
-}
-func (*UnimplementedApiServer) TopRoutes(context.Context, *TopRoutesRequest) (*TopRoutesResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method TopRoutes not implemented")
-}
-func (*UnimplementedApiServer) ListPods(context.Context, *ListPodsRequest) (*ListPodsResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method ListPods not implemented")
-}
-func (*UnimplementedApiServer) ListServices(context.Context, *ListServicesRequest) (*ListServicesResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method ListServices not implemented")
-}
-func (*UnimplementedApiServer) SelfCheck(context.Context, *SelfCheckRequest) (*SelfCheckResponse, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method SelfCheck not implemented")
-}
-
-func RegisterApiServer(s *grpc.Server, srv ApiServer) {
-	s.RegisterService(&_Api_serviceDesc, srv)
-}
-
-func _Api_StatSummary_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(StatSummaryRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ApiServer).StatSummary(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/linkerd2.viz.Api/StatSummary",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ApiServer).StatSummary(ctx, req.(*StatSummaryRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _Api_Edges_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(EdgesRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ApiServer).Edges(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/linkerd2.viz.Api/Edges",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ApiServer).Edges(ctx, req.(*EdgesRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _Api_Gateways_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(GatewaysRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ApiServer).Gateways(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/linkerd2.viz.Api/Gateways",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ApiServer).Gateways(ctx, req.(*GatewaysRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _Api_TopRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(TopRoutesRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ApiServer).TopRoutes(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/linkerd2.viz.Api/TopRoutes",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ApiServer).TopRoutes(ctx, req.(*TopRoutesRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _Api_ListPods_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(ListPodsRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ApiServer).ListPods(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/linkerd2.viz.Api/ListPods",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ApiServer).ListPods(ctx, req.(*ListPodsRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _Api_ListServices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(ListServicesRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ApiServer).ListServices(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/linkerd2.viz.Api/ListServices",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ApiServer).ListServices(ctx, req.(*ListServicesRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _Api_SelfCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(SelfCheckRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(ApiServer).SelfCheck(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/linkerd2.viz.Api/SelfCheck",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(ApiServer).SelfCheck(ctx, req.(*SelfCheckRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-var _Api_serviceDesc = grpc.ServiceDesc{
-	ServiceName: "linkerd2.viz.Api",
-	HandlerType: (*ApiServer)(nil),
-	Methods: []grpc.MethodDesc{
-		{
-			MethodName: "StatSummary",
-			Handler:    _Api_StatSummary_Handler,
-		},
-		{
-			MethodName: "Edges",
-			Handler:    _Api_Edges_Handler,
-		},
-		{
-			MethodName: "Gateways",
-			Handler:    _Api_Gateways_Handler,
-		},
-		{
-			MethodName: "TopRoutes",
-			Handler:    _Api_TopRoutes_Handler,
-		},
-		{
-			MethodName: "ListPods",
-			Handler:    _Api_ListPods_Handler,
-		},
-		{
-			MethodName: "ListServices",
-			Handler:    _Api_ListServices_Handler,
-		},
-		{
-			MethodName: "SelfCheck",
-			Handler:    _Api_SelfCheck_Handler,
-		},
-	},
-	Streams:  []grpc.StreamDesc{},
-	Metadata: "viz.proto",
-}
diff --git a/viz/metrics-api/gen/viz/viz_grpc.pb.go b/viz/metrics-api/gen/viz/viz_grpc.pb.go
new file mode 100644
index 000000000..953b4166d
--- /dev/null
+++ b/viz/metrics-api/gen/viz/viz_grpc.pb.go
@@ -0,0 +1,317 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+
+package viz
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// ApiClient is the client API for Api service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type ApiClient interface {
+	StatSummary(ctx context.Context, in *StatSummaryRequest, opts ...grpc.CallOption) (*StatSummaryResponse, error)
+	Edges(ctx context.Context, in *EdgesRequest, opts ...grpc.CallOption) (*EdgesResponse, error)
+	Gateways(ctx context.Context, in *GatewaysRequest, opts ...grpc.CallOption) (*GatewaysResponse, error)
+	TopRoutes(ctx context.Context, in *TopRoutesRequest, opts ...grpc.CallOption) (*TopRoutesResponse, error)
+	ListPods(ctx context.Context, in *ListPodsRequest, opts ...grpc.CallOption) (*ListPodsResponse, error)
+	ListServices(ctx context.Context, in *ListServicesRequest, opts ...grpc.CallOption) (*ListServicesResponse, error)
+	SelfCheck(ctx context.Context, in *SelfCheckRequest, opts ...grpc.CallOption) (*SelfCheckResponse, error)
+}
+
+type apiClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewApiClient(cc grpc.ClientConnInterface) ApiClient {
+	return &apiClient{cc}
+}
+
+func (c *apiClient) StatSummary(ctx context.Context, in *StatSummaryRequest, opts ...grpc.CallOption) (*StatSummaryResponse, error) {
+	out := new(StatSummaryResponse)
+	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/StatSummary", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *apiClient) Edges(ctx context.Context, in *EdgesRequest, opts ...grpc.CallOption) (*EdgesResponse, error) {
+	out := new(EdgesResponse)
+	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/Edges", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *apiClient) Gateways(ctx context.Context, in *GatewaysRequest, opts ...grpc.CallOption) (*GatewaysResponse, error) {
+	out := new(GatewaysResponse)
+	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/Gateways", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *apiClient) TopRoutes(ctx context.Context, in *TopRoutesRequest, opts ...grpc.CallOption) (*TopRoutesResponse, error) {
+	out := new(TopRoutesResponse)
+	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/TopRoutes", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *apiClient) ListPods(ctx context.Context, in *ListPodsRequest, opts ...grpc.CallOption) (*ListPodsResponse, error) {
+	out := new(ListPodsResponse)
+	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/ListPods", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *apiClient) ListServices(ctx context.Context, in *ListServicesRequest, opts ...grpc.CallOption) (*ListServicesResponse, error) {
+	out := new(ListServicesResponse)
+	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/ListServices", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+func (c *apiClient) SelfCheck(ctx context.Context, in *SelfCheckRequest, opts ...grpc.CallOption) (*SelfCheckResponse, error) {
+	out := new(SelfCheckResponse)
+	err := c.cc.Invoke(ctx, "/linkerd2.viz.Api/SelfCheck", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// ApiServer is the server API for Api service.
+// All implementations must embed UnimplementedApiServer
+// for forward compatibility
+type ApiServer interface {
+	StatSummary(context.Context, *StatSummaryRequest) (*StatSummaryResponse, error)
+	Edges(context.Context, *EdgesRequest) (*EdgesResponse, error)
+	Gateways(context.Context, *GatewaysRequest) (*GatewaysResponse, error)
+	TopRoutes(context.Context, *TopRoutesRequest) (*TopRoutesResponse, error)
+	ListPods(context.Context, *ListPodsRequest) (*ListPodsResponse, error)
+	ListServices(context.Context, *ListServicesRequest) (*ListServicesResponse, error)
+	SelfCheck(context.Context, *SelfCheckRequest) (*SelfCheckResponse, error)
+	mustEmbedUnimplementedApiServer()
+}
+
+// UnimplementedApiServer must be embedded to have forward compatible implementations.
+type UnimplementedApiServer struct {
+}
+
+func (UnimplementedApiServer) StatSummary(context.Context, *StatSummaryRequest) (*StatSummaryResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method StatSummary not implemented")
+}
+func (UnimplementedApiServer) Edges(context.Context, *EdgesRequest) (*EdgesResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Edges not implemented")
+}
+func (UnimplementedApiServer) Gateways(context.Context, *GatewaysRequest) (*GatewaysResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Gateways not implemented")
+}
+func (UnimplementedApiServer) TopRoutes(context.Context, *TopRoutesRequest) (*TopRoutesResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method TopRoutes not implemented")
+}
+func (UnimplementedApiServer) ListPods(context.Context, *ListPodsRequest) (*ListPodsResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method ListPods not implemented")
+}
+func (UnimplementedApiServer) ListServices(context.Context, *ListServicesRequest) (*ListServicesResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method ListServices not implemented")
+}
+func (UnimplementedApiServer) SelfCheck(context.Context, *SelfCheckRequest) (*SelfCheckResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method SelfCheck not implemented")
+}
+func (UnimplementedApiServer) mustEmbedUnimplementedApiServer() {}
+
+// UnsafeApiServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to ApiServer will
+// result in compilation errors.
+type UnsafeApiServer interface {
+	mustEmbedUnimplementedApiServer()
+}
+
+func RegisterApiServer(s grpc.ServiceRegistrar, srv ApiServer) {
+	s.RegisterService(&Api_ServiceDesc, srv)
+}
+
+func _Api_StatSummary_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(StatSummaryRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ApiServer).StatSummary(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/linkerd2.viz.Api/StatSummary",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ApiServer).StatSummary(ctx, req.(*StatSummaryRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Api_Edges_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(EdgesRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ApiServer).Edges(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/linkerd2.viz.Api/Edges",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ApiServer).Edges(ctx, req.(*EdgesRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Api_Gateways_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GatewaysRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ApiServer).Gateways(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/linkerd2.viz.Api/Gateways",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ApiServer).Gateways(ctx, req.(*GatewaysRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Api_TopRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(TopRoutesRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ApiServer).TopRoutes(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/linkerd2.viz.Api/TopRoutes",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ApiServer).TopRoutes(ctx, req.(*TopRoutesRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Api_ListPods_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ListPodsRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ApiServer).ListPods(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/linkerd2.viz.Api/ListPods",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ApiServer).ListPods(ctx, req.(*ListPodsRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Api_ListServices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(ListServicesRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ApiServer).ListServices(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/linkerd2.viz.Api/ListServices",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ApiServer).ListServices(ctx, req.(*ListServicesRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+func _Api_SelfCheck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(SelfCheckRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(ApiServer).SelfCheck(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/linkerd2.viz.Api/SelfCheck",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(ApiServer).SelfCheck(ctx, req.(*SelfCheckRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+// Api_ServiceDesc is the grpc.ServiceDesc for Api service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Api_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "linkerd2.viz.Api",
+	HandlerType: (*ApiServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "StatSummary",
+			Handler:    _Api_StatSummary_Handler,
+		},
+		{
+			MethodName: "Edges",
+			Handler:    _Api_Edges_Handler,
+		},
+		{
+			MethodName: "Gateways",
+			Handler:    _Api_Gateways_Handler,
+		},
+		{
+			MethodName: "TopRoutes",
+			Handler:    _Api_TopRoutes_Handler,
+		},
+		{
+			MethodName: "ListPods",
+			Handler:    _Api_ListPods_Handler,
+		},
+		{
+			MethodName: "ListServices",
+			Handler:    _Api_ListServices_Handler,
+		},
+		{
+			MethodName: "SelfCheck",
+			Handler:    _Api_SelfCheck_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "viz.proto",
+}
diff --git a/viz/metrics-api/grpc_server.go b/viz/metrics-api/grpc_server.go
index 62985a8d2..a5af5bf35 100644
--- a/viz/metrics-api/grpc_server.go
+++ b/viz/metrics-api/grpc_server.go
@@ -24,6 +24,7 @@ type Server interface {
 }
 
 type grpcServer struct {
+	pb.UnimplementedApiServer
 	prometheusAPI       promv1.API
 	k8sAPI              *k8s.API
 	controllerNamespace string
diff --git a/viz/tap/api/grpc_server.go b/viz/tap/api/grpc_server.go
index ac674e3ad..2ffb3a731 100644
--- a/viz/tap/api/grpc_server.go
+++ b/viz/tap/api/grpc_server.go
@@ -37,6 +37,7 @@ const defaultMaxRps = 100.0
 
 // GRPCTapServer describes the gRPC server implementing pb.TapServer
 type GRPCTapServer struct {
+	tapPb.UnimplementedTapServer
 	tapPort             uint
 	k8sAPI              *k8s.API
 	controllerNamespace string
diff --git a/viz/tap/gen/tap/viz_tap.pb.go b/viz/tap/gen/tap/viz_tap.pb.go
index bc492174f..20b0f8de8 100644
--- a/viz/tap/gen/tap/viz_tap.pb.go
+++ b/viz/tap/gen/tap/viz_tap.pb.go
@@ -1,19 +1,15 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
 // 	protoc-gen-go v1.26.0
-// 	protoc        v3.6.0
+// 	protoc        v3.15.7
 // source: viz_tap.proto
 
 package tap
 
 import (
-	context "context"
 	duration "github.com/golang/protobuf/ptypes/duration"
 	net "github.com/linkerd/linkerd2/controller/gen/common/net"
 	viz "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
-	grpc "google.golang.org/grpc"
-	codes "google.golang.org/grpc/codes"
-	status "google.golang.org/grpc/status"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
@@ -1935,179 +1931,3 @@ func file_viz_tap_proto_init() {
 	file_viz_tap_proto_goTypes = nil
 	file_viz_tap_proto_depIdxs = nil
 }
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ context.Context
-var _ grpc.ClientConnInterface
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion6
-
-// TapClient is the client API for Tap service.
-//
-// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
-type TapClient interface {
-	// Deprecated: Do not use.
-	Tap(ctx context.Context, in *TapRequest, opts ...grpc.CallOption) (Tap_TapClient, error)
-	// Deprecated: Do not use.
-	TapByResource(ctx context.Context, in *TapByResourceRequest, opts ...grpc.CallOption) (Tap_TapByResourceClient, error)
-}
-
-type tapClient struct {
-	cc grpc.ClientConnInterface
-}
-
-func NewTapClient(cc grpc.ClientConnInterface) TapClient {
-	return &tapClient{cc}
-}
-
-// Deprecated: Do not use.
-func (c *tapClient) Tap(ctx context.Context, in *TapRequest, opts ...grpc.CallOption) (Tap_TapClient, error) {
-	stream, err := c.cc.NewStream(ctx, &_Tap_serviceDesc.Streams[0], "/linkerd2.tap.Tap/Tap", opts...)
-	if err != nil {
-		return nil, err
-	}
-	x := &tapTapClient{stream}
-	if err := x.ClientStream.SendMsg(in); err != nil {
-		return nil, err
-	}
-	if err := x.ClientStream.CloseSend(); err != nil {
-		return nil, err
-	}
-	return x, nil
-}
-
-type Tap_TapClient interface {
-	Recv() (*TapEvent, error)
-	grpc.ClientStream
-}
-
-type tapTapClient struct {
-	grpc.ClientStream
-}
-
-func (x *tapTapClient) Recv() (*TapEvent, error) {
-	m := new(TapEvent)
-	if err := x.ClientStream.RecvMsg(m); err != nil {
-		return nil, err
-	}
-	return m, nil
-}
-
-// Deprecated: Do not use.
-func (c *tapClient) TapByResource(ctx context.Context, in *TapByResourceRequest, opts ...grpc.CallOption) (Tap_TapByResourceClient, error) {
-	stream, err := c.cc.NewStream(ctx, &_Tap_serviceDesc.Streams[1], "/linkerd2.tap.Tap/TapByResource", opts...)
-	if err != nil {
-		return nil, err
-	}
-	x := &tapTapByResourceClient{stream}
-	if err := x.ClientStream.SendMsg(in); err != nil {
-		return nil, err
-	}
-	if err := x.ClientStream.CloseSend(); err != nil {
-		return nil, err
-	}
-	return x, nil
-}
-
-type Tap_TapByResourceClient interface {
-	Recv() (*TapEvent, error)
-	grpc.ClientStream
-}
-
-type tapTapByResourceClient struct {
-	grpc.ClientStream
-}
-
-func (x *tapTapByResourceClient) Recv() (*TapEvent, error) {
-	m := new(TapEvent)
-	if err := x.ClientStream.RecvMsg(m); err != nil {
-		return nil, err
-	}
-	return m, nil
-}
-
-// TapServer is the server API for Tap service.
-type TapServer interface {
-	// Deprecated: Do not use.
-	Tap(*TapRequest, Tap_TapServer) error
-	// Deprecated: Do not use.
-	TapByResource(*TapByResourceRequest, Tap_TapByResourceServer) error
-}
-
-// UnimplementedTapServer can be embedded to have forward compatible implementations.
-type UnimplementedTapServer struct {
-}
-
-func (*UnimplementedTapServer) Tap(*TapRequest, Tap_TapServer) error {
-	return status.Errorf(codes.Unimplemented, "method Tap not implemented")
-}
-func (*UnimplementedTapServer) TapByResource(*TapByResourceRequest, Tap_TapByResourceServer) error {
-	return status.Errorf(codes.Unimplemented, "method TapByResource not implemented")
-}
-
-func RegisterTapServer(s *grpc.Server, srv TapServer) {
-	s.RegisterService(&_Tap_serviceDesc, srv)
-}
-
-func _Tap_Tap_Handler(srv interface{}, stream grpc.ServerStream) error {
-	m := new(TapRequest)
-	if err := stream.RecvMsg(m); err != nil {
-		return err
-	}
-	return srv.(TapServer).Tap(m, &tapTapServer{stream})
-}
-
-type Tap_TapServer interface {
-	Send(*TapEvent) error
-	grpc.ServerStream
-}
-
-type tapTapServer struct {
-	grpc.ServerStream
-}
-
-func (x *tapTapServer) Send(m *TapEvent) error {
-	return x.ServerStream.SendMsg(m)
-}
-
-func _Tap_TapByResource_Handler(srv interface{}, stream grpc.ServerStream) error {
-	m := new(TapByResourceRequest)
-	if err := stream.RecvMsg(m); err != nil {
-		return err
-	}
-	return srv.(TapServer).TapByResource(m, &tapTapByResourceServer{stream})
-}
-
-type Tap_TapByResourceServer interface {
-	Send(*TapEvent) error
-	grpc.ServerStream
-}
-
-type tapTapByResourceServer struct {
-	grpc.ServerStream
-}
-
-func (x *tapTapByResourceServer) Send(m *TapEvent) error {
-	return x.ServerStream.SendMsg(m)
-}
-
-var _Tap_serviceDesc = grpc.ServiceDesc{
-	ServiceName: "linkerd2.tap.Tap",
-	HandlerType: (*TapServer)(nil),
-	Methods:     []grpc.MethodDesc{},
-	Streams: []grpc.StreamDesc{
-		{
-			StreamName:    "Tap",
-			Handler:       _Tap_Tap_Handler,
-			ServerStreams: true,
-		},
-		{
-			StreamName:    "TapByResource",
-			Handler:       _Tap_TapByResource_Handler,
-			ServerStreams: true,
-		},
-	},
-	Metadata: "viz_tap.proto",
-}
diff --git a/viz/tap/gen/tap/viz_tap_grpc.pb.go b/viz/tap/gen/tap/viz_tap_grpc.pb.go
new file mode 100644
index 000000000..5085a7a2c
--- /dev/null
+++ b/viz/tap/gen/tap/viz_tap_grpc.pb.go
@@ -0,0 +1,197 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+
+package tap
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// TapClient is the client API for Tap service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type TapClient interface {
+	// Deprecated: Do not use.
+	Tap(ctx context.Context, in *TapRequest, opts ...grpc.CallOption) (Tap_TapClient, error)
+	// Deprecated: Do not use.
+	TapByResource(ctx context.Context, in *TapByResourceRequest, opts ...grpc.CallOption) (Tap_TapByResourceClient, error)
+}
+
+type tapClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewTapClient(cc grpc.ClientConnInterface) TapClient {
+	return &tapClient{cc}
+}
+
+// Deprecated: Do not use.
+func (c *tapClient) Tap(ctx context.Context, in *TapRequest, opts ...grpc.CallOption) (Tap_TapClient, error) {
+	stream, err := c.cc.NewStream(ctx, &Tap_ServiceDesc.Streams[0], "/linkerd2.tap.Tap/Tap", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &tapTapClient{stream}
+	if err := x.ClientStream.SendMsg(in); err != nil {
+		return nil, err
+	}
+	if err := x.ClientStream.CloseSend(); err != nil {
+		return nil, err
+	}
+	return x, nil
+}
+
+type Tap_TapClient interface {
+	Recv() (*TapEvent, error)
+	grpc.ClientStream
+}
+
+type tapTapClient struct {
+	grpc.ClientStream
+}
+
+func (x *tapTapClient) Recv() (*TapEvent, error) {
+	m := new(TapEvent)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+// Deprecated: Do not use.
+func (c *tapClient) TapByResource(ctx context.Context, in *TapByResourceRequest, opts ...grpc.CallOption) (Tap_TapByResourceClient, error) {
+	stream, err := c.cc.NewStream(ctx, &Tap_ServiceDesc.Streams[1], "/linkerd2.tap.Tap/TapByResource", opts...)
+	if err != nil {
+		return nil, err
+	}
+	x := &tapTapByResourceClient{stream}
+	if err := x.ClientStream.SendMsg(in); err != nil {
+		return nil, err
+	}
+	if err := x.ClientStream.CloseSend(); err != nil {
+		return nil, err
+	}
+	return x, nil
+}
+
+type Tap_TapByResourceClient interface {
+	Recv() (*TapEvent, error)
+	grpc.ClientStream
+}
+
+type tapTapByResourceClient struct {
+	grpc.ClientStream
+}
+
+func (x *tapTapByResourceClient) Recv() (*TapEvent, error) {
+	m := new(TapEvent)
+	if err := x.ClientStream.RecvMsg(m); err != nil {
+		return nil, err
+	}
+	return m, nil
+}
+
+// TapServer is the server API for Tap service.
+// All implementations must embed UnimplementedTapServer
+// for forward compatibility
+type TapServer interface {
+	// Deprecated: Do not use.
+	Tap(*TapRequest, Tap_TapServer) error
+	// Deprecated: Do not use.
+	TapByResource(*TapByResourceRequest, Tap_TapByResourceServer) error
+	mustEmbedUnimplementedTapServer()
+}
+
+// UnimplementedTapServer must be embedded to have forward compatible implementations.
+type UnimplementedTapServer struct {
+}
+
+func (UnimplementedTapServer) Tap(*TapRequest, Tap_TapServer) error {
+	return status.Errorf(codes.Unimplemented, "method Tap not implemented")
+}
+func (UnimplementedTapServer) TapByResource(*TapByResourceRequest, Tap_TapByResourceServer) error {
+	return status.Errorf(codes.Unimplemented, "method TapByResource not implemented")
+}
+func (UnimplementedTapServer) mustEmbedUnimplementedTapServer() {}
+
+// UnsafeTapServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to TapServer will
+// result in compilation errors.
+type UnsafeTapServer interface {
+	mustEmbedUnimplementedTapServer()
+}
+
+func RegisterTapServer(s grpc.ServiceRegistrar, srv TapServer) {
+	s.RegisterService(&Tap_ServiceDesc, srv)
+}
+
+func _Tap_Tap_Handler(srv interface{}, stream grpc.ServerStream) error {
+	m := new(TapRequest)
+	if err := stream.RecvMsg(m); err != nil {
+		return err
+	}
+	return srv.(TapServer).Tap(m, &tapTapServer{stream})
+}
+
+type Tap_TapServer interface {
+	Send(*TapEvent) error
+	grpc.ServerStream
+}
+
+type tapTapServer struct {
+	grpc.ServerStream
+}
+
+func (x *tapTapServer) Send(m *TapEvent) error {
+	return x.ServerStream.SendMsg(m)
+}
+
+func _Tap_TapByResource_Handler(srv interface{}, stream grpc.ServerStream) error {
+	m := new(TapByResourceRequest)
+	if err := stream.RecvMsg(m); err != nil {
+		return err
+	}
+	return srv.(TapServer).TapByResource(m, &tapTapByResourceServer{stream})
+}
+
+type Tap_TapByResourceServer interface {
+	Send(*TapEvent) error
+	grpc.ServerStream
+}
+
+type tapTapByResourceServer struct {
+	grpc.ServerStream
+}
+
+func (x *tapTapByResourceServer) Send(m *TapEvent) error {
+	return x.ServerStream.SendMsg(m)
+}
+
+// Tap_ServiceDesc is the grpc.ServiceDesc for Tap service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Tap_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "linkerd2.tap.Tap",
+	HandlerType: (*TapServer)(nil),
+	Methods:     []grpc.MethodDesc{},
+	Streams: []grpc.StreamDesc{
+		{
+			StreamName:    "Tap",
+			Handler:       _Tap_Tap_Handler,
+			ServerStreams: true,
+		},
+		{
+			StreamName:    "TapByResource",
+			Handler:       _Tap_TapByResource_Handler,
+			ServerStreams: true,
+		},
+	},
+	Metadata: "viz_tap.proto",
+}
diff --git a/web/app/package.json b/web/app/package.json
index 24683e8a8..70598b7dd 100644
--- a/web/app/package.json
+++ b/web/app/package.json
@@ -32,7 +32,7 @@
     "react-page-visibility": "^6.1.0",
     "react-router": "5.1.2",
     "react-router-dom": "5.1.2",
-    "react-router-prop-types": "1.0.4",
+    "react-router-prop-types": "1.0.5",
     "use-query-params": "1.1.1",
     "whatwg-fetch": "3.0.0"
   },
@@ -70,7 +70,7 @@
     "eslint-plugin-react-hooks": "^4.2.0",
     "eslint-webpack-plugin": "^2.5.3",
     "file-loader": "^6.2.0",
-    "history": "4.10.1",
+    "history": "5.0.0",
     "html-webpack-plugin": "^5.3.1",
     "jest": "^26.6.3",
     "jest-dot-reporter": "1.0.14",
@@ -83,7 +83,7 @@
     "url-loader": "^4.1.1",
     "wdio-chromedriver-service": "6.0.2",
     "webdriverio": "6.1.2",
-    "webpack": "^5.28.0",
+    "webpack": "^5.40.0",
     "webpack-bundle-analyzer": "4.4.0",
     "webpack-cli": "4.5.0",
     "webpack-dev-server": "3.11.2"
diff --git a/web/app/yarn.lock b/web/app/yarn.lock
index cbc9a819b..9fcd5ce22 100644
--- a/web/app/yarn.lock
+++ b/web/app/yarn.lock
@@ -953,10 +953,10 @@
     core-js-pure "^3.0.0"
     regenerator-runtime "^0.13.4"
 
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
-  version "7.13.10"
-  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d"
-  integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
+  version "7.14.6"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
+  integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
   dependencies:
     regenerator-runtime "^0.13.4"
 
@@ -1649,16 +1649,11 @@
     "@types/estree" "*"
     "@types/json-schema" "*"
 
-"@types/estree@*":
+"@types/estree@*", "@types/estree@^0.0.47":
   version "0.0.47"
   resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4"
   integrity sha512-c5ciR06jK8u9BstrmJyO97m+klJrrhCf9u3rLu3DEAJBirxRqSCvDQoYKmxuYwQI5SZChAWu+tq9oVlGRuzPAg==
 
-"@types/estree@^0.0.46":
-  version "0.0.46"
-  resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe"
-  integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==
-
 "@types/glob@^7.1.1":
   version "7.1.3"
   resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
@@ -1753,7 +1748,7 @@
   resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.3.tgz#ef65165aea2924c9359205bf748865b8881753c0"
   integrity sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA==
 
-"@types/prop-types@*", "@types/prop-types@^15.5.3":
+"@types/prop-types@*", "@types/prop-types@^15.7.3":
   version "15.7.3"
   resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
   integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
@@ -2250,10 +2245,10 @@ acorn@^7.1.1, acorn@^7.4.0:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
   integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
 
-acorn@^8.0.4, acorn@^8.0.5:
-  version "8.1.0"
-  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe"
-  integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==
+acorn@^8.0.4, acorn@^8.0.5, acorn@^8.2.1:
+  version "8.4.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.0.tgz#af53266e698d7cffa416714b503066a82221be60"
+  integrity sha512-ULr0LDaEqQrMFGyQ3bhJkLsbtrQ8QibAseGZeaSUiT/6zb9IvIkomWHJIvgvwad+hinRAgsI51JcWk2yvwyL+w==
 
 agent-base@5:
   version "5.1.1"
@@ -4474,10 +4469,10 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1:
   dependencies:
     once "^1.4.0"
 
-enhanced-resolve@^5.7.0:
-  version "5.7.0"
-  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.7.0.tgz#525c5d856680fbd5052de453ac83e32049958b5c"
-  integrity sha512-6njwt/NsZFUKhM6j9U8hzVyD4E4r0x7NQzhTCbcWOJ0IQjNSAoalWmb0AE51Wn+fwan5qVESWi7t2ToBxs9vrw==
+enhanced-resolve@^5.8.0:
+  version "5.8.2"
+  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz#15ddc779345cbb73e97c611cd00c01c1e7bf4d8b"
+  integrity sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==
   dependencies:
     graceful-fs "^4.2.4"
     tapable "^2.2.0"
@@ -4626,10 +4621,10 @@ es-abstract@^1.17.4, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2:
     string.prototype.trimstart "^1.0.4"
     unbox-primitive "^1.0.0"
 
-es-module-lexer@^0.4.0:
-  version "0.4.1"
-  resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.4.1.tgz#dda8c6a14d8f340a24e34331e0fab0cb50438e0e"
-  integrity sha512-ooYciCUtfw6/d2w56UVeqHPcoCFAiJdz5XOkYpv/Txl1HMUozpXjz/2RIQgqwKdXNDPSF1W7mJCFse3G+HDyAA==
+es-module-lexer@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.6.0.tgz#e72ab05b7412e62b9be37c37a09bdb6000d706f0"
+  integrity sha512-f8kcHX1ArhllUtb/wVSyvygoKCznIjnxhLxy7TCvIiMdT7fL4ZDTIKaadMe6eLvOXg6Wk02UeoFgUoZ2EKZZUA==
 
 es-to-primitive@^1.2.1:
   version "1.2.1"
@@ -4800,7 +4795,7 @@ eslint-scope@5.1.0:
     esrecurse "^4.1.0"
     estraverse "^4.1.1"
 
-eslint-scope@^5.1.1:
+eslint-scope@5.1.1, eslint-scope@^5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
   integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
@@ -5770,7 +5765,14 @@ he@1.2.0, he@^1.2.0:
   resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
   integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
 
-history@4.10.1, history@^4.9.0:
+history@5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/history/-/history-5.0.0.tgz#0cabbb6c4bbf835addb874f8259f6d25101efd08"
+  integrity sha512-3NyRMKIiFSJmIPdq7FxkNMJkQ7ZEtVblOQ38VtKaA0zZMW1Eo6Q6W8oDKEflr1kNNTItSnk4JMCO1deeSgbLLg==
+  dependencies:
+    "@babel/runtime" "^7.7.6"
+
+history@^4.9.0:
   version "4.10.1"
   resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
   integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
@@ -7130,6 +7132,15 @@ jest-worker@^26.6.2:
     merge-stream "^2.0.0"
     supports-color "^7.0.0"
 
+jest-worker@^27.0.2:
+  version "27.0.2"
+  resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.2.tgz#4ebeb56cef48b3e7514552f80d0d80c0129f0b05"
+  integrity sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg==
+  dependencies:
+    "@types/node" "*"
+    merge-stream "^2.0.0"
+    supports-color "^8.0.0"
+
 jest@^26.6.3:
   version "26.6.3"
   resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef"
@@ -9010,7 +9021,7 @@ prop-types-exact@^1.2.0:
     object.assign "^4.1.0"
     reflect.ownkeys "^0.2.0"
 
-prop-types@15.7.2, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
+prop-types@15.7.2, prop-types@^15.6.2, prop-types@^15.7.2:
   version "15.7.2"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
   integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -9251,13 +9262,13 @@ react-router-dom@5.1.2:
     tiny-invariant "^1.0.2"
     tiny-warning "^1.0.0"
 
-react-router-prop-types@1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/react-router-prop-types/-/react-router-prop-types-1.0.4.tgz#74716e92d014bb51ee4376ee198f34903cf8dc1d"
-  integrity sha512-tXDQe0pnBTXjFivBa69hYibtgI3hz+Q/VmhMT7vIzYVPv574dd+lIuBIWOBH9dZkHeSuD6iur6zkmss3QVTeew==
+react-router-prop-types@1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/react-router-prop-types/-/react-router-prop-types-1.0.5.tgz#2e671d8412a793106bf70dc15c9ecc83ea4bc15b"
+  integrity sha512-q1xlFU2ol2U5zeVbA5hyBuxD3scHenqgMgCTuJQUanA2SyG8A3Fb1S6DleOo1cnGJB5Q05hnLge64kRj+xsuPA==
   dependencies:
-    "@types/prop-types" "^15.5.3"
-    prop-types "^15.6.1"
+    "@types/prop-types" "^15.7.3"
+    prop-types "^15.7.2"
 
 react-router@5.1.2:
   version "5.1.2"
@@ -10516,6 +10527,13 @@ supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0:
   dependencies:
     has-flag "^4.0.0"
 
+supports-color@^8.0.0:
+  version "8.1.1"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+  integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+  dependencies:
+    has-flag "^4.0.0"
+
 supports-hyperlinks@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47"
@@ -10588,17 +10606,17 @@ terminal-link@^2.0.0:
     ansi-escapes "^4.2.1"
     supports-hyperlinks "^2.0.0"
 
-terser-webpack-plugin@^5.1.1:
-  version "5.1.1"
-  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz#7effadee06f7ecfa093dbbd3e9ab23f5f3ed8673"
-  integrity sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==
+terser-webpack-plugin@^5.1.3:
+  version "5.1.3"
+  resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.1.3.tgz#30033e955ca28b55664f1e4b30a1347e61aa23af"
+  integrity sha512-cxGbMqr6+A2hrIB5ehFIF+F/iST5ZOxvOmy9zih9ySbP1C2oEWQSOUS+2SNBTjzx5xLKO4xnod9eywdfq1Nb9A==
   dependencies:
-    jest-worker "^26.6.2"
+    jest-worker "^27.0.2"
     p-limit "^3.1.0"
     schema-utils "^3.0.0"
     serialize-javascript "^5.0.1"
     source-map "^0.6.1"
-    terser "^5.5.1"
+    terser "^5.7.0"
 
 terser@^4.6.3:
   version "4.8.0"
@@ -10609,10 +10627,10 @@ terser@^4.6.3:
     source-map "~0.6.1"
     source-map-support "~0.5.12"
 
-terser@^5.5.1:
-  version "5.6.1"
-  resolved "https://registry.yarnpkg.com/terser/-/terser-5.6.1.tgz#a48eeac5300c0a09b36854bf90d9c26fb201973c"
-  integrity sha512-yv9YLFQQ+3ZqgWCUk+pvNJwgUTdlIxUk1WTN+RnaFJe2L7ipG2csPT0ra2XRm7Cs8cxN7QXmK1rFzEwYEQkzXw==
+terser@^5.7.0:
+  version "5.7.0"
+  resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.0.tgz#a761eeec206bc87b605ab13029876ead938ae693"
+  integrity sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==
   dependencies:
     commander "^2.20.0"
     source-map "~0.7.2"
@@ -11131,10 +11149,10 @@ walker@^1.0.7, walker@~1.0.5:
   dependencies:
     makeerror "1.0.x"
 
-watchpack@^2.0.0:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.1.1.tgz#e99630550fca07df9f90a06056987baa40a689c7"
-  integrity sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==
+watchpack@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce"
+  integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==
   dependencies:
     glob-to-regexp "^0.4.1"
     graceful-fs "^4.1.2"
@@ -11353,30 +11371,30 @@ webpack-merge@^5.7.3:
     clone-deep "^4.0.1"
     wildcard "^2.0.0"
 
-webpack-sources@^2.1.1:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.2.0.tgz#058926f39e3d443193b6c31547229806ffd02bac"
-  integrity sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==
+webpack-sources@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.0.tgz#9ed2de69b25143a4c18847586ad9eccb19278cfa"
+  integrity sha512-WyOdtwSvOML1kbgtXbTDnEW0jkJ7hZr/bDByIwszhWd/4XX1A3XMkrbFMsuH4+/MfLlZCUzlAdg4r7jaGKEIgQ==
   dependencies:
     source-list-map "^2.0.1"
     source-map "^0.6.1"
 
-webpack@^5.28.0:
-  version "5.28.0"
-  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.28.0.tgz#0de8bcd706186b26da09d4d1e8cbd3e4025a7c2f"
-  integrity sha512-1xllYVmA4dIvRjHzwELgW4KjIU1fW4PEuEnjsylz7k7H5HgPOctIq7W1jrt3sKH9yG5d72//XWzsHhfoWvsQVg==
+webpack@^5.40.0:
+  version "5.40.0"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.40.0.tgz#3182cfd324759d715252cf541901a226e57b5061"
+  integrity sha512-c7f5e/WWrxXWUzQqTBg54vBs5RgcAgpvKE4F4VegVgfo4x660ZxYUF2/hpMkZUnLjgytVTitjeXaN4IPlXCGIw==
   dependencies:
     "@types/eslint-scope" "^3.7.0"
-    "@types/estree" "^0.0.46"
+    "@types/estree" "^0.0.47"
     "@webassemblyjs/ast" "1.11.0"
     "@webassemblyjs/wasm-edit" "1.11.0"
     "@webassemblyjs/wasm-parser" "1.11.0"
-    acorn "^8.0.4"
+    acorn "^8.2.1"
     browserslist "^4.14.5"
     chrome-trace-event "^1.0.2"
-    enhanced-resolve "^5.7.0"
-    es-module-lexer "^0.4.0"
-    eslint-scope "^5.1.1"
+    enhanced-resolve "^5.8.0"
+    es-module-lexer "^0.6.0"
+    eslint-scope "5.1.1"
     events "^3.2.0"
     glob-to-regexp "^0.4.1"
     graceful-fs "^4.2.4"
@@ -11386,9 +11404,9 @@ webpack@^5.28.0:
     neo-async "^2.6.2"
     schema-utils "^3.0.0"
     tapable "^2.1.1"
-    terser-webpack-plugin "^5.1.1"
-    watchpack "^2.0.0"
-    webpack-sources "^2.1.1"
+    terser-webpack-plugin "^5.1.3"
+    watchpack "^2.2.0"
+    webpack-sources "^2.3.0"
 
 websocket-driver@>=0.5.1, websocket-driver@^0.7.4:
   version "0.7.4"


Test patch:
diff --git a/pkg/prometheus/test_helper.go b/pkg/prometheus/test_helper.go
index b5ab3be3b..6c59b3245 100644
--- a/pkg/prometheus/test_helper.go
+++ b/pkg/prometheus/test_helper.go
@@ -69,8 +69,8 @@ func (m *MockProm) Flags(ctx context.Context) (promv1.FlagsResult, error) {
 	return promv1.FlagsResult{}, nil
 }
 
-// LabelValues performs a query for the values of the given label.
-func (m *MockProm) LabelValues(ctx context.Context, label string, startTime time.Time, endTime time.Time) (model.LabelValues, promv1.Warnings, error) {
+// LabelValues performs a query for the values of the given label, time range and matchers.
+func (m *MockProm) LabelValues(ctx context.Context, label string, matches []string, startTime time.Time, endTime time.Time) (model.LabelValues, promv1.Warnings, error) {
 	return nil, nil, nil
 }
 
@@ -92,8 +92,8 @@ func (m *MockProm) Targets(ctx context.Context) (promv1.TargetsResult, error) {
 	return promv1.TargetsResult{}, nil
 }
 
-// LabelNames returns all the unique label names present in the block in sorted order.
-func (m *MockProm) LabelNames(ctx context.Context, startTime time.Time, endTime time.Time) ([]string, promv1.Warnings, error) {
+// LabelNames returns the unique label names present in the block in sorted order by given time range and matchers.
+func (m *MockProm) LabelNames(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]string, promv1.Warnings, error) {
 	return []string{}, nil, nil
 }
 
@@ -116,3 +116,18 @@ func (m *MockProm) Rules(ctx context.Context) (promv1.RulesResult, error) {
 func (m *MockProm) TargetsMetadata(ctx context.Context, matchTarget string, metric string, limit string) ([]promv1.MetricMetadata, error) {
 	return []promv1.MetricMetadata{}, nil
 }
+
+// Buildinfo returns various build information properties about the Prometheus server
+func (m *MockProm) Buildinfo(ctx context.Context) (promv1.BuildinfoResult, error) {
+	return promv1.BuildinfoResult{}, nil
+}
+
+// QueryExemplars performs a query for exemplars by the given query and time range.
+func (m *MockProm) QueryExemplars(ctx context.Context, query string, startTime time.Time, endTime time.Time) ([]promv1.ExemplarQueryResult, error) {
+	return []promv1.ExemplarQueryResult{}, nil
+}
+
+// TSDB returns the cardinality statistics.
+func (m *MockProm) TSDB(ctx context.Context) (promv1.TSDBResult, error) {
+	return promv1.TSDBResult{}, nil
+}
diff --git a/viz/metrics-api/http_server_test.go b/viz/metrics-api/http_server_test.go
index d05bf279b..90a2cc703 100644
--- a/viz/metrics-api/http_server_test.go
+++ b/viz/metrics-api/http_server_test.go
@@ -19,6 +19,7 @@ type mockServer struct {
 }
 
 type mockGrpcServer struct {
+	pb.UnimplementedApiServer
 	mockServer
 }