Class: PostHog::Client

Inherits:
Object
  • Object
show all
Includes:
Logging, Utils
Defined in:
lib/posthog/client.rb

Constant Summary

Constants included from Utils

Utils::UTC_OFFSET_WITHOUT_COLON, Utils::UTC_OFFSET_WITH_COLON

Instance Method Summary collapse

Methods included from Logging

included, #logger

Methods included from Utils

#convert_to_datetime, #date_in_iso8601, #datetime_in_iso8601, #formatted_offset, #is_valid_regex, #isoify_dates, #isoify_dates!, #seconds_to_utc_offset, #stringify_keys, #symbolize_keys, #symbolize_keys!, #time_in_iso8601, #uid

Constructor Details

#initialize(opts = {}) ⇒ Client

Returns a new instance of Client.

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :api_key (String)

    Your project’s api_key

  • :personal_api_key (String)

    Your personal API key

  • :max_queue_size (FixNum)

    Maximum number of calls to be remain queued. Defaults to 10_000.

  • :test_mode (Bool)

    true if messages should remain queued for testing. Defaults to false.

  • :on_error (Proc)

    Handles error calls from the API.

  • :host (String)

    Fully qualified hostname of the PostHog server. Defaults to ‘app.posthog.com`

  • :feature_flags_polling_interval (Integer)

    How often to poll for feature flag definition changes. Measured in seconds, defaults to 30.

  • :feature_flag_request_timeout_seconds (Integer)

    How long to wait for feature flag evaluation. Measured in seconds, defaults to 3.



27
28
29
30
31
32
33
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
# File 'lib/posthog/client.rb', line 27

def initialize(opts = {})
  symbolize_keys!(opts)

  opts[:host] ||= 'https://app.posthog.com'

  @queue = Queue.new
  @api_key = opts[:api_key]
  @max_queue_size = opts[:max_queue_size] || Defaults::Queue::MAX_SIZE
  @worker_mutex = Mutex.new
  @worker = if opts[:test_mode]
    NoopWorker.new(@queue)
  else
    SendWorker.new(@queue, @api_key, opts)
  end
  @worker_thread = nil
  @feature_flags_poller = nil
  @personal_api_key = opts[:personal_api_key]

  check_api_key!

  @feature_flags_poller =
    FeatureFlagsPoller.new(
      opts[:feature_flags_polling_interval],
      opts[:personal_api_key],
      @api_key,
      opts[:host],
      opts[:feature_flag_request_timeout_seconds] || Defaults::FeatureFlags::FLAG_REQUEST_TIMEOUT_SECONDS,
      opts[:on_error]
    )
  
  @distinct_id_has_sent_flag_calls = SizeLimitedHash.new(Defaults::MAX_HASH_SIZE) { |hash, key| hash[key] = Array.new }
end

Instance Method Details

#alias(attrs) ⇒ Object

Aliases a user from one id to another

Parameters:

  • attrs (Hash)

Options Hash (attrs):

  • :alias (String)

    The alias to give the distinct id

  • :message_id (String)

    ID that uniquely identifies a message across the API. (optional)

  • :timestamp (Time)

    When the event occurred (optional)

  • :distinct_id (String)

    The ID for this user in your database



134
135
136
137
# File 'lib/posthog/client.rb', line 134

def alias(attrs)
  symbolize_keys! attrs
  enqueue(FieldParser.parse_for_alias(attrs))
end

#capture(attrs) ⇒ Object

Captures an event

Parameters:

  • attrs (Hash)

Options Hash (attrs):

  • :event (String)

    Event name

  • :properties (Hash)

    Event properties (optional)

  • :send_feature_flags (Bool)

    Whether to send feature flags with this event (optional)

  • :message_id (String)

    ID that uniquely identifies a message across the API. (optional)

  • :timestamp (Time)

    When the event occurred (optional)

  • :distinct_id (String)

    The ID for this user in your database



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/posthog/client.rb', line 92

def capture(attrs)
  symbolize_keys! attrs

  if attrs[:send_feature_flags]
    feature_variants = @feature_flags_poller.get_feature_variants(attrs[:distinct_id], attrs[:groups] || {})

    attrs[:feature_variants] = feature_variants
  end

  enqueue(FieldParser.parse_for_capture(attrs))
end

#clearObject

Clears the queue without waiting.

Use only in test mode



74
75
76
# File 'lib/posthog/client.rb', line 74

def clear
  @queue.clear
end

#dequeue_last_messageHash

Returns pops the last message from the queue.

Returns:

  • (Hash)

    pops the last message from the queue



140
141
142
# File 'lib/posthog/client.rb', line 140

def dequeue_last_message
  @queue.pop
end

#flushObject

Synchronously waits until the worker has cleared the queue.

Use only for scripts which are not long-running, and will specifically exit



64
65
66
67
68
69
# File 'lib/posthog/client.rb', line 64

def flush
  while !@queue.empty? || @worker.is_requesting?
    ensure_worker_running
    sleep(0.1)
  end
end

#get_all_flags(distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false) ⇒ Hash

Returns all flags for a given user

Parameters:

  • distinct_id (String)

    The distinct id of the user

  • groups (Hash) (defaults to: {})
  • person_properties (Hash) (defaults to: {})

    key-value pairs of properties to associate with the user.

  • group_properties (Hash) (defaults to: {})

Returns:

  • (Hash)

    String (not symbol) key value pairs of flag and their values



208
209
210
211
# File 'lib/posthog/client.rb', line 208

def get_all_flags(distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false)
  person_properties, group_properties = add_local_person_and_group_properties(distinct_id, groups, person_properties, group_properties)
  return @feature_flags_poller.get_all_flags(distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
end

#get_all_flags_and_payloads(distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false) ⇒ Object

Returns all flags and payloads for a given user

Parameters:

  • distinct_id (String)

    The distinct id of the user

  • [Hash] (Hash)

    a customizable set of options

  • [Boolean] (Hash)

    a customizable set of options



236
237
238
239
# File 'lib/posthog/client.rb', line 236

def get_all_flags_and_payloads(distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false)
  person_properties, group_properties = add_local_person_and_group_properties(distinct_id, groups, person_properties, group_properties)
  @feature_flags_poller.get_all_flags_and_payloads(distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
end

#get_feature_flag(key, distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false, send_feature_flag_events: true) ⇒ String?

Returns whether the given feature flag is enabled for the given user or not

The provided properties are used to calculate feature flags locally, if possible.

‘groups` are a mapping from group type to group key. So, if you have a group type of “organization” and a group key of “5”, you would pass groups=“5”. `group_properties` take the format: { group_type_name: { group_properties } } So, for example, if you have the group type “organization” and the group key “5”, with the properties name, and employee count, you’ll send these as: “‘ruby

group_properties: {"organization": {"name": "PostHog", "employees": 11}}

“‘

Parameters:

  • key (String)

    The key of the feature flag

  • distinct_id (String)

    The distinct id of the user

  • groups (Hash) (defaults to: {})
  • person_properties (Hash) (defaults to: {})

    key-value pairs of properties to associate with the user.

  • group_properties (Hash) (defaults to: {})

Returns:

  • (String, nil)

    The value of the feature flag



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/posthog/client.rb', line 177

def get_feature_flag(key, distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false, send_feature_flag_events: true)
  person_properties, group_properties = add_local_person_and_group_properties(distinct_id, groups, person_properties, group_properties)
  feature_flag_response, flag_was_locally_evaluated = @feature_flags_poller.get_feature_flag(key, distinct_id, groups, person_properties, group_properties, only_evaluate_locally)

  feature_flag_reported_key = "#{key}_#{feature_flag_response}"
  if !@distinct_id_has_sent_flag_calls[distinct_id].include?(feature_flag_reported_key) && send_feature_flag_events
    capture(
      {
        'distinct_id': distinct_id,
        'event': '$feature_flag_called',
        'properties': {
          '$feature_flag' => key,
          '$feature_flag_response' => feature_flag_response,
          'locally_evaluated' => flag_was_locally_evaluated
        },
        'groups': groups,
      }
    )
    @distinct_id_has_sent_flag_calls[distinct_id] << feature_flag_reported_key
  end
  feature_flag_response
end

#get_feature_flag_payload(key, distinct_id, match_value: nil, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false) ⇒ Object

Returns payload for a given feature flag

Parameters:

  • key (String)

    The key of the feature flag

  • distinct_id (String)

    The distinct id of the user

  • [String (Hash)

    a customizable set of options

  • [Hash] (Hash)

    a customizable set of options

  • [Boolean] (Hash)

    a customizable set of options



223
224
225
226
# File 'lib/posthog/client.rb', line 223

def get_feature_flag_payload(key, distinct_id, match_value: nil, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false)
  person_properties, group_properties = add_local_person_and_group_properties(distinct_id, groups, person_properties, group_properties)
  @feature_flags_poller.get_feature_flag_payload(key, distinct_id, match_value, groups, person_properties, group_properties, only_evaluate_locally)
end

#group_identify(attrs) ⇒ Object

Identifies a group

Parameters:

  • attrs (Hash)

Options Hash (attrs):

  • :group_type (String)

    Group type

  • :group_key (String)

    Group key

  • :properties (Hash)

    Group properties (optional)

  • :message_id (String)

    ID that uniquely identifies a message across the API. (optional)

  • :timestamp (Time)

    When the event occurred (optional)

  • :distinct_id (String)

    The ID for this user in your database



123
124
125
126
# File 'lib/posthog/client.rb', line 123

def group_identify(attrs)
  symbolize_keys! attrs
  enqueue(FieldParser.parse_for_group_identify(attrs))
end

#identify(attrs) ⇒ Object

Identifies a user

Parameters:

  • attrs (Hash)

Options Hash (attrs):

  • :properties (Hash)

    User properties (optional)

  • :message_id (String)

    ID that uniquely identifies a message across the API. (optional)

  • :timestamp (Time)

    When the event occurred (optional)

  • :distinct_id (String)

    The ID for this user in your database



110
111
112
113
# File 'lib/posthog/client.rb', line 110

def identify(attrs)
  symbolize_keys! attrs
  enqueue(FieldParser.parse_for_identify(attrs))
end

#is_feature_enabled(flag_key, distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false, send_feature_flag_events: true) ⇒ Object



149
150
151
152
153
154
155
# File 'lib/posthog/client.rb', line 149

def is_feature_enabled(flag_key, distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false, send_feature_flag_events: true)
  response = get_feature_flag(flag_key, distinct_id, groups: groups, person_properties: person_properties, group_properties: group_properties, only_evaluate_locally: only_evaluate_locally, send_feature_flag_events: send_feature_flag_events)
  if response.nil?
    return nil
  end
  !!response
end

#queued_messagesFixnum

Returns number of messages in the queue.

Returns:

  • (Fixnum)

    number of messages in the queue



145
146
147
# File 'lib/posthog/client.rb', line 145

def queued_messages
  @queue.length
end

#reload_feature_flagsObject



241
242
243
244
245
246
247
248
249
# File 'lib/posthog/client.rb', line 241

def reload_feature_flags
  unless @personal_api_key
    logger.error(
      'You need to specify a personal_api_key to locally evaluate feature flags'
    )
    return
  end
  @feature_flags_poller.load_feature_flags(true)
end

#shutdownObject



251
252
253
254
# File 'lib/posthog/client.rb', line 251

def shutdown
  @feature_flags_poller.shutdown_poller
  flush
end