Draft: SPIKE: Add traversal_path dimension to ClickHouse aggregation engines
What does this MR do and why?
This MR is extracted from !250580 (closed) so the new framework piece can be reviewed on its own.
It adds TraversalPathDimension to the ClickHouse aggregation engine framework in lib/gitlab/database/aggregation/click_house/, registered under the DSL keyword traversal_path.
TraversalPathDimension is a parameterized dimension. It extracts the namespace id at a requested depth from a traversal path column, for example a path like 9/12/34/, so results can be grouped by a level of the namespace hierarchy. It is built with Arel only, with no SQL string interpolation.
Depth is relative to the aggregated scope
A request against flightjs/subgroup and a request against flightjs both use the default depth of 1 to group by their own direct children. Clients never need to know how deep their group sits in the hierarchy, and the same query means the same thing everywhere.
The reference point is base_traversal_depth in the engine context. BaseEngineResolver sets it from the groups and projects it already authorizes, using the number of traversal path segments they share: the scope's own depth for a single group, and their common ancestor for several. Organization-level requests have no shared prefix, so depth 1 there is the top-level group, which is the same intent one level up. Requests built directly in Ruby usually omit the key, and depth is then absolute as before.
This is the reason to review the MR now rather than after !250580 (closed) merges. Once a client passes depth, moving from absolute to relative is a silent breaking change with no schema difference to signal it.
Other behaviour
with_organizationcovers path columns that carry a leading organization segment, astraversal_path(with_organization: true)builds. Four existing engines use that convention, including the two named in the follow-up issues below.- Paths shorter than the resolved depth produce a
NULLbucket viatoUInt64OrNull. That is also how events attributed to the scope itself, rather than to one of its children, are reported. depthis validated against the engine-declared range and must be a positive integer. ClickHousearrayElementis 1-based and raises on index0instead of returning the documentedNULLbucket, so the guard sits in the dimension rather than relying on every engine declaring a sound range.
Here is the shape of SQL the dimension generates for the direct children of a top-level group:
toUInt64OrNull(arrayElement(splitByChar('/', namespace_path), 2))Example engine usage:
dimensions do
traversal_path :group_id, :integer, -> { sql('namespace_path') }, association: true, parameters: {
depth: { type: :integer, in: 1..20 }
}
endThis MR also includes the developer docs section for the new dimension in doc/development/aggregation_engines.md, the specs, and a new externalized string in locale/gitlab.pot.
No engine uses the dimension yet, so there is no user-facing change here. The first consumer is !250580 (closed), which wires it into the AiUsageEvents engine for GitLab Duo usage analytics, for https://gitlab.com/gitlab-org/gitlab/-/issues/605518. It is also planned for reuse by https://gitlab.com/gitlab-org/gitlab/-/issues/605525 (MergeRequests engine) and #608747 (Deployments engine).
References
Split out of !250580 (closed), which implements https://gitlab.com/gitlab-org/gitlab/-/issues/605518.
The traversal_path dimension is built at the framework level on purpose, so it can be reused by other engines. Planned follow-ups:
- https://gitlab.com/gitlab-org/gitlab/-/issues/605525 (MergeRequests engine)
- #608747 (Deployments engine)
How to set up and validate locally
Run the specs. The dimension spec needs ClickHouse running in GDK:
bundle exec rspec spec/lib/gitlab/database/aggregation/click_house/traversal_path_dimension_spec.rb
bundle exec rspec spec/lib/gitlab/database/aggregation/engine_spec.rb
bundle exec rspec ee/spec/graphql/resolvers/analytics/aggregation/engine_resolver_spec.rbMR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.