@@ -193,9 +193,11 @@ def get_feature_flag(
193193
194194 request_id = nil
195195 evaluated_at = nil
196+ feature_flag_error = nil
196197
197198 if !flag_was_locally_evaluated && !only_evaluate_locally
198199 begin
200+ errors = [ ]
199201 flags_data = get_all_flags_and_payloads ( distinct_id , groups , person_properties , group_properties ,
200202 only_evaluate_locally , true )
201203 if flags_data . key? ( :featureFlags )
@@ -205,17 +207,44 @@ def get_feature_flag(
205207 else
206208 logger . debug "Missing feature flags key: #{ flags_data . to_json } "
207209 flags = { }
210+ errors << FeatureFlagError ::UNKNOWN_ERROR
211+ end
212+
213+ status = flags_data [ :status ]
214+ if status && status >= 400
215+ errors << FeatureFlagError . api_error ( status )
216+ end
217+
218+ if flags_data [ :errorsWhileComputingFlags ]
219+ errors << FeatureFlagError ::ERRORS_WHILE_COMPUTING
220+ end
221+
222+ if flags_data [ :quotaLimited ] &.include? ( 'feature_flags' )
223+ errors << FeatureFlagError ::QUOTA_LIMITED
224+ end
225+
226+ unless flags . key? ( key . to_s )
227+ errors << FeatureFlagError ::FLAG_MISSING
208228 end
209229
210230 response = flags [ key ]
211231 response = false if response . nil?
232+ feature_flag_error = errors . join ( ',' ) unless errors . empty?
233+
212234 logger . debug "Successfully computed flag remotely: #{ key } -> #{ response } "
235+ rescue Timeout ::Error , Net ::ReadTimeout , Net ::WriteTimeout
236+ @on_error . call ( -1 , 'Timeout while fetching flags remotely' )
237+ feature_flag_error = FeatureFlagError ::TIMEOUT
238+ rescue Errno ::ECONNRESET , Errno ::ECONNREFUSED , EOFError , SocketError => e
239+ @on_error . call ( -1 , "Connection error while fetching flags remotely: #{ e } " )
240+ feature_flag_error = FeatureFlagError ::CONNECTION_ERROR
213241 rescue StandardError => e
214242 @on_error . call ( -1 , "Error computing flag remotely: #{ e } . #{ e . backtrace . join ( "\n " ) } " )
243+ feature_flag_error = FeatureFlagError ::UNKNOWN_ERROR
215244 end
216245 end
217246
218- [ response , flag_was_locally_evaluated , request_id , evaluated_at ]
247+ [ response , flag_was_locally_evaluated , request_id , evaluated_at , feature_flag_error ]
219248 end
220249
221250 def get_all_flags (
@@ -270,19 +299,26 @@ def get_all_flags_and_payloads(
270299 fallback_to_server = true
271300 end
272301
302+ errors_while_computing = false
303+ quota_limited = nil
304+ status_code = nil
305+
273306 if fallback_to_server && !only_evaluate_locally
274307 begin
275308 flags_and_payloads = get_flags ( distinct_id , groups , person_properties , group_properties )
309+ errors_while_computing = flags_and_payloads [ :errorsWhileComputingFlags ] || false
310+ quota_limited = flags_and_payloads [ :quotaLimited ]
311+ status_code = flags_and_payloads [ :status ]
276312
277313 unless flags_and_payloads . key? ( :featureFlags )
278314 raise StandardError , "Error flags response: #{ flags_and_payloads } "
279- end
280-
281315 # Check if feature_flags are quota limited
282- if flags_and_payloads [ :quotaLimited ] &.include? ( 'feature_flags' )
316+ if quota_limited &.include? ( 'feature_flags' )
283317 logger . warn '[FEATURE FLAGS] Quota limited for feature flags'
284318 flags = { }
285319 payloads = { }
320+ request_id = flags_and_payloads [ :requestId ]
321+ evaluated_at = flags_and_payloads [ :evaluatedAt ]
286322 else
287323 flags = stringify_keys ( flags_and_payloads [ :featureFlags ] || { } )
288324 payloads = stringify_keys ( flags_and_payloads [ :featureFlagPayloads ] || { } )
@@ -299,7 +335,10 @@ def get_all_flags_and_payloads(
299335 featureFlags : flags ,
300336 featureFlagPayloads : payloads ,
301337 requestId : request_id ,
302- evaluatedAt : evaluated_at
338+ evaluatedAt : evaluated_at ,
339+ errorsWhileComputingFlags : errors_while_computing ,
340+ quotaLimited : quota_limited ,
341+ status : status_code
303342 }
304343 end
305344
0 commit comments