Enable air-gapped billable usage capture by default
What does this MR do and why?
Makes offline-licensed (air-gapped) instances record billable usage locally by default:
- Enables
local_billing_persistenceby default, and changes it to thebetatype, sincedevelopmentflags cannot be enabled by default. On an offline-licensed instance, billing events are written tobillable_usage_daily_namespace_aggregatesinstead of being sent to the collector. Gitlab::BillingEvents::Client#record_usageno longer requiresbilling_event_trackingwhen local persistence is enabled. That flag is enabled only on GitLab.com, so offline-licensed instances recorded nothing unless both flags were turned on.
"Offline-licensed" includes instances on a legacy licence file, even connected ones: like offline cloud licences, legacy licences never sync with CustomersDot, so their usage is recorded locally rather than emitted.
billing_event_tracking itself is unchanged, and still gates emission everywhere else.
References
- Rollout issue for
local_billing_persistence: #628679 - Agreement to bypass
billing_event_trackingfor local persistence: #628679 (comment 3961959823) - Flags introduced in !249324 (merged) and !240688 (merged)
Screenshots or screen recordings
Not applicable, no UI change.
How to set up and validate locally
On this branch, in a Rails console:
-
Remove any overrides, so both flags fall back to their definitions:
Feature.remove(:local_billing_persistence) Feature.remove(:billing_event_tracking) Feature.enabled?(:local_billing_persistence, :instance) # => true (default) Feature.enabled?(:billing_event_tracking, :instance) # => false (default) -
Make the instance offline-licensed for this session:
lic = License.current lic.define_singleton_method(:online_cloud_license?) { false } lic.define_singleton_method(:offline_cloud_license?) { true } License.define_singleton_method(:current) { lic } Gitlab::BillingEvents::Client.new.local_persistence_enabled? # => true -
Record three events and read the row back:
ns = Group.first 3.times do Gitlab::BillingEvents::Client.track_billing_event( event_type: 'secrets_read', category: 'Validation', unit_of_measure: 'request', quantity: 1, namespace: ns, metadata: { feature_qualified_name: 'secrets_read' }) end Utilization::BillableUsage::DailyNamespaceAggregate .find_by(usage_date: Time.current.utc.to_date, root_namespace_id: ns.root_ancestor.id, event_type: 'secrets_read') .slice(:quantity, :events_count)Expect
quantity3 andevents_count3. -
In
log/application_json.log, the three events each logBillingEvents: internal event tracked, and none logsBillingEvents: billing event tracked, so nothing is sent to the collector.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.