Skip to content

[Bug] Generate unique check IDs and detail routes #10

Description

@kilemensi

What happened

ProbeView discovers and deduplicates Synthetic Monitoring checks using the (job, instance) pair, but generates the public check ID from slugify(job) alone.

Grafana defines a check's identity as the combination of Job name + Target, so two valid checks can share a job name while targeting different URLs. Those checks receive the same ProbeView ID. Distinct job names can also collide after slug normalization, for example Public API and Public-API.

The duplicate ID is then used as:

  • the React list key on the overview;
  • the /site/<id> detail URL; and
  • the lookup key in getSiteHistory(), which returns the first matching check.

As a result, overview rows can have duplicate keys and URLs, and at least one affected check has no independently addressable detail page.

What you expected

Every discovered (job, instance) check should have a unique, stable public ID and detail route, even when job names are duplicated or normalize to the same slug.

Existing non-colliding detail URLs should remain compatible where practical.

Steps to reproduce

  1. Configure two Grafana Synthetic Monitoring checks with the same Job name and different Targets, or with names such as Public API and Public-API.
  2. Load the ProbeView overview.
  3. Observe that both checks receive the same /site/<id> link and React key.
  4. Open that detail URL and observe that checks.find((c) => c.id === id) always selects the first matching check.

Environment

  • App version / commit: 7ad4ff8
  • Node version: v24.18.0
  • Running mode: [x] live (Grafana) [ ] sample data (MOCK=1 / no creds)
  • Host: [x] local [ ] Vercel [ ] other (specify)

Diagnostics

Not applicable. The collision follows from check discovery and route construction and does not depend on a failed Grafana query.

Relevant implementation:

  • lib/synthetics.ts: deduplication uses (job, instance), while id uses slugify(job).
  • components/Overview.tsx: c.id is used for the list key and detail URL.
  • lib/synthetics.ts: detail lookup uses the first check matching id.

Grafana documents Job name + Target as the check identifier:
https://grafana.com/docs/grafana-cloud/testing/synthetic-monitoring/create-checks/checks/

Logs / screenshots

No runtime error is required to trigger the bug.

Acceptance criteria

  • Every discovered (job, instance) pair receives a unique, deterministic ID.
  • Job names that collide after slug normalization remain independently addressable.
  • Overview list keys and links are unique.
  • Detail routes resolve the intended check deterministically.
  • Existing non-colliding URLs remain compatible, or a migration strategy is documented.
  • Unit and end-to-end tests cover duplicate job names and slug collisions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions