posthog-ruby 2.11.0 → 3.0.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 +4 -4
- data/bin/posthog +1 -0
- data/lib/posthog/backoff_policy.rb +3 -1
- data/lib/posthog/client.rb +8 -9
- data/lib/posthog/defaults.rb +5 -3
- data/lib/posthog/feature_flag.rb +54 -50
- data/lib/posthog/feature_flags.rb +28 -30
- data/lib/posthog/field_parser.rb +7 -5
- data/lib/posthog/logging.rb +3 -1
- data/lib/posthog/message_batch.rb +3 -1
- data/lib/posthog/noop_worker.rb +3 -1
- data/lib/posthog/response.rb +3 -1
- data/lib/posthog/send_worker.rb +3 -1
- data/lib/posthog/transport.rb +3 -1
- data/lib/posthog/utils.rb +12 -10
- data/lib/posthog/version.rb +4 -2
- data/lib/posthog.rb +2 -0
- metadata +2 -3
- data/lib/posthog-ruby.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 253c223f00642a02c72d074b6fbf7a523d5799b2a03eed42794e3ab03d6d9c82
|
4
|
+
data.tar.gz: e6c509257a8b09588a3cfd4081ef79184150d28e1d9d9b41a189364c9758e99a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 824adb5f3f57fbc404876cf8a3a05736ee1b9d5e42114f5a51cfd6d833a35ddff0a45eb9010aaa2744d1c3ea5e150807a2b05d4e88ed7883d579d9debd71a53f
|
7
|
+
data.tar.gz: d48f1843633e2a8ff16a5f17a9ada51d431a1219ca91b273e72872e8e6acae2f0d409252247c1ec0b7c165ea11fe844313dbad57f16322de20c0bf53651cf6fb
|
data/bin/posthog
CHANGED
data/lib/posthog/client.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'time'
|
3
4
|
|
4
5
|
require 'posthog/defaults'
|
@@ -8,7 +9,7 @@ require 'posthog/send_worker'
|
|
8
9
|
require 'posthog/noop_worker'
|
9
10
|
require 'posthog/feature_flags'
|
10
11
|
|
11
|
-
|
12
|
+
module PostHog
|
12
13
|
class Client
|
13
14
|
include PostHog::Utils
|
14
15
|
include PostHog::Logging
|
@@ -410,7 +411,7 @@ class PostHog
|
|
410
411
|
end
|
411
412
|
|
412
413
|
def worker_running?
|
413
|
-
@worker_thread
|
414
|
+
@worker_thread&.alive?
|
414
415
|
end
|
415
416
|
|
416
417
|
def add_local_person_and_group_properties(distinct_id, groups, person_properties, group_properties)
|
@@ -429,12 +430,10 @@ class PostHog
|
|
429
430
|
all_person_properties = { distinct_id: distinct_id }.merge(person_properties)
|
430
431
|
|
431
432
|
all_group_properties = {}
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
}.merge((group_properties && group_properties[group_name]) || {})
|
437
|
-
end
|
433
|
+
groups&.each do |group_name, group_key|
|
434
|
+
all_group_properties[group_name] = {
|
435
|
+
'$group_key': group_key
|
436
|
+
}.merge((group_properties && group_properties[group_name]) || {})
|
438
437
|
end
|
439
438
|
|
440
439
|
[all_person_properties, all_group_properties]
|
data/lib/posthog/defaults.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PostHog
|
2
4
|
module Defaults
|
3
5
|
MAX_HASH_SIZE = 50_000
|
4
6
|
|
5
7
|
module Request
|
6
|
-
HOST = 'app.posthog.com'
|
8
|
+
HOST = 'app.posthog.com'
|
7
9
|
PORT = 443
|
8
|
-
PATH = '/batch/'
|
10
|
+
PATH = '/batch/'
|
9
11
|
SSL = true
|
10
12
|
HEADERS = {
|
11
13
|
'Accept' => 'application/json',
|
data/lib/posthog/feature_flag.rb
CHANGED
@@ -1,62 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Represents a feature flag returned by /flags v2
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
def initialize(json)
|
6
|
-
json.transform_keys!(&:to_s)
|
7
|
-
@key = json['key']
|
8
|
-
@enabled = json['enabled']
|
9
|
-
@variant = json['variant']
|
10
|
-
@reason = json['reason'] ? EvaluationReason.new(json['reason']) : nil
|
11
|
-
@metadata = json['metadata'] ? FeatureFlagMetadata.new(json['metadata'].transform_keys(&:to_s)) : nil
|
12
|
-
end
|
4
|
+
module PostHog
|
5
|
+
class FeatureFlag
|
6
|
+
attr_reader :key, :enabled, :variant, :reason, :metadata
|
13
7
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
8
|
+
def initialize(json)
|
9
|
+
json.transform_keys!(&:to_s)
|
10
|
+
@key = json['key']
|
11
|
+
@enabled = json['enabled']
|
12
|
+
@variant = json['variant']
|
13
|
+
@reason = json['reason'] ? EvaluationReason.new(json['reason']) : nil
|
14
|
+
@metadata = json['metadata'] ? FeatureFlagMetadata.new(json['metadata'].transform_keys(&:to_s)) : nil
|
15
|
+
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
# TODO: Rename to `value` in future version
|
18
|
+
def get_value # rubocop:disable Naming/AccessorMethodName
|
19
|
+
@variant || @enabled
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
'
|
31
|
-
'
|
32
|
-
'
|
33
|
-
'
|
34
|
-
|
35
|
-
|
22
|
+
def payload
|
23
|
+
@metadata&.payload
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.from_value_and_payload(key, value, payload)
|
27
|
+
new({
|
28
|
+
'key' => key,
|
29
|
+
'enabled' => value.is_a?(String) || value,
|
30
|
+
'variant' => value.is_a?(String) ? value : nil,
|
31
|
+
'reason' => nil,
|
32
|
+
'metadata' => {
|
33
|
+
'id' => nil,
|
34
|
+
'version' => nil,
|
35
|
+
'payload' => payload,
|
36
|
+
'description' => nil
|
37
|
+
}
|
38
|
+
})
|
39
|
+
end
|
36
40
|
end
|
37
|
-
end
|
38
41
|
|
39
|
-
# Represents the reason why a flag was enabled/disabled
|
40
|
-
class EvaluationReason
|
41
|
-
|
42
|
+
# Represents the reason why a flag was enabled/disabled
|
43
|
+
class EvaluationReason
|
44
|
+
attr_reader :code, :description, :condition_index
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
46
|
+
def initialize(json)
|
47
|
+
json.transform_keys!(&:to_s)
|
48
|
+
@code = json['code']
|
49
|
+
@description = json['description']
|
50
|
+
@condition_index = json['condition_index'].to_i if json['condition_index']
|
51
|
+
end
|
48
52
|
end
|
49
|
-
end
|
50
53
|
|
51
|
-
# Represents metadata about a feature flag
|
52
|
-
class FeatureFlagMetadata
|
53
|
-
|
54
|
+
# Represents metadata about a feature flag
|
55
|
+
class FeatureFlagMetadata
|
56
|
+
attr_reader :id, :version, :payload, :description
|
54
57
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
def initialize(json)
|
59
|
+
json.transform_keys!(&:to_s)
|
60
|
+
@id = json['id']
|
61
|
+
@version = json['version']
|
62
|
+
@payload = json['payload']
|
63
|
+
@description = json['description']
|
64
|
+
end
|
61
65
|
end
|
62
66
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'concurrent'
|
2
4
|
require 'net/http'
|
3
5
|
require 'json'
|
@@ -6,7 +8,7 @@ require 'posthog/logging'
|
|
6
8
|
require 'posthog/feature_flag'
|
7
9
|
require 'digest'
|
8
10
|
|
9
|
-
|
11
|
+
module PostHog
|
10
12
|
class InconclusiveMatchError < StandardError
|
11
13
|
end
|
12
14
|
|
@@ -125,9 +127,9 @@ class PostHog
|
|
125
127
|
# v3 format
|
126
128
|
flags_response[:featureFlags] = flags_response[:featureFlags] || {}
|
127
129
|
flags_response[:featureFlagPayloads] = flags_response[:featureFlagPayloads] || {}
|
128
|
-
flags_response[:flags] = flags_response[:featureFlags].
|
130
|
+
flags_response[:flags] = flags_response[:featureFlags].to_h do |key, value|
|
129
131
|
[key, FeatureFlag.from_value_and_payload(key, value, flags_response[:featureFlagPayloads][key])]
|
130
|
-
end
|
132
|
+
end
|
131
133
|
end
|
132
134
|
flags_response
|
133
135
|
end
|
@@ -242,17 +244,15 @@ class PostHog
|
|
242
244
|
request_id = nil # Only for /flags requests
|
243
245
|
|
244
246
|
@feature_flags.each do |flag|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
fallback_to_server = true
|
255
|
-
end
|
247
|
+
match_value = _compute_flag_locally(flag, distinct_id, groups, person_properties, group_properties)
|
248
|
+
flags[flag[:key]] = match_value
|
249
|
+
match_payload = _compute_flag_payload_locally(flag[:key], match_value)
|
250
|
+
payloads[flag[:key]] = match_payload if match_payload
|
251
|
+
rescue InconclusiveMatchError
|
252
|
+
fallback_to_server = true
|
253
|
+
rescue StandardError => e
|
254
|
+
@on_error.call(-1, "Error computing flag locally: #{e}. #{e.backtrace.join("\n")} ")
|
255
|
+
fallback_to_server = true
|
256
256
|
end
|
257
257
|
|
258
258
|
if fallback_to_server && !only_evaluate_locally
|
@@ -264,7 +264,7 @@ class PostHog
|
|
264
264
|
end
|
265
265
|
|
266
266
|
# Check if feature_flags are quota limited
|
267
|
-
if flags_and_payloads[:quotaLimited]
|
267
|
+
if flags_and_payloads[:quotaLimited]&.include?('feature_flags')
|
268
268
|
logger.warn '[FEATURE FLAGS] Quota limited for feature flags'
|
269
269
|
flags = {}
|
270
270
|
payloads = {}
|
@@ -505,22 +505,20 @@ class PostHog
|
|
505
505
|
# NOTE: This NEEDS to be `each` because `each_key` breaks
|
506
506
|
# This is not a hash, it's just an array with 2 entries
|
507
507
|
sorted_flag_conditions.each do |condition, _idx| # rubocop:disable Style/HashEachMethods
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
break
|
520
|
-
end
|
521
|
-
rescue InconclusiveMatchError
|
522
|
-
is_inconclusive = true
|
508
|
+
if is_condition_match(flag, distinct_id, condition, properties)
|
509
|
+
variant_override = condition[:variant]
|
510
|
+
flag_multivariate = flag_filters[:multivariate] || {}
|
511
|
+
flag_variants = flag_multivariate[:variants] || []
|
512
|
+
variant = if flag_variants.map { |variant| variant[:key] }.include?(condition[:variant])
|
513
|
+
variant_override
|
514
|
+
else
|
515
|
+
get_matching_variant(flag, distinct_id)
|
516
|
+
end
|
517
|
+
result = variant || true
|
518
|
+
break
|
523
519
|
end
|
520
|
+
rescue InconclusiveMatchError
|
521
|
+
is_inconclusive = true
|
524
522
|
end
|
525
523
|
|
526
524
|
if !result.nil?
|
data/lib/posthog/field_parser.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'posthog/logging'
|
2
4
|
|
3
|
-
|
5
|
+
module PostHog
|
4
6
|
class FieldParser
|
5
7
|
class << self
|
6
8
|
include PostHog::Utils
|
@@ -55,7 +57,7 @@ class PostHog
|
|
55
57
|
{
|
56
58
|
type: 'identify',
|
57
59
|
event: '$identify',
|
58
|
-
|
60
|
+
'$set': properties,
|
59
61
|
properties: properties.merge(common[:properties] || {})
|
60
62
|
}
|
61
63
|
)
|
@@ -79,9 +81,9 @@ class PostHog
|
|
79
81
|
{
|
80
82
|
event: '$groupidentify',
|
81
83
|
properties: {
|
82
|
-
|
83
|
-
|
84
|
-
|
84
|
+
'$group_type': group_type,
|
85
|
+
'$group_key': group_key,
|
86
|
+
'$group_set': properties.merge(common[:properties] || {})
|
85
87
|
}
|
86
88
|
}
|
87
89
|
)
|
data/lib/posthog/logging.rb
CHANGED
data/lib/posthog/noop_worker.rb
CHANGED
data/lib/posthog/response.rb
CHANGED
data/lib/posthog/send_worker.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'posthog/defaults'
|
2
4
|
require 'posthog/message_batch'
|
3
5
|
require 'posthog/transport'
|
4
6
|
require 'posthog/utils'
|
5
7
|
|
6
|
-
|
8
|
+
module PostHog
|
7
9
|
class SendWorker
|
8
10
|
include PostHog::Utils
|
9
11
|
include PostHog::Defaults
|
data/lib/posthog/transport.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'posthog/defaults'
|
2
4
|
require 'posthog/utils'
|
3
5
|
require 'posthog/response'
|
@@ -7,7 +9,7 @@ require 'net/http'
|
|
7
9
|
require 'net/https'
|
8
10
|
require 'json'
|
9
11
|
|
10
|
-
|
12
|
+
module PostHog
|
11
13
|
class Transport
|
12
14
|
include PostHog::Defaults::Request
|
13
15
|
include PostHog::Utils
|
data/lib/posthog/utils.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'securerandom'
|
2
4
|
|
3
|
-
|
5
|
+
module PostHog
|
4
6
|
class InconclusiveMatchError < StandardError
|
5
7
|
end
|
6
8
|
|
@@ -10,7 +12,7 @@ class PostHog
|
|
10
12
|
# public: Return a new hash with keys converted from strings to symbols
|
11
13
|
#
|
12
14
|
def symbolize_keys(hash)
|
13
|
-
hash.
|
15
|
+
hash.transform_keys(&:to_sym)
|
14
16
|
end
|
15
17
|
|
16
18
|
# public: Convert hash keys from strings to symbols in place
|
@@ -22,15 +24,15 @@ class PostHog
|
|
22
24
|
# public: Return a new hash with keys as strings
|
23
25
|
#
|
24
26
|
def stringify_keys(hash)
|
25
|
-
hash.
|
27
|
+
hash.transform_keys(&:to_s)
|
26
28
|
end
|
27
29
|
|
28
30
|
# public: Returns a new hash with all the date values in the into iso8601
|
29
31
|
# strings
|
30
32
|
#
|
31
33
|
def isoify_dates(hash)
|
32
|
-
hash.
|
33
|
-
|
34
|
+
hash.transform_values do |v|
|
35
|
+
datetime_in_iso8601(v)
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
@@ -65,7 +67,7 @@ class PostHog
|
|
65
67
|
|
66
68
|
def time_in_iso8601(time, fraction_digits = 3)
|
67
69
|
fraction =
|
68
|
-
(('.%06i' % time.usec)[0, fraction_digits + 1] if fraction_digits
|
70
|
+
(('.%06i' % time.usec)[0, fraction_digits + 1] if fraction_digits.positive?) # rubocop:disable Style/FormatString
|
69
71
|
|
70
72
|
"#{time.strftime('%Y-%m-%dT%H:%M:%S')}#{fraction}#{formatted_offset(time, true, 'Z')}"
|
71
73
|
end
|
@@ -80,7 +82,7 @@ class PostHog
|
|
80
82
|
end
|
81
83
|
|
82
84
|
def seconds_to_utc_offset(seconds, colon = true)
|
83
|
-
format((colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON), (seconds
|
85
|
+
format((colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON), (seconds.negative? ? '-' : '+'),
|
84
86
|
seconds.abs / 3600, (seconds.abs % 3600) / 60)
|
85
87
|
end
|
86
88
|
|
@@ -99,7 +101,7 @@ class PostHog
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
102
|
-
UTC_OFFSET_WITH_COLON = '%s%02d:%02d'
|
104
|
+
UTC_OFFSET_WITH_COLON = '%s%02d:%02d'
|
103
105
|
UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.sub(':', '')
|
104
106
|
|
105
107
|
# TODO: Rename to `valid_regex?` in future version
|
@@ -111,8 +113,8 @@ class PostHog
|
|
111
113
|
end
|
112
114
|
|
113
115
|
class SizeLimitedHash < Hash
|
114
|
-
def initialize(max_length,
|
115
|
-
super(
|
116
|
+
def initialize(max_length, ...)
|
117
|
+
super(...)
|
116
118
|
@max_length = max_length
|
117
119
|
end
|
118
120
|
|
data/lib/posthog/version.rb
CHANGED
data/lib/posthog.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: posthog-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ''
|
@@ -33,7 +33,6 @@ files:
|
|
33
33
|
- bin/helpers/_utils.sh
|
34
34
|
- bin/posthog
|
35
35
|
- bin/test
|
36
|
-
- lib/posthog-ruby.rb
|
37
36
|
- lib/posthog.rb
|
38
37
|
- lib/posthog/backoff_policy.rb
|
39
38
|
- lib/posthog/client.rb
|
@@ -61,7 +60,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
61
60
|
requirements:
|
62
61
|
- - ">="
|
63
62
|
- !ruby/object:Gem::Version
|
64
|
-
version: '
|
63
|
+
version: '3.0'
|
65
64
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
65
|
requirements:
|
67
66
|
- - ">="
|
data/lib/posthog-ruby.rb
DELETED