Record the client version on backend analytics events
What does this MR do and why?
GitLab Rails resolves the client type and name of every request from the X-Gitlab-Client-Type and X-Gitlab-Client-Name headers (!257624 (merged)), but drops the X-Gitlab-Client-Version header the same clients send, although the gitlab_standard Snowplow context already has a client_version field and the AI Gateway and the Duo Workflow Service already fill it on their own events. Without it, analytics cannot tell the builds of a client apart, for example to cut a metric at the release that changed its headers.
This MR carries the version through the same path as the type and the name:
Gitlab::Tracking::ClientIdentityreadsX-Gitlab-Client-Versionfor a client that declared its type or name, and keeps it only when it is shaped like a version (an optionalv, a leading digit, then digits, letters,.,-,+and_, at most 64 characters), so no free text is stored. A bare version header without identity headers is ignored.Gitlab::Middleware::RequestContextstores it onApplicationContextasclient_version, so Sidekiq jobs the request enqueues inherit it through Labkit and the structured logs carry it asmeta.client_version.Gitlab::Tracking::StandardContextemitsclient_versioninto thegitlab_standardcontext (schema1-1-8defines the field as a nullable string of up to 64 characters), and AI usage events carry it in theirextrasbesideclient_typeandclient_name.- Documentation: the client identity page gains a "Client version" section.
- Side effect, regenerated in the second commit: the admin Sidekiq queues REST endpoint and the
AdminSidekiqQueuesDeleteJobsmutation take one filter perApplicationContext.allowed_job_keysentry, soclient_versionbecomes aDELETE /admin/sidekiq/queues/:queue_namequery parameter and aclientVersionmutation argument.doc/api/openapi/openapi_v3.yaml, the GraphQL reference and the introspection schemas are regenerated, anddoc/api/admin_sidekiq_queues.mddocuments the parameter besideclient_typeandclient_name.
Verification: RuboCop clean on the nine changed files. spec/lib/gitlab/tracking/client_identity_spec.rb, spec/lib/gitlab/tracking/standard_context_spec.rb and spec/lib/gitlab/middleware/request_context_spec.rb are green locally (106 examples). ee/spec/lib/gitlab/tracking/ai_tracking_spec.rb cannot run locally because it needs a ClickHouse configuration (as noted on !257624 (merged)); CI covers it.
References
Follows !257624 (merged) (client type and name) and !257626 (merged) (Workhorse forwarding). The mobile app sends the header from https://gitlab.com/mvanremmerden/gitlab-mobile; the IDE extensions and the Duo CLI already send it. Related: #630922.
How to set up and validate locally
- Send a request with
curl -H 'X-Gitlab-Client-Name: gitlab-mobile-ios' -H 'X-Gitlab-Client-Version: 1.2.0' http://gdk.test:3000/api/v4/userwith a token and checklog/api_json.logformeta.client_version: "1.2.0". - Send the same request with
-H 'X-Gitlab-Client-Version: latest'and check thatmeta.client_versionis absent. - In a Rails console inside such a request context,
Gitlab::Tracking::StandardContext.new.to_h.slice(:client_type, :client_name, :client_version)includes the version.
Reviewer notes
- Needs an
~"analytics instrumentation"review; the label is applied. - No new Snowplow schema version:
client_versionhas been part ofgitlab_standard1-1-8. - Labelled
pipeline:run-as-if-fossbecause CE and EE both change. - No database migration, no feature flag: the change only reads one more header and copies it along the existing path.
MR acceptance checklist
Evaluated against the MR acceptance checklist.