Fix type-mixed rows_added_slice breaking refresh log ingestion
What does this MR do and why?
Since September 2023, no authorized_projects_refresh log line with rows_added_count > 0 has been indexed in Elasticsearch on GitLab.com. Kibana shows zero such documents over any time range, while documents with rows_deleted_count > 0 index normally (1,200+ in the last month). Meanwhile the Prometheus counter gitlab_authorized_projects_safety_net_refresh_rows_total{direction="added"}, incremented from the same value, shows added rows do occur (for example a ~557k-row burst on GitLab.com on 2026-08-25).
The cause is Users::RefreshAuthorizedProjectsService#log_refresh_details, which logs rows_added_slice as add.first(5).map(&:values). The add array holds hashes of {user_id:, project_id:, access_level:}, all integers. Commit ca040214 ("Write project_authorizations.is_unique on create") added ProjectAuthorizations::Changes#insert_all_in_batches, which mutates those same hash objects in place, setting attrs[:is_unique] = true, before calling insert_all. Logging happens after apply!, so every logged row is actually [user_id, project_id, access_level, true] - integers mixed with a boolean.
Elasticsearch flattens the nested arrays into one field, maps its type from the first (integer) value, and then throws a mapper parsing exception on the boolean, rejecting the whole document. Empty slices (no rows added) have no boolean and index fine, which is why only add-row documents are missing, and why the field doesn't even exist in the Kibana data view.
The fix logs the three integer attributes by name, row.values_at(:user_id, :project_id, :access_level), so the array stays homogeneous regardless of what ProjectAuthorizations::Changes adds to the hashes later. This follows GitLab's logging guideline that list elements in a log field must be the same type. The existing spec expectation is updated from [[user_id, project_id, access_level, true]] to [[user_id, project_id, access_level]].
How to set up and validate locally
- Run
bundle exec rspec spec/services/users/refresh_authorized_projects_service_spec.rb - Optionally, in a rails console, refresh a user with a missing authorization and confirm the logged
rows_added_slicecontains only integers.