posthog-ruby 2.7.2 → 2.8.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/helpers/_utils.sh +15 -0
- data/bin/test +7 -0
- data/lib/posthog/client.rb +9 -3
- data/lib/posthog/feature_flag.rb +61 -0
- data/lib/posthog/feature_flags.rb +38 -6
- data/lib/posthog/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 403175c4385fd299bfb3288ec55ea218b5108efba7a2096574be5d57db3ad828
|
4
|
+
data.tar.gz: 31283de954af3bc6624c90ea5975df2451c901bd8a198f782938d74e73f7d6a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c566381334794edd10f75f20b28fc804cb18f950cb02e8fd381b39f7453b83af372c642e9fea14c17e204c50141ed49cf4a4e3d15057e6878d3460471b7a9ed
|
7
|
+
data.tar.gz: 761aba06f50b414406abfd8a40b00403e8002184406b13fbd1c728e03fb3379a995864da24931fd0bd6bb7227be07b1850eb88cce81fd54321d0bb1014d231cc
|
@@ -0,0 +1,15 @@
|
|
1
|
+
error() {
|
2
|
+
echo "$@" >&2
|
3
|
+
}
|
4
|
+
|
5
|
+
fatal() {
|
6
|
+
error "$@"
|
7
|
+
exit 1
|
8
|
+
}
|
9
|
+
|
10
|
+
set_source_and_root_dir() {
|
11
|
+
{ set +x; } 2>/dev/null
|
12
|
+
source_dir="$( cd -P "$( dirname "$0" )" >/dev/null 2>&1 && pwd )"
|
13
|
+
root_dir=$(cd $source_dir && cd ../ && pwd)
|
14
|
+
cd $root_dir
|
15
|
+
}
|
data/bin/test
ADDED
data/lib/posthog/client.rb
CHANGED
@@ -183,7 +183,7 @@ class PostHog
|
|
183
183
|
# ```
|
184
184
|
def get_feature_flag(key, distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false, send_feature_flag_events: true)
|
185
185
|
person_properties, group_properties = add_local_person_and_group_properties(distinct_id, groups, person_properties, group_properties)
|
186
|
-
feature_flag_response, flag_was_locally_evaluated = @feature_flags_poller.get_feature_flag(key, distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
|
186
|
+
feature_flag_response, flag_was_locally_evaluated, request_id = @feature_flags_poller.get_feature_flag(key, distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
|
187
187
|
|
188
188
|
feature_flag_reported_key = "#{key}_#{feature_flag_response}"
|
189
189
|
if !@distinct_id_has_sent_flag_calls[distinct_id].include?(feature_flag_reported_key) && send_feature_flag_events
|
@@ -195,7 +195,7 @@ class PostHog
|
|
195
195
|
'$feature_flag' => key,
|
196
196
|
'$feature_flag_response' => feature_flag_response,
|
197
197
|
'locally_evaluated' => flag_was_locally_evaluated
|
198
|
-
},
|
198
|
+
}.merge(request_id ? {'$feature_flag_request_id' => request_id} : {}),
|
199
199
|
'groups': groups,
|
200
200
|
}
|
201
201
|
)
|
@@ -233,6 +233,10 @@ class PostHog
|
|
233
233
|
end
|
234
234
|
|
235
235
|
# Returns all flags and payloads for a given user
|
236
|
+
#
|
237
|
+
# @return [Hash] A hash with the following keys:
|
238
|
+
# featureFlags: A hash of feature flags
|
239
|
+
# featureFlagPayloads: A hash of feature flag payloads
|
236
240
|
#
|
237
241
|
# @param [String] distinct_id The distinct id of the user
|
238
242
|
# @option [Hash] groups
|
@@ -242,7 +246,9 @@ class PostHog
|
|
242
246
|
#
|
243
247
|
def get_all_flags_and_payloads(distinct_id, groups: {}, person_properties: {}, group_properties: {}, only_evaluate_locally: false)
|
244
248
|
person_properties, group_properties = add_local_person_and_group_properties(distinct_id, groups, person_properties, group_properties)
|
245
|
-
@feature_flags_poller.get_all_flags_and_payloads(distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
|
249
|
+
response = @feature_flags_poller.get_all_flags_and_payloads(distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
|
250
|
+
response.delete(:requestId) # remove internal information.
|
251
|
+
response
|
246
252
|
end
|
247
253
|
|
248
254
|
def reload_feature_flags
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Represents a feature flag returned by /decide v4
|
2
|
+
class FeatureFlag
|
3
|
+
attr_reader :key, :enabled, :variant, :reason, :metadata
|
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
|
13
|
+
|
14
|
+
def get_value
|
15
|
+
@variant || @enabled
|
16
|
+
end
|
17
|
+
|
18
|
+
def payload
|
19
|
+
@metadata&.payload
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_value_and_payload(key, value, payload)
|
23
|
+
new({
|
24
|
+
"key" => key,
|
25
|
+
"enabled" => value.is_a?(String) ? true : value,
|
26
|
+
"variant" => value.is_a?(String) ? value : nil,
|
27
|
+
"reason" => nil,
|
28
|
+
"metadata" => {
|
29
|
+
"id" => nil,
|
30
|
+
"version" => nil,
|
31
|
+
"payload" => payload,
|
32
|
+
"description" => nil
|
33
|
+
}
|
34
|
+
})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Represents the reason why a flag was enabled/disabled
|
39
|
+
class EvaluationReason
|
40
|
+
attr_reader :code, :description, :condition_index
|
41
|
+
|
42
|
+
def initialize(json)
|
43
|
+
json.transform_keys!(&:to_s)
|
44
|
+
@code = json["code"]
|
45
|
+
@description = json["description"]
|
46
|
+
@condition_index = json["condition_index"]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Represents metadata about a feature flag
|
51
|
+
class FeatureFlagMetadata
|
52
|
+
attr_reader :id, :version, :payload, :description
|
53
|
+
|
54
|
+
def initialize(json)
|
55
|
+
json.transform_keys!(&:to_s)
|
56
|
+
@id = json["id"]
|
57
|
+
@version = json["version"]
|
58
|
+
@payload = json["payload"]
|
59
|
+
@description = json["description"]
|
60
|
+
end
|
61
|
+
end
|
@@ -3,6 +3,7 @@ require 'net/http'
|
|
3
3
|
require 'json'
|
4
4
|
require 'posthog/version'
|
5
5
|
require 'posthog/logging'
|
6
|
+
require 'posthog/feature_flag'
|
6
7
|
require 'digest'
|
7
8
|
|
8
9
|
class PostHog
|
@@ -77,7 +78,26 @@ class PostHog
|
|
77
78
|
"group_properties": group_properties,
|
78
79
|
}
|
79
80
|
|
80
|
-
|
81
|
+
decide_response = _request_feature_flag_evaluation(request_data)
|
82
|
+
|
83
|
+
# Only normalize if we have flags in the response
|
84
|
+
if decide_response[:flags]
|
85
|
+
#v4 format
|
86
|
+
flags_hash = decide_response[:flags].transform_values do |flag|
|
87
|
+
FeatureFlag.new(flag)
|
88
|
+
end
|
89
|
+
decide_response[:flags] = flags_hash
|
90
|
+
decide_response[:featureFlags] = flags_hash.transform_values(&:get_value).transform_keys(&:to_sym)
|
91
|
+
decide_response[:featureFlagPayloads] = flags_hash.transform_values(&:payload).transform_keys(&:to_sym)
|
92
|
+
elsif decide_response[:featureFlags]
|
93
|
+
#v3 format
|
94
|
+
decide_response[:featureFlags] = decide_response[:featureFlags] || {}
|
95
|
+
decide_response[:featureFlagPayloads] = decide_response[:featureFlagPayloads] || {}
|
96
|
+
decide_response[:flags] = decide_response[:featureFlags].map do |key, value|
|
97
|
+
[key, FeatureFlag.from_value_and_payload(key, value, decide_response[:featureFlagPayloads][key])]
|
98
|
+
end.to_h
|
99
|
+
end
|
100
|
+
decide_response
|
81
101
|
end
|
82
102
|
|
83
103
|
def get_remote_config_payload(flag_key)
|
@@ -119,9 +139,19 @@ class PostHog
|
|
119
139
|
|
120
140
|
flag_was_locally_evaluated = !response.nil?
|
121
141
|
|
142
|
+
request_id = nil
|
143
|
+
|
122
144
|
if !flag_was_locally_evaluated && !only_evaluate_locally
|
123
145
|
begin
|
124
|
-
|
146
|
+
decide_data = get_all_flags_and_payloads(distinct_id, groups, person_properties, group_properties, false, true)
|
147
|
+
if !decide_data.key?(:featureFlags)
|
148
|
+
logger.debug "Missing feature flags key: #{decide_data.to_json}"
|
149
|
+
flags = {}
|
150
|
+
else
|
151
|
+
flags = stringify_keys(decide_data[:featureFlags] || {})
|
152
|
+
request_id = decide_data[:requestId]
|
153
|
+
end
|
154
|
+
|
125
155
|
response = flags[key]
|
126
156
|
if response.nil?
|
127
157
|
response = false
|
@@ -132,7 +162,7 @@ class PostHog
|
|
132
162
|
end
|
133
163
|
end
|
134
164
|
|
135
|
-
[response, flag_was_locally_evaluated]
|
165
|
+
[response, flag_was_locally_evaluated, request_id]
|
136
166
|
end
|
137
167
|
|
138
168
|
def get_all_flags(distinct_id, groups = {}, person_properties = {}, group_properties = {}, only_evaluate_locally = false)
|
@@ -142,7 +172,7 @@ class PostHog
|
|
142
172
|
end
|
143
173
|
# returns a string hash of all flags
|
144
174
|
response = get_all_flags_and_payloads(distinct_id, groups, person_properties, group_properties, only_evaluate_locally)
|
145
|
-
|
175
|
+
response[:featureFlags]
|
146
176
|
end
|
147
177
|
|
148
178
|
def get_all_flags_and_payloads(distinct_id, groups = {}, person_properties = {}, group_properties = {}, only_evaluate_locally = false, raise_on_error = false)
|
@@ -151,6 +181,7 @@ class PostHog
|
|
151
181
|
flags = {}
|
152
182
|
payloads = {}
|
153
183
|
fallback_to_decide = @feature_flags.empty?
|
184
|
+
request_id = nil # Only for /decide requests
|
154
185
|
|
155
186
|
@feature_flags.each do |flag|
|
156
187
|
begin
|
@@ -183,13 +214,14 @@ class PostHog
|
|
183
214
|
else
|
184
215
|
flags = stringify_keys(flags_and_payloads[:featureFlags] || {})
|
185
216
|
payloads = stringify_keys(flags_and_payloads[:featureFlagPayloads] || {})
|
217
|
+
request_id = flags_and_payloads[:requestId]
|
186
218
|
end
|
187
219
|
rescue StandardError => e
|
188
220
|
@on_error.call(-1, "Error computing flag remotely: #{e}")
|
189
221
|
raise if raise_on_error
|
190
222
|
end
|
191
223
|
end
|
192
|
-
{"featureFlags": flags, "featureFlagPayloads": payloads}
|
224
|
+
{"featureFlags": flags, "featureFlagPayloads": payloads, "requestId": request_id}
|
193
225
|
end
|
194
226
|
|
195
227
|
def get_feature_flag_payload(key, distinct_id, match_value = nil, groups = {}, person_properties = {}, group_properties = {}, only_evaluate_locally = false)
|
@@ -534,7 +566,7 @@ class PostHog
|
|
534
566
|
end
|
535
567
|
|
536
568
|
def _request_feature_flag_evaluation(data={})
|
537
|
-
uri = URI("#{@host}/decide/?v=
|
569
|
+
uri = URI("#{@host}/decide/?v=4")
|
538
570
|
req = Net::HTTP::Post.new(uri)
|
539
571
|
req['Content-Type'] = 'application/json'
|
540
572
|
data['token'] = @project_api_key
|
data/lib/posthog/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: posthog-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ''
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date: 2025-
|
10
|
+
date: 2025-04-07 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: concurrent-ruby
|
@@ -143,12 +142,15 @@ executables:
|
|
143
142
|
extensions: []
|
144
143
|
extra_rdoc_files: []
|
145
144
|
files:
|
145
|
+
- bin/helpers/_utils.sh
|
146
146
|
- bin/posthog
|
147
|
+
- bin/test
|
147
148
|
- lib/posthog-ruby.rb
|
148
149
|
- lib/posthog.rb
|
149
150
|
- lib/posthog/backoff_policy.rb
|
150
151
|
- lib/posthog/client.rb
|
151
152
|
- lib/posthog/defaults.rb
|
153
|
+
- lib/posthog/feature_flag.rb
|
152
154
|
- lib/posthog/feature_flags.rb
|
153
155
|
- lib/posthog/field_parser.rb
|
154
156
|
- lib/posthog/logging.rb
|
@@ -163,7 +165,6 @@ homepage: https://github.com/PostHog/posthog-ruby
|
|
163
165
|
licenses:
|
164
166
|
- MIT
|
165
167
|
metadata: {}
|
166
|
-
post_install_message:
|
167
168
|
rdoc_options: []
|
168
169
|
require_paths:
|
169
170
|
- lib
|
@@ -178,8 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
179
|
- !ruby/object:Gem::Version
|
179
180
|
version: '0'
|
180
181
|
requirements: []
|
181
|
-
rubygems_version: 3.
|
182
|
-
signing_key:
|
182
|
+
rubygems_version: 3.6.6
|
183
183
|
specification_version: 4
|
184
184
|
summary: PostHog library
|
185
185
|
test_files: []
|