Skip the YAML round trip when inserting web hook logs
What does this MR do and why?
Why
Opportunistic fix which could indirectly help with &21116. This worker is technically on catchall, and GVL contention on catchall isn't actually that bad, but this does account for a very large sum fraction of all CPU on that shard, so it's plausible this would still help reduce contention and thereby buy us more capacity on the pgbouncer main connection pool, which catchall shares with other low urgency shards, and hence help with &21116.
What
Stops WebHookLog.insert_log! from round-tripping the web hook payload through YAML before inserting it. This roughly halves the CPU cost of writing a web hook log, and saves more on large payloads.
Reading a serialized attribute back from an unsaved record makes Rails copy it with deserialize(serialize(value)) (ActiveModel::Type::Helpers::Mutable#cast), which is a full YAML dump and parse. insert_log! did this for request_headers, request_data and response_headers, first when redacting emails and then when building the row with log.attributes. The INSERT then dumped each column again.
- Email redaction moves from a
before_savestep into arequest_data=writer, so it no longer has to read the attribute back. Every path that setsrequest_dataassigns it, so this does not change which data gets redacted. - Behind the
web_hook_log_insert_without_yaml_round_tripflag (actor: the hook's project, then group, then the current request),insert_log!takes the three serialized columns as assigned withread_attribute_before_type_cast. The INSERT dumps each one exactly once.
Measurements and safety
CPU per log write, including the INSERT, measured in GDK:
| Payload | Size | Before | After |
|---|---|---|---|
| Push, 20 commits | 17 KB | 4.6 ms | 2.2 ms |
| Pipeline, 200 builds | 153 KB | 62 ms | 24 ms |
| Pipeline, 600 builds | 458 KB | 176 ms | 71 ms |
The stored row is byte-for-byte the same in both modes, and a spec covers this. The round trip normalized nothing, because LogExecutionService calls as_json on the data and insert_log! therefore only receives JSON values. Values that YAML cannot load back still fail at insert time, because the column coder checks permitted classes when it dumps.
References
- Follows !260454 (merged), which removed the
web_hook_log_insert_without_transactionflag. - Rollout issue: #632726
Screenshots or screen recordings
Not applicable, no UI change.
How to set up and validate locally
- In a Rails console, enable the flag:
Feature.enable(:web_hook_log_insert_without_yaml_round_trip) - Trigger a project webhook, for example with Settings > Webhooks > Test on any project hook.
- Check that the event appears under Recent events with its request and response data, and that email addresses in the request body show as
[REDACTED].
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.