Add metrics and event tracking for Immutable Container Tags
Overview
This MR adds usage metrics, a setting metric, and internal event tracking for Immutable Container Tags feature. This is the third and final MR in a series to split container registry protection instrumentation into smaller, focused changes.
What's Changed
Metrics Added (EE-only - Ultimate tier)
Database Metrics (state)
-
counts.projects_with_container_registry_immutable_tag_rules- Count of distinct projects that have at least one immutable container tag rule
- Instrumentation:
CountProjectsWithContainerRegistryImmutableTagRulesMetric
-
counts.container_registry_immutable_tag_rules- Total count of all immutable container tag rules across all projects
- Instrumentation:
CountContainerRegistryImmutableTagRulesMetric
-
counts.distinct_top_level_groups_with_container_registry_immutable_tag_rules- Count of distinct top-level groups (customers) that have projects with immutable container tag rules
- Instrumentation:
CountDistinctTopLevelGroupsWithContainerRegistryImmutableTagRulesMetric
-
settings.container_registry_immutable_tag_rules_enabled- Boolean indicating whether immutable container tag rules feature is enabled on the instance
- Instrumentation:
ContainerRegistryImmutableTagRulesEnabledMetric
Event-Based Metrics (activity)
-
counts.create_container_registry_immutable_tag_rule- Count of immutable container tag rules created (all-time)
- Data source:
internal_events
Event Tracking
-
create_container_registry_immutable_tag_rule- Tracked in
EE::ContainerRegistry::Protection::CreateTagRuleServiceoverride - Includes context:
project,namespace,user,additional_properties: { rule_type: 'immutable' }
- Tracked in
Note: The delete_container_registry_protected_tag_rule event (tracked in DeleteTagRuleService) is shared with mutable tag rules and was included in MR 2. The rule_type context distinguishes between mutable and immutable rules.
Files Changed
-
Metrics: 4 new metric instrumentation classes (EE - in
ee/lib/) -
Metric Definitions: 5 new metric YAML files (EE - in
ee/config/metrics/)- 3 database metrics
- 1 setting metric
- 1 event-based metric
-
Events: 1 new event YAML definition (EE - in
ee/config/events/) -
Service Classes: Added event tracking in EE
CreateTagRuleServiceoverride -
Specs: Added tests for metrics and event tracking (EE - in
ee/spec/)
Why Metrics Are in EE
Immutable container tag rules are an EE-only feature (Ultimate tier), so all metrics and event tracking are implemented in EE. This is a licensed feature that requires an Ultimate license.
[Keep the Database Review section as-is - it's already correct]
Testing
-
✅ Metric instrumentation specs added -
✅ Event tracking specs added in EE service specs -
✅ All existing tests pass
Related MRs
This MR is part of a series:
- MR 1: Protected Container Repositories - !213721 (merged)
- MR 2: Protected Container Tags (mutable) - !213723 (merged)
- MR 3 (this MR): Immutable Container Tags
Feature Information
- Feature: Immutable Container Tags
- Feature Availability: Ultimate tier only (EE feature)
- Metrics Tracking: EE (Ultimate tier only)
- Product Group: Container Registry
- Product Category: Container Registry
Database Review
This MR adds three new database metrics for immutable container tag rules. Below are the SQL queries for database review.
Query 1: counts.container_registry_immutable_tag_rules
Description: Total count of immutable container tag rules
SQL Query:
SELECT COUNT("container_registry_protection_tag_rules"."id")
FROM "container_registry_protection_tag_rules"
WHERE "container_registry_protection_tag_rules"."minimum_access_level_for_push" IS NULL
AND "container_registry_protection_tag_rules"."minimum_access_level_for_delete" IS NULL;
Query Plan:
Summary:
- Link: https://postgres.ai/console/gitlab/gitlab-production-main/sessions/45807/commands/140236
- Execution time: 1.332 ms (planning: 0.604 ms, execution: 0.728 ms)
- Uses Index Scan on
unique_protection_tag_rules_immutableindex - Found 43 immutable tag rules in the snapshot
- Very efficient query with minimal I/O
Query 2: counts.projects_with_container_registry_immutable_tag_rules
Description: Count of distinct projects with immutable container tag rules
SQL Query:
SELECT COUNT(DISTINCT "container_registry_protection_tag_rules"."project_id")
FROM "container_registry_protection_tag_rules"
WHERE "container_registry_protection_tag_rules"."minimum_access_level_for_push" IS NULL
AND "container_registry_protection_tag_rules"."minimum_access_level_for_delete" IS NULL;
Query Plan:
Summary:
- Link: https://postgres.ai/console/gitlab/gitlab-production-main/sessions/45807/commands/140237
- Execution time: 0.693 ms (planning: 0.589 ms, execution: 0.104 ms)
- Uses Index Only Scan on
unique_protection_tag_rules_immutableindex - Found 43 rows in the snapshot
- Very efficient query with all data from buffer pool (no disk I/O)
Query 3: counts.distinct_top_level_groups_with_container_registry_immutable_tag_rules
Description: Count of distinct top-level groups with immutable container tag rules
SQL Query:
SELECT COUNT(DISTINCT "root_namespaces"."id")
FROM "container_registry_protection_tag_rules"
INNER JOIN "projects" ON "projects"."id" = "container_registry_protection_tag_rules"."project_id"
INNER JOIN "namespaces" ON "namespaces"."id" = "projects"."namespace_id"
INNER JOIN namespaces AS root_namespaces ON root_namespaces.id = namespaces.traversal_ids[1]
WHERE "container_registry_protection_tag_rules"."minimum_access_level_for_push" IS NULL
AND "container_registry_protection_tag_rules"."minimum_access_level_for_delete" IS NULL
AND (root_namespaces.type = 'Group' AND root_namespaces.parent_id IS NULL);
Query Plan:
Summary:
- Link: https://postgres.ai/console/gitlab/gitlab-production-main/sessions/45807/commands/140238
- Execution time: 271.956 ms (planning: 6.182 ms, execution: 265.774 ms)
- Uses Sort operation with multiple joins (container_registry_protection_tag_rules → projects → namespaces → root_namespaces)
- Found 43 rows in the snapshot
- Most time spent on I/O reads (259.289 ms) - acceptable for a Service Ping metric that runs periodically, not in real-time
- Uses array indexing on
traversal_ids[1]which is a common pattern in GitLab for hierarchical namespace structures
Notes
- All metrics use
time_frame: all, so they count all records without time constraints - The queries filter for immutable tag rules only (using the
.immutablescope) by selecting rules where bothminimum_access_level_for_pushandminimum_access_level_for_deleteare NULL - The queries are executed as part of Service Ping collection
- The
container_registry_protection_tag_rulestable has a foreign key index onproject_idwhich will help with Query 2 - Query 3 uses array indexing on
traversal_ids[1]to get the root namespace, which is a common pattern in GitLab for hierarchical namespace structures - All queries are simple aggregations that should scale well as the table grows