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_persistence by default, and changes it to the beta type, since development flags cannot be enabled by default. On an offline-licensed instance, billing events are written to billable_usage_daily_namespace_aggregates instead of being sent to the collector.
  • Gitlab::BillingEvents::Client#record_usage no longer requires billing_event_tracking when 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

Screenshots or screen recordings

Not applicable, no UI change.

How to set up and validate locally

On this branch, in a Rails console:

  1. 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)
  2. 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
  3. 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 quantity 3 and events_count 3.

  4. In log/application_json.log, the three events each log BillingEvents: internal event tracked, and none logs BillingEvents: billing event tracked, so nothing is sent to the collector.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist.

Edited by Vijay Hawoldar

Merge request reports

Loading
Loading