public ValidatorResult IsValid(string trafficType, string method) { if (trafficType == null) { _log.Error($"{method}: you passed a null traffic_type, traffic_type must be a non-empty string"); return(new ValidatorResult { Success = false }); } if (trafficType == string.Empty) { _log.Error($"{method}: you passed an empty traffic_type, traffic_type must be a non-empty string"); return(new ValidatorResult { Success = false }); } if (trafficType.Any(ch => char.IsUpper(ch))) { _log.Warn($"{method}: {trafficType} should be all lowercase - converting string to lowercase"); trafficType = trafficType.ToLower(); } if (!_splitCache.TrafficTypeExists(trafficType)) { _log.Warn($"Track: Traffic Type {trafficType} does not have any corresponding Splits in this environment, make sure you’re tracking your events to a valid traffic type defined in the Split console."); } return(new ValidatorResult { Success = true, Value = trafficType }); }
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); } } }
public async void StartSse() { try { var response = await _authApiClient.AuthenticateAsync(); _log.Debug($"Auth service response pushEnabled: {response.PushEnabled}."); if (response.PushEnabled.Value) { _sseHandler.Start(response.Token, response.Channels); _backOff.Reset(); ScheduleNextTokenRefresh(response.Expiration.Value); } else { StopSse(); } if (response.Retry.Value) { ScheduleNextTokenRefresh(_backOff.GetInterval()); } } catch (Exception ex) { _log.Error($"StartSse: {ex.Message}"); } }
public async Task <bool> StartSse() { try { var response = await _authApiClient.AuthenticateAsync(); _log.Debug($"Auth service response pushEnabled: {response.PushEnabled}."); if (response.PushEnabled.Value && _sseHandler.Start(response.Token, response.Channels)) { _backOff.Reset(); ScheduleNextTokenRefresh(response.Expiration.Value); _telemetryRuntimeProducer.RecordStreamingEvent(new StreamingEvent(EventTypeEnum.TokenRefresh, CalcularteNextTokenExpiration(response.Expiration.Value))); return(true); } StopSse(); if (response.Retry.Value) { ScheduleNextTokenRefresh(_backOff.GetInterval()); } else { ForceCancellationToken(); } } catch (Exception ex) { _log.Error($"StartSse: {ex.Message}"); } return(false); }
public virtual async Task <HTTPResult> ExecuteGet(string requestUri, bool cacheControlHeadersEnabled = false) { var result = new HTTPResult(); var request = new HttpRequestMessage { RequestUri = new Uri(_httpClient.BaseAddress, requestUri), Method = HttpMethod.Get }; if (cacheControlHeadersEnabled) { request.Headers.Add(Constants.Http.CacheControlKey, Constants.Http.CacheControlValue); } try { using (var response = await _httpClient.SendAsync(request)) { result.statusCode = response.StatusCode; result.content = await response.Content.ReadAsStringAsync(); } } catch (Exception e) { _log.Error(string.Format("Exception caught executing GET {0}", requestUri), e); } return(result); }
public ParsedSplit Parse(Split split) { try { var isValidStatus = Enum.TryParse(split.status, out StatusEnum result); if (!isValidStatus || result != StatusEnum.ACTIVE) { return(null); } var parsedSplit = new ParsedSplit { name = split.name, killed = split.killed, defaultTreatment = split.defaultTreatment, seed = split.seed, conditions = new List <ConditionWithLogic>(), changeNumber = split.changeNumber, trafficTypeName = split.trafficTypeName, algo = split.algo == 0 || split.algo == null ? AlgorithmEnum.LegacyHash : (AlgorithmEnum)split.algo, trafficAllocation = split.trafficAllocation, trafficAllocationSeed = split.trafficAllocationSeed ?? 0, configurations = split.configurations }; return(ParseConditions(split, parsedSplit)); } catch (Exception e) { _log.Error("Exception caught parsing split", e); return(null); } }
public List <string> SplitNamesAreValid(List <string> splitNames, string method) { if (splitNames == null) { _log.Error($"{method}: split_names must be a non-empty array"); return(splitNames); } if (!splitNames.Any()) { _log.Error($"{method}: split_names must be a non-empty array"); return(splitNames); } var dicSplits = new Dictionary <string, string>(); foreach (var name in splitNames) { var splitNameResult = SplitNameIsValid(name, method); if (splitNameResult.Success) { try { dicSplits.Add(splitNameResult.Value, splitNameResult.Value); } catch { } } } return(dicSplits.Keys.ToList()); }
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 SendCountMetrics(string metrics) { var response = await ExecutePost(MetricsUrlTemplate.Replace("{endpoint}", "counters"), metrics); if ((int)response.statusCode < (int)HttpStatusCode.OK || (int)response.statusCode >= (int)HttpStatusCode.Ambiguous) { Log.Error(string.Format("Http status executing SendCountMetrics: {0} - {1}", response.statusCode.ToString(), response.content)); } }
public async void SendBulkImpressions(List <KeyImpression> impressions) { var impressionsJson = ConvertToJson(impressions); var response = await ExecutePost(TestImpressionsUrlTemplate, impressionsJson); if ((int)response.statusCode < (int)HttpStatusCode.OK || (int)response.statusCode >= (int)HttpStatusCode.Ambiguous) { Log.Error(string.Format("Http status executing SendBulkImpressions: {0} - {1}", response.statusCode.ToString(), response.content)); } }
public void Validate(string apiKey) { if (apiKey == string.Empty) { _log.Error("factory instantiation: you passed and empty api_key, api_key must be a non-empty string."); } if (apiKey == null) { _log.Error("factory instantiation: you passed a null api_key, api_key must be a non-empty string."); } }
public void Count(string counter, long delta) { try { var task = new Task(() => worker.Count(counter, delta)); task.Start(); } catch (Exception e) { Logger.Error("Exception running count metrics task", e); } }
private string ConvertCountMetricsToJson(Dictionary <string, Counter> countMetrics) { try { return(JsonConvert.SerializeObject(countMetrics.Select(x => new { name = x.Key, delta = x.Value.GetDelta() }))); } catch (Exception e) { Logger.Error("Exception ocurred serializing count metrics", e); return(string.Empty); } }
public virtual bool Track(string key, string trafficType, string eventType, double?value = null, Dictionary <string, object> properties = null) { if (Destroyed) { return(false); } 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 }; Task.Factory.StartNew(() => { _eventsLog.Log(new WrappedEvent { Event = eventToLog, Size = eventPropertiesResult.EventSize }); }); return(true); } catch (Exception e) { _log.Error("Exception caught trying to track an event", e); return(false); } }
public async Task <string> FetchSegmentChanges(string name, long since) { var clock = new Stopwatch(); clock.Start(); try { var requestUri = GetRequestUri(name, since); var response = await ExecuteGet(requestUri); if ((int)response.statusCode >= (int)HttpStatusCode.OK && (int)response.statusCode < (int)HttpStatusCode.Ambiguous) { if (_metricsLog != null) { _metricsLog.Time(SegmentFetcherTime, clock.ElapsedMilliseconds); _metricsLog.Count(string.Format(SegmentFetcherStatus, response.statusCode), 1); } if (_log.IsDebugEnabled) { _log.Debug($"FetchSegmentChanges with name '{name}' took {clock.ElapsedMilliseconds} milliseconds using uri '{requestUri}'"); } return(response.content); } if (_metricsLog != null) { _metricsLog.Count(string.Format(SegmentFetcherStatus, response.statusCode), 1); } _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" : string.Format("Http status executing FetchSegmentChanges: {0} - {1}", response.statusCode.ToString(), response.content)); return(string.Empty); } catch (Exception e) { _log.Error("Exception caught executing FetchSegmentChanges", e); if (_metricsLog != null) { _metricsLog.Count(SegmentFetcherException, 1); } return(string.Empty); } }
private async Task ConnectAsync() { try { UpdateFinishedConnection(finished: false); _splitHttpClient = new SplitioHttpClient(new Dictionary <string, string> { { "Accept", "text/event-stream" } }); _cancellationTokenSource = new CancellationTokenSource(); using (var response = await _splitHttpClient.GetAsync(_url, HttpCompletionOption.ResponseHeadersRead, _cancellationTokenSource.Token)) { _log.Debug($"Response from {_url}: {response.StatusCode}"); if (response.IsSuccessStatusCode) { try { using (var stream = await response.Content.ReadAsStreamAsync()) { _log.Info($"Connected to {_url}"); UpdateStatus(connected: true); DispatchConnected(); await ReadStreamAsync(stream); } } catch (Exception ex) { _log.Error($"Error reading stream: {ex.Message}"); Disconnect(reconnect: true); return; } } } } catch (Exception ex) { _log.Error($"Error connecting to {_url}: {ex.Message}"); } finally { UpdateFinishedConnection(finished: true); } _log.Debug("Finished Event Source client ConnectAsync."); Disconnect(); }
public void AddToQueue(long changeNumber) { try { if (_queue != null) { _log.Debug($"Add to queue: {changeNumber}"); _queue.TryAdd(changeNumber); } } catch (Exception ex) { _log.Error($"AddToQueue: {ex.Message}"); } }
public async Task <AuthenticationResponse> AuthenticateAsync() { try { var response = await _splitioHttpClient.GetAsync(_url); if (response.statusCode == HttpStatusCode.OK) { _log.Debug($"Success connection to: {_url}"); 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}"); return(new AuthenticationResponse { PushEnabled = false, Retry = false }); } return(new AuthenticationResponse { PushEnabled = false, Retry = true }); } catch (Exception ex) { _log.Error(ex.Message); return(new AuthenticationResponse { PushEnabled = false, Retry = false }); } }
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); } }
private void SendBulkEvents() { if (_wrappedEventsCache.HasReachedMaxSize()) { Logger.Warn("Split SDK events queue is full. Events may have been dropped. Consider increasing capacity."); } var wrappedEvents = _wrappedEventsCache.FetchAllAndClear(); if (wrappedEvents.Count > 0) { try { var events = wrappedEvents .Select(x => x.Event) .ToList(); _apiClient.SendBulkEvents(events); _acumulateSize = 0; } catch (Exception e) { Logger.Error("Exception caught updating events.", e); } } }
private void ProcessEventControl(IncomingNotification notification) { var controlEvent = (ControlNotification)notification; switch (controlEvent.ControlType) { case ControlType.STREAMING_PAUSED: DispatchOccupancyEvent(publisherAvailable: false); break; case ControlType.STREAMING_RESUMED: if (IsPublisherAvailable()) { DispatchOccupancyEvent(publisherAvailable: true); } break; case ControlType.STREAMING_DISABLED: DispatchPushShutdown(); break; default: _log.Error($"Incorrect control type. {controlEvent.ControlType}"); break; } }
public void Proccess(IncomingNotification notification) { try { switch (notification.Type) { case NotificationType.SPLIT_UPDATE: var scn = (SplitChangeNotifiaction)notification; _splitsWorker.AddToQueue(scn.ChangeNumber); break; case NotificationType.SPLIT_KILL: var skn = (SplitKillNotification)notification; _splitsWorker.KillSplit(skn.ChangeNumber, skn.SplitName, skn.DefaultTreatment); _splitsWorker.AddToQueue(skn.ChangeNumber); break; case NotificationType.SEGMENT_UPDATE: var sc = (SegmentChangeNotification)notification; _segmentsWorker.AddToQueue(sc.ChangeNumber, sc.SegmentName); break; default: _log.Debug($"Incorrect Event type: {notification}"); break; } } catch (Exception ex) { _log.Error($"Processor: {ex.Message}"); } }
public async Task <bool> FetchSegment(FetchOptions fetchOptions) { var success = false; while (true) { var changeNumber = _segmentCache.GetChangeNumber(Name); try { var response = await _segmentChangeFetcher.Fetch(Name, changeNumber, fetchOptions); if (response == null) { break; } if (changeNumber >= response.till) { success = true; break; } if (response.added.Count() > 0 || response.removed.Count() > 0) { _segmentCache.AddToSegment(Name, response.added); _segmentCache.RemoveFromSegment(Name, response.removed); if (_log.IsDebugEnabled) { if (response.added.Count() > 0) { _log.Debug($"Segment {Name} - Added : {string.Join(" - ", response.added)}"); } if (response.removed.Count() > 0) { _log.Debug($"Segment {Name} - Removed : {string.Join(" - ", response.removed)}"); } } } _segmentCache.SetChangeNumber(Name, response.till); } catch (Exception e) { _log.Error("Exception caught refreshing segment", e); } finally { if (_log.IsDebugEnabled) { _log.Debug($"segment {Name} fetch before: {changeNumber}, after: {_segmentCache.GetChangeNumber(Name)}"); } } } return(success); }
public void AddToQueue(long changeNumber, string segmentName) { try { if (_queue != null) { _log.Debug($"Add to queue: {segmentName} - {changeNumber}"); _queue.TryAdd(new SegmentQueueDto { ChangeNumber = changeNumber, SegmentName = segmentName }); } } catch (Exception ex) { _log.Error($"AddToQueue: {ex.Message}"); } }
public void HandleIncomingEvent(IncomingNotification notification) { switch (notification.Type) { case NotificationType.CONTROL: ProcessEventControl(notification); break; case NotificationType.OCCUPANCY: ProcessEventOccupancy(notification); break; default: _log.Error($"Incorrect notification type: {notification.Type}"); break; } }
private void RecordInit() { try { var config = new Config { BURTimeouts = _telemetryStorageConsumer.GetBURTimeouts(), EventsQueueSize = _configurationOptions.EventLogSize, Rates = new Rates { Events = _configurationOptions.EventLogRefreshRate, Impressions = _configurationOptions.TreatmentLogRefreshRate, Segments = _configurationOptions.SegmentRefreshRate, Splits = _configurationOptions.SplitsRefreshRate, Telemetry = _configurationOptions.TelemetryRefreshRate }, UrlOverrides = new UrlOverrides { Sdk = !_configurationOptions.BaseUrl.Equals(Constants.Urls.BaseUrl), Events = !_configurationOptions.EventsBaseUrl.Equals(Constants.Urls.EventsBaseUrl), Auth = !_configurationOptions.AuthServiceURL.Equals(Constants.Urls.AuthServiceURL), Stream = !_configurationOptions.StreamingServiceURL.Equals(Constants.Urls.StreamingServiceURL), Telemetry = !_configurationOptions.TelemetryServiceURL.Equals(Constants.Urls.TelemetryServiceURL) }, StreamingEnabled = _configurationOptions.StreamingEnabled, ImpressionsMode = _configurationOptions.ImpressionsMode, ImpressionListenerEnabled = _configurationOptions.ImpressionListener != null, OperationMode = (int)_configurationOptions.Mode, ImpressionsQueueSize = _configurationOptions.TreatmentLogSize, Tags = _telemetryStorageConsumer.PopTags().ToList(), TimeUntilSDKReady = CurrentTimeHelper.CurrentTimeMillis() - _configurationOptions.SdkStartTime, ActiveFactories = _factoryInstantiationsService.GetActiveFactories(), RedundantActiveFactories = _factoryInstantiationsService.GetRedundantActiveFactories(), Storage = Constants.StorageType.Memory, SDKNotReadyUsage = _telemetryStorageConsumer.GetNonReadyUsages(), HTTPProxyDetected = IsHTTPProxyDetected() }; _telemetryAPI.RecordConfigInit(config); } catch (Exception ex) { _log.Error("Something were wrong posting Config.", ex); } }
public async Task <string> FetchSplitChanges(long since) { var clock = new Stopwatch(); clock.Start(); try { var requestUri = GetRequestUri(since); var response = await ExecuteGet(requestUri); if ((int)response.statusCode >= (int)HttpStatusCode.OK && (int)response.statusCode < (int)HttpStatusCode.Ambiguous) { if (_metricsLog != null) { _metricsLog.Time(SplitFetcherTime, clock.ElapsedMilliseconds); _metricsLog.Count(string.Format(SplitFetcherStatus, response.statusCode), 1); } return(response.content); } else { _log.Error(string.Format("Http status executing FetchSplitChanges: {0} - {1}", response.statusCode.ToString(), response.content)); if (_metricsLog != null) { _metricsLog.Count(string.Format(SplitFetcherStatus, response.statusCode), 1); } return(string.Empty); } } catch (Exception e) { _log.Error("Exception caught executing FetchSplitChanges", e); if (_metricsLog != null) { _metricsLog.Count(SplitFetcherException, 1); } return(string.Empty); } }
public void SetChangeNumber(long changeNumber) { if (changeNumber < _changeNumber) { Log.Error("ChangeNumber for splits cache is less than previous"); } _changeNumber = changeNumber; }
public void AddToQueue(long changeNumber) { try { if (!_running) { _log.Debug("Splits Worker not running."); return; } _log.Debug($"Add to queue: {changeNumber}"); _queue.TryAdd(changeNumber); } catch (Exception ex) { _log.Error($"AddToQueue: {ex.Message}"); } }
public async void RefreshSegment() { while (true) { var changeNumber = segmentCache.GetChangeNumber(name); try { var response = await segmentChangeFetcher.Fetch(name, changeNumber); if (response == null) { break; } if (changeNumber >= response.till) { gates.SegmentIsReady(name); break; } if (response.added.Count() > 0 || response.removed.Count() > 0) { segmentCache.AddToSegment(name, response.added); segmentCache.RemoveFromSegment(name, response.removed); if (response.added.Count() > 0) { if (Log.IsDebugEnabled) { Log.Debug(string.Format("Segment {0} - Added : {1}", name, string.Join(" - ", response.added))); } } if (response.removed.Count() > 0) { if (Log.IsDebugEnabled) { Log.Debug(string.Format("Segment {0} - Removed : {1}", name, string.Join(" - ", response.removed))); } } } segmentCache.SetChangeNumber(name, response.till); } catch (Exception e) { Log.Error("Exception caught refreshing segment", e); } finally { if (Log.IsDebugEnabled) { Log.Debug(string.Format("segment {0} fetch before: {1}, after: {2}", name, changeNumber, segmentCache.GetChangeNumber(name))); } } } }