dotCMS / dotCMS/core

Analytics: Environment Filtering (read Production data from Authoring)

Open
#37,349 0 comments 0 reactions 1 assignee View on GitHub

@jcastro-dotcms is already working on this.

Since Sep 8, 2026.

dotCMS : Analytics Epic Team : Falcon
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Summary

Make environment a first-class dimension of the Content Analytics pipeline, so a user working in Authoring can select Production and read its analytics, and so non-production traffic stops sitting inside production numbers.

Tracking epic. Child issues to be filed per component; this issue holds scope, sequencing, and acceptance only.

Background

Events are captured by the Production front end, and the dashboard reads only the environment it runs in. Enterprises restrict Production access to a small group for essential activities, so the people who need content performance data cannot open the dashboard. A pilot candidate declined the Early Adopter program for exactly this reason.

Spike #37107 confirmed the underlying state is worse than "cross-environment viewing is missing": environment is not captured anywhere today, and a customer's environments already resolve to the same tenant + project. No environment is distinguished at all, so every environment's traffic is commingled in one dataset.

Approach: reset, not migration

Spike #37107 produced a data-preserving plan (10 ClickHouse table migrations under ADR-0022, with backfill) sized at roughly 15-23 developer-days. That plan was discarded as too complex for the value.

The agreed approach is to reset the Content Analytics infrastructure: drop existing data, recreate the tables with environment in the schema from the start, no backfill. The spike's per-table migration runbooks are not the plan any more; what survives from it is the current-state audit, the environment-identity design, and the API/core/UI scope.

Why this quarter: the reset is cheap only while there is no production analytics data anyone will miss. Every tenant onboarded raises the cost of the drop, and after GA the cheap path is gone and this reverts to the 15-23 day migration.

Gate before work starts

  • Confirm no analytics data needs to be preserved, per tenant and environment, including dotcms.com, dev.dotcms.com, and every onboarded Early Adopter tenant. If any of it must survive, the reset approach is invalid and this epic reverts to the migration plan. This is a gate, not a task.

Scope

Component Track
ClickHouse schema Recreate the raw events table and the 10 downstream aggregate tables with environment as a key dimension
Event manager (CAEM) Accept environment at ingest; filter on it in the three live query endpoints
dotCMS core Environment identity for the instance, the available-environments list, collector plumbing, and a config endpoint for the UI
Dashboard (Angular) Environment selector in the analytics portlet, driven entirely by config
Servers / infrastructure Surface the configuration per customer and roll it out; analytics server upgrade in the same window
Documentation Dashboard docs, configuration reference, data-reset notice

The dashboard selector and the infrastructure rollout were not in the original component list. Without the selector nothing changes for the customer who declined the pilot, and without the infrastructure rollout the selector has nothing to populate from.

Out of scope

  • Preserving existing analytics data. The reset drops it.
  • Authorization for cross-environment reads. Deferred by team decision during the spike; CAEM auth is tenant-scoped, so nothing in it distinguishes an Authoring instance's query from any other. Needs an explicit product answer before GA, tracked separately.
  • The deprecated per-metric analytics controllers.
  • Self-hosted and non-Cloud deployments. Environment identity comes from Cloud labels; self-hosted needs a sane default, not a feature.
  • Automatic discovery of a customer's sibling environments.
  • ADR-0022 --migrate CLI tooling (#37237). This work is executed by hand.
  • Environment as a reporting dimension (prod vs. staging side by side, breakdowns grouped by environment). Scope is one selector that scopes the whole dashboard.

Epic acceptance

  • A user in Authoring selects Production and sees its data across every metric and dimension on the three live endpoints, not a subset
  • The selector is populated from live configuration on every customer, with no environment name hardcoded, defaulting to the current environment
  • Ingested events carry the environment that emitted them, auto-derived, with no manual per-customer entry
  • Omitting the new parameter reproduces today's unfiltered behavior exactly
  • Non-production traffic is separable from production traffic in every dashboard number
  • Data-reset notice and the "production numbers will change" note land before the release, not after

Dependencies

  • Platform: configuration rollout per customer and the server upgrade. Infrastructure itself is already cleared — the Authoring instance already talks to the same analytics service and the same ClickHouse, so there is no new network path.
  • Experiments on CAEM (#36763, #37227, and the experiment columns from #37016 / #37017) share the schema this epic recreates. Sequence the reset with that work; the experiment columns must survive the recreate.
  • #37237 (--migrate CLI) cites this work as its motivating use case. Coordinate so the migration ledger baselines on the post-reset schema.

Notes on sizing

The 3-4 day figure from the spike's closing comment is the ClickHouse reset, not the epic. The epic spans schema, ingest, query API, core configuration, the Angular portlet, an infrastructure rollout, a server upgrade, and docs, across three teams.

Amendment (2026-09-09): environment is required at ingest, not optional

What changed: While specifying the CAEM sub-task (#37407), we decided environment must be a required, non-blank parameter on POST /v1/event/ingest — a missing or blank value is rejected with 400, mirroring how project is already handled today. This replaces the optional-with-default-'' design this epic's scope and acceptance criteria originally assumed (see "Scope" → Event manager (CAEM) row, and the second Epic acceptance bullet below).

Why: environment is an identity dimension for an event — on par with tenant and project — not an incidental label.
Because this epic's own "reset, not migration" decision means there is no legacy/unlabeled analytics data to preserve, there is no reason to let a new event land without a real environment value; doing so would just recreate this epic's own commingling problem one event at a time.

This is formalized as a documented, narrowly-scoped exception in dot-ca-event-manager's constitution (bumped to v1.2.0 — Principle II, "reset-driven required ingest parameters"), gated on: the change being tied to this epic's deliberate reset, the reversal being documented in the sub-task spec, and every existing ingest integration test being updated (not deleted) to supply the new required parameter.

What this changes about this epic's own text — these are necessary, already-settled consequences of the design decision above, not open risks requiring further discussion:

  • Epic acceptance"Omitting the new parameter reproduces today's unfiltered behavior exactly" now holds only for the three query endpoints. At ingest, omitting (or blanking) environment is rejected outright. This can't be otherwise: allowing a blank value in and updating it later would reintroduce the exact backfill problem this epic's reset exists to avoid — environment is part of the key that gets a specific environment's data back out, so it cannot be written unlabeled and reconciled after the fact.
  • Rollout ordering — a customer's dotCMS-core collector must be upgraded to send environment on every event before that customer can be pointed at an updated CAEM. This is an expected, necessary consequence of requiring the field, not a new risk to resolve — the "dotCMS core" and "Event manager (CAEM)" rows in the Scope table above roll out to a given customer in that order, full stop.
  • Self-hosted is unaffected — this epic's Out of scope section already excludes self-hosted/non-Cloud deployments. The required-environment ingest behavior is being enabled for Cloud customers only, so this change introduces no new gap there.

Full detail: specs/003-environment-filtering/spec.md in dot-ca-event-manager (not yet in a PR — currently local spec work on #37407).

Links

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.