Skip to content

Observability refactor - update merge in current origin main, image fix - #776

Merged
braxtonj merged 11 commits into
mainfrom
observability_refactor
Nov 4, 2026
Merged

braxtonj merged 11 commits into
mainfrom
observability_refactor

Conversation

@braxtonj

Copy link
Copy Markdown
Contributor

Checkly exposes metrics on one Prometheus endpoint and sends check runs as OpenTelemetry spans to one OTLP endpoint. The pages for that are split between Integrations > Observability and Resolve > Traces > Exporting today, and Chronosphere is not in the nav. This PR puts them in one place.

What changes

  • Integrations > Observability now holds everything that leaves Checkly: an Overview with a decision table, a Metrics subgroup with one Prometheus page, and a Traces subgroup with a generic OTLP page, Coralogix and thin vendor pages (Chronosphere, ClickStack, Cribl Stream, Dash0, Datadog, Grafana Tempo, Honeycomb, New Relic).
  • Resolve > Traces > Exporting becomes one router page that links the Integrations pages. No page path appears in two nav groups.
  • Prometheus is one page. The v2 content is the page, with labels, windows and edge cases documented from the current implementation. The v1 endpoint is a clearly labeled legacy section at the end with a deprecation warning. /integrations/observability/prometheus-v2 redirects to /integrations/observability/prometheus and the #heartbeat-metrics anchor survives.
  • The OTLP page is new and carries the span schema, the trace headers, the tags rules, a tested Collector receiver recipe, transport facts and troubleshooting. Vendor pages only carry the values each vendor needs and link back for everything else.
  • Coralogix is corrected in place: key location, endpoint derivation, the attribute list, the custom trace header behavior, and current RUM key names.
  • Resolve > Traces pages point at the new locations; how-it-works keeps its diagram and gets the four-type coverage wording. A vendor-neutral Mermaid version of the diagram sits on the page inside an MDX comment, ready to swap in.

Moves and redirects

Old New
resolve/traces/export/grafana-tempo integrations/observability/traces/grafana-tempo
resolve/traces/export/honeycomb integrations/observability/traces/honeycomb
resolve/traces/export/new-relic integrations/observability/traces/new-relic
resolve/traces/export/dash0 integrations/observability/traces/dash0
resolve/traces/export/to-chronosphere integrations/observability/traces/chronosphere
integrations/observability/prometheus-v2 merged into integrations/observability/prometheus

All six have docs.json redirects, so existing links, including the ones in the web app, keep working.

Verification

  • Schemas, labels and attributes were taken from the current implementation and checked live, not copied from the old pages.
  • Live verification on 2026-10-30: spans captured for every check type from public and private locations through a bearer-authenticated OpenTelemetry Collector, the receiver recipe on the OTLP page. The scrape config, every PromQL example, the Collector prometheus receiver block and the legacy v1 config were run in Prometheus 3.0.0 and otelcol-contrib 0.160.0. Both Prometheus endpoints were scraped and compared with the documented metric families (35 of 35 v2, 6 of 6 v1).
  • Vendor pages were validated against vendor documentation. Anything that could not be confirmed was left off.
  • Screenshots: fresh Checkly-side captures of the Prometheus card, the Export Traces settings and the Coralogix form, values masked. The Export Traces capture is reused on the Dash0 and Grafana Tempo pages. The existing vendor-side screenshots on those pages and on Coralogix sit under the rewritten steps, and the Prometheus page keeps its two earlier setup captures. The token visible in dash0-token.png is masked.

Deliberately dropped

  • Three old Checkly screenshots: dash0-checkly.png and export-traces-to-grafana-config.png (the old Export Traces form, replaced by the fresh capture) and prometheus_step2.png (the v1 activation card; v1 setup is now one sentence under Legacy v1 endpoint). The files stay on disk.
  • Grafana's "check that Tempo is installed" step and the third-party base64 website (replaced by a shell one-liner).
  • New Relic's "Traces feature enabled" step (not in New Relic's documentation).
  • The v2 page's Info banner and the v1 Warning (replaced by one deprecation Warning), the v1 "inactive after six hours" sentence, the v1 "30 to 60 s interval" advice, and the enable_compression tip (the endpoint gzips when the scraper asks, which Prometheus does by default).
  • A link to the private location agent metrics page: docs(private-locations): agent Prometheus metrics and single server port #755 is still open. Once it lands, add one sentence on the Prometheus page and point its Prometheus link at /integrations/observability/prometheus.
  • The deprecated agentic check type from the check_type enumeration.

Follow-up

  • Redraw checkly_otel_diagram.png on how-it-works: it hardcodes tracestate: checkly=true and lists Baselime among the vendors. The Mermaid version on the page is the starting point.

Open PRs that touch the same files

…merge the Prometheus pages

Move the Grafana Tempo, Honeycomb, New Relic, Dash0 and Chronosphere export pages from Resolve > Traces > Exporting to Integrations > Observability > Traces, with redirects from the old paths. Fold the Prometheus V2 page into the Prometheus page, keep the v1 content as a deprecated legacy section and redirect /integrations/observability/prometheus-v2 to it. Add a one-page Exporting router under Resolve > Traces, drop an unreferenced screenshot, repoint inbound links and regenerate the sitemap.
Document every v2 metric with its labels and window semantics from the current API code, including the hourly reset at 01:30, the +Inf-only histogram buckets, the tag parsing rule, token rotation, rate limit and error codes. Add an OpenTelemetry Collector receiver recipe and point Dashboards readers at the endpoint. Correct the legacy v1 section from code and a live scrape, and add the fallback scrape protocol Prometheus 3 needs for it. The scrape config, every PromQL example and the collector block were run against a live account. One new screenshot of the integration card replaces the two outdated activation screenshots.
…d the Datadog, ClickStack and Cribl Stream pages

The overview states the model in two sentences, routes readers with a decision table and lists coverage and limits. The OTLP page documents the span schema, trace headers, tag rules, transport facts and troubleshooting from the runner code, and carries the OpenTelemetry Collector receiver configuration that received real spans during verification. The three new vendor pages follow the thin template. Nav entries and a fresh Export Traces screenshot are included.
Coralogix: current key location and names, region versus team name, the attribute list deferred to the OTLP page, the custom trace header behavior, RUM key naming, and a fresh form screenshot. Vendor pages: one template with the endpoint, the key location, the header rows and where the spans appear, with values checked against each vendor's documentation. Grafana's third-party base64 site is replaced by a shell one-liner, the stale New Relic and Honeycomb paths are fixed, Dash0's trailing slash is gone and Chronosphere notes the Cortex XCOR rename.
The Exporting router lists every export page, the Resolve cards link the OTLP page, how-it-works gets a vendor-neutral Mermaid diagram and the four-type coverage wording with the span schema deferred to the OTLP page, and the custom headers section notes when CHECKLY_TRACEPARENT is empty. Link text on the heartbeat, autoscaling and dashboards pages matches the new Prometheus page title.
Tighten conditions the code imposes: when checkly_check_status is absent, the 0 reading of the HTTP status gauge, the 400 for non-boolean parameters, the cache refresh wait, revoked tokens working for up to ten minutes, the hourly window wording, the private location queue series sources, and tag keys that collide with built-in labels. On the OTLP page: what the URL check covers, header templating with environment variables and secrets, the instrumentation scope names, when checkly_debug appears, and the Coralogix custom header on Browser and Multistep checks. Reader fixes from review: a Collector row and limits on the overview, a fallback for unlisted backends, TLS in front of the sample receiver, and a troubleshooting entry for credentials in the URL.
# Conflicts:
#	integrations/observability/coralogix.mdx
#	integrations/observability/prometheus-v2.mdx
@braxtonj
braxtonj requested a review from stefanjudis October 30, 2026 22:20
stefanjudis
stefanjudis previously approved these changes Nov 3, 2026

@stefanjudis stefanjudis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

:shipit:

I skimmed the pages and checkt the redirects. LGTM.

@hlenke hlenke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Needs changes · The last merge from main left docs.json invalid JSON, so the Mintlify deployment and every CI job fail. Fix the redirect block at docs.json:2482 first, then re-run CI.

The content holds up well. I checked the Prometheus v2 schema, limits and labels and the OTLP export behavior against the current source, and almost everything matched. Two statements need a fix. The rest of the items below are small.

Merge readiness

  • CI is red because docs.json does not parse. static-docs-checks fails with SyntaxError: Expected ',' or '}' after property value in JSON at position 99108 (line 2483 column 7). Mintlify Deployment fails for the same reason, and preview-checks and docs-gate fail because the deployment failed. The prometheus-v2 redirect object has lost its closing }, and the next object's opening {, so it runs straight into the /platform/rocky-ai redirect. There is a one-click suggestion inline. No preview was built, so nothing on this branch has been rendered yet.
  • Mergeable, no conflicts. mergeStateStatus is BLOCKED only because of the failing checks.
  • Overlap. #446 and #449 (Mintlify bot) both edit integrations/observability/prometheus-v2.mdx, which this PR deletes. Land this PR first, then close those two or rebase what is still useful onto prometheus.mdx. #774 (draft, sentence case) touches the moved pages too. The PR description already covers that one.
  • Redirects and inbound links (pr_impact.py, after patching the JSON locally so it could run): all six removed pages have a redirect in docs.json. No link in the head points at a removed page, and no new broken links or anchors were found. #heartbeat-metrics survives on the merged page.

Outside the diff

  • Important: platform/private-locations/agent-metrics.mdx:51 is now on main and still links [Prometheus V2 integration](/integrations/observability/prometheus-v2/). The redirect covers it. The PR description says #755 is still open, but that page has since landed, so the follow-up you planned can go in this PR. Point the link at /integrations/observability/prometheus and add the one sentence on the Prometheus page that links to agent metrics.

Inline comments

1 blocker, 2 important, 1 wording.

What I checked
  • Diff 54c23c8d..bd38402c (merge base = current origin/main), every text file read top to bottom. Sitemaps and PNGs were reviewed separately.
  • CI: gh pr checks 776 and the failed logs of runs 41640322922 (static-docs-checks), 41640322970 (docs-gate) and 41640322895 (preview-checks). gh pr view for mergeability. Overlap from gh pr list --json number,files.
  • pr_impact.py: it crashed on the head snapshot's invalid docs.json. I added the missing },{ to the cached snapshot only (not the repo) and re-ran it, which produced the redirect and link results above.
  • Prometheus v2, against monorepo origin/main@28c905592a:
    • The endpoint's route definition: the three query flags, all default false, validated as booleans. The hourly window offset is 90 s, which gives the HH:01:30 reset.
    • API config defaults: 50 requests per 60 s for v2 and 300 per 60 s for v1. The ClickHouse query timeout is 25 s.
    • The v2 controller: 60 s cache, gzip only when the scraper asks for it, one cache entry per parameter combination.
    • The v1 module: 30 s cache, plus a 600 s in-memory token cache, which supports "revoked token can work for up to 10 minutes".
    • The token service caps an account at 2 tokens.
    • The v2 golden output (__goldens__/prometheus-v2.bb-spec.ts/active-account.txt): type values for web vitals, browser errors and API timings, base labels, group and tag labels.
  • OTLP export, same commit:
    • Go API/URL runner: checkly-tracer scope, the 5 s export timeout, OTLP/HTTP protobuf, header values rendered from environment variables, and cx.* resource attributes whenever the Coralogix integration is on.
    • Browser and PWCS runners: the tracestate members including checkly_debug=true on ad hoc and test-session runs, the checkly-browser-tracer scope, span kind CLIENT with status always OK, service.name=checkly.
    • Playwright Check Suites build a span too, but only for the Checkly-owned integration (CHECKLY_OTEL), not for the customer export (HOSTED_OTEL). The "four check types" statement holds.
  • UI labels against the webapp i18n and component tests: Create Prometheus endpoint, Bearer tokens, Add token, Add Coralogix integration, Enable sending traces to Coralogix, Custom trace header, Enable Coralogix RUM, RUM Region, RUM application name, RUM API key, Enable exporting traces, Add header, + Add more channels, New alert channel, Save Coralogix webhook. All match.
  • Vendor docs:
  • Screenshots: I read cx_otel_int1.png, prometheus_integration_card.png, dash0-token.png and otel_export_traces_settings.png (new or changed), plus the reused prometheus_step1.png and prometheus_v2_step2.png. Tokens are masked and I found no PII. One reused image is outdated (inline).
  • No end-to-end tests. The claims are about the production Prometheus endpoint, the trace export pipeline and third-party intakes, which the local app cannot show. I verified against source instead.
  • Could not verify:
    • Datadog's per-site OTLP hosts in the table (the Datadog page uses a placeholder).
    • That Chronosphere hosts stay <instance>.chronosphere.io. The XCOR page says TENANT and does not mention the rename.
    • ClickStack, Cribl Stream and Dash0 setup steps.
    • The private location queue sampling windows and the 250 s agent window.
    • Coralogix's current API-key menu path.

Comment thread docs.json
Comment on lines +2482 to 2483
"destination": "/integrations/observability/prometheus"
"source": "/platform/rocky-ai",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Blocker: The merge dropped the end of this redirect object and the start of the next one. docs.json no longer parses, which fails the Mintlify deployment and static-docs-checks (Expected ',' or '}' after property value ... line 2483 column 7).

Suggested change
"destination": "/integrations/observability/prometheus"
"source": "/platform/rocky-ai",
"destination": "/integrations/observability/prometheus"
},
{
"source": "/platform/rocky-ai",


- **Caching and limits.** Responses are cached for 60 seconds, so a scrape interval below 60 seconds fetches the same data. Responses are gzip compressed when the scraper asks for it, which Prometheus does by default. The endpoint allows 50 requests per minute per account. Above that it returns `429` with `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers. If you run multiple Prometheus instances, each instance scrapes independently. Align their scrape intervals where possible.
- **Errors.** An unknown token or a lapsed account returns `401`. A revoked token can keep working for up to 10 minutes. Tokens do not expire. A plan without the Prometheus integration returns `403`.
- **Timeouts.** A scrape fails as a whole if any part of the backing query fails. The query times out after 25 seconds, and a scrape that arrives while another one is refreshing the cache waits up to 20 seconds for it, which is why the sample sets `scrape_timeout: 30s`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Important: The 20-second wait no longer matches the code. On monorepo main, a scrape that arrives during a cache refresh waits on the regeneration lock for up to 45 seconds. That timeout was raised on 2026-10-28, see apps/backend/api/src/modules/public-api/prometheus-v2/PrometheusV2Controller.ts. So the wait does not explain the 30 s scrape_timeout anymore. I would drop the number rather than chase it:

Suggested change
- **Timeouts.** A scrape fails as a whole if any part of the backing query fails. The query times out after 25 seconds, and a scrape that arrives while another one is refreshing the cache waits up to 20 seconds for it, which is why the sample sets `scrape_timeout: 30s`.
- **Timeouts.** A scrape fails as a whole if any part of the backing query fails. The query times out after 25 seconds, and a scrape that arrives while another one is refreshing the cache waits for that refresh. For accounts with many checks, keep `scrape_timeout` at `30s` or higher.

![Prometheus integration card with the Create Prometheus endpoint button](/images/docs/images/integrations/prometheus_step1.png)
![Prometheus integration card in account settings](/images/docs/images/integrations/prometheus_integration_card.png)
2. Under **Bearer tokens**, click **Add token** and copy the value. The full value is shown only once, right after you create it. An account can have at most two tokens, so you can rotate: add a token, point your scrape config at it, then revoke the old one.
![Prometheus endpoint URL and bearer token on the integration card](/images/docs/images/integrations/prometheus_v2_step2.png)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Important: This reused capture shows the old card with a single Bearer token field and no Bearer tokens list or Add token button, so it contradicts step 2 right above it. The new prometheus_integration_card.png in step 1 already shows the token list and Add token. Remove this image, or replace it with a capture of the token row right after Add token.

---

Before you start, read the prerequisites on the [OTLP export page](/integrations/observability/traces/otlp) and check [what is sent](/integrations/observability/traces/otlp#what-is-sent).
This page only covers the values Chronosphere needs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wording (optional): The "Before you start…" lead-in, the "Find the spans… filter on checkly.check.status with the value FAILED" step and the closing "The OTLP export page has the span schema" line repeat word for word on all eight vendor pages. Under the repo's three-or-more-pages rule, that boilerplate belongs in a snippet under snippets/, so a later change to the schema link or the status values happens in one place. This can be a follow-up.

@mintlify

mintlify Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
checkly-422f444a 🟢 Ready View Preview Nov 3, 2026, 10:47 PM

@braxtonj

braxtonj commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

updated per your comments @hlenke. but things still seem to be problematic on the gates above. not clear to me why those three were cancelled however, perhaps a timeout thing? but i do not have permissions to try and trigger or dig deeper on the setup here from what I can tell

cc @stefanjudis

@braxtonj

braxtonj commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

so strange. no change made on the commit but simply re-triggering the PR/GH checks above via the cli led to everything passing this time. beats me what happened but always down for the simplicity of did you turn it off and on solutions. re-requesting review @hlenke

@braxtonj
braxtonj requested a review from hlenke November 3, 2026 22:56

@hlenke hlenke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ready to merge · The docs.json fix is in, CI is green, and the other four items from the last review are all addressed. The two wording notes below are optional.

This is a re-review of the one commit since my review at bd38402c (41ef019, "minor tweaks to copy and docs.json cleanup").

From the last review

  • Blocker, docs.json: fixed. The prometheus-v2 redirect is closed and the /platform/rocky-ai object is restored. All checks pass: static-docs-checks, preview-checks, docs-gate, Mintlify Deployment and link-rot.
  • Important, timeouts: fixed. The line no longer gives a wait number, and it still explains why scrape_timeout should stay at 30s.
  • Important, outdated screenshot: fixed. prometheus_v2_step2.png is removed from step 2.
  • Important, agent metrics link: fixed. agent-metrics.mdx now links /integrations/observability/prometheus, and the Prometheus page links back to Agent metrics.
  • Wording, repeated vendor boilerplate: done. The lead-in and the closing lines now come from snippets/otlp-vendor-intro.mdx and snippets/otlp-vendor-outro.mdx on all eight vendor pages.

Merge readiness

  • Mergeable, mergeStateStatus is CLEAN.
  • Staleness: since the merge base, main has changed only admin/team-management/single-sign-on.mdx (#786), which this PR does not touch.
  • Overlap: unchanged. #446 and #449 still edit the deleted prometheus-v2.mdx. Land this PR first.
  • Nit, PR description: it still says #755 is open and lists its link as a follow-up. That page has landed and this PR now fixes the link, so the bullet can go.

Inline comments

0 blockers, 0 important, 2 wording (optional).

What I checked
  • Incremental diff bd38402c..41ef019d (13 files), read in full. Merge base with origin/main is still 54c23c8d, and origin/main is at 9bd2ca0f.
  • gh pr checks 776: every check passes, and vale-spellcheck is skipped. gh pr view shows the PR is mergeable and CLEAN.
  • git log 54c23c8d..origin/main --stat: one commit, which touches only admin/team-management/single-sign-on.mdx.
  • pr_impact.py on the full PR, now that docs.json parses:
    • All six removed pages have redirects, and no links in the head still point at them.
    • It reports both new snippets as "rendered on 0 pages". That is a false positive: all eight vendor pages import them by /snippets/... path, the same pattern other pages on main use.
  • Snippet props: I fetched the Mintlify preview of traces/new-relic. {vendor} renders as "…the values New Relic needs.", and the outro renders as its own paragraph after the vendor docs line.
  • I read prometheus.mdx and agent-metrics.mdx at the head in full. The sample's scrape_interval: 60s stays above scrape_timeout: 30s, so the "30s or higher" advice is consistent with it.
  • The verification of the unchanged content from the last review still applies (monorepo 28c905592a, vendor docs). Its "could not verify" items are unchanged.
  • No end-to-end tests. These are copy and config changes with no runnable claims.

| `state` | `queued`: scheduled but not yet picked up by an agent. `inflight`: being executed by an agent. |
| `stat` | `avg`, `p90`, `p99` over the 2-minute window. |

For metrics scraped from the agent container itself, including an opt-in per-check set with the `checkly_agent_` prefix, see [Agent metrics](/platform/private-locations/agent-metrics).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wording (optional): The always-on agent metrics carry the checkly_agent_ prefix too, so as written the sentence reads as if only the per-check set does.

Suggested change
For metrics scraped from the agent container itself, including an opt-in per-check set with the `checkly_agent_` prefix, see [Agent metrics](/platform/private-locations/agent-metrics).
To scrape metrics from the agent container itself, including opt-in per-check metrics, see [Agent metrics](/platform/private-locations/agent-metrics).

New Relic limits each request to 1 MB.

New Relic documents the endpoints in its [OTLP best practices](https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp/).
<OtlpVendorOutro />

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wording (optional), all eight vendor pages: Moving "To see failed runs, filter on checkly.check.status…" into the outro takes it out of step 4 ("Find the spans"). In the preview it now renders after the "New Relic documents the endpoints…" line, so the tip reads as an afterthought. One fix: put the filter sentence back at the end of step 4 and keep only the span-schema line in the outro snippet. This can be a follow-up.

hlenke added a commit that referenced this pull request Nov 4, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@braxtonj
braxtonj merged commit e905ff0 into main Nov 4, 2026
6 of 9 checks passed
@braxtonj
braxtonj deleted the observability_refactor branch November 4, 2026 03:01

This branch was successfully deployed

1 active deployment
staging — 41ef019d Deployed Nov 3, 2026 by mintlify[bot]
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.

3 participants