Skip to content

Add Topology docs page for the dashboard - #392

Open
hank-metalbear wants to merge 10 commits into
mainfrom
han/topology-docs
Open

hank-metalbear wants to merge 10 commits into
mainfrom
han/topology-docs

Conversation

@hank-metalbear

Copy link
Copy Markdown
Contributor
  • New page under Dashboard: how to turn on operator.topology, what the operator records, how to read the map, and why a connection can be missing.
  • Covers the cloud identity-sharing requirement, since service names only leave the cluster with identity.
  • Added to the sidebar between Cloud Setup and Usage API.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Retrigger

[Low risk] Adds documentation page for dashboard topology feature.

The PR should not merge until the cloud prerequisites account for the anonymization override.

Fix All in CursorFindings

  1. P1 Anonymization override omitted ▶
Fix with agent prompt
### Issue 1
docs/managing-mirrord/dashboard/topology.md:18
The cloud requirement says identity sharing on the API key is enough, but `cloud.anonymizeData: true` overrides it. An operator can follow these requirements and still send anonymized telemetry, leaving the Topology tab empty. Please include this override here and in the missing-connection guidance. Greptile automatically discovered a related ticket stating that anonymization overrides identity-sharing consent, which informed this comment.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Summary

Adds a Topology guide under Dashboard, covering setup, recorded connections, map controls, and reasons connections may be missing.

  • Links the new page between Cloud Setup and Usage API.
  • Describes cloud identity sharing as a prerequisite, but omits the operator setting that can override it.

Reviews (1) · Last reviewed commit: "Add Topology docs page for the dashboard"


- Operator chart 3.211.0 or newer.
- A dashboard, set up either way: [Cloud Setup](cloud.md) or [License Server Setup](license-server.md). With a license server, run the license server from the same release or newer.
- On the cloud dashboard, identity sharing turned on for the operator's API key. Service names only leave the cluster with identity, so with sharing off the tab stays empty.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Anonymization override omitted

The cloud requirement says identity sharing on the API key is enough, but cloud.anonymizeData: true overrides it. An operator can follow these requirements and still send anonymized telemetry, leaving the Topology tab empty. Please include this override here and in the missing-connection guidance. Greptile automatically discovered a related ticket stating that anonymization overrides identity-sharing consent, which informed this comment.

Source Used: Linear — Docs: how customers enable the cloud dashboard

Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/managing-mirrord/dashboard/topology.md
Line: 18

Comment:
**Anonymization override omitted**

The cloud requirement says identity sharing on the API key is enough, but `cloud.anonymizeData: true` overrides it. An operator can follow these requirements and still send anonymized telemetry, leaving the Topology tab empty. Please include this override here and in the missing-connection guidance. Greptile automatically discovered a related ticket stating that anonymization overrides identity-sharing consent, which informed this comment.

**Source Used:** Linear — [Docs: how customers enable the cloud dashboard](https://linear.app/metalbear/issue/PRO-228/docs-how-customers-enable-the-cloud-dashboard)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Cursor Fix in Codex Fix in Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Requirements now say cloud.anonymizeData must not be true, and the missing-connection list covers it too.

hank-metalbear and others added 5 commits September 29, 2026 12:43
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Topology

The **Topology** tab in the dashboard draws the services in your cluster and the connections between them. The map is built from mirrord sessions: when a session opens a connection to a Kubernetes Service, or receives one, the operator records it. You don't declare dependencies anywhere; the map shows what sessions actually connected to.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The **Topology** tab in the dashboard draws the services in your cluster and the connections between them. The map is built from mirrord sessions: when a session opens a connection to a Kubernetes Service, or receives one, the operator records it. You don't declare dependencies anywhere; the map shows what sessions actually connected to.
The **Topology** tab in the dashboard shows the services in your cluster and the connections between them. The map is built from mirrord sessions: when a session opens a connection to a Kubernetes Service, or receives one, the operator records it. You don't declare dependencies anywhere; the map shows what sessions actually connected to, so it fills in as your team uses mirrord.
% hint style="info" %}
The map only includes connections that went through a mirrord session. To fill it in for a whole namespace at once, see Map the whole cluster at once (#map-the-whole-cluster-at-once). If a connection you expect is missing, see Why a connection is missing (#why-a-connection-is-missing).
{% endhint %}```

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied, with the hint syntax and both anchor links fixed.


The **Topology** tab in the dashboard draws the services in your cluster and the connections between them. The map is built from mirrord sessions: when a session opens a connection to a Kubernetes Service, or receives one, the operator records it. You don't declare dependencies anywhere; the map shows what sessions actually connected to.

![Topology tab showing services in the shop, infra and mirrord namespaces, with preview environments and data stores](../../.gitbook/assets/topology-map.png)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
![Topology tab showing services in the shop, infra and mirrord namespaces, with preview environments and data stores](../../.gitbook/assets/topology-map.png)
The map is from MetalMart (https://github.com/metalbear-co/playground/tree/main/apps/shop), our open-source demo shop: its services run in the shop namespace, and the databases and message brokers they use run in infra.
Topology tab for the MetalMart demo app, showing its services, data stores, message queues and preview environments (../../.gitbook/assets/topology-map.png)```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something like this, i think i didnt put the link to metalmart correctly so pay attention please

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied. The link now points to the shop app in the playground repo, and the caption is the image alt text.

Comment on lines +18 to +20
- Operator chart 3.211.0 or newer.
- A dashboard, set up either way: [Cloud Setup](cloud.md) or [License Server Setup](license-server.md). With a license server, run the license server from the same release or newer.
- On the cloud dashboard, identity sharing turned on for the operator's API key, and `cloud.anonymizeData` left at `false`. Service names only leave the cluster with identity, so otherwise the tab stays empty.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Operator chart 3.211.0 or newer.
- A dashboard, set up either way: [Cloud Setup](cloud.md) or [License Server Setup](license-server.md). With a license server, run the license server from the same release or newer.
- On the cloud dashboard, identity sharing turned on for the operator's API key, and `cloud.anonymizeData` left at `false`. Service names only leave the cluster with identity, so otherwise the tab stays empty.
- Operator chart 3.211.0 or newer.
- A dashboard, set up with either [Cloud Setup](cloud.md) or [License Server Setup](license-server.md). With a license server, the license server also needs to be 3.211.0 or newer.
- Cloud dashboard only: an API key created with identity sharing on (see Cloud Setup (cloud.md#new-customers-set-up-the-cloud-dashboard)), and `cloud.anonymizeData` not set to `true`. Service names only leave the cluster with identity, so without it the tab stays empty.```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validate my suggestion please

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied and validated. 3.211.0 is the first release with the license server topology endpoint, the Cloud Setup anchor resolves, and cloud.anonymizeData: true does override identity sharing.

Comment on lines +22 to +41
## Turn it on

Topology is off by default. Set it in the operator's Helm values and upgrade:

```yaml
# values.yaml
operator:
topology: true
```

```bash
helm upgrade mirrord-operator metalbear/mirrord-operator -f values.yaml
```

With this on, the operator watches every Service and EndpointSlice in the cluster so it can tell which Service an address belongs to. The chart makes two RBAC changes for this:

- The operator's ClusterRole gets `get`, `list` and `watch` on `endpointslices`.
- The user ClusterRole gets `get` and `list` on `mirrordclusterservicegraphs`, the operator's read-only view of the graph.

Then run a few sessions. A session reports its connections when it ends, so a new edge shows up on the map shortly after the session that made it stops.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Turn it on
Topology is off by default. Set it in the operator's Helm values and upgrade:
```yaml
# values.yaml
operator:
topology: true
```
```bash
helm upgrade mirrord-operator metalbear/mirrord-operator -f values.yaml
```
With this on, the operator watches every Service and EndpointSlice in the cluster so it can tell which Service an address belongs to. The chart makes two RBAC changes for this:
- The operator's ClusterRole gets `get`, `list` and `watch` on `endpointslices`.
- The user ClusterRole gets `get` and `list` on `mirrordclusterservicegraphs`, the operator's read-only view of the graph.
Then run a few sessions. A session reports its connections when it ends, so a new edge shows up on the map shortly after the session that made it stops.
## Turn it on
Topology is off by default.
1. Set it in the operator's Helm values:
```yaml
# values.yaml
operator:
topology: true
  1. Upgrade the operator
helm upgrade mirrord-operator metalbear/mirrord-operator -f values.yaml
  1. Run a few mirrord sessions, then open the Topology tab. A session reports its connections when it ends, so each new connection shows up shortly after the session that made it stops.

{% hint style="info" %}
With topology on, the operator watches every Service and EndpointSlice in the cluster so it can tell which Service an address belongs to. The chart makes two RBAC changes for this:

  • The operator's ClusterRole gets get, list and watch on endpointslices
  • The user ClusterRole gets get and list on mirrordclusterservicegraphs, the operator's read-only view of the graph.
    {% endhint %}```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again please review and dont just accept changes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied as numbered steps. Checked against the chart: the value is operator.topology, default off, and the two RBAC changes match what the chart renders. Only change from your text: "view of the graph" became "view of the map".

calls it makes go through mirrord.
```

Once the sessions end, refresh the **Topology** tab. Every connection those sessions made is on the map.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Once the sessions end, refresh the **Topology** tab. Every connection those sessions made is on the map.
Once the sessions end, refresh the **Topology** tab. The connections those sessions made are on the map.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied.

| **Data store** | Reached on a well-known database port (Postgres, MySQL, Redis, MongoDB, and so on) |
| **Queue** | Reached on a well-known broker port (Kafka, RabbitMQ, NATS, and so on) |
| **Infrastructure** | Reached on a well-known infrastructure port |
| **Preview env** | A preview environment |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

service? or env? what if the env have 3 services within it? it will be shown as one node or 3?

@hank-metalbear hank-metalbear Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Up to three. Each preview Service that appears in a connection is its own node, labelled with the preview's key, and its replicas share that node. The table row says so now.


Categories come from ports and from which end of a connection a service was on. Service names are never used to guess them, so a Postgres served on a custom port shows up as a plain **Service**. Click a chip in the legend to hide that category.

A node marked **Discovered** was only ever seen as the other end of a connection. No session targeted it, so its session count is the sum over the edges pointing at it, and its user count is the highest count on any single edge it's part of.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh ok, clear now.
so move it from here to the table. it will be easier to understand.

@hank-metalbear hank-metalbear Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. The definition sits in the Entry point row. The paragraph below covers how a Service is matched to a workload and how a Discovered node's counts are worked out.

Other controls:

- **Find a service** searches by name. Press `/` to jump to it.
- **Busiest paths** keeps the busiest quarter of the edges lit and dims the rest.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the word edge is weird. make sure to replace it everywhere i didnt please

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

node it ok, 'connection' also makes sense in some sentences.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced everywhere with "connection". "Node" stays.

- The connection failed. Only successful connections count.
- The address belongs to more than one Service with different pods behind them, so it can't be attributed to one.
- The connection used UDP. Only TCP is recorded.
- The session targeted pods by label selector instead of a workload.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sad, but ok

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets open a ticket for the future to make sure we do this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Opened PRO-245 to record connections for sessions that target pods by label selector.

- The session targeted pods by label selector instead of a workload.
- The service called itself. Connections to the session's own target aren't recorded.
- The connection happened in the first moments after the operator started, before it finished loading the cluster's Services.
- The session connected to a very large number of Services. Each session reports a limited list, keeping the most recent ones.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why Services with camel case? not sure its correct (everywhere)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capitalized only where it means the Kubernetes Service resource, same as the Kubernetes docs. Generic "services" stay lowercase.

hank-metalbear and others added 2 commits October 1, 2026 23:20
- Clearer intro with a note that only mirrord-session traffic is mapped
- Name and link the MetalMart demo behind the screenshot
- Numbered steps to turn it on, with the RBAC changes in a note
- Warn that exercising endpoints sends real requests
- Explain the user count, list the ports behind each category, define Discovered
  in the table and explain how preview environments become nodes
- Say "connection" instead of "edge"

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

PRO-246

PRO-245

hank-metalbear and others added 2 commits October 2, 2026 15:53
…y docs

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants