.ai/principles/distilled/analytics.md
config/events or ee/config/events.Gitlab::Tracking.event, Redis, or RedisHLL tracking); use track_internal_event (backend) or trackEvent (frontend) instead.action name follows the naming convention.description is clear to readers outside the team.ee/config/events if the event fires only from EE code.action field of an existing event changes, confirm the author considered the renaming implications.~database label and request a database review for metrics based on database queries.description field is accurate and meaningful.key_path is correct.product_group field corresponds to the stages fileee/.data_source: internal_events for new metrics; hand off to the Analytics Instrumentation team if data_source: database is used.redis or redis_hll data sources for new metrics; see the migration guide.@csops-team, @gitlab-data/analytics-engineers, and @gitlab-data/product-analysts via a comment on the issue, and all groups have acknowledged the change.rails generate gitlab:usage_metric ClassName --type TYPE --operation OPERATION to generate new instrumentation class and spec files; DO NOT create them manually.DatabaseMetric, NumbersMetric, or GenericMetric (or PrometheusMetric) — one instrumentation class per metric.DatabaseMetric; database metrics can create unnecessary load on larger instances.start/finish values, and avoid joins where possible.cache_start_and_finish_as when start and finish are expensive queries reused across multiple metrics.estimate_batch_distinct_count, ensure the relation includes a numeric primary key, the joined relation has no one-to-many relationship, and start/finish always represent primary key values.require_relative 'spec/support/helpers/service_ping_helpers.rb'; ServicePingHelpers.get_current_usage_metric_value(key_path) with the metric's key_path.track_internal_event from the Gitlab::InternalEventsTracking module, passing user, namespace, and project arguments; fill out as many as possible to maximize data quality.unique property (e.g., unique: project.id), ensure the corresponding argument (e.g., project) is always provided to track_internal_event.ProductAnalyticsTracking module for controller-level event tracking and the Gitlab::InternalEvents::ServiceTracking concern for service objects instead of calling track_internal_event inline.additional_properties, DO NOT include sensitive information; define each custom property in the event definition's additional_properties field.Gitlab::InternalEvents.with_batched_redis_writes to batch Redis writes into a single call.InternalEvents Vue mixin (InternalEvents.mixin()) for Vue component tracking, raw InternalEvents.trackEvent(...) for arbitrary JavaScript, or data-event-tracking attributes for declarative HTML/Haml tracking.data-event-tracking-load="true" alongside data-event-tracking to fire an event on component render rather than on click.window.location does not pseudonymize project and namespace information.trigger_internal_events and increment_usage_metrics RSpec matchers (not manual stubs) to assert backend event firing and metric increments.useMockInternalEventsTracking / bindInternalEventDocument helpers to assert trackEvent calls in JavaScript and Vue component tests.trigger_internal_events matcher with .on_click or .on_load chain methods to assert Haml data-attribute tracking in view and ViewComponent specs.:clean_gitlab_redis_shared_state trait when tests fail due to metrics not being incremented, to clear the Redis cache between examples.~analytics instrumentation and ~analytics instrumentation::review pending labels when an Analytics Instrumentation review is needed but was not assigned automatically.~"analytics instrumentation::approved" upon completion.~analytics instrumentation reviews.For the full picture, see: