Class: Mixpanel::Flags::FlagsProvider

Inherits:
Object
  • Object
show all
Defined in:
lib/mixpanel-ruby/flags/flags_provider.rb

Overview

Base class for feature flags providers Provides common HTTP handling and exposure event tracking

Direct Known Subclasses

LocalFlagsProvider, RemoteFlagsProvider

Instance Method Summary collapse

Constructor Details

#initialize(provider_config, endpoint, tracker_callback, evaluation_mode, error_handler) ⇒ FlagsProvider

Returns a new instance of FlagsProvider.

Parameters:

  • provider_config (Hash)

    Configuration with :token, :api_host, :request_timeout_in_seconds, :credentials (optional)

  • endpoint (String)

    API endpoint path (e.g., '/flags' or '/flags/definitions')

  • tracker_callback (Proc)

    Function used to track events (bound tracker.track method)

  • evaluation_mode (String)

    The feature flag evaluation mode. This is either 'local' or 'remote'

  • error_handler (Mixpanel::ErrorHandler)

    Error handler instance



20
21
22
23
24
25
26
27
# File 'lib/mixpanel-ruby/flags/flags_provider.rb', line 20

def initialize(provider_config, endpoint, tracker_callback, evaluation_mode, error_handler)
  @provider_config = provider_config
  @endpoint = endpoint
  @tracker_callback = tracker_callback
  @evaluation_mode = evaluation_mode
  @error_handler = error_handler
  @credentials = provider_config[:credentials]
end

Instance Method Details

#call_flags_endpoint(additional_params = nil) ⇒ Hash

Make HTTP request to flags API endpoint

Parameters:

  • additional_params (Hash, nil) (defaults to: nil)

    Additional query parameters

Returns:

  • (Hash)

    Parsed JSON response

Raises:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/mixpanel-ruby/flags/flags_provider.rb', line 34

def call_flags_endpoint(additional_params = nil)
  # Always use token in query params
  common_params = Utils.prepare_common_query_params(
    @provider_config[:token],
    Mixpanel::VERSION
  )

  params = common_params.merge(additional_params || {})

  # Add project_id as query parameter when using service account credentials
  # Note: project_id is required for service account auth but not used for token auth
  if @credentials
    params['project_id'] = @credentials.project_id
  end

  query_string = URI.encode_www_form(params)

  uri = URI::HTTPS.build(
    host: @provider_config[:api_host],
    path: @endpoint,
    query: query_string
  )

  http = Net::HTTP.new(uri.host, uri.port)

  http.use_ssl = true
  http.open_timeout = @provider_config[:request_timeout_in_seconds]
  http.read_timeout = @provider_config[:request_timeout_in_seconds]

  request = Net::HTTP::Get.new(uri.request_uri)

  # Use service account credentials for basic auth if provided, otherwise use token
  if @credentials
    request.basic_auth(@credentials.username, @credentials.secret)
  else
    request.basic_auth(@provider_config[:token], '')
  end

  request['Content-Type'] = 'application/json'
  request['traceparent'] = Utils.generate_traceparent

  begin
    response = http.request(request)
  rescue Net::OpenTimeout, Net::ReadTimeout => e
    raise ConnectionError.new("Request timeout: #{e.message}")
  rescue StandardError => e
    raise ConnectionError.new("Network error: #{e.message}")
  end

  unless response.code == '200'
    raise ServerError.new("HTTP #{response.code}: #{response.body}")
  end

  begin
    JSON.parse(response.body)
  rescue JSON::ParserError => e
    raise ServerError.new("Invalid JSON response: #{e.message}")
  end
end

#shutdownObject



94
# File 'lib/mixpanel-ruby/flags/flags_provider.rb', line 94

def shutdown; end

#track_exposure_event(flag_key, selected_variant, context, latency_ms = nil) ⇒ Object

Track exposure event to Mixpanel

Parameters:

  • flag_key (String)

    Feature flag key

  • selected_variant (SelectedVariant)

    The selected variant

  • context (Hash)

    User context (must include 'distinct_id')

  • latency_ms (Integer, nil) (defaults to: nil)

    Optional latency in milliseconds



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/mixpanel-ruby/flags/flags_provider.rb', line 101

def track_exposure_event(flag_key, selected_variant, context, latency_ms = nil)
  distinct_id = context['distinct_id'] || context[:distinct_id]

  unless distinct_id
    return
  end

  properties = {
    'distinct_id' => distinct_id,
    'Experiment name' => flag_key,
    'Variant name' => selected_variant.variant_key,
    '$experiment_type' => 'feature_flag',
    'Flag evaluation mode' => @evaluation_mode
  }

  properties['Variant fetch latency (ms)'] = latency_ms if latency_ms
  properties['$experiment_id'] = selected_variant.experiment_id if selected_variant.experiment_id
  properties['$is_experiment_active'] = selected_variant.is_experiment_active unless selected_variant.is_experiment_active.nil?
  properties['$is_qa_tester'] = selected_variant.is_qa_tester unless selected_variant.is_qa_tester.nil?

  begin
    @tracker_callback.call(distinct_id, Utils::EXPOSURE_EVENT, properties)
  rescue MixpanelError => e
    @error_handler.handle(e)
  end
end