Repository: linkerd/linkerd2
Pull request #6613 (2021-08-05 17:04:51)

Bump @babel/eslint-parser from 7.14.9 to 7.15.0 in /web/app
Bumps [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) from 7.14.9 to 7.15.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/babel/babel/releases"><code>@​babel/eslint-parser</code>'s releases</a>.</em></p>
<blockquote>
<h2>v7.15.0 (2021-08-04)</h2>
<p>Thanks <a href="https://github.com/a-tarasyuk"><code>@​a-tarasyuk</code></a> and <a href="https://github.com/gausie"><code>@​gausie</code></a> for your first PRs!</p>
<h4>:eyeglasses: Spec Compliance</h4>
<ul>
<li><code>babel-parser</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13523">#13523</a> feat(ts): raise error for abstract property with initializer (<a href="https://github.com/fedeci"><code>@​fedeci</code></a>)</li>
</ul>
</li>
</ul>
<h4>:rocket: New Feature</h4>
<ul>
<li><code>babel-parser</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13229">#13229</a> Add <code>attachComment</code> parser option to disable comment attachment (<a href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-standalone</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13476">#13476</a> standalone: update <code>preset-stage-*</code> (<a href="https://github.com/sosukesuzuki"><code>@​sosukesuzuki</code></a>)</li>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13555">#13555</a> feat: support hack pipeline in <code>@babel/standalone</code> (<a href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-parser</code>, <code>babel-preset-env</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13387">#13387</a> Enable top-level <code>await</code> parsing by default (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-typescript</code>, <code>babel-preset-typescript</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13324">#13324</a> Support TypeScript const enums (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-typescript</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13528">#13528</a> feat(typescript): implement namespace alias (<a href="https://github.com/colinaaa"><code>@​colinaaa</code></a>)</li>
</ul>
</li>
<li><code>babel-core</code>, <code>babel-helper-create-class-features-plugin</code>, <code>babel-helper-module-transforms</code>, <code>babel-plugin-transform-modules-commonjs</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13290">#13290</a> feat: add <code>noIncompleteNsImportDetection</code> assumption to <code>plugin-transform-modules-commonjs</code> (<a href="https://github.com/fedeci"><code>@​fedeci</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-react-display-name</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13501">#13501</a> Add display name after create context (<a href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-parser</code>, <code>babel-plugin-proposal-pipeline-operator</code>, <code>babel-plugin-syntax-pipeline-operator</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13416">#13416</a> Hack-pipe proposal with <code>%</code> topic token (<a href="https://github.com/js-choi"><code>@​js-choi</code></a>)</li>
</ul>
</li>
<li><code>babel-generator</code>, <code>babel-parser</code>, <code>babel-plugin-proposal-pipeline-operator</code>, <code>babel-plugin-syntax-pipeline-operator</code>, <code>babel-traverse</code>, <code>babel-types</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13191">#13191</a> Add support for the &quot;Hack&quot; pipeline proposal (<a href="https://github.com/js-choi"><code>@​js-choi</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-runtime</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13398">#13398</a> Expose <code>@babel/eslint-parser/experimental-worker</code> (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-compat-data</code>, <code>babel-helper-compilation-targets</code>, <code>babel-preset-env</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13448">#13448</a> Add support for rhino as a compilation target (<a href="https://github.com/gausie"><code>@​gausie</code></a>)</li>
</ul>
</li>
<li><code>babel-compat-data</code>, <code>babel-parser</code>, <code>babel-preset-env</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13554">#13554</a> Enable ergonomic brand checks (<code>#priv in</code>) by default (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
</ul>
<h4>:bug: Bug Fix</h4>
<ul>
<li><code>babel-parser</code>, <code>babel-plugin-transform-typescript</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13513">#13513</a> [ts] support optional chain call with generic (<a href="https://github.com/lala7573"><code>@​lala7573</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-typescript</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13605">#13605</a> Handle typescript function overloading in a default export (<a href="https://github.com/tony-go"><code>@​tony-go</code></a>)</li>
</ul>
</li>
<li><code>babel-parser</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13536">#13536</a> Fix <code>%==</code> parsing in hack pipes (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13426">#13426</a> parser: Fix Hack/smart-pipe error positions (<a href="https://github.com/js-choi"><code>@​js-choi</code></a>)</li>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13622">#13622</a> fix(ts): raise error for <code>export default interface {}</code> (<a href="https://github.com/a-tarasyuk"><code>@​a-tarasyuk</code></a>)</li>
</ul>
</li>
</ul>
<h4>:memo: Documentation</h4>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13607">#13607</a> chore(doc): add jest specific pckg command (<a href="https://github.com/tony-go"><code>@​tony-go</code></a>)</li>
</ul>
<h4>Committers: 10</h4>
<ul>
<li>Federico Ciardi (<a href="https://github.com/fedeci"><code>@​fedeci</code></a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/babel/babel/blob/main/CHANGELOG.md"><code>@​babel/eslint-parser</code>'s changelog</a>.</em></p>
<blockquote>
<h2>v7.15.0 (2021-08-04)</h2>
<h4>:eyeglasses: Spec Compliance</h4>
<ul>
<li><code>babel-parser</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13523">#13523</a> feat(ts): raise error for abstract property with initializer (<a href="https://github.com/fedeci"><code>@​fedeci</code></a>)</li>
</ul>
</li>
</ul>
<h4>:rocket: New Feature</h4>
<ul>
<li><code>babel-parser</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13229">#13229</a> Add <code>attachComment</code> parser option to disable comment attachment (<a href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-standalone</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13476">#13476</a> standalone: update <code>preset-stage-*</code> (<a href="https://github.com/sosukesuzuki"><code>@​sosukesuzuki</code></a>)</li>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13555">#13555</a> feat: support hack pipeline in <code>@babel/standalone</code> (<a href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-parser</code>, <code>babel-preset-env</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13387">#13387</a> Enable top-level <code>await</code> parsing by default (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-typescript</code>, <code>babel-preset-typescript</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13324">#13324</a> Support TypeScript const enums (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-typescript</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13528">#13528</a> feat(typescript): implement namespace alias (<a href="https://github.com/colinaaa"><code>@​colinaaa</code></a>)</li>
</ul>
</li>
<li><code>babel-core</code>, <code>babel-helper-create-class-features-plugin</code>, <code>babel-helper-module-transforms</code>, <code>babel-plugin-transform-modules-commonjs</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13290">#13290</a> feat: add <code>noIncompleteNsImportDetection</code> assumption to <code>plugin-transform-modules-commonjs</code> (<a href="https://github.com/fedeci"><code>@​fedeci</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-react-display-name</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13501">#13501</a> Add display name after create context (<a href="https://github.com/JLHwung"><code>@​JLHwung</code></a>)</li>
</ul>
</li>
<li><code>babel-parser</code>, <code>babel-plugin-proposal-pipeline-operator</code>, <code>babel-plugin-syntax-pipeline-operator</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13416">#13416</a> Hack-pipe proposal with <code>%</code> topic token (<a href="https://github.com/js-choi"><code>@​js-choi</code></a>)</li>
</ul>
</li>
<li><code>babel-generator</code>, <code>babel-parser</code>, <code>babel-plugin-proposal-pipeline-operator</code>, <code>babel-plugin-syntax-pipeline-operator</code>, <code>babel-traverse</code>, <code>babel-types</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13191">#13191</a> Add support for the &quot;Hack&quot; pipeline proposal (<a href="https://github.com/js-choi"><code>@​js-choi</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-runtime</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13398">#13398</a> Expose <code>@babel/eslint-parser/experimental-worker</code> (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
<li><code>babel-compat-data</code>, <code>babel-helper-compilation-targets</code>, <code>babel-preset-env</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13448">#13448</a> Add support for rhino as a compilation target (<a href="https://github.com/gausie"><code>@​gausie</code></a>)</li>
</ul>
</li>
<li><code>babel-compat-data</code>, <code>babel-parser</code>, <code>babel-preset-env</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13554">#13554</a> Enable ergonomic brand checks (<code>#priv in</code>) by default (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
</ul>
</li>
</ul>
<h4>:bug: Bug Fix</h4>
<ul>
<li><code>babel-parser</code>, <code>babel-plugin-transform-typescript</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13513">#13513</a> [ts] support optional chain call with generic (<a href="https://github.com/lala7573"><code>@​lala7573</code></a>)</li>
</ul>
</li>
<li><code>babel-plugin-transform-typescript</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13605">#13605</a> Handle typescript function overloading in a default export (<a href="https://github.com/tony-go"><code>@​tony-go</code></a>)</li>
</ul>
</li>
<li><code>babel-parser</code>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13536">#13536</a> Fix <code>%==</code> parsing in hack pipes (<a href="https://github.com/nicolo-ribaudo"><code>@​nicolo-ribaudo</code></a>)</li>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13426">#13426</a> parser: Fix Hack/smart-pipe error positions (<a href="https://github.com/js-choi"><code>@​js-choi</code></a>)</li>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13622">#13622</a> fix(ts): raise error for <code>export default interface {}</code> (<a href="https://github.com/a-tarasyuk"><code>@​a-tarasyuk</code></a>)</li>
</ul>
</li>
</ul>
<h4>:memo: Documentation</h4>
<ul>
<li><a href="https://github-redirect.dependabot.com/babel/babel/pull/13607">#13607</a> chore(doc): add jest specific pckg command (<a href="https://github.com/tony-go"><code>@​tony-go</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/babel/babel/commit/6912f968a6445248f97b1a2e8c86220fa8fdf25d"><code>6912f96</code></a> v7.15.0</li>
<li><a href="https://github.com/babel/babel/commit/d5b0d9e33d340accb02593b341e61750f5879125"><code>d5b0d9e</code></a> Add <code>attachComment</code> parser option to disable comment attachment (<a href="https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser/issues/13229">#13229</a>)</li>
<li><a href="https://github.com/babel/babel/commit/885e1e02f55073d005df6f5972dff168ec191da6"><code>885e1e0</code></a> Expose <code>@babel/eslint-parser/experimental-worker</code> (<a href="https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser/issues/13398">#13398</a>)</li>
<li>See full diff in <a href="https://github.com/babel/babel/commits/v7.15.0/eslint/babel-eslint-parser">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@babel/eslint-parser&package-manager=npm_and_yarn&previous-version=7.14.9&new-version=7.15.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>

codecov-commenter: # [Codecov](https://codecov.io/gh/linkerd/linkerd2/pull/6613?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd) Report
> Merging [#6613](https://codecov.io/gh/linkerd/linkerd2/pull/6613?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd) (0bf4d31) into [main](https://codecov.io/gh/linkerd/linkerd2/commit/a7806ec1ce7f14d785b1b9c5ec6280e6f7781c1d?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd) (a7806ec) will **increase** coverage by `22.67%`.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/linkerd/linkerd2/pull/6613/graphs/tree.svg?width=650&height=150&src=pr&token=FCBISvpqTv&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd)](https://codecov.io/gh/linkerd/linkerd2/pull/6613?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd)

```diff
@@             Coverage Diff             @@
##             main    #6613       +/-   ##
===========================================
+ Coverage   44.09%   66.76%   +22.67%     
===========================================
  Files         143       39      -104     
  Lines       22968     1396    -21572     
  Branches        0      290      +290     
===========================================
- Hits        10127      932     -9195     
+ Misses      12065      460    -11605     
+ Partials      776        4      -772     
```

| Flag | Coverage Δ | |
|---|---|---|
| golang | `?` | |
| javascript | `66.76% <ø> (?)` | |
| unittests | `66.76% <ø> (+22.67%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/linkerd/linkerd2/pull/6613?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd) | Coverage Δ | |
|---|---|---|
| [controller/api/destination/watcher/prometheus.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-Y29udHJvbGxlci9hcGkvZGVzdGluYXRpb24vd2F0Y2hlci9wcm9tZXRoZXVzLmdv) | | |
| [pkg/charts/charts.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-cGtnL2NoYXJ0cy9jaGFydHMuZ28=) | | |
| [multicluster/service-mirror/jittered\_ticker.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-bXVsdGljbHVzdGVyL3NlcnZpY2UtbWlycm9yL2ppdHRlcmVkX3RpY2tlci5nbw==) | | |
| [viz/tap/api/sever.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-dml6L3RhcC9hcGkvc2V2ZXIuZ28=) | | |
| [testutil/test\_helper.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-dGVzdHV0aWwvdGVzdF9oZWxwZXIuZ28=) | | |
| [pkg/version/version.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-cGtnL3ZlcnNpb24vdmVyc2lvbi5nbw==) | | |
| [web/srv/server.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-d2ViL3Nydi9zZXJ2ZXIuZ28=) | | |
| [pkg/k8s/k8s.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-cGtnL2s4cy9rOHMuZ28=) | | |
| [pkg/tls/creds\_watcher.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-cGtnL3Rscy9jcmVkc193YXRjaGVyLmdv) | | |
| [cli/cmd/diagnostics.go](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd#diff-Y2xpL2NtZC9kaWFnbm9zdGljcy5nbw==) | | |
| ... and [172 more](https://codecov.io/gh/linkerd/linkerd2/pull/6613/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/linkerd/linkerd2/pull/6613?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/linkerd/linkerd2/pull/6613?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd). Last update [a7806ec...0bf4d31](https://codecov.io/gh/linkerd/linkerd2/pull/6613?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=linkerd).


Patch:
diff --git a/pkg/k8s/api.go b/pkg/k8s/api.go
index 55e1014c2..27c5a889b 100644
--- a/pkg/k8s/api.go
+++ b/pkg/k8s/api.go
@@ -285,13 +285,3 @@ func GetProxyVersion(pod corev1.Pod) string {
 	}
 	return ""
 }
-
-// GetAddOnsConfigMap returns the data in the add-ons configmap
-func GetAddOnsConfigMap(ctx context.Context, kubeAPI kubernetes.Interface, namespace string) (map[string]string, error) {
-	cm, err := kubeAPI.CoreV1().ConfigMaps(namespace).Get(ctx, AddOnsConfigMapName, metav1.GetOptions{})
-	if err != nil {
-		return nil, err
-	}
-
-	return cm.Data, nil
-}
diff --git a/pkg/k8s/labels.go b/pkg/k8s/labels.go
index 0d99e8b55..09d14ed00 100644
--- a/pkg/k8s/labels.go
+++ b/pkg/k8s/labels.go
@@ -21,10 +21,6 @@ const (
 	// Prefix is the prefix common to all labels and annotations injected by Linkerd
 	Prefix = "linkerd.io"
 
-	// LinkerdNamespaceLabel is a label that helps identifying the namespaces
-	// that contain a Linkerd control plane
-	LinkerdNamespaceLabel = Prefix + "/is-control-plane"
-
 	// LinkerdExtensionLabel is a label that helps identifying the namespace
 	// that contain a Linkerd Extension
 	LinkerdExtensionLabel = Prefix + "/extension"
@@ -95,10 +91,6 @@ const (
 	// (e.g. linkerd/cli v2.0.0).
 	CreatedByAnnotation = Prefix + "/created-by"
 
-	// IdentityIssuerExpiryAnnotation indicates the time at which this set of identity
-	// issuer credentials will cease to be valid.
-	IdentityIssuerExpiryAnnotation = Prefix + "/identity-issuer-expiry"
-
 	// ProxyVersionAnnotation indicates the version of the injected data plane
 	// (e.g. v0.1.3).
 	ProxyVersionAnnotation = Prefix + "/proxy-version"
@@ -270,9 +262,6 @@ const (
 	// AddOnsConfigMapName is the name of the ConfigMap containing the linkerd add-ons configuration.
 	AddOnsConfigMapName = "linkerd-config-addons"
 
-	// DebugSidecarName is the name of the default linkerd debug container
-	DebugSidecarName = "linkerd-debug"
-
 	// DebugSidecarImage is the image name of the default linkerd debug container
 	DebugSidecarImage = "cr.l5d.io/linkerd/debug"
 
@@ -326,12 +315,6 @@ const (
 	// SPValidatorWebhookConfigName is the name of the validating webhook configuration
 	SPValidatorWebhookConfigName = SPValidatorWebhookServiceName + "-webhook-config"
 
-	// TapServiceName is the name of the tap APIService
-	TapServiceName = "linkerd-tap"
-
-	// TapAPIRegistrationServiceName is the name of the tap APIService registration resource
-	TapAPIRegistrationServiceName = "v1alpha1.tap.linkerd.io"
-
 	// AdmissionWebhookLabel indicates whether admission webhooks are enabled for a namespace
 	AdmissionWebhookLabel = ProxyConfigAnnotationsPrefix + "/admission-webhooks"
 
@@ -352,22 +335,9 @@ const (
 	// the service account token
 	MountPathServiceAccount = "/var/run/secrets/kubernetes.io/serviceaccount"
 
-	// MountPathGlobalConfig is the path at which the global config file is mounted.
-	MountPathGlobalConfig = MountPathBase + "/config/global"
-
-	// MountPathProxyConfig is the path at which the global config file is mounted.
-	MountPathProxyConfig = MountPathBase + "/config/proxy"
-
-	// MountPathInstallConfig is the path at which the install config file is mounted.
-	MountPathInstallConfig = MountPathBase + "/config/install"
-
 	// MountPathValuesConfig is the path at which the values config file is mounted.
 	MountPathValuesConfig = MountPathBase + "/config/values"
 
-	// MountPathEndEntity is the path at which a tmpfs directory is mounted to
-	// store identity credentials.
-	MountPathEndEntity = MountPathBase + "/identity/end-entity"
-
 	// MountPathTLSBase is the path at which the TLS cert and key PEM files are mounted
 	MountPathTLSBase = MountPathBase + "/tls"
 
@@ -377,16 +347,6 @@ const (
 	// MountPathTLSCrtPEM is the path at which the TLS cert PEM file is mounted.
 	MountPathTLSCrtPEM = MountPathTLSBase + "/tls.crt"
 
-	// MountPathXtablesLock is the path at which the proxy init container mounts xtables
-	// This is necessary for xtables-legacy support
-	MountPathXtablesLock = "/run"
-
-	// IdentityServiceAccountTokenPath is the path to the kubernetes service
-	// account token used by proxies to provision identity.
-	//
-	// In the future, this should be changed to a time- and audience-scoped secret.
-	IdentityServiceAccountTokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token"
-
 	/*
 	 * Service mirror constants
 	 */
@@ -426,11 +386,6 @@ const (
 	// on the remote cluster
 	RemoteServiceFqName = SvcMirrorPrefix + "/remote-svc-fq-name"
 
-	// RemoteGatewayResourceVersionAnnotation is the last observed remote resource
-	// version of the gateway for a particular mirrored service. It is used
-	// in cases we detect a change in a remote gateway
-	RemoteGatewayResourceVersionAnnotation = SvcMirrorPrefix + "/remote-gateway-resource-version"
-
 	// RemoteGatewayIdentity follows the same kind of logic as RemoteGatewayNameLabel
 	RemoteGatewayIdentity = SvcMirrorPrefix + "/remote-gateway-identity"
 
@@ -452,9 +407,6 @@ const (
 
 	// ProbePortName is the name of the probe port of the gateway
 	ProbePortName = "mc-probe"
-
-	// ServiceMirrorLabel is the value used in the controller component label
-	ServiceMirrorLabel = "servicemirror"
 )
 
 // CreatedByAnnotationValue returns the value associated with
diff --git a/viz/cmd/stat.go b/viz/cmd/stat.go
index d549d61a7..c00e580c9 100644
--- a/viz/cmd/stat.go
+++ b/viz/cmd/stat.go
@@ -310,6 +310,7 @@ type row struct {
 	status string
 	*rowStats
 	*tsStats
+	*dstStats
 }
 
 type tsStats struct {
@@ -318,6 +319,11 @@ type tsStats struct {
 	weight string
 }
 
+type dstStats struct {
+	dst    string
+	weight string
+}
+
 var (
 	nameHeader      = "NAME"
 	namespaceHeader = "NAMESPACE"
@@ -331,7 +337,7 @@ func statHasRequestData(stat *pb.BasicStats) bool {
 }
 
 func isPodOwnerResource(typ string) bool {
-	return typ != k8s.TrafficSplit && typ != k8s.Authority
+	return typ != k8s.TrafficSplit && typ != k8s.Authority && typ != k8s.Service
 }
 
 func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer, options *statOptions) {
@@ -339,6 +345,7 @@ func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer,
 	maxNamespaceLength := len(namespaceHeader)
 	maxApexLength := len(apexHeader)
 	maxLeafLength := len(leafHeader)
+	maxDstLength := len(dstHeader)
 	maxWeightLength := len(weightHeader)
 
 	statTables := make(map[string]map[string]*row)
@@ -373,7 +380,7 @@ func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer,
 
 		namespace := r.Resource.Namespace
 		key := fmt.Sprintf("%s/%s", namespace, name)
-		if r.Resource.Type == k8s.TrafficSplit {
+		if r.Resource.Type == k8s.TrafficSplit || (r.Resource.Type == k8s.Service && r.TsStats != nil) {
 			key = fmt.Sprintf("%s/%s/%s", namespace, name, r.TsStats.Leaf)
 		}
 		resourceKey := r.Resource.Type
@@ -391,7 +398,7 @@ func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer,
 		}
 
 		meshedCount := fmt.Sprintf("%d/%d", r.MeshedPodCount, r.RunningPodCount)
-		if resourceKey == k8s.Authority {
+		if resourceKey == k8s.Authority || resourceKey == k8s.Service {
 			meshedCount = "-"
 		}
 		statTables[resourceKey][key] = &row{
@@ -412,26 +419,40 @@ func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer,
 			}
 		}
 		if r.TsStats != nil {
-			leaf := r.TsStats.Leaf
-			apex := r.TsStats.Apex
-			weight := r.TsStats.Weight
+			if r.GetResource().GetType() == k8s.TrafficSplit {
+				leaf := r.TsStats.Leaf
+				apex := r.TsStats.Apex
+				weight := r.TsStats.Weight
 
-			if len(leaf) > maxLeafLength {
-				maxLeafLength = len(leaf)
-			}
+				if len(leaf) > maxLeafLength {
+					maxLeafLength = len(leaf)
+				}
 
-			if len(apex) > maxApexLength {
-				maxApexLength = len(apex)
-			}
+				if len(apex) > maxApexLength {
+					maxApexLength = len(apex)
+				}
 
-			if len(weight) > maxWeightLength {
-				maxWeightLength = len(weight)
-			}
+				statTables[resourceKey][key].tsStats = &tsStats{
+					apex:   apex,
+					leaf:   leaf,
+					weight: weight,
+				}
+			} else {
+				dst := r.TsStats.Leaf
+				weight := r.TsStats.Weight
+
+				if len(dst) > maxDstLength {
+					maxDstLength = len(dst)
+				}
+
+				if len(weight) > maxWeightLength {
+					maxWeightLength = len(weight)
+				}
 
-			statTables[resourceKey][key].tsStats = &tsStats{
-				apex:   apex,
-				leaf:   leaf,
-				weight: weight,
+				statTables[resourceKey][key].dstStats = &dstStats{
+					dst:    dst,
+					weight: weight,
+				}
 			}
 		}
 	}
@@ -442,13 +463,13 @@ func writeStatsToBuffer(rows []*pb.StatTable_PodGroup_Row, w *tabwriter.Writer,
 			fmt.Fprintln(os.Stderr, "No traffic found.")
 			return
 		}
-		printStatTables(statTables, w, maxNameLength, maxNamespaceLength, maxLeafLength, maxApexLength, maxWeightLength, options)
+		printStatTables(statTables, w, maxNameLength, maxNamespaceLength, maxLeafLength, maxApexLength, maxDstLength, maxWeightLength, options)
 	case jsonOutput:
 		printStatJSON(statTables, w)
 	}
 }
 
-func printStatTables(statTables map[string]map[string]*row, w *tabwriter.Writer, maxNameLength, maxNamespaceLength, maxLeafLength, maxApexLength, maxWeightLength int, options *statOptions) {
+func printStatTables(statTables map[string]map[string]*row, w *tabwriter.Writer, maxNameLength, maxNamespaceLength, maxLeafLength, maxApexLength, maxDstLength, maxWeightLength int, options *statOptions) {
 	usePrefix := false
 	if len(statTables) > 1 {
 		usePrefix = true
@@ -465,7 +486,7 @@ func printStatTables(statTables map[string]map[string]*row, w *tabwriter.Writer,
 			if !usePrefix {
 				resourceTypeLabel = ""
 			}
-			printSingleStatTable(stats, resourceTypeLabel, resourceType, w, maxNameLength, maxNamespaceLength, maxLeafLength, maxApexLength, maxWeightLength, options)
+			printSingleStatTable(stats, resourceTypeLabel, resourceType, w, maxNameLength, maxNamespaceLength, maxLeafLength, maxApexLength, maxDstLength, maxWeightLength, options)
 		}
 	}
 }
@@ -479,14 +500,29 @@ func showTCPConns(resourceType string) bool {
 	return resourceType != k8s.Authority && resourceType != k8s.TrafficSplit
 }
 
-func printSingleStatTable(stats map[string]*row, resourceTypeLabel, resourceType string, w *tabwriter.Writer, maxNameLength, maxNamespaceLength, maxLeafLength, maxApexLength, maxWeightLength int, options *statOptions) {
+func printSingleStatTable(stats map[string]*row, resourceTypeLabel, resourceType string, w *tabwriter.Writer, maxNameLength, maxNamespaceLength, maxLeafLength, maxApexLength, maxDstLength, maxWeightLength int, options *statOptions) {
 	headers := make([]string, 0)
 	nameTemplate := fmt.Sprintf("%%-%ds", maxNameLength)
 	namespaceTemplate := fmt.Sprintf("%%-%ds", maxNamespaceLength)
 	apexTemplate := fmt.Sprintf("%%-%ds", maxApexLength)
 	leafTemplate := fmt.Sprintf("%%-%ds", maxLeafLength)
+	dstTemplate := fmt.Sprintf("%%-%ds", maxDstLength)
 	weightTemplate := fmt.Sprintf("%%-%ds", maxWeightLength)
 
+	hasDstStats := false
+	for _, r := range stats {
+		if r.dstStats != nil {
+			hasDstStats = true
+		}
+	}
+
+	hasTsStats := false
+	for _, r := range stats {
+		if r.tsStats != nil {
+			hasTsStats = true
+		}
+	}
+
 	if options.allNamespaces {
 		headers = append(headers,
 			fmt.Sprintf(namespaceTemplate, namespaceHeader))
@@ -499,7 +535,11 @@ func printSingleStatTable(stats map[string]*row, resourceTypeLabel, resourceType
 		headers = append(headers, "STATUS")
 	}
 
-	if resourceType == k8s.TrafficSplit {
+	if hasDstStats {
+		headers = append(headers,
+			fmt.Sprintf(dstTemplate, dstHeader),
+			fmt.Sprintf(weightTemplate, weightHeader))
+	} else if hasTsStats {
 		headers = append(headers,
 			fmt.Sprintf(apexTemplate, apexHeader),
 			fmt.Sprintf(leafTemplate, leafHeader),
@@ -542,9 +582,12 @@ func printSingleStatTable(stats map[string]*row, resourceTypeLabel, resourceType
 			templateStringEmpty = "%s\t" + templateStringEmpty
 		}
 
-		if resourceType == k8s.TrafficSplit {
+		if hasTsStats {
 			templateString = "%s\t%s\t%s\t%s\t%.2f%%\t%.1frps\t%dms\t%dms\t%dms\t"
 			templateStringEmpty = "%s\t%s\t%s\t%s\t-\t-\t-\t-\t-\t"
+		} else if hasDstStats {
+			templateString = "%s\t%s\t%s\t%.2f%%\t%.1frps\t%dms\t%dms\t%dms\t"
+			templateStringEmpty = "%s\t%s\t%s\t-\t-\t-\t-\t-\t"
 		}
 
 		if !showTCPConns(resourceType) {
@@ -578,6 +621,7 @@ func printSingleStatTable(stats map[string]*row, resourceTypeLabel, resourceType
 
 		apexPadding := 0
 		leafPadding := 0
+		dstPadding := 0
 
 		if stats[key].tsStats != nil {
 			if maxApexLength > len(stats[key].tsStats.apex) {
@@ -586,6 +630,10 @@ func printSingleStatTable(stats map[string]*row, resourceTypeLabel, resourceType
 			if maxLeafLength > len(stats[key].tsStats.leaf) {
 				leafPadding = maxLeafLength - len(stats[key].tsStats.leaf)
 			}
+		} else if stats[key].dstStats != nil {
+			if maxDstLength > len(stats[key].dstStats.dst) {
+				dstPadding = maxDstLength - len(stats[key].dstStats.dst)
+			}
 		}
 
 		values = append(values, name+strings.Repeat(" ", padding))
@@ -593,12 +641,17 @@ func printSingleStatTable(stats map[string]*row, resourceTypeLabel, resourceType
 			values = append(values, stats[key].status)
 		}
 
-		if resourceType == k8s.TrafficSplit {
+		if hasTsStats {
 			values = append(values,
 				stats[key].tsStats.apex+strings.Repeat(" ", apexPadding),
 				stats[key].tsStats.leaf+strings.Repeat(" ", leafPadding),
 				stats[key].tsStats.weight,
 			)
+		} else if hasDstStats {
+			values = append(values,
+				stats[key].dstStats.dst+strings.Repeat(" ", dstPadding),
+				stats[key].dstStats.weight,
+			)
 		} else {
 			values = append(values, []interface{}{
 				stats[key].meshed,
@@ -656,6 +709,7 @@ type jsonStats struct {
 	TCPWriteBytes  *float64 `json:"tcp_write_bytes_rate,omitempty"`
 	Apex           string   `json:"apex,omitempty"`
 	Leaf           string   `json:"leaf,omitempty"`
+	Dst            string   `json:"dst,omitempty"`
 	Weight         string   `json:"weight,omitempty"`
 }
 
@@ -692,7 +746,10 @@ func printStatJSON(statTables map[string]map[string]*row, w *tabwriter.Writer) {
 				if stats[key].tsStats != nil {
 					entry.Apex = stats[key].apex
 					entry.Leaf = stats[key].leaf
-					entry.Weight = stats[key].weight
+					entry.Weight = stats[key].tsStats.weight
+				} else if stats[key].dstStats != nil {
+					entry.Dst = stats[key].dstStats.dst
+					entry.Weight = stats[key].dstStats.weight
 				}
 				entries = append(entries, entry)
 			}
diff --git a/viz/metrics-api/prometheus.go b/viz/metrics-api/prometheus.go
index bdacb3f97..1eb039640 100644
--- a/viz/metrics-api/prometheus.go
+++ b/viz/metrics-api/prometheus.go
@@ -39,6 +39,7 @@ const (
 	gatewayNameLabel       = model.LabelName("gateway_name")
 	gatewayNamespaceLabel  = model.LabelName("gateway_namespace")
 	remoteClusterNameLabel = model.LabelName("target_cluster_name")
+	authorityLabel         = model.LabelName("authority")
 )
 
 var (
@@ -163,7 +164,7 @@ func generateLabelStringWithRegex(l model.LabelSet, labelName string, stringToMa
 	for l, v := range l {
 		lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v))
 	}
-	lstrs = append(lstrs, fmt.Sprintf(`%s=~"^%s.+"`, labelName, stringToMatch))
+	lstrs = append(lstrs, fmt.Sprintf(`%s=~"^%s.*"`, labelName, stringToMatch))
 
 	sort.Strings(lstrs)
 	return fmt.Sprintf("{%s}", strings.Join(lstrs, ", "))
diff --git a/viz/metrics-api/stat_summary.go b/viz/metrics-api/stat_summary.go
index d0f18ff50..c53e9d3fe 100644
--- a/viz/metrics-api/stat_summary.go
+++ b/viz/metrics-api/stat_summary.go
@@ -5,14 +5,17 @@ import (
 	"fmt"
 	"reflect"
 	"sort"
+	"strings"
 
 	proto "github.com/golang/protobuf/proto"
 	"github.com/linkerd/linkerd2/pkg/k8s"
 	pb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
-	"github.com/linkerd/linkerd2/viz/pkg/util"
+	vizutil "github.com/linkerd/linkerd2/viz/pkg/util"
 	"github.com/prometheus/common/model"
 	"github.com/servicemeshinterface/smi-sdk-go/pkg/apis/split/v1alpha1"
+	log "github.com/sirupsen/logrus"
 	corev1 "k8s.io/api/core/v1"
+	kerrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/meta"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
@@ -23,7 +26,6 @@ type resourceResult struct {
 	res *pb.StatTable
 	err error
 }
-
 type k8sStat struct {
 	object   metav1.Object
 	podStats *podStats
@@ -44,6 +46,13 @@ type tsKey struct {
 	Weight    string
 }
 
+type dstKey struct {
+	Namespace string
+	Service   string
+	Dst       string
+	Weight    string
+}
+
 const (
 	success = "success"
 	failure = "failure"
@@ -53,6 +62,8 @@ const (
 	tcpConnectionsQuery  = "sum(tcp_open_connections%s) by (%s)"
 	tcpReadBytesQuery    = "sum(increase(tcp_read_bytes_total%s[%s])) by (%s)"
 	tcpWriteBytesQuery   = "sum(increase(tcp_write_bytes_total%s[%s])) by (%s)"
+
+	regexAny = ".+"
 )
 
 type podStats struct {
@@ -76,9 +87,9 @@ func (s *grpcServer) StatSummary(ctx context.Context, req *pb.StatSummaryRequest
 		return statSummaryError(req, "StatSummary request missing Selector Resource"), nil
 	}
 
-	// special case to check for services as outbound only
-	if isInvalidServiceRequest(req.Selector, req.GetFromResource()) {
-		return statSummaryError(req, "service only supported as a target on 'from' queries, or as a destination on 'to' queries"), nil
+	// err if --from is a service
+	if req.GetFromResource() != nil && req.GetFromResource().GetType() == k8s.Service {
+		return statSummaryError(req, "service is not supported as a target on 'from' queries, or as a target with 'to' queries"), nil
 	}
 
 	switch req.Outbound.(type) {
@@ -111,6 +122,8 @@ func (s *grpcServer) StatSummary(ctx context.Context, req *pb.StatSummaryRequest
 		go func() {
 			if isNonK8sResourceQuery(statReq.GetSelector().GetResource().GetType()) {
 				resultChan <- s.nonK8sResourceQuery(ctx, statReq)
+			} else if statReq.GetSelector().GetResource().GetType() == k8s.Service {
+				resultChan <- s.serviceResourceQuery(ctx, statReq)
 			} else if isTrafficSplitQuery(statReq.GetSelector().GetResource().GetType()) {
 				resultChan <- s.trafficSplitResourceQuery(ctx, statReq)
 			} else {
@@ -122,7 +135,7 @@ func (s *grpcServer) StatSummary(ctx context.Context, req *pb.StatSummaryRequest
 	for i := 0; i < len(resourcesToQuery); i++ {
 		result := <-resultChan
 		if result.err != nil {
-			return nil, util.GRPCError(result.err)
+			return nil, vizutil.GRPCError(result.err)
 		}
 		statTables = append(statTables, result.res)
 	}
@@ -135,17 +148,10 @@ func (s *grpcServer) StatSummary(ctx context.Context, req *pb.StatSummaryRequest
 		},
 	}
 
+	log.Debugf("Sent response as %+v\n", statTables)
 	return &rsp, nil
 }
 
-func isInvalidServiceRequest(selector *pb.ResourceSelection, fromResource *pb.Resource) bool {
-	if fromResource != nil {
-		return fromResource.Type == k8s.Service
-	}
-
-	return selector.Resource.Type == k8s.Service
-}
-
 func statSummaryError(req *pb.StatSummaryRequest, message string) *pb.StatSummaryResponse {
 	return &pb.StatSummaryResponse{
 		Response: &pb.StatSummaryResponse_Error{
@@ -198,6 +204,7 @@ func (s *grpcServer) getKubernetesObjectStats(req *pb.StatSummaryRequest) (map[r
 }
 
 func (s *grpcServer) k8sResourceQuery(ctx context.Context, req *pb.StatSummaryRequest) resourceResult {
+
 	k8sObjects, err := s.getKubernetesObjectStats(req)
 	if err != nil {
 		return resourceResult{res: nil, err: err}
@@ -288,8 +295,8 @@ func (s *grpcServer) getTrafficSplits(req *pb.StatSummaryRequest) ([]*v1alpha1.T
 }
 
 func (s *grpcServer) trafficSplitResourceQuery(ctx context.Context, req *pb.StatSummaryRequest) resourceResult {
-	tss, err := s.getTrafficSplits(req)
 
+	tss, err := s.getTrafficSplits(req)
 	if err != nil {
 		return resourceResult{res: nil, err: err}
 	}
@@ -359,11 +366,88 @@ func (s *grpcServer) trafficSplitResourceQuery(ctx context.Context, req *pb.Stat
 	return resourceResult{res: &rsp, err: nil}
 }
 
+func (s *grpcServer) serviceResourceQuery(ctx context.Context, req *pb.StatSummaryRequest) resourceResult {
+
+	rows := make([]*pb.StatTable_PodGroup_Row, 0)
+	dstBasicStats := make(map[dstKey]*pb.BasicStats)
+	dstTCPStats := make(map[dstKey]*pb.TcpStats)
+
+	if !req.SkipStats {
+		var err error
+		dstBasicStats, dstTCPStats, err = s.getServiceMetrics(ctx, req, req.TimeWindow)
+		if err != nil {
+			return resourceResult{res: nil, err: err}
+		}
+	}
+
+	weights := make(map[dstKey]string)
+	for k := range dstBasicStats {
+		weights[k] = ""
+	}
+
+	name := req.GetSelector().GetResource().GetName()
+	namespace := req.GetSelector().GetResource().GetNamespace()
+
+	// Check if a ServiceProfile exists for the Service
+	spName := fmt.Sprintf("%s.%s.svc.%s", name, namespace, s.clusterDomain)
+	sp, err := s.k8sAPI.SP().Lister().ServiceProfiles(namespace).Get(spName)
+	if err == nil {
+		for _, weightedDst := range sp.Spec.DstOverrides {
+			weights[dstKey{
+				Namespace: namespace,
+				Service:   name,
+				Dst:       dstFromAuthority(weightedDst.Authority),
+			}] = weightedDst.Weight.String()
+		}
+	} else if !kerrors.IsNotFound(err) {
+		log.Errorf("Failed to get weights from ServiceProfile %s: %v", spName, err)
+	}
+
+	for k, weight := range weights {
+		row := pb.StatTable_PodGroup_Row{
+			Resource: &pb.Resource{
+				Name:      k.Service,
+				Namespace: k.Namespace,
+				Type:      req.GetSelector().GetResource().GetType(),
+			},
+			TimeWindow: req.TimeWindow,
+			Stats:      dstBasicStats[k],
+			TcpStats:   dstTCPStats[k],
+		}
+
+		// Set TrafficSplitStats only when weight is not empty
+		if weight != "" {
+			row.TsStats = &pb.TrafficSplitStats{
+				Apex:   k.Service,
+				Leaf:   k.Dst,
+				Weight: weight,
+			}
+		}
+		rows = append(rows, &row)
+	}
+
+	// sort rows before returning in order to have a consistent order for tests
+	rows = sortTrafficSplitRows(rows)
+
+	rsp := pb.StatTable{
+		Table: &pb.StatTable_PodGroup_{
+			PodGroup: &pb.StatTable_PodGroup{
+				Rows: rows,
+			},
+		},
+	}
+
+	return resourceResult{res: &rsp, err: nil}
+}
+
 func sortTrafficSplitRows(rows []*pb.StatTable_PodGroup_Row) []*pb.StatTable_PodGroup_Row {
 	sort.Slice(rows, func(i, j int) bool {
-		key1 := rows[i].TsStats.Apex + rows[i].TsStats.Leaf
-		key2 := rows[j].TsStats.Apex + rows[j].TsStats.Leaf
-		return key1 < key2
+		if rows[i].TsStats != nil && rows[j].TsStats != nil {
+			key1 := rows[i].TsStats.Apex + rows[i].TsStats.Leaf
+			key2 := rows[j].TsStats.Apex + rows[j].TsStats.Leaf
+			return key1 < key2
+		}
+		return false
 	})
 	return rows
 }
@@ -464,28 +548,30 @@ func buildRequestLabels(req *pb.StatSummaryRequest) (labels model.LabelSet, labe
 	return
 }
 
-func buildTrafficSplitRequestLabels(req *pb.StatSummaryRequest) (labels model.LabelSet, labelNames model.LabelNames) {
-	// Trafficsplit labels are always direction="outbound". If the --from or --to flags were used,
-	// we merge an additional ToResource or FromResource label. Trafficsplit metrics results are
-	// always grouped by dst_service.
-	// N.b. requests to a traffic split may come from any namespace so we do not do any filtering
-	// by namespace.
+func buildServiceRequestLabels(req *pb.StatSummaryRequest) (labels model.LabelSet, labelNames model.LabelNames) {
+	// Service Request labels are always direction="outbound". If the --from or --to flags were used,
+	// we merge an additional ToResource or FromResource label. Service metrics results are
+	// always grouped by dst_service, and dst_namespace (to avoid conflicts) .
 	labels = model.LabelSet{
 		"direction": model.LabelValue("outbound"),
 	}
 
 	switch out := req.Outbound.(type) {
 	case *pb.StatSummaryRequest_ToResource:
+		// if --to flag is passed, Calculate traffic sent to the service
+		// with additional filtering narrowing down to the workload
+		// it is sent to.
 		labels = labels.Merge(promDstQueryLabels(out.ToResource))
 
 	case *pb.StatSummaryRequest_FromResource:
+		// if --from flag is passed, FromResource is never a service here
 		labels = labels.Merge(promQueryLabels(out.FromResource))
 
 	default:
 		// no extra labels needed
 	}
 
-	groupBy := model.LabelNames{model.LabelName("dst_service")}
+	groupBy := model.LabelNames{model.LabelName("dst_namespace"), model.LabelName("dst_service")}
 
 	return labels, groupBy
 }
@@ -530,26 +616,23 @@ func (s *grpcServer) getStatMetrics(ctx context.Context, req *pb.StatSummaryRequ
 
 func (s *grpcServer) getTrafficSplitMetrics(ctx context.Context, req *pb.StatSummaryRequest, tsStats *trafficSplitStats, timeWindow string) (map[tsKey]*pb.BasicStats, error) {
 	tsBasicStats := make(map[tsKey]*pb.BasicStats)
-	labels, groupBy := buildTrafficSplitRequestLabels(req)
+	labels, groupBy := buildServiceRequestLabels(req)
 
 	apex := tsStats.apex
 	namespace := tsStats.namespace
 	// TODO: add cluster domain to stringToMatch
 	stringToMatch := fmt.Sprintf("%s.%s.svc", apex, namespace)
 
-	reqLabels := generateLabelStringWithRegex(labels, "authority", stringToMatch)
+	reqLabels := generateLabelStringWithRegex(labels, string(authorityLabel), stringToMatch)
 
 	promQueries := map[promType]string{
 		promRequests: fmt.Sprintf(reqQuery, reqLabels, timeWindow, groupBy.String()),
 	}
-
 	quantileQueries := generateQuantileQueries(latencyQuantileQuery, reqLabels, timeWindow, groupBy.String())
 	results, err := s.getPrometheusMetrics(ctx, promQueries, quantileQueries)
-
 	if err != nil {
 		return nil, err
 	}
-
 	basicStats, _ := processPrometheusMetrics(req, results, groupBy) // we don't need tcpStat info for traffic split
 
 	for rKey, basicStatsVal := range basicStats {
@@ -564,6 +647,75 @@ func (s *grpcServer) getTrafficSplitMetrics(ctx context.Context, req *pb.StatSum
 	return tsBasicStats, nil
 }
 
+func (s *grpcServer) getServiceMetrics(ctx context.Context, req *pb.StatSummaryRequest, timeWindow string) (map[dstKey]*pb.BasicStats, map[dstKey]*pb.TcpStats, error) {
+	dstBasicStats := make(map[dstKey]*pb.BasicStats)
+	dstTCPStats := make(map[dstKey]*pb.TcpStats)
+	labels, groupBy := buildServiceRequestLabels(req)
+
+	service := req.GetSelector().GetResource().GetName()
+	namespace := req.GetSelector().GetResource().GetNamespace()
+
+	if service == "" {
+		service = regexAny
+	}
+	authority := fmt.Sprintf("%s.%s.svc.%s", service, namespace, s.clusterDomain)
+
+	reqLabels := generateLabelStringWithRegex(labels, string(authorityLabel), authority)
+
+	promQueries := map[promType]string{
+		promRequests: fmt.Sprintf(reqQuery, reqLabels, timeWindow, groupBy.String()),
+	}
+
+	if req.TcpStats {
+		// Service stats always need to have `peer=dst`, cuz there is no `src` with `authority` label
+		tcpLabels := labels.Merge(promPeerLabel("dst"))
+		tcpLabelString := generateLabelStringWithRegex(tcpLabels, string(authorityLabel), authority)
+		promQueries[promTCPConnections] = fmt.Sprintf(tcpConnectionsQuery, tcpLabelString, groupBy.String())
+		promQueries[promTCPReadBytes] = fmt.Sprintf(tcpReadBytesQuery, tcpLabelString, timeWindow, groupBy.String())
+		promQueries[promTCPWriteBytes] = fmt.Sprintf(tcpWriteBytesQuery, tcpLabelString, timeWindow, groupBy.String())
+	}
+
+	quantileQueries := generateQuantileQueries(latencyQuantileQuery, reqLabels, timeWindow, groupBy.String())
+	results, err := s.getPrometheusMetrics(ctx, promQueries, quantileQueries)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	basicStats, tcpStats := processPrometheusMetrics(req, results, groupBy)
+
+	for rKey, basicStatsVal := range basicStats {
+
+		// Use the returned `dst_service` in the `all` svc case
+		svcName := service
+		if svcName == regexAny {
+			svcName = rKey.Name
+		}
+
+		dstBasicStats[dstKey{
+			Namespace: rKey.Namespace,
+			Service:   svcName,
+			Dst:       rKey.Name,
+		}] = basicStatsVal
+	}
+
+	for rKey, tcpStatsVal := range tcpStats {
+
+		// Use the returned `dst_service` in the `all` svc case
+		svcName := service
+		if svcName == regexAny {
+			svcName = rKey.Name
+		}
+
+		dstTCPStats[dstKey{
+			Namespace: rKey.Namespace,
+			Service:   svcName,
+			Dst:       rKey.Name,
+		}] = tcpStatsVal
+	}
+
+	return dstBasicStats, dstTCPStats, nil
+}
+
 func processPrometheusMetrics(req *pb.StatSummaryRequest, results []promResult, groupBy model.LabelNames) (map[rKey]*pb.BasicStats, map[rKey]*pb.TcpStats) {
 	basicStats := make(map[rKey]*pb.BasicStats)
 	tcpStats := make(map[rKey]*pb.TcpStats)
@@ -717,3 +869,13 @@ func getLabelSelector(req *pb.StatSummaryRequest) (labels.Selector, error) {
 	}
 	return labelSelector, nil
 }
+
+func dstFromAuthority(authority string) string {
+	// name.namespace.svc.suffix
+	labels := strings.Split(authority, ".")
+	if len(labels) >= 3 && labels[2] == "svc" {
+		// name
+		return labels[0]
+	}
+	return authority
+}
diff --git a/web/app/package.json b/web/app/package.json
index 92cbe20f9..a3680e060 100644
--- a/web/app/package.json
+++ b/web/app/package.json
@@ -7,7 +7,7 @@
     "@babel/eslint-plugin": "7.14.5",
     "@fortawesome/fontawesome-svg-core": "1.2.36",
     "@fortawesome/free-regular-svg-icons": "5.15.4",
-    "@fortawesome/free-solid-svg-icons": "5.15.3",
+    "@fortawesome/free-solid-svg-icons": "5.15.4",
     "@fortawesome/react-fontawesome": "0.1.15",
     "@lingui/core": "^3.10.4",
     "@lingui/macro": "3.10.2",
@@ -42,7 +42,7 @@
   },
   "devDependencies": {
     "@babel/core": "^7.15.0",
-    "@babel/eslint-parser": "^7.14.9",
+    "@babel/eslint-parser": "^7.15.0",
     "@babel/plugin-proposal-class-properties": "^7.13.0",
     "@babel/preset-env": "^7.15.0",
     "@babel/preset-react": "^7.14.5",
@@ -78,7 +78,7 @@
     "sinon-stub-promise": "4.0.0",
     "style-loader": "^3.2.1",
     "url-loader": "^4.1.1",
-    "webpack": "^5.48.0",
+    "webpack": "^5.49.0",
     "webpack-bundle-analyzer": "4.4.2",
     "webpack-cli": "4.7.2",
     "webpack-dev-server": "3.11.2"
diff --git a/web/app/yarn.lock b/web/app/yarn.lock
index 77c138af8..bde4682a9 100644
--- a/web/app/yarn.lock
+++ b/web/app/yarn.lock
@@ -42,10 +42,10 @@
     semver "^6.3.0"
     source-map "^0.5.0"
 
-"@babel/eslint-parser@^7.14.9":
-  version "7.14.9"
-  resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.14.9.tgz#b2cfaf67cc7f7a9b475d3ee9b166755ffd44e086"
-  integrity sha512-W3En2CT6iOZJ+jEujLlwL2h/Jraj6S/IHrh63nV+TfX83DYe9pI4pcu0Luj6/hJ2kIr/3hOttxzaEsSQnUKx+w==
+"@babel/eslint-parser@^7.15.0":
+  version "7.15.0"
+  resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.15.0.tgz#b54f06e04d0e93aebcba99f89251e3bf0ee39f21"
+  integrity sha512-+gSPtjSBxOZz4Uh8Ggqu7HbfpB8cT1LwW0DnVVLZEJvzXauiD0Di3zszcBkRmfGGrLdYeHUwcflG7i3tr9kQlw==
   dependencies:
     eslint-scope "^5.1.1"
     eslint-visitor-keys "^2.1.0"
@@ -1042,7 +1042,7 @@
     minimatch "^3.0.4"
     strip-json-comments "^3.1.1"
 
-"@fortawesome/fontawesome-common-types@^0.2.35", "@fortawesome/fontawesome-common-types@^0.2.36":
+"@fortawesome/fontawesome-common-types@^0.2.36":
   version "0.2.36"
   resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz#b44e52db3b6b20523e0c57ef8c42d315532cb903"
   integrity sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==
@@ -1061,12 +1061,12 @@
   dependencies:
     "@fortawesome/fontawesome-common-types" "^0.2.36"
 
-"@fortawesome/free-solid-svg-icons@5.15.3":
-  version "5.15.3"
-  resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz#52eebe354f60dc77e0bde934ffc5c75ffd04f9d8"
-  integrity sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q==
+"@fortawesome/free-solid-svg-icons@5.15.4":
+  version "5.15.4"
+  resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz#2a68f3fc3ddda12e52645654142b9e4e8fbb6cc5"
+  integrity sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==
   dependencies:
-    "@fortawesome/fontawesome-common-types" "^0.2.35"
+    "@fortawesome/fontawesome-common-types" "^0.2.36"
 
 "@fortawesome/react-fontawesome@0.1.15":
   version "0.1.15"
@@ -9521,10 +9521,10 @@ webpack-sources@^3.2.0:
   resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.0.tgz#b16973bcf844ebcdb3afde32eda1c04d0b90f89d"
   integrity sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==
 
-webpack@^5.48.0:
-  version "5.48.0"
-  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.48.0.tgz#06180fef9767a6fd066889559a4c4d49bee19b83"
-  integrity sha512-CGe+nfbHrYzbk7SKoYITCgN3LRAG0yVddjNUecz9uugo1QtYdiyrVD8nP1PhkNqPfdxC2hknmmKpP355Epyn6A==
+webpack@^5.49.0:
+  version "5.49.0"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.49.0.tgz#e250362b781a9fb614ba0a97ed67c66b9c5310cd"
+  integrity sha512-XarsANVf28A7Q3KPxSnX80EkCcuOer5hTOEJWJNvbskOZ+EK3pobHarGHceyUZMxpsTHBHhlV7hiQyLZzGosYw==
   dependencies:
     "@types/eslint-scope" "^3.7.0"
     "@types/estree" "^0.0.50"


Test patch:
diff --git a/controller/api/destination/watcher/test_util.go b/controller/api/destination/watcher/test_util.go
index 1b31ca266..5d3253a5e 100644
--- a/controller/api/destination/watcher/test_util.go
+++ b/controller/api/destination/watcher/test_util.go
@@ -25,7 +25,6 @@ func NewDeletingProfileListener() *DeletingProfileListener {
 func (dpl *DeletingProfileListener) Update(profile *sp.ServiceProfile) {
 	if profile == nil {
 		dpl.NumDeletes = dpl.NumDeletes + 1
-
 	}
 }
 
diff --git a/test/integration/stat/stat_test.go b/test/integration/stat/stat_test.go
index 8beb724e0..9dea7f5c8 100644
--- a/test/integration/stat/stat_test.go
+++ b/test/integration/stat/stat_test.go
@@ -118,6 +118,12 @@ func TestCliStatForLinkerdNamespace(t *testing.T) {
 				prometheusAuthority: "-",
 			},
 		},
+		{
+			args: []string{"viz", "stat", "au", "-n", TestHelper.GetVizNamespace(), "--to", fmt.Sprintf("po/%s", prometheusPod), "--to-namespace", prometheusNamespace},
+			expectedRows: map[string]string{
+				prometheusAuthority: "-",
+			},
+		},
 	}
 
 	if !TestHelper.ExternalPrometheus() {
@@ -146,7 +152,7 @@ func TestCliStatForLinkerdNamespace(t *testing.T) {
 			{
 				args: []string{"viz", "stat", "svc", "prometheus", "-n", TestHelper.GetVizNamespace(), "--from", "deploy/metrics-api", "--from-namespace", TestHelper.GetVizNamespace()},
 				expectedRows: map[string]string{
-					"prometheus": "1/1",
+					"prometheus": "-",
 				},
 			},
 		}...,
@@ -177,42 +183,87 @@ func TestCliStatForLinkerdNamespace(t *testing.T) {
 		)
 	}
 
-	for _, tt := range testCases {
-		tt := tt // pin
-		timeout := 20 * time.Second
-		t.Run("linkerd "+strings.Join(tt.args, " "), func(t *testing.T) {
-			err := TestHelper.RetryFor(timeout, func() error {
-				// Use a short time window so that transient errors at startup
-				// fall out of the window.
-				tt.args = append(tt.args, "-t", "30s")
-				out, err := TestHelper.LinkerdRun(tt.args...)
-				if err != nil {
-					testutil.AnnotatedFatalf(t, "unexpected stat error",
-						"unexpected stat error: %s\n%s", err, out)
-				}
+	// Apply a sample application
+	TestHelper.WithDataPlaneNamespace(ctx, "stat-test", map[string]string{}, t, func(t *testing.T, prefixedNs string) {
+		out, err := TestHelper.LinkerdRun("inject", "--manual", "../trafficsplit/testdata/application.yaml")
+		if err != nil {
+			testutil.AnnotatedFatal(t, "'linkerd inject' command failed", err)
+		}
 
-				expectedColumnCount := 8
-				if tt.status != "" {
-					expectedColumnCount++
-				}
-				rowStats, err := testutil.ParseRows(out, len(tt.expectedRows), expectedColumnCount)
-				if err != nil {
-					return err
+		out, err = TestHelper.KubectlApply(out, prefixedNs)
+		if err != nil {
+			testutil.AnnotatedFatalf(t, "'kubectl apply' command failed",
+				"'kubectl apply' command failed\n%s", out)
+		}
+
+		// wait for deployments to start
+		for _, deploy := range []string{"backend", "failing", "slow-cooker"} {
+			if err := TestHelper.CheckPods(ctx, prefixedNs, deploy, 1); err != nil {
+				if rce, ok := err.(*testutil.RestartCountError); ok {
+					testutil.AnnotatedWarn(t, "CheckPods timed-out", rce)
+				} else {
+					testutil.AnnotatedError(t, "CheckPods timed-out", err)
 				}
+			}
+		}
+
+		testCases = append(testCases, []struct {
+			args         []string
+			expectedRows map[string]string
+			status       string
+		}{
+			{
+				args: []string{"viz", "stat", "svc", "-n", prefixedNs},
+				expectedRows: map[string]string{
+					"backend-svc": "-",
+				},
+			},
+			{
+				args: []string{"viz", "stat", "svc/backend-svc", "-n", prefixedNs, "--from", "deploy/slow-cooker"},
+				expectedRows: map[string]string{
+					"backend-svc": "-",
+				},
+			},
+		}...,
+		)
 
-				for name, meshed := range tt.expectedRows {
-					if err := validateRowStats(name, meshed, tt.status, rowStats); err != nil {
+		for _, tt := range testCases {
+			tt := tt // pin
+			timeout := 20 * time.Second
+			t.Run("linkerd "+strings.Join(tt.args, " "), func(t *testing.T) {
+				err := TestHelper.RetryFor(timeout, func() error {
+					// Use a short time window so that transient errors at startup
+					// fall out of the window.
+					tt.args = append(tt.args, "-t", "30s")
+					out, err := TestHelper.LinkerdRun(tt.args...)
+					if err != nil {
+						testutil.AnnotatedFatalf(t, "unexpected stat error",
+							"unexpected stat error: %s\n%s", err, out)
+					}
+
+					expectedColumnCount := 8
+					if tt.status != "" {
+						expectedColumnCount++
+					}
+					rowStats, err := testutil.ParseRows(out, len(tt.expectedRows), expectedColumnCount)
+					if err != nil {
 						return err
 					}
-				}
 
-				return nil
+					for name, meshed := range tt.expectedRows {
+						if err := validateRowStats(name, meshed, tt.status, rowStats); err != nil {
+							return err
+						}
+					}
+
+					return nil
+				})
+				if err != nil {
+					testutil.AnnotatedFatal(t, fmt.Sprintf("timed-out checking stats (%s)", timeout), err)
+				}
 			})
-			if err != nil {
-				testutil.AnnotatedFatal(t, fmt.Sprintf("timed-out checking stats (%s)", timeout), err)
-			}
-		})
-	}
+		}
+	})
 }
 
 func validateRowStats(name, expectedMeshCount, expectedStatus string, rowStats map[string]*testutil.RowStat) error {
diff --git a/viz/metrics-api/prometheus_test.go b/viz/metrics-api/prometheus_test.go
new file mode 100644
index 000000000..ec4388479
--- /dev/null
+++ b/viz/metrics-api/prometheus_test.go
@@ -0,0 +1,14 @@
+package api
+
+import (
+	"testing"
+
+	"github.com/prometheus/common/model"
+)
+
+func TestGenerateLabelStringWithRegex(t *testing.T) {
+	query := generateLabelStringWithRegex(model.LabelSet{}, "key", "value")
+	if query != "{key=~\"^value.*\"}" {
+		t.Errorf("Expected 'key=~\"^value.+\"', got '%s'", query)
+	}
+}
diff --git a/viz/metrics-api/stat_summary_test.go b/viz/metrics-api/stat_summary_test.go
index 755e04a79..a0b93a17e 100644
--- a/viz/metrics-api/stat_summary_test.go
+++ b/viz/metrics-api/stat_summary_test.go
@@ -1406,13 +1406,16 @@ status:
 											Rows: []*pb.StatTable_PodGroup_Row{
 												{
 													Resource: &pb.Resource{
-														Namespace: "emojivoto",
-														Type:      pkgK8s.Service,
-														Name:      "emoji-svc",
+														Type: pkgK8s.Service,
+													},
+													TimeWindow: "1m",
+													Stats: &pb.BasicStats{
+														SuccessCount: 123,
+														FailureCount: 0,
+														LatencyMsP50: 123,
+														LatencyMsP95: 123,
+														LatencyMsP99: 123,
 													},
-													TimeWindow:      "1m",
-													MeshedPodCount:  1,
-													RunningPodCount: 1,
 												},
 											},
 										},
@@ -1514,21 +1517,37 @@ status:
 				req: &pb.StatSummaryRequest{
 					Selector: &pb.ResourceSelection{
 						Resource: &pb.Resource{
+							Type: pkgK8s.Pod,
+						},
+					},
+					Outbound: &pb.StatSummaryRequest_FromResource{
+						FromResource: &pb.Resource{
 							Type: pkgK8s.Service,
 						},
 					},
 				},
 			},
+		}
+
+		for _, invalid := range invalidRequests {
+			rsp, err := fakeGrpcServer.StatSummary(context.TODO(), invalid.req)
+
+			if err != nil || rsp.GetError() == nil {
+				t.Fatalf("Expected validation error on StatSummaryResponse, got %v, %v", rsp, err)
+			}
+		}
+
+		validRequests := []statSumExpected{
 			{
 				req: &pb.StatSummaryRequest{
 					Selector: &pb.ResourceSelection{
 						Resource: &pb.Resource{
-							Type: pkgK8s.Service,
+							Type: pkgK8s.Pod,
 						},
 					},
 					Outbound: &pb.StatSummaryRequest_ToResource{
 						ToResource: &pb.Resource{
-							Type: pkgK8s.Pod,
+							Type: pkgK8s.Service,
 						},
 					},
 				},
@@ -1537,37 +1556,21 @@ status:
 				req: &pb.StatSummaryRequest{
 					Selector: &pb.ResourceSelection{
 						Resource: &pb.Resource{
-							Type: pkgK8s.Pod,
-						},
-					},
-					Outbound: &pb.StatSummaryRequest_FromResource{
-						FromResource: &pb.Resource{
 							Type: pkgK8s.Service,
 						},
 					},
 				},
 			},
-		}
-
-		for _, invalid := range invalidRequests {
-			rsp, err := fakeGrpcServer.StatSummary(context.TODO(), invalid.req)
-
-			if err != nil || rsp.GetError() == nil {
-				t.Fatalf("Expected validation error on StatSummaryResponse, got %v, %v", rsp, err)
-			}
-		}
-
-		validRequests := []statSumExpected{
 			{
 				req: &pb.StatSummaryRequest{
 					Selector: &pb.ResourceSelection{
 						Resource: &pb.Resource{
-							Type: pkgK8s.Pod,
+							Type: pkgK8s.Service,
 						},
 					},
 					Outbound: &pb.StatSummaryRequest_ToResource{
 						ToResource: &pb.Resource{
-							Type: pkgK8s.Service,
+							Type: pkgK8s.Pod,
 						},
 					},
 				},