Draft: Add personalization metrics
What does this MR do and why?
Note: For this draft MR I wanted to see the capabilities of Duo CLI
Implements the personalization metrics tracking system as defined in the Personalization Engine design document.
This MR adds the foundation for tracking user actions and milestones to enable personalized experiences in GitLab. The implementation follows a user-centric approach with optional namespace context for future extensibility.
Key Features
Database Schema:
- User-level metric tracking with optional namespace context
- Composite unique constraint on
[:user_id, :namespace_id, :metric] - Indexes optimized for both user-level and namespace-level queries
- Foreign key constraints with appropriate cascade/nullify behavior
Model Implementation:
-
Personalization::Metricsmodel with user and namespace associations - Three initial metric types:
-
code_push_activity- Tracks when users push code -
pipeline_success- Tracks successful pipeline completions -
merge_request_completion- Tracks merged merge requests
-
- Class methods for recording and querying metric completions
- Automatic root namespace resolution for nested namespaces
Design Decisions:
- User-level tracking: Primary model maintains user-level metrics
- Optional namespace context: Enables future namespace-level personalization without schema changes
- Normalization on read: Data stored at user level, aggregated when querying for namespace insights
-
Safe deletion handling: Namespace deletion nullifies
namespace_idrather than deleting metrics
Changelog: added EE: true
References
- Parent Epic: https://gitlab.com/groups/gitlab-org/-/epics/18239
- Implementation Epic: https://gitlab.com/groups/gitlab-org/-/epics/19831
- Design Document: Personalization Engine
Database Review
This MR includes:
- New table:
personalization_metrics - Columns:
id,user_id,namespace_id,metric,created_at,updated_at - Indexes:
-
index_personalization_metric_on_user_id(user_id) -
unique_personalization_metric_user_id_namespace_id_and_metric(user_id, namespace_id, metric) - UNIQUE -
index_personalization_metrics_on_namespace_id_and_metric(namespace_id, metric) -
index_personalization_metric_completions_on_completed_at(created_at)
-
- Foreign Keys:
-
user_id→users.id(ON DELETE CASCADE) -
namespace_id→namespaces.id(ON DELETE NULLIFY)
-
How to set up and validate locally
# Create a user and namespace
user = User.find_by(username: 'root')
namespace = user.namespace
# Record a metric without namespace context
Personalization::Metrics.record_completion(user, :code_push_activity)
# Record a metric with namespace context
Personalization::Metrics.record_completion(user, :pipeline_success, namespace: namespace)
# Check if a metric is completed
Personalization::Metrics.completed?(user, :code_push_activity)
# => true
Personalization::Metrics.completed?(user, :pipeline_success, namespace: namespace)
# => true
# Query metrics
Personalization::Metrics.for_user(user)
Personalization::Metrics.for_namespace(namespace)
Personalization::Metrics.by_metric(:code_push_activity)
MR 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.
Edited by Jay Montal