ablaevent-ruby 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/posthog +109 -0
- data/lib/posthog/backoff_policy.rb +44 -0
- data/lib/posthog/client.rb +291 -0
- data/lib/posthog/defaults.rb +39 -0
- data/lib/posthog/feature_flags.rb +466 -0
- data/lib/posthog/field_parser.rb +169 -0
- data/lib/posthog/logging.rb +68 -0
- data/lib/posthog/message_batch.rb +71 -0
- data/lib/posthog/noop_worker.rb +16 -0
- data/lib/posthog/response.rb +13 -0
- data/lib/posthog/send_worker.rb +67 -0
- data/lib/posthog/transport.rb +144 -0
- data/lib/posthog/utils.rb +132 -0
- data/lib/posthog/version.rb +3 -0
- data/lib/posthog-ruby.rb +1 -0
- data/lib/posthog.rb +9 -0
- metadata +185 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 593ac5ac8af6a3e678b7af74f678f28c1b13bcd90c414c90b853d000f4b3b822
|
|
4
|
+
data.tar.gz: 0b901a391a410da624d1ddd2e2fc570de473174be9afa03c3990265259790d20
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4d77f12b6e30ca51d9b30db45eaec75ae6491e6546b9d93feb1a139bb848fc734c140a10e5f9ffaf40b4c0533b8ee8a9a859b88ea7ba4aa0449c4c0821ee8353
|
|
7
|
+
data.tar.gz: 6eb786e2594776410e06227be296d96f7c0f038f2567de11a2924dd66685befc229303a1417bbad38cea404bf6c443d8543e8b809748ee9dbd8998e92c1794ac
|
data/bin/posthog
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'posthog'
|
|
4
|
+
require 'rubygems'
|
|
5
|
+
require 'commander/import'
|
|
6
|
+
require 'time'
|
|
7
|
+
require 'json'
|
|
8
|
+
|
|
9
|
+
program :name, 'posthog'
|
|
10
|
+
program :version, '1.0.0'
|
|
11
|
+
program :description, 'PostHog API'
|
|
12
|
+
|
|
13
|
+
def json_hash(str)
|
|
14
|
+
return JSON.parse(str) if str
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
command :capture do |c|
|
|
18
|
+
c.description = 'capture an event'
|
|
19
|
+
|
|
20
|
+
c.option '--api-key=<string>', String, 'The PostHog API Key'
|
|
21
|
+
c.option '--api-host=<url>',
|
|
22
|
+
String,
|
|
23
|
+
'The PostHog API URL host part (scheme+domain)'
|
|
24
|
+
c.option '--distinct-id=<distinct_id>',
|
|
25
|
+
String,
|
|
26
|
+
'The distinct id to send the event as'
|
|
27
|
+
c.option '--event=<event>', String, 'The event name to send with the event'
|
|
28
|
+
c.option '--properties=<properties>', 'The properties to send (JSON-encoded)'
|
|
29
|
+
|
|
30
|
+
c.action do |args, options|
|
|
31
|
+
posthog =
|
|
32
|
+
PostHog::Client.new(
|
|
33
|
+
{
|
|
34
|
+
api_key: options.api_key,
|
|
35
|
+
api_host: options.api_host,
|
|
36
|
+
on_error: Proc.new { |status, msg| print msg }
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
posthog.capture(
|
|
41
|
+
{
|
|
42
|
+
distinct_id: options.distinct_id,
|
|
43
|
+
event: options.event,
|
|
44
|
+
properties: json_hash(options.properties)
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
posthog.flush
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
command :identify do |c|
|
|
53
|
+
c.description = 'identify the user'
|
|
54
|
+
|
|
55
|
+
c.option '--api-key=<api_key>', String, 'The PostHog API Key'
|
|
56
|
+
c.option '--api-host=<url>',
|
|
57
|
+
String,
|
|
58
|
+
'The PostHog API URL host part (scheme+domain)'
|
|
59
|
+
c.option '--distinct-id=<distinct_id>',
|
|
60
|
+
String,
|
|
61
|
+
'The distinct id to send the event as'
|
|
62
|
+
c.option '--properties=<properties>', 'The properties to send (JSON-encoded)'
|
|
63
|
+
|
|
64
|
+
c.action do |args, options|
|
|
65
|
+
posthog =
|
|
66
|
+
PostHog::Client.new(
|
|
67
|
+
{
|
|
68
|
+
api_key: options.api_key,
|
|
69
|
+
api_host: options.api_host,
|
|
70
|
+
on_error: Proc.new { |status, msg| print msg }
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
posthog.identify(
|
|
75
|
+
{
|
|
76
|
+
distinct_id: options.distinct_id,
|
|
77
|
+
properties: json_hash(options.properties)
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
posthog.flush
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
command :alias do |c|
|
|
86
|
+
c.description = 'set an alias for a distinct id'
|
|
87
|
+
|
|
88
|
+
c.option '--api-key=<api_key>', String, 'The PostHog API Key'
|
|
89
|
+
c.option '--api-host=<url>',
|
|
90
|
+
String,
|
|
91
|
+
'The PostHog API URL host part (scheme+domain)'
|
|
92
|
+
c.option '--distinct-id=<distinct_id>', String, 'The distinct id'
|
|
93
|
+
c.option '--alias=<alias>', 'The alias to give to the distinct id'
|
|
94
|
+
|
|
95
|
+
c.action do |args, options|
|
|
96
|
+
posthog =
|
|
97
|
+
PostHog::Client.new(
|
|
98
|
+
{
|
|
99
|
+
api_key: options.api_key,
|
|
100
|
+
api_host: options.api_host,
|
|
101
|
+
on_error: Proc.new { |status, msg| print msg }
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
posthog.alias({ distinct_id: options.distinct_id, alias: options.alias })
|
|
106
|
+
|
|
107
|
+
posthog.flush
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require 'posthog/defaults'
|
|
2
|
+
|
|
3
|
+
class PostHog
|
|
4
|
+
class BackoffPolicy
|
|
5
|
+
include PostHog::Defaults::BackoffPolicy
|
|
6
|
+
|
|
7
|
+
# @param [Hash] opts
|
|
8
|
+
# @option opts [Numeric] :min_timeout_ms The minimum backoff timeout
|
|
9
|
+
# @option opts [Numeric] :max_timeout_ms The maximum backoff timeout
|
|
10
|
+
# @option opts [Numeric] :multiplier The value to multiply the current
|
|
11
|
+
# interval with for each retry attempt
|
|
12
|
+
# @option opts [Numeric] :randomization_factor The randomization factor
|
|
13
|
+
# to use to create a range around the retry interval
|
|
14
|
+
def initialize(opts = {})
|
|
15
|
+
@min_timeout_ms = opts[:min_timeout_ms] || MIN_TIMEOUT_MS
|
|
16
|
+
@max_timeout_ms = opts[:max_timeout_ms] || MAX_TIMEOUT_MS
|
|
17
|
+
@multiplier = opts[:multiplier] || MULTIPLIER
|
|
18
|
+
@randomization_factor =
|
|
19
|
+
opts[:randomization_factor] || RANDOMIZATION_FACTOR
|
|
20
|
+
|
|
21
|
+
@attempts = 0
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [Numeric] the next backoff interval, in milliseconds.
|
|
25
|
+
def next_interval
|
|
26
|
+
interval = @min_timeout_ms * (@multiplier**@attempts)
|
|
27
|
+
interval = add_jitter(interval, @randomization_factor)
|
|
28
|
+
|
|
29
|
+
@attempts += 1
|
|
30
|
+
|
|
31
|
+
[interval, @max_timeout_ms].min
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def add_jitter(base, randomization_factor)
|
|
37
|
+
random_number = rand
|
|
38
|
+
max_deviation = base * randomization_factor
|
|
39
|
+
deviation = random_number * max_deviation
|
|
40
|
+
|
|
41
|
+
random_number < 0.5 ? base - deviation : base + deviation
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
require 'time'
|
|
3
|
+
|
|
4
|
+
require 'posthog/defaults'
|
|
5
|
+
require 'posthog/logging'
|
|
6
|
+
require 'posthog/utils'
|
|
7
|
+
require 'posthog/send_worker'
|
|
8
|
+
require 'posthog/noop_worker'
|
|
9
|
+
require 'posthog/feature_flags'
|
|
10
|
+
|
|
11
|
+
class PostHog
|
|
12
|
+
class Client
|
|
13
|
+
include PostHog::Utils
|
|
14
|
+
include PostHog::Logging
|
|
15
|
+
|
|
16
|
+
# @param [Hash] opts
|
|
17
|
+
# @option opts [String] :api_key Your project's api_key
|
|
18
|
+
# @option opts [FixNum] :max_queue_size Maximum number of calls to be
|
|
19
|
+
# remain queued. Defaults to 10_000.
|
|
20
|
+
# @option opts [Bool] :test_mode +true+ if messages should remain
|
|
21
|
+
# queued for testing. Defaults to +false+.
|
|
22
|
+
# @option opts [Proc] :on_error Handles error calls from the API.
|
|
23
|
+
# @option opts [String] :host Fully qualified hostname of the PostHog server. Defaults to `https://e.abla.io`
|
|
24
|
+
# @option opts [Integer] :feature_flags_polling_interval How often to poll for feature flag definition changes. Measured in seconds, defaults to 30.
|
|
25
|
+
def initialize(opts = {})
|
|
26
|
+
symbolize_keys!(opts)
|
|
27
|
+
|
|
28
|
+
opts[:host] ||= 'https://e.abla.io'
|
|
29
|
+
|
|
30
|
+
@queue = Queue.new
|
|
31
|
+
@api_key = opts[:api_key]
|
|
32
|
+
@max_queue_size = opts[:max_queue_size] || Defaults::Queue::MAX_SIZE
|
|
33
|
+
@worker_mutex = Mutex.new
|
|
34
|
+
@worker = if opts[:test_mode]
|
|
35
|
+
NoopWorker.new(@queue)
|
|
36
|
+
else
|
|
37
|
+
SendWorker.new(@queue, @api_key, opts)
|
|
38
|
+
end
|
|
39
|
+
@worker_thread = nil
|
|
40
|
+
@feature_flags_poller = nil
|
|
41
|
+
@personal_api_key = opts[:personal_api_key]
|
|
42
|
+
|
|
43
|
+
check_api_key!
|
|
44
|
+
|
|
45
|
+
@feature_flags_poller =
|
|
46
|
+
FeatureFlagsPoller.new(
|
|
47
|
+
opts[:feature_flags_polling_interval],
|
|
48
|
+
opts[:personal_api_key],
|
|
49
|
+
@api_key,
|
|
50
|
+
opts[:host]
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
@distinct_id_has_sent_flag_calls = SizeLimitedHash.new(Defaults::MAX_HASH_SIZE) { |hash, key| hash[key] = Array.new }
|
|
54
|
+
|
|
55
|
+
at_exit { @worker_thread && @worker_thread[:should_exit] = true }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Synchronously waits until the worker has cleared the queue.
|
|
59
|
+
#
|
|
60
|
+
# Use only for scripts which are not long-running, and will specifically
|
|
61
|
+
# exit
|
|
62
|
+
def flush
|
|
63
|
+
while !@queue.empty? || @worker.is_requesting?
|
|
64
|
+
ensure_worker_running
|
|
65
|
+
sleep(0.1)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Clears the queue without waiting.
|
|
70
|
+
#
|
|
71
|
+
# Use only in test mode
|
|
72
|
+
def clear
|
|
73
|
+
@queue.clear
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# @!macro common_attrs
|
|
77
|
+
# @option attrs [String] :message_id ID that uniquely
|
|
78
|
+
# identifies a message across the API. (optional)
|
|
79
|
+
# @option attrs [Time] :timestamp When the event occurred (optional)
|
|
80
|
+
# @option attrs [String] :distinct_id The ID for this user in your database
|
|
81
|
+
|
|
82
|
+
# Captures an event
|
|
83
|
+
#
|
|
84
|
+
# @param [Hash] attrs
|
|
85
|
+
#
|
|
86
|
+
# @option attrs [String] :event Event name
|
|
87
|
+
# @option attrs [Hash] :properties Event properties (optional)
|
|
88
|
+
# @option attrs [Bool] :send_feature_flags Whether to send feature flags with this event (optional)
|
|
89
|
+
# @macro common_attrs
|
|
90
|
+
def capture(attrs)
|
|
91
|
+
symbolize_keys! attrs
|
|
92
|
+
|
|
93
|
+
if attrs[:send_feature_flags]
|
|
94
|
+
feature_variants = @feature_flags_poller._get_active_feature_variants(attrs[:distinct_id], attrs[:groups])
|
|
95
|
+
|
|
96
|
+
attrs[:feature_variants] = feature_variants
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
enqueue(FieldParser.parse_for_capture(attrs))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Identifies a user
|
|
103
|
+
#
|
|
104
|
+
# @param [Hash] attrs
|
|
105
|
+
#
|
|
106
|
+
# @option attrs [Hash] :properties User properties (optional)
|
|
107
|
+
# @macro common_attrs
|
|
108
|
+
def identify(attrs)
|
|
109
|
+
symbolize_keys! attrs
|
|
110
|
+
enqueue(FieldParser.parse_for_identify(attrs))
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Identifies a group
|
|
114
|
+
#
|
|
115
|
+
# @param [Hash] attrs
|
|
116
|
+
#
|
|
117
|
+
# @option attrs [String] :group_type Group type
|
|
118
|
+
# @option attrs [String] :group_key Group key
|
|
119
|
+
# @option attrs [Hash] :properties Group properties (optional)
|
|
120
|
+
# @macro common_attrs
|
|
121
|
+
def group_identify(attrs)
|
|
122
|
+
symbolize_keys! attrs
|
|
123
|
+
enqueue(FieldParser.parse_for_group_identify(attrs))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Aliases a user from one id to another
|
|
127
|
+
#
|
|
128
|
+
# @param [Hash] attrs
|
|
129
|
+
#
|
|
130
|
+
# @option attrs [String] :alias The alias to give the distinct id
|
|
131
|
+
# @macro common_attrs
|
|
132
|
+
def alias(attrs)
|
|
133
|
+
symbolize_keys! attrs
|
|
134
|
+
enqueue(FieldParser.parse_for_alias(attrs))
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# @return [Hash] pops the last message from the queue
|
|
138
|
+
def dequeue_last_message
|
|
139
|
+
@queue.pop
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# @return [Fixnum] number of messages in the queue
|
|
143
|
+
def queued_messages
|
|
144
|
+
@queue.length
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def is_feature_enabled(flag_key, distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false, send_feature_flag_events: true)
|
|
148
|
+
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)
|
|
149
|
+
if response.nil?
|
|
150
|
+
return nil
|
|
151
|
+
end
|
|
152
|
+
!!response
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Returns whether the given feature flag is enabled for the given user or not
|
|
156
|
+
#
|
|
157
|
+
# @param [String] key The key of the feature flag
|
|
158
|
+
# @param [String] distinct_id The distinct id of the user
|
|
159
|
+
# @param [Hash] groups
|
|
160
|
+
# @param [Hash] person_properties key-value pairs of properties to associate with the user.
|
|
161
|
+
# @param [Hash] group_properties
|
|
162
|
+
#
|
|
163
|
+
# @return [String, nil] The value of the feature flag
|
|
164
|
+
#
|
|
165
|
+
# The provided properties are used to calculate feature flags locally, if possible.
|
|
166
|
+
#
|
|
167
|
+
# `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",
|
|
168
|
+
# you would pass groups={"organization": "5"}.
|
|
169
|
+
# `group_properties` take the format: { group_type_name: { group_properties } }
|
|
170
|
+
# So, for example, if you have the group type "organization" and the group key "5", with the properties name, and employee count,
|
|
171
|
+
# you'll send these as:
|
|
172
|
+
# ```ruby
|
|
173
|
+
# group_properties: {"organization": {"name": "PostHog", "employees": 11}}
|
|
174
|
+
# ```
|
|
175
|
+
def get_feature_flag(key, distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false, send_feature_flag_events: true)
|
|
176
|
+
feature_flag_response, flag_was_locally_evaluated = @feature_flags_poller.get_feature_flag(key, distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
|
|
177
|
+
|
|
178
|
+
feature_flag_reported_key = "#{key}_#{feature_flag_response}"
|
|
179
|
+
if !@distinct_id_has_sent_flag_calls[distinct_id].include?(feature_flag_reported_key) && send_feature_flag_events
|
|
180
|
+
capture(
|
|
181
|
+
{
|
|
182
|
+
'distinct_id': distinct_id,
|
|
183
|
+
'event': '$feature_flag_called',
|
|
184
|
+
'properties': {
|
|
185
|
+
'$feature_flag' => key,
|
|
186
|
+
'$feature_flag_response' => feature_flag_response,
|
|
187
|
+
'locally_evaluated' => flag_was_locally_evaluated
|
|
188
|
+
},
|
|
189
|
+
'groups': groups,
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
@distinct_id_has_sent_flag_calls[distinct_id] << feature_flag_reported_key
|
|
193
|
+
end
|
|
194
|
+
feature_flag_response
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Returns all flags for a given user
|
|
198
|
+
#
|
|
199
|
+
# @param [String] distinct_id The distinct id of the user
|
|
200
|
+
# @param [Hash] groups
|
|
201
|
+
# @param [Hash] person_properties key-value pairs of properties to associate with the user.
|
|
202
|
+
# @param [Hash] group_properties
|
|
203
|
+
#
|
|
204
|
+
# @return [Hash] String (not symbol) key value pairs of flag and their values
|
|
205
|
+
def get_all_flags(distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false)
|
|
206
|
+
return @feature_flags_poller.get_all_flags(distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Returns payload for a given feature flag
|
|
210
|
+
#
|
|
211
|
+
# @param [String] key The key of the feature flag
|
|
212
|
+
# @param [String] distinct_id The distinct id of the user
|
|
213
|
+
# @option [String or boolean] match_value The value of the feature flag to be matched
|
|
214
|
+
# @option [Hash] groups
|
|
215
|
+
# @option [Hash] person_properties key-value pairs of properties to associate with the user.
|
|
216
|
+
# @option [Hash] group_properties
|
|
217
|
+
# @option [Boolean] only_evaluate_locally
|
|
218
|
+
#
|
|
219
|
+
def get_feature_flag_payload(key, distinct_id, match_value: nil, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false)
|
|
220
|
+
@feature_flags_poller.get_feature_flag_payload(key, distinct_id, match_value, groups, person_properties, group_properties, only_evaluate_locally)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Returns all flags and payloads for a given user
|
|
224
|
+
#
|
|
225
|
+
# @param [String] distinct_id The distinct id of the user
|
|
226
|
+
# @option [Hash] groups
|
|
227
|
+
# @option [Hash] person_properties key-value pairs of properties to associate with the user.
|
|
228
|
+
# @option [Hash] group_properties
|
|
229
|
+
# @option [Boolean] only_evaluate_locally
|
|
230
|
+
#
|
|
231
|
+
def get_all_flags_and_payloads(distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false)
|
|
232
|
+
@feature_flags_poller.get_all_flags_and_payloads(distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def reload_feature_flags
|
|
236
|
+
unless @personal_api_key
|
|
237
|
+
logger.error(
|
|
238
|
+
'You need to specify a personal_api_key to locally evaluate feature flags'
|
|
239
|
+
)
|
|
240
|
+
return
|
|
241
|
+
end
|
|
242
|
+
@feature_flags_poller.load_feature_flags(true)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def shutdown
|
|
246
|
+
@feature_flags_poller.shutdown_poller
|
|
247
|
+
flush
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
private
|
|
251
|
+
|
|
252
|
+
# private: Enqueues the action.
|
|
253
|
+
#
|
|
254
|
+
# returns Boolean of whether the item was added to the queue.
|
|
255
|
+
def enqueue(action)
|
|
256
|
+
# add our request id for tracing purposes
|
|
257
|
+
action[:messageId] ||= uid
|
|
258
|
+
|
|
259
|
+
if @queue.length < @max_queue_size
|
|
260
|
+
@queue << action
|
|
261
|
+
ensure_worker_running
|
|
262
|
+
|
|
263
|
+
true
|
|
264
|
+
else
|
|
265
|
+
logger.warn(
|
|
266
|
+
'Queue is full, dropping events. The :max_queue_size ' \
|
|
267
|
+
'configuration parameter can be increased to prevent this from ' \
|
|
268
|
+
'happening.'
|
|
269
|
+
)
|
|
270
|
+
false
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# private: Checks that the api_key is properly initialized
|
|
275
|
+
def check_api_key!
|
|
276
|
+
raise ArgumentError, 'API key must be initialized' if @api_key.nil?
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def ensure_worker_running
|
|
280
|
+
return if worker_running?
|
|
281
|
+
@worker_mutex.synchronize do
|
|
282
|
+
return if worker_running?
|
|
283
|
+
@worker_thread = Thread.new { @worker.run }
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def worker_running?
|
|
288
|
+
@worker_thread && @worker_thread.alive?
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
class PostHog
|
|
2
|
+
module Defaults
|
|
3
|
+
|
|
4
|
+
MAX_HASH_SIZE = 50_000
|
|
5
|
+
|
|
6
|
+
module Request
|
|
7
|
+
HOST = 'e.abla.io'
|
|
8
|
+
PORT = 443
|
|
9
|
+
PATH = '/batch/'
|
|
10
|
+
SSL = true
|
|
11
|
+
HEADERS = {
|
|
12
|
+
'Accept' => 'application/json',
|
|
13
|
+
'Content-Type' => 'application/json',
|
|
14
|
+
'User-Agent' => "posthog-ruby/#{PostHog::VERSION}"
|
|
15
|
+
}
|
|
16
|
+
RETRIES = 10
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
module Queue
|
|
20
|
+
MAX_SIZE = 10_000
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module Message
|
|
24
|
+
MAX_BYTES = 32_768 # 32Kb
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module MessageBatch
|
|
28
|
+
MAX_BYTES = 512_000 # 500Kb
|
|
29
|
+
MAX_SIZE = 100
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
module BackoffPolicy
|
|
33
|
+
MIN_TIMEOUT_MS = 100
|
|
34
|
+
MAX_TIMEOUT_MS = 10_000
|
|
35
|
+
MULTIPLIER = 1.5
|
|
36
|
+
RANDOMIZATION_FACTOR = 0.5
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|