public void BlockUntilReady(int blockMilisecondsUntilReady) { if (!IsSdkReady()) { var ready = false; using (var clock = new Util.SplitStopwatch()) { clock.Start(); while (clock.ElapsedMilliseconds <= blockMilisecondsUntilReady) { if (IsSdkReady()) { ready = true; break; } Thread.Sleep(500); } if (!ready) { throw new TimeoutException($"SDK was not ready in {blockMilisecondsUntilReady}. Could not connect to Redis"); } } } }
public async Task <string> FetchSplitChanges(long since, FetchOptions fetchOptions) { using (var clock = new Util.SplitStopwatch()) { clock.Start(); try { var requestUri = GetRequestUri(since, fetchOptions.Till); var response = await ExecuteGet(requestUri, fetchOptions.CacheControlHeaders); if ((int)response.statusCode >= (int)HttpStatusCode.OK && (int)response.statusCode < (int)HttpStatusCode.Ambiguous) { _telemetryRuntimeProducer.RecordSyncLatency(ResourceEnum.SplitSync, Util.Metrics.Bucket(clock.ElapsedMilliseconds)); _telemetryRuntimeProducer.RecordSuccessfulSync(ResourceEnum.SplitSync, CurrentTimeHelper.CurrentTimeMillis()); return(response.content); } _log.Error($"Http status executing FetchSplitChanges: {response.statusCode.ToString()} - {response.content}"); _telemetryRuntimeProducer.RecordSyncError(ResourceEnum.SplitSync, (int)response.statusCode); return(string.Empty); } catch (Exception e) { _log.Error("Exception caught executing FetchSplitChanges", e); return(string.Empty); } } }
private async Task BuildJsonAndPost(List <Event> events, Util.SplitStopwatch clock) { var eventsJson = JsonConvert.SerializeObject(events, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); for (int i = 0; i < MaxAttempts; i++) { if (i > 0) { _wrapperAdapter.TaskDelay(500).Wait(); } var response = await ExecutePost(EventsUrlTemplate, eventsJson); RecordTelemetry(nameof(SendBulkEventsTask), (int)response.statusCode, response.content, ResourceEnum.EventSync, clock); if (response.statusCode >= System.Net.HttpStatusCode.OK && response.statusCode < System.Net.HttpStatusCode.Ambiguous) { _log.Debug($"Post bulk events success in {i} attempts."); return; } } _log.Debug($"Post bulk events fail after {MaxAttempts} attempts."); }
private async Task SendBulkEventsAsync(List <Event> events) { try { using (var clock = new Util.SplitStopwatch()) { clock.Start(); if (events.Count <= _maxBulkSize) { await BuildJsonAndPost(events, clock); return; } while (events.Count > 0) { var bulkToPost = Util.Helper.TakeFromList(events, _maxBulkSize); await BuildJsonAndPost(bulkToPost, clock); } } } catch (Exception ex) { _log.Error("Exception caught sending bulk of events", ex); } }
public virtual bool Track(string key, string trafficType, string eventType, double?value = null, Dictionary <string, object> properties = null) { if (_statusManager.IsDestroyed()) { return(false); } using (var clock = new Util.SplitStopwatch()) { clock.Start(); var keyResult = _keyValidator.IsValid(new Key(key, null), nameof(Track)); var eventTypeResult = _eventTypeValidator.IsValid(eventType, nameof(eventType)); var eventPropertiesResult = _eventPropertiesValidator.IsValid(properties); var trafficTypeResult = _blockUntilReadyService.IsSdkReady() ? _trafficTypeValidator.IsValid(trafficType, nameof(trafficType)) : new ValidatorResult { Success = true, Value = trafficType }; if (!keyResult || !trafficTypeResult.Success || !eventTypeResult || !eventPropertiesResult.Success) { return(false); } try { var eventToLog = new Event { key = key, trafficTypeName = trafficTypeResult.Value, eventTypeId = eventType, value = value, timestamp = CurrentTimeHelper.CurrentTimeMillis(), properties = (Dictionary <string, object>)eventPropertiesResult.Value }; _tasksManager.Start(() => { _eventsLog.Log(new WrappedEvent { Event = eventToLog, Size = eventPropertiesResult.EventSize }); }, new CancellationTokenSource(), "Track"); RecordLatency(nameof(Track), clock.ElapsedMilliseconds); return(true); } catch (Exception e) { _log.Error("Exception caught trying to track an event", e); RecordException(nameof(Track)); return(false); } } }
public async void SendBulkImpressionsCount(ConcurrentDictionary <KeyCache, int> impressionsCount) { using (var clock = new Util.SplitStopwatch()) { clock.Start(); var json = ConvertToJson(impressionsCount); var response = await ExecutePost(ImpressionsCountUrlTemplate, json); RecordTelemetry(nameof(SendBulkImpressionsCount), (int)response.statusCode, response.content, ResourceEnum.ImpressionCountSync, clock); } }
public async Task <AuthenticationResponse> AuthenticateAsync() { using (var clock = new Util.SplitStopwatch()) { clock.Start(); try { var response = await _splitioHttpClient.GetAsync(_url); if (response.statusCode == HttpStatusCode.OK) { _log.Debug($"Success connection to: {_url}"); _telemetryRuntimeProducer.RecordSyncLatency(ResourceEnum.TokenSync, Util.Metrics.Bucket(clock.ElapsedMilliseconds)); _telemetryRuntimeProducer.RecordSuccessfulSync(ResourceEnum.TokenSync, CurrentTimeHelper.CurrentTimeMillis()); return(GetSuccessResponse(response.content)); } else if (response.statusCode >= HttpStatusCode.BadRequest && response.statusCode < HttpStatusCode.InternalServerError) { _log.Debug($"Problem to connect to : {_url}. Response status: {response.statusCode}"); _telemetryRuntimeProducer.RecordAuthRejections(); return(new AuthenticationResponse { PushEnabled = false, Retry = false }); } _telemetryRuntimeProducer.RecordSyncError(ResourceEnum.TokenSync, (int)response.statusCode); return(new AuthenticationResponse { PushEnabled = false, Retry = true }); } catch (Exception ex) { _log.Error(ex.Message); return(new AuthenticationResponse { PushEnabled = false, Retry = false }); } } }
public MultipleEvaluatorResult EvaluateFeatures(Key key, List <string> featureNames, Dictionary <string, object> attributes = null) { var exception = false; var treatmentsForFeatures = new Dictionary <string, TreatmentResult>(); using (var clock = new Util.SplitStopwatch()) { clock.Start(); try { var splits = _splitCache.FetchMany(featureNames); foreach (var feature in featureNames) { var split = splits.FirstOrDefault(s => feature.Equals(s?.name)); var result = EvaluateTreatment(key, split, feature, attributes: attributes); treatmentsForFeatures.Add(feature, result); } } catch (Exception e) { _log.Error($"Exception caught getting treatments", e); foreach (var name in featureNames) { treatmentsForFeatures.Add(name, new TreatmentResult(Labels.Exception, Control, elapsedMilliseconds: clock.ElapsedMilliseconds)); } exception = true; } return(new MultipleEvaluatorResult { TreatmentResults = treatmentsForFeatures, ElapsedMilliseconds = clock.ElapsedMilliseconds, Exception = exception }); } }
public TreatmentResult EvaluateFeature(Key key, string featureName, Dictionary <string, object> attributes = null) { using (var clock = new Util.SplitStopwatch()) { clock.Start(); try { var parsedSplit = _splitCache.GetSplit(featureName); return(EvaluateTreatment(key, parsedSplit, featureName, clock, attributes)); } catch (Exception e) { _log.Error($"Exception caught getting treatment for feature: {featureName}", e); return(new TreatmentResult(Labels.Exception, Control, elapsedMilliseconds: clock.ElapsedMilliseconds, exception: true)); } } }
public async void SendBulkImpressions(List <KeyImpression> impressions) { using (var clock = new Util.SplitStopwatch()) { clock.Start(); if (impressions.Count <= _maxBulkSize) { await BuildJsonAndPost(impressions, clock); return; } while (impressions.Count > 0) { var bulkToPost = Util.Helper.TakeFromList(impressions, _maxBulkSize); await BuildJsonAndPost(bulkToPost, clock); } } }
public async Task <string> FetchSegmentChanges(string name, long since, FetchOptions fetchOptions) { using (var clock = new Util.SplitStopwatch()) { clock.Start(); try { var requestUri = GetRequestUri(name, since, fetchOptions.Till); var response = await ExecuteGet(requestUri, fetchOptions.CacheControlHeaders); if ((int)response.statusCode >= (int)HttpStatusCode.OK && (int)response.statusCode < (int)HttpStatusCode.Ambiguous) { if (_log.IsDebugEnabled) { _log.Debug($"FetchSegmentChanges with name '{name}' took {clock.ElapsedMilliseconds} milliseconds using uri '{requestUri}'"); } _telemetryRuntimeProducer.RecordSyncLatency(ResourceEnum.SegmentSync, Util.Metrics.Bucket(clock.ElapsedMilliseconds)); _telemetryRuntimeProducer.RecordSuccessfulSync(ResourceEnum.SegmentSync, CurrentTimeHelper.CurrentTimeMillis()); return(response.content); } _log.Error(response.statusCode == HttpStatusCode.Forbidden ? "factory instantiation: you passed a browser type api_key, please grab an api key from the Split console that is of type sdk" : $"Http status executing FetchSegmentChanges: {response.statusCode.ToString()} - {response.content}"); _telemetryRuntimeProducer.RecordSyncError(ResourceEnum.SegmentSync, (int)response.statusCode); return(string.Empty); } catch (Exception e) { _log.Error("Exception caught executing FetchSegmentChanges", e); return(string.Empty); } } }
private TreatmentResult EvaluateTreatment(Key key, ParsedSplit parsedSplit, string featureName, Util.SplitStopwatch clock = null, Dictionary <string, object> attributes = null) { try { if (clock == null) { clock = new Util.SplitStopwatch(); clock.Start(); } if (parsedSplit == null) { _log.Warn($"GetTreatment: you passed {featureName} that does not exist in this environment, please double check what Splits exist in the web console."); return(new TreatmentResult(Labels.SplitNotFound, Control, elapsedMilliseconds: clock.ElapsedMilliseconds)); } var treatmentResult = GetTreatmentResult(key, parsedSplit, attributes); if (parsedSplit.configurations != null && parsedSplit.configurations.ContainsKey(treatmentResult.Treatment)) { treatmentResult.Config = parsedSplit.configurations[treatmentResult.Treatment]; } treatmentResult.ElapsedMilliseconds = clock.ElapsedMilliseconds; return(treatmentResult); } catch (Exception e) { _log.Error($"Exception caught getting treatment for feature: {featureName}", e); return(new TreatmentResult(Labels.Exception, Control, elapsedMilliseconds: clock.ElapsedMilliseconds)); } finally { clock.Dispose(); } }
private async Task BuildJsonAndPost(List <KeyImpression> impressions, Util.SplitStopwatch clock) { var impressionsJson = ConvertToJson(impressions); for (int i = 0; i < MaxAttempts; i++) { if (i > 0) { _wrapperAdapter.TaskDelay(500).Wait(); } var response = await ExecutePost(TestImpressionsUrlTemplate, impressionsJson); RecordTelemetry(nameof(SendBulkImpressions), (int)response.statusCode, response.content, ResourceEnum.ImpressionSync, clock); if (response.statusCode >= System.Net.HttpStatusCode.OK && response.statusCode < System.Net.HttpStatusCode.Ambiguous) { _log.Debug($"Post bulk impressions success in {i} attempts."); return; } } _log.Debug($"Post bulk impressions fail after {MaxAttempts} attempts."); }
protected void RecordTelemetry(string method, int statusCode, string content, ResourceEnum resource, Util.SplitStopwatch clock) { if (statusCode >= (int)HttpStatusCode.OK && statusCode < (int)HttpStatusCode.Ambiguous) { _telemetryRuntimeProducer.RecordSyncLatency(resource, Util.Metrics.Bucket(clock.ElapsedMilliseconds)); _telemetryRuntimeProducer.RecordSuccessfulSync(resource, CurrentTimeHelper.CurrentTimeMillis()); } else { _log.Error($"Http status executing {method}: {statusCode.ToString()} - {content}"); _telemetryRuntimeProducer.RecordSyncError(resource, statusCode); } }