Skip billing emission on offline-licensed instances
What does this MR do and why?
On an air-gapped self-managed instance (offline cloud licence), every Secrets Manager billing event is still sent to the billing collector unless local_billing_persistence is on. That flag ships with default_enabled: false. This affects secrets_read on every allowed read, in SecretsManagement::AuditLogWorker, and the nightly secrets_stored once per root group. Each attempt holds a billing emitter thread (Gitlab::Tracking::BillingAuthEmitter, an AsyncEmitter) for the 30 s connect timeout, then fails with Net::OpenTimeout and a failed to be reported to collector error log line.
This MR adds an emission_enabled? hook to Gitlab::BillingEvents::Client:
- CE: always
true, so nothing changes. - EE:
falseon a self-managed instance whose licence isoffline_cloud_license?, whatever the state of the feature flag. SaaS is excluded by the same realm guardlocal_persistence_enabled?uses.
Resulting behaviour on an offline-licensed instance:
local_billing_persistence |
Before | After |
|---|---|---|
| on | persisted locally | persisted locally (unchanged) |
| off | emitted, emitter thread held 30 s, error log | not emitted, info log billing event emission skipped |
The internal event (usage_billing_event) is tracked in every case. The feature flag and its rollout (#628679) are not changed.
Resolves https://gitlab.com/gitlab-org/gitlab/-/issues/630795
Out of scope / follow-ups
- Legacy licences (issue item 2): still emit. The test suite's default licence is a legacy one, and GDKs often run one too, so skipping them would change behaviour much more widely. The Secrets Manager add-on is provisioned through cloud licensing, so I expect a legacy instance not to emit Secrets Manager events at all. Not verified end to end.
- Collector connect timeout (issue item 3): a connected instance with blocked egress still has each attempt hold an emitter thread for 30 s and log an error. That needs its own change.
Cost
None: License.current is cached, and the check only runs on the non-local path.
How to set up and validate locally
- Use an offline cloud licence, or stub
License.current.offline_cloud_license?to returntruein a Rails console. - Keep
Feature.disable(:local_billing_persistence)andFeature.enable(:billing_event_tracking). Gitlab::BillingEvents::Client.track_billing_event(event_type: 'secrets_read', category: 'Test', unit_of_measure: 'request', quantity: 1, namespace: Group.first)- The call returns immediately.
log/application_json.logshowsBillingEvents: billing event emission skipped, and no Snowplow billing request is made.
Specs
ee/spec/lib/ee/gitlab/billing_events/client_spec.rb:
#emission_enabled?: offline licence, with the flag on and off, returns false. Returns true for a non-offline licence, for no licence, and on SaaS.- With the flag off on an offline-licensed instance: neither emits nor persists, for both the counter and snapshot entry points. Logs the skip and still tracks the internal event.
I undid each production change separately, the elsif, the EE override and the SaaS guard, and confirmed that a spec fails for each.
MR acceptance checklist
Please evaluate this MR against the MR acceptance checklist.