Register the Duo Chat token usage events and setting ahead of use
What does this MR do and why?
Adds the Duo Chat AI usage events and setting key that !259436 (merged) writes, a release ahead of it, so previous-release nodes can drain, read and save them (expand and contract).
report_duo_chat_token_usage(54) andcomplete_duo_chat_response(55): event definitions,AiTrackingregistration andAiUsageEventTypevalues. Without them, the drain raises on the unknown ID (usage_event.rb:29) and puts the batch back (write_buffer_processor_worker.rb:43-45), andaiUsageDatacannot return the non-nullableevent(ai_usage_event_type.rb:15-18).duo_token_usage_tracking_enabledin theAi::Settingschema, which rejects keys it does not list (ai_setting_feature_settings.json:5) on every save (setting.rb:26-27).
From 19.5, POST /api/v4/usage_data/track_events accepts both event names, like every AiTracking event, though nothing in 19.5 sends them. If a client sends one during an upgrade to 19.5, 19.4 nodes put the batch holding it back and cannot return it from aiUsageData, while 19.5 nodes drain and return it. The jsonb_accessor line stays in the token usage MR, because its default becomes part of the feature_settings attribute default (macro.rb:71) and would put the key on new rows. IDs 50 to 53 stay with !256439 and !254619.
Only generated GraphQL reference docs change, including both events' new aiUserMetrics count fields.
Release path
flowchart LR
X["This MR merges<br/>milestone 19.5"] --> RC["19.5 release candidate<br/>built from GitLab.com production"]
RC --> U["Token usage MR merges<br/>milestone 19.6"]
U --> R["19.6 released"]
X -.-> W0["Upgrade 19.4 to 19.5:<br/>nothing in 19.5 sends<br/>54 or 55 or writes the key"]
U -.-> W1["GitLab.com deploy or rollback:<br/>every node already knows 54, 55 and the key"]
R -.-> W2["Zero-downtime upgrade 19.5 to 19.6:<br/>19.5 nodes drain, read<br/>and save what 19.6 writes"]References
- Related to #631777
How to set up and validate locally
With ClickHouse running, bundle exec rspec ee/spec/graphql/types/analytics/ai_usage/ai_usage_event_type_enum_spec.rb ee/spec/lib/gitlab/tracking/ai_tracking_spec.rb ee/spec/models/ai/setting_spec.rb ee/spec/requests/api/graphql/analytics/ai_analytics/ai_user_metrics_spec.rb spec/lib/gitlab/tracking/event_definition_spec.rb ee/spec/requests/api/usage_data_spec.rb passes.
| Case, as one example on each branch | Master (cbfb4aa00c) |
This MR |
|---|---|---|
| A buffer holding events 6, 54 and 55 drains into PostgreSQL | '54' is not a valid event, no rows, the batch back in the buffer |
3 rows with their extras, buffer empty |
Instance aiUsageData reads rows with events 54 and 55 from PostgreSQL |
Cannot return null for non-nullable field AiInstanceUsageEvent.event |
both events |
| The same read from ClickHouse | no data: AiUsageEvent.event returned 54, which isn't a valid AiUsageEventType value |
both events |
A row holding the key as false takes a column save, a sibling key save and PUT /api/v4/application/settings |
Feature settings must be a valid json schema twice, then 500 |
saved, saved, 200, and the stored false kept |
Ai::Setting.for_organization creates a row, then a column save and a sibling save |
no key | no key |
An authenticated user sends either event to POST /api/v4/usage_data/track_events |
422, no row | 200, and the drain stores one row each |
This MR was prepared with assistance from Claude Code.
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.