https://mattermost.atlassian.net/browse/MM-34932

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2021-06-03 12:59:05 +05:30
коммит произвёл GitHub
родитель fff09bf210
Коммит 3299a72adb
776 изменённых файлов: 40081 добавлений и 44702 удалений

115
vendor/github.com/splitio/go-client/v6/splitio/client/client.go сгенерированный поставляемый
Просмотреть файл

@@ -12,21 +12,30 @@ import (
"github.com/splitio/go-split-commons/v3/dtos"
"github.com/splitio/go-split-commons/v3/provisional"
"github.com/splitio/go-split-commons/v3/storage"
"github.com/splitio/go-split-commons/v3/util"
"github.com/splitio/go-split-commons/v3/telemetry"
"github.com/splitio/go-toolkit/v4/logging"
)
const (
treatment = "Treatment"
treatments = "Treatments"
treatmentWithConfig = "TreatmentWithConfig"
treatmentsWithConfig = "TreatmentsWithConfig"
)
// SplitClient is the entry-point of the split SDK.
type SplitClient struct {
logger logging.LoggerInterface
evaluator evaluator.Interface
impressions storage.ImpressionStorageProducer
metrics storage.MetricsStorageProducer
events storage.EventStorageProducer
validator inputValidation
factory *SplitFactory
impressionListener *impressionlistener.WrapperImpressionListener
impressionManager provisional.ImpressionManager
logger logging.LoggerInterface
evaluator evaluator.Interface
impressions storage.ImpressionStorageProducer
events storage.EventStorageProducer
validator inputValidation
factory *SplitFactory
impressionListener *impressionlistener.WrapperImpressionListener
impressionManager provisional.ImpressionManager
initTelemetry storage.TelemetryConfigProducer
evaluationTelemetry storage.TelemetryEvaluationProducer
runtimeTelemetry storage.TelemetryRuntimeProducer
}
// TreatmentResult struct that includes the Treatment evaluation with the corresponding Config
@@ -36,17 +45,12 @@ type TreatmentResult struct {
}
// getEvaluationResult calls evaluation for one particular split
func (c *SplitClient) getEvaluationResult(
matchingKey string,
bucketingKey *string,
feature string,
attributes map[string]interface{},
operation string,
) *evaluator.Result {
func (c *SplitClient) getEvaluationResult(matchingKey string, bucketingKey *string, feature string, attributes map[string]interface{}, operation string) *evaluator.Result {
if c.isReady() {
return c.evaluator.EvaluateFeature(matchingKey, bucketingKey, feature, attributes)
}
c.logger.Warning(operation + ": the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method")
c.initTelemetry.RecordNonReadyUsage()
return &evaluator.Result{
Treatment: evaluator.Control,
Label: impressionlabels.ClientNotReady,
@@ -55,17 +59,12 @@ func (c *SplitClient) getEvaluationResult(
}
// getEvaluationsResult calls evaluation for multiple treatments at once
func (c *SplitClient) getEvaluationsResult(
matchingKey string,
bucketingKey *string,
features []string,
attributes map[string]interface{},
operation string,
) evaluator.Results {
func (c *SplitClient) getEvaluationsResult(matchingKey string, bucketingKey *string, features []string, attributes map[string]interface{}, operation string) evaluator.Results {
if c.isReady() {
return c.evaluator.EvaluateFeatures(matchingKey, bucketingKey, features, attributes)
}
c.logger.Warning(operation + ": the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method")
c.initTelemetry.RecordNonReadyUsage()
result := evaluator.Results{
EvaluationTimeNs: 0,
Evaluations: make(map[string]evaluator.Result),
@@ -81,14 +80,7 @@ func (c *SplitClient) getEvaluationsResult(
}
// createImpression creates impression to be stored and used by listener
func (c *SplitClient) createImpression(
feature string,
bucketingKey *string,
evaluationLabel string,
matchingKey string,
treatment string,
changeNumber int64,
) dtos.Impression {
func (c *SplitClient) createImpression(feature string, bucketingKey *string, evaluationLabel string, matchingKey string, treatment string, changeNumber int64) dtos.Impression {
var label string
if c.factory.cfg.LabelsEnabled {
label = evaluationLabel
@@ -126,23 +118,11 @@ func (c *SplitClient) storeData(impressions []dtos.Impression, attributes map[st
}
// Store latency
if c.metrics != nil {
bucket := util.Bucket(evaluationTimeNs)
c.metrics.IncLatency(metricsLabel, bucket)
} else {
c.logger.Warning("No metrics storage set in client. Not sending latencies!")
}
c.evaluationTelemetry.RecordLatency(metricsLabel, int64(telemetry.Bucket(evaluationTimeNs)))
}
// doTreatmentCall retrieves treatments of an specific feature with configurations object if it is present
// for a certain key and set of attributes
func (c *SplitClient) doTreatmentCall(
key interface{},
feature string,
attributes map[string]interface{},
operation string,
metricsLabel string,
) (t TreatmentResult) {
// doTreatmentCall retrieves treatments of an specific feature with configurations object if it is present for a certain key and set of attributes
func (c *SplitClient) doTreatmentCall(key interface{}, feature string, attributes map[string]interface{}, operation string, metricsLabel string) (t TreatmentResult) {
controlTreatment := TreatmentResult{
Treatment: evaluator.Control,
Config: nil,
@@ -153,6 +133,7 @@ func (c *SplitClient) doTreatmentCall(
if r := recover(); r != nil {
// At this point we'll only trust that the logger isn't panicking trust
// that the logger isn't panicking
c.evaluationTelemetry.RecordException(metricsLabel)
c.logger.Error(
"SDK is panicking with the following error", r, "\n",
string(debug.Stack()), "\n",
@@ -200,13 +181,13 @@ func (c *SplitClient) doTreatmentCall(
// Treatment implements the main functionality of split. Retrieve treatments of a specific feature
// for a certain key and set of attributes
func (c *SplitClient) Treatment(key interface{}, feature string, attributes map[string]interface{}) string {
return c.doTreatmentCall(key, feature, attributes, "Treatment", "sdk.getTreatment").Treatment
return c.doTreatmentCall(key, feature, attributes, treatment, telemetry.Treatment).Treatment
}
// TreatmentWithConfig implements the main functionality of split. Retrieves the treatment of a specific feature with
// the corresponding configuration if it is present
func (c *SplitClient) TreatmentWithConfig(key interface{}, feature string, attributes map[string]interface{}) TreatmentResult {
return c.doTreatmentCall(key, feature, attributes, "TreatmentWithConfig", "sdk.getTreatmentWithConfig")
return c.doTreatmentCall(key, feature, attributes, treatmentWithConfig, telemetry.TreatmentWithConfig)
}
// Generates control treatments
@@ -225,15 +206,8 @@ func (c *SplitClient) generateControlTreatments(features []string, operation str
return treatments
}
// doTreatmentsCall retrieves treatments of an specific array of features with configurations object if it is present
// for a certain key and set of attributes
func (c *SplitClient) doTreatmentsCall(
key interface{},
features []string,
attributes map[string]interface{},
operation string,
metricsLabel string,
) (t map[string]TreatmentResult) {
// doTreatmentsCall retrieves treatments of an specific array of features with configurations object if it is present for a certain key and set of attributes
func (c *SplitClient) doTreatmentsCall(key interface{}, features []string, attributes map[string]interface{}, operation string, metricsLabel string) (t map[string]TreatmentResult) {
treatments := make(map[string]TreatmentResult)
// Set up a guard deferred function to recover if the SDK starts panicking
@@ -241,10 +215,11 @@ func (c *SplitClient) doTreatmentsCall(
if r := recover(); r != nil {
// At this point we'll only trust that the logger isn't panicking trust
// that the logger isn't panicking
c.evaluationTelemetry.RecordException(metricsLabel)
c.logger.Error(
"SDK is panicking with the following error", r, "\n",
string(debug.Stack()), "\n")
t = treatments
t = c.generateControlTreatments(features, operation)
}
}()
@@ -290,17 +265,17 @@ func (c *SplitClient) doTreatmentsCall(
// Treatments evaluates multiple featers for a single user and set of attributes at once
func (c *SplitClient) Treatments(key interface{}, features []string, attributes map[string]interface{}) map[string]string {
treatments := map[string]string{}
result := c.doTreatmentsCall(key, features, attributes, "Treatments", "sdk.getTreatments")
treatmentsResult := map[string]string{}
result := c.doTreatmentsCall(key, features, attributes, treatments, telemetry.Treatments)
for feature, treatmentResult := range result {
treatments[feature] = treatmentResult.Treatment
treatmentsResult[feature] = treatmentResult.Treatment
}
return treatments
return treatmentsResult
}
// TreatmentsWithConfig evaluates multiple featers for a single user and set of attributes at once and returns configurations
func (c *SplitClient) TreatmentsWithConfig(key interface{}, features []string, attributes map[string]interface{}) map[string]TreatmentResult {
return c.doTreatmentsCall(key, features, attributes, "TreatmentsWithConfig", "sdk.getTreatmentsWithConfig")
return c.doTreatmentsCall(key, features, attributes, treatmentsWithConfig, telemetry.TreatmentsWithConfig)
}
// isDestroyed returns true if the client has been destroyed
@@ -321,24 +296,17 @@ func (c *SplitClient) Destroy() {
}
// Track an event and its custom value
func (c *SplitClient) Track(
key string,
trafficType string,
eventType string,
value interface{},
properties map[string]interface{},
) (ret error) {
func (c *SplitClient) Track(key string, trafficType string, eventType string, value interface{}, properties map[string]interface{}) (ret error) {
defer func() {
if r := recover(); r != nil {
// At this point we'll only trust that the logger isn't panicking
c.evaluationTelemetry.RecordException(telemetry.Track)
c.logger.Error(
"SDK is panicking with the following error", r, "\n",
string(debug.Stack()), "\n",
)
ret = errors.New("Track is panicking. Please check logs")
}
return
}()
if c.isDestroyed() {
@@ -348,6 +316,7 @@ func (c *SplitClient) Track(
if !c.isReady() {
c.logger.Warning("Track: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method")
c.initTelemetry.RecordNonReadyUsage()
}
key, trafficType, eventType, value, err := c.validator.ValidateTrackInputs(

207
vendor/github.com/splitio/go-client/v6/splitio/client/factory.go сгенерированный поставляемый
Просмотреть файл

@@ -18,20 +18,22 @@ import (
config "github.com/splitio/go-split-commons/v3/conf"
"github.com/splitio/go-split-commons/v3/dtos"
"github.com/splitio/go-split-commons/v3/provisional"
"github.com/splitio/go-split-commons/v3/service"
"github.com/splitio/go-split-commons/v3/service/api"
"github.com/splitio/go-split-commons/v3/service/local"
"github.com/splitio/go-split-commons/v3/storage"
"github.com/splitio/go-split-commons/v3/storage/mutexmap"
"github.com/splitio/go-split-commons/v3/storage/mutexqueue"
"github.com/splitio/go-split-commons/v3/storage/inmemory"
"github.com/splitio/go-split-commons/v3/storage/inmemory/mutexmap"
"github.com/splitio/go-split-commons/v3/storage/inmemory/mutexqueue"
"github.com/splitio/go-split-commons/v3/storage/mocks"
"github.com/splitio/go-split-commons/v3/storage/redis"
"github.com/splitio/go-split-commons/v3/synchronizer"
"github.com/splitio/go-split-commons/v3/synchronizer/worker/event"
"github.com/splitio/go-split-commons/v3/synchronizer/worker/impression"
"github.com/splitio/go-split-commons/v3/synchronizer/worker/impressionscount"
"github.com/splitio/go-split-commons/v3/synchronizer/worker/metric"
"github.com/splitio/go-split-commons/v3/synchronizer/worker/segment"
"github.com/splitio/go-split-commons/v3/synchronizer/worker/split"
"github.com/splitio/go-split-commons/v3/tasks"
"github.com/splitio/go-split-commons/v3/telemetry"
"github.com/splitio/go-toolkit/v4/logging"
)
@@ -44,15 +46,18 @@ const (
)
type sdkStorages struct {
splits storage.SplitStorageConsumer
segments storage.SegmentStorageConsumer
impressions storage.ImpressionStorageProducer
events storage.EventStorageProducer
telemetry storage.MetricsStorageProducer
splits storage.SplitStorageConsumer
segments storage.SegmentStorageConsumer
impressions storage.ImpressionStorageProducer
events storage.EventStorageProducer
initTelemetry storage.TelemetryConfigProducer
runtimeTelemetry storage.TelemetryRuntimeProducer
evaluationTelemetry storage.TelemetryEvaluationProducer
}
// SplitFactory struct is responsible for instantiating and storing instances of client and manager.
type SplitFactory struct {
startTime time.Time // Tracking startTime
metadata dtos.Metadata
storages sdkStorages
apikey string
@@ -64,6 +69,7 @@ type SplitFactory struct {
impressionListener *impressionlistener.WrapperImpressionListener
logger logging.LoggerInterface
syncManager synchronizer.Manager
telemetrySync telemetry.TelemetrySynchronizer // To execute SynchronizeInit
impressionManager provisional.ImpressionManager
}
@@ -73,25 +79,28 @@ func (f *SplitFactory) Client() *SplitClient {
logger: f.logger,
evaluator: evaluator.NewEvaluator(f.storages.splits, f.storages.segments, engine.NewEngine(f.logger), f.logger),
impressions: f.storages.impressions,
metrics: f.storages.telemetry,
events: f.storages.events,
validator: inputValidation{
logger: f.logger,
splitStorage: f.storages.splits,
},
factory: f,
impressionListener: f.impressionListener,
impressionManager: f.impressionManager,
factory: f,
impressionListener: f.impressionListener,
impressionManager: f.impressionManager,
initTelemetry: f.storages.initTelemetry, // For capturing NonReadyUsages
runtimeTelemetry: f.storages.runtimeTelemetry, // For capturing runtime stats
evaluationTelemetry: f.storages.evaluationTelemetry, // For capturing treatment stats
}
}
// Manager returns the split manager instantiated by the factory
func (f *SplitFactory) Manager() *SplitManager {
return &SplitManager{
splitStorage: f.storages.splits,
validator: inputValidation{logger: f.logger},
logger: f.logger,
factory: f,
splitStorage: f.storages.splits,
validator: inputValidation{logger: f.logger},
logger: f.logger,
factory: f,
initTelemetry: f.storages.initTelemetry, // For capturing NonReadyUsages
}
}
@@ -110,7 +119,7 @@ func (f *SplitFactory) initializationLocalhost(readyChannel chan int) {
f.syncManager.Start()
<-readyChannel
f.broadcastReadiness(sdkStatusReady)
f.broadcastReadiness(sdkStatusReady, make([]string, 0))
}
// initializates tasks for in-memory mode
@@ -120,14 +129,51 @@ func (f *SplitFactory) initializationInMemory(readyChannel chan int) {
switch msg {
case synchronizer.Ready:
// Broadcast ready status for SDK
f.broadcastReadiness(sdkStatusReady)
f.broadcastReadiness(sdkStatusReady, make([]string, 0))
default:
f.broadcastReadiness(sdkInitializationFailed)
f.broadcastReadiness(sdkInitializationFailed, make([]string, 0))
}
}
// recordInitTelemetry In charge of recording init stats from redis and memory
func (f *SplitFactory) recordInitTelemetry(tags []string) {
if f.telemetrySync == nil {
f.logger.Debug("Discarding init telemetry")
return
}
f.logger.Debug("Sending init telemetry")
f.telemetrySync.SynchronizeConfig(
telemetry.InitConfig{
AdvancedConfig: config.AdvancedConfig{
HTTPTimeout: f.cfg.Advanced.HTTPTimeout,
SegmentQueueSize: f.cfg.Advanced.SegmentQueueSize,
SegmentWorkers: f.cfg.Advanced.SegmentWorkers,
SdkURL: f.cfg.Advanced.SdkURL,
EventsURL: f.cfg.Advanced.EventsURL,
TelemetryServiceURL: f.cfg.Advanced.TelemetryServiceURL,
EventsBulkSize: f.cfg.Advanced.EventsBulkSize,
EventsQueueSize: f.cfg.Advanced.EventsQueueSize,
ImpressionsQueueSize: f.cfg.Advanced.ImpressionsQueueSize,
ImpressionsBulkSize: f.cfg.Advanced.ImpressionsBulkSize,
StreamingEnabled: f.cfg.Advanced.StreamingEnabled,
AuthServiceURL: f.cfg.Advanced.AuthServiceURL,
StreamingServiceURL: f.cfg.Advanced.StreamingServiceURL,
},
TaskPeriods: config.TaskPeriods(f.cfg.TaskPeriods),
ManagerConfig: config.ManagerConfig{
OperationMode: f.cfg.OperationMode,
ImpressionsMode: f.cfg.ImpressionsMode,
ListenerEnabled: f.cfg.Advanced.ImpressionListener != nil,
},
},
time.Now().UTC().Sub(f.startTime).Milliseconds(),
getFactories(),
tags,
)
}
// broadcastReadiness broadcasts message to all the subscriptors
func (f *SplitFactory) broadcastReadiness(status int) {
func (f *SplitFactory) broadcastReadiness(status int, tags []string) {
f.mutex.Lock()
defer f.mutex.Unlock()
if f.status.Load() == sdkStatusInitializing && status == sdkStatusReady {
@@ -136,6 +182,8 @@ func (f *SplitFactory) broadcastReadiness(status int) {
for _, subscriptor := range f.readinessSubscriptors {
subscriptor <- status
}
// At this point the SDK is ready for sending telemetry
f.recordInitTelemetry(tags)
}
// subscribes listener
@@ -191,6 +239,7 @@ func (f *SplitFactory) BlockUntilReady(timer int) error {
return errors.New("SDK Initialization failed")
}
case <-time.After(time.Second * time.Duration(timer)):
f.storages.initTelemetry.RecordBURTimeout() // Records BURTimeout
return fmt.Errorf("SDK Initialization: time of %d exceeded", timer)
}
@@ -203,6 +252,9 @@ func (f *SplitFactory) Destroy() {
removeInstanceFromTracker(f.apikey)
}
f.status.Store(sdkStatusDestroyed)
if f.storages.runtimeTelemetry != nil {
f.storages.runtimeTelemetry.RecordSessionLength(int64(time.Since(f.startTime) * time.Millisecond))
}
if f.cfg.OperationMode == conf.RedisConsumer {
return
@@ -234,48 +286,43 @@ func setupInMemoryFactory(
advanced.StreamingEnabled = false
}
/*
err := api.ValidateApikey(apikey, *advanced)
if err != nil {
return nil, err
}
*/
inMememoryFullQueue := make(chan string, 2) // Size 2: So that it's able to accept one event from each resource simultaneously.
splitsStorage := mutexmap.NewMMSplitStorage()
segmentsStorage := mutexmap.NewMMSegmentStorage()
impressionsStorage := mutexqueue.NewMQImpressionsStorage(cfg.Advanced.ImpressionsQueueSize, inMememoryFullQueue, logger)
telemetryStorage := mutexmap.NewMMMetricsStorage()
eventsStorage := mutexqueue.NewMQEventsStorage(cfg.Advanced.EventsQueueSize, inMememoryFullQueue, logger)
metricsWrapper := storage.NewMetricWrapper(telemetryStorage, nil, logger)
telemetryStorage, err := inmemory.NewTelemetryStorage()
impressionsStorage := mutexqueue.NewMQImpressionsStorage(cfg.Advanced.ImpressionsQueueSize, inMememoryFullQueue, logger, telemetryStorage)
eventsStorage := mutexqueue.NewMQEventsStorage(cfg.Advanced.EventsQueueSize, inMememoryFullQueue, logger, telemetryStorage)
if err != nil {
return nil, err
}
managerConfig := config.ManagerConfig{
ImpressionsMode: cfg.ImpressionsMode,
OperationMode: cfg.OperationMode,
ListenerEnabled: cfg.Advanced.ImpressionListener != nil,
}
splitAPI := service.NewSplitAPI(apikey, advanced, logger, metadata)
splitAPI := api.NewSplitAPI(apikey, advanced, logger, metadata)
workers := synchronizer.Workers{
SplitFetcher: split.NewSplitFetcher(splitsStorage, splitAPI.SplitFetcher, metricsWrapper, logger),
SegmentFetcher: segment.NewSegmentFetcher(splitsStorage, segmentsStorage, splitAPI.SegmentFetcher, metricsWrapper, logger),
EventRecorder: event.NewEventRecorderSingle(eventsStorage, splitAPI.EventRecorder, metricsWrapper, logger, metadata),
ImpressionRecorder: impression.NewRecorderSingle(impressionsStorage, splitAPI.ImpressionRecorder, metricsWrapper, logger, metadata, managerConfig),
TelemetryRecorder: metric.NewRecorderSingle(telemetryStorage, splitAPI.MetricRecorder, metadata),
SplitFetcher: split.NewSplitFetcher(splitsStorage, splitAPI.SplitFetcher, logger, telemetryStorage),
SegmentFetcher: segment.NewSegmentFetcher(splitsStorage, segmentsStorage, splitAPI.SegmentFetcher, logger, telemetryStorage),
EventRecorder: event.NewEventRecorderSingle(eventsStorage, splitAPI.EventRecorder, logger, metadata, telemetryStorage),
ImpressionRecorder: impression.NewRecorderSingle(impressionsStorage, splitAPI.ImpressionRecorder, logger, metadata, managerConfig, telemetryStorage),
TelemetryRecorder: telemetry.NewTelemetrySynchronizer(telemetryStorage, splitAPI.TelemetryRecorder, splitsStorage, segmentsStorage, logger, metadata, telemetryStorage),
}
splitTasks := synchronizer.SplitTasks{
SplitSyncTask: tasks.NewFetchSplitsTask(workers.SplitFetcher, cfg.TaskPeriods.SplitSync, logger),
SegmentSyncTask: tasks.NewFetchSegmentsTask(workers.SegmentFetcher, cfg.TaskPeriods.SegmentSync, advanced.SegmentWorkers, advanced.SegmentQueueSize, logger),
EventSyncTask: tasks.NewRecordEventsTask(workers.EventRecorder, advanced.EventsBulkSize, cfg.TaskPeriods.EventsSync, logger),
ImpressionSyncTask: tasks.NewRecordImpressionsTask(workers.ImpressionRecorder, cfg.TaskPeriods.ImpressionSync, logger, advanced.ImpressionsBulkSize),
TelemetrySyncTask: tasks.NewRecordTelemetryTask(workers.TelemetryRecorder, cfg.TaskPeriods.LatencySync, logger),
TelemetrySyncTask: tasks.NewRecordTelemetryTask(workers.TelemetryRecorder, cfg.TaskPeriods.TelemetrySync, logger),
}
var impressionsCounter *provisional.ImpressionsCounter
if cfg.ImpressionsMode == config.ImpressionsModeOptimized {
impressionsCounter = provisional.NewImpressionsCounter()
workers.ImpressionsCountRecorder = impressionscount.NewRecorderSingle(impressionsCounter, splitAPI.ImpressionRecorder, metadata, logger)
workers.ImpressionsCountRecorder = impressionscount.NewRecorderSingle(impressionsCounter, splitAPI.ImpressionRecorder, metadata, logger, telemetryStorage)
splitTasks.ImpressionsCountSyncTask = tasks.NewRecordImpressionsCountTask(workers.ImpressionsCountRecorder, logger)
}
impressionManager, err := provisional.NewImpressionManager(managerConfig, impressionsCounter)
impressionManager, err := provisional.NewImpressionManager(managerConfig, impressionsCounter, telemetryStorage)
if err != nil {
return nil, err
}
@@ -289,6 +336,7 @@ func setupInMemoryFactory(
)
readyChannel := make(chan int, 1)
clientKey := apikey[len(apikey)-4:]
syncManager, err := synchronizer.NewSynchronizerManager(
syncImpl,
logger,
@@ -296,29 +344,37 @@ func setupInMemoryFactory(
splitAPI.AuthClient,
splitsStorage,
readyChannel,
telemetryStorage,
metadata,
&clientKey,
)
if err != nil {
return nil, err
}
splitFactory := SplitFactory{
startTime: time.Now().UTC(),
apikey: apikey,
cfg: cfg,
metadata: metadata,
logger: logger,
operationMode: conf.InMemoryStandAlone,
storages: sdkStorages{
splits: splitsStorage,
events: eventsStorage,
impressions: impressionsStorage,
segments: segmentsStorage,
telemetry: telemetryStorage,
splits: splitsStorage,
events: eventsStorage,
impressions: impressionsStorage,
segments: segmentsStorage,
initTelemetry: telemetryStorage,
evaluationTelemetry: telemetryStorage,
runtimeTelemetry: telemetryStorage,
},
readinessSubscriptors: make(map[int]chan int),
syncManager: syncManager,
telemetrySync: workers.TelemetryRecorder,
}
splitFactory.status.Store(sdkStatusInitializing)
splitFactory.impressionManager = impressionManager
setFactory(splitFactory.apikey, splitFactory.logger)
go splitFactory.initializationInMemory(readyChannel)
@@ -332,15 +388,18 @@ func setupRedisFactory(apikey string, cfg *conf.SplitSdkConfig, logger logging.L
return nil, err
}
telemetryStorage := redis.NewTelemetryStorage(redisClient, logger, metadata)
storages := sdkStorages{
splits: redis.NewSplitStorage(redisClient, logger),
segments: redis.NewSegmentStorage(redisClient, logger),
impressions: redis.NewImpressionStorage(redisClient, metadata, logger),
telemetry: redis.NewMetricsStorage(redisClient, metadata, logger),
events: redis.NewEventsStorage(redisClient, metadata, logger),
splits: redis.NewSplitStorage(redisClient, logger),
segments: redis.NewSegmentStorage(redisClient, logger),
impressions: redis.NewImpressionStorage(redisClient, metadata, logger),
events: redis.NewEventsStorage(redisClient, metadata, logger),
initTelemetry: telemetryStorage,
evaluationTelemetry: telemetryStorage,
}
factory := &SplitFactory{
startTime: time.Now().UTC(),
apikey: apikey,
cfg: cfg,
metadata: metadata,
@@ -348,17 +407,23 @@ func setupRedisFactory(apikey string, cfg *conf.SplitSdkConfig, logger logging.L
operationMode: conf.RedisConsumer,
storages: storages,
readinessSubscriptors: make(map[int]chan int),
telemetrySync: telemetry.NewSynchronizerRedis(telemetryStorage, logger),
}
factory.status.Store(sdkStatusInitializing)
impressionManager, err := provisional.NewImpressionManager(config.ManagerConfig{
OperationMode: cfg.OperationMode,
ImpressionsMode: cfg.ImpressionsMode,
ListenerEnabled: cfg.Advanced.ImpressionListener != nil,
}, nil)
}, nil, mocks.MockTelemetryStorage{
RecordSyncLatencyCall: func(resource int, latency int64) {},
RecordImpressionsStatsCall: func(dataType int, count int64) {},
})
if err != nil {
return nil, err
}
factory.impressionManager = impressionManager
factory.status.Store(sdkStatusReady)
setFactory(factory.apikey, factory.logger)
factory.broadcastReadiness(sdkStatusReady, make([]string, 0))
return factory, nil
}
@@ -369,17 +434,23 @@ func setupLocalhostFactory(
metadata dtos.Metadata,
) (*SplitFactory, error) {
splitStorage := mutexmap.NewMMSplitStorage()
telemetryStorage, err := inmemory.NewTelemetryStorage()
if err != nil {
return nil, err
}
splitPeriod := cfg.TaskPeriods.SplitSync
readyChannel := make(chan int, 1)
splitAPI := &service.SplitAPI{SplitFetcher: local.NewFileSplitFetcher(cfg.SplitFile, logger)}
splitAPI := &api.SplitAPI{SplitFetcher: local.NewFileSplitFetcher(cfg.SplitFile, logger)}
syncManager, err := synchronizer.NewSynchronizerManager(
synchronizer.NewLocal(splitPeriod, splitAPI, splitStorage, logger),
synchronizer.NewLocal(splitPeriod, splitAPI, splitStorage, logger, telemetryStorage),
logger,
config.AdvancedConfig{StreamingEnabled: false},
nil,
splitStorage,
readyChannel,
telemetryStorage,
metadata,
nil,
)
if err != nil {
@@ -387,16 +458,19 @@ func setupLocalhostFactory(
}
splitFactory := &SplitFactory{
apikey: apikey,
cfg: cfg,
metadata: metadata,
logger: logger,
startTime: time.Now().UTC(),
apikey: apikey,
cfg: cfg,
metadata: metadata,
logger: logger,
storages: sdkStorages{
splits: splitStorage,
impressions: mutexqueue.NewMQImpressionsStorage(cfg.Advanced.ImpressionsQueueSize, make(chan string, 1), logger),
telemetry: mutexmap.NewMMMetricsStorage(),
events: mutexqueue.NewMQEventsStorage(cfg.Advanced.EventsQueueSize, make(chan string, 1), logger),
segments: mutexmap.NewMMSegmentStorage(),
splits: splitStorage,
impressions: mutexqueue.NewMQImpressionsStorage(cfg.Advanced.ImpressionsQueueSize, make(chan string, 1), logger, telemetryStorage),
events: mutexqueue.NewMQEventsStorage(cfg.Advanced.EventsQueueSize, make(chan string, 1), logger, telemetryStorage),
segments: mutexmap.NewMMSegmentStorage(),
initTelemetry: telemetryStorage,
evaluationTelemetry: telemetryStorage,
runtimeTelemetry: telemetryStorage,
},
readinessSubscriptors: make(map[int]chan int),
syncManager: syncManager,
@@ -407,11 +481,12 @@ func setupLocalhostFactory(
OperationMode: cfg.OperationMode,
ImpressionsMode: cfg.ImpressionsMode,
ListenerEnabled: cfg.Advanced.ImpressionListener != nil,
}, nil)
}, nil, telemetryStorage)
if err != nil {
return nil, err
}
splitFactory.impressionManager = impressionManager
setFactory(splitFactory.apikey, splitFactory.logger)
// Call fetching tasks as goroutine
go splitFactory.initializationLocalhost(readyChannel)

13
vendor/github.com/splitio/go-client/v6/splitio/client/factory_tracker.go сгенерированный поставляемый
Просмотреть файл

@@ -10,7 +10,7 @@ import (
// factoryInstances factory tracker instantiations
var factoryInstances = make(map[string]int64)
var mutex = &sync.Mutex{}
var mutex = &sync.RWMutex{}
func setFactory(apikey string, logger logging.LoggerInterface) {
mutex.Lock()
@@ -67,6 +67,15 @@ func NewSplitFactory(apikey string, cfg *conf.SplitSdkConfig) (*SplitFactory, er
}
splitFactory, err := newFactory(apikey, cfg, logger)
setFactory(apikey, logger)
return splitFactory, err
}
func getFactories() map[string]int64 {
toReturn := make(map[string]int64)
mutex.RLock()
defer mutex.RUnlock()
for k, v := range factoryInstances {
toReturn[k] = v
}
return toReturn
}

18
vendor/github.com/splitio/go-client/v6/splitio/client/manager.go сгенерированный поставляемый
Просмотреть файл

@@ -10,10 +10,11 @@ import (
// SplitManager provides information of the currently stored splits
type SplitManager struct {
splitStorage storage.SplitStorageConsumer
validator inputValidation
logger logging.LoggerInterface
factory *SplitFactory
splitStorage storage.SplitStorageConsumer
validator inputValidation
logger logging.LoggerInterface
factory *SplitFactory
initTelemetry storage.TelemetryConfigProducer
}
// SplitView is a partial representation of a currently stored split
@@ -51,7 +52,8 @@ func (m *SplitManager) SplitNames() []string {
}
if !m.isReady() {
m.logger.Warning("splitNames: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method")
m.logger.Warning("SplitNames: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method")
m.initTelemetry.RecordNonReadyUsage()
}
return m.splitStorage.SplitNames()
@@ -65,7 +67,8 @@ func (m *SplitManager) Splits() []SplitView {
}
if !m.isReady() {
m.logger.Warning("splits: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method")
m.logger.Warning("Splits: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method")
m.initTelemetry.RecordNonReadyUsage()
}
splitViews := make([]SplitView, 0)
@@ -84,7 +87,8 @@ func (m *SplitManager) Split(feature string) *SplitView {
}
if !m.isReady() {
m.logger.Warning("split: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method")
m.logger.Warning("Split: the SDK is not ready, results may be incorrect. Make sure to wait for SDK readiness before using this method")
m.initTelemetry.RecordNonReadyUsage()
}
err := m.validator.ValidateManagerInputs(feature)

1
vendor/github.com/splitio/go-client/v6/splitio/conf/defaults.go сгенерированный поставляемый
Просмотреть файл

@@ -3,6 +3,7 @@ package conf
const (
defaultHTTPTimeout = 30
defaultTaskPeriod = 60
defaultTelemetrySync = 3600
defaultRedisHost = "localhost"
defaultRedisPort = 6379
defaultRedisDb = 0

21
vendor/github.com/splitio/go-client/v6/splitio/conf/sdkconf.go сгенерированный поставляемый
Просмотреть файл

@@ -67,6 +67,7 @@ type TaskPeriods struct {
CounterSync int
LatencySync int
EventsSync int
TelemetrySync int
}
// AdvancedConfig exposes more configurable parameters that can be used to further tailor the sdk to the user's needs
@@ -83,6 +84,7 @@ type AdvancedConfig struct {
SdkURL string
EventsURL string
StreamingServiceURL string
TelemetryServiceURL string
EventsBulkSize int64
EventsQueueSize int
ImpressionsQueueSize int
@@ -126,9 +128,10 @@ func Default() *SplitSdkConfig {
Prefix: "",
},
TaskPeriods: TaskPeriods{
GaugeSync: defaultTaskPeriod,
CounterSync: defaultTaskPeriod,
LatencySync: defaultTaskPeriod,
GaugeSync: defaultTelemetrySync,
CounterSync: defaultTelemetrySync,
LatencySync: defaultTelemetrySync,
TelemetrySync: defaultTelemetrySync,
ImpressionSync: defaultImpressionSyncOptimized,
SegmentSync: defaultTaskPeriod,
SplitSync: defaultTaskPeriod,
@@ -139,6 +142,7 @@ func Default() *SplitSdkConfig {
EventsURL: "",
SdkURL: "",
StreamingServiceURL: "",
TelemetryServiceURL: "",
HTTPTimeout: 0,
ImpressionListener: nil,
SegmentQueueSize: 500,
@@ -203,14 +207,8 @@ func validConfigRates(cfg *SplitSdkConfig) error {
if cfg.TaskPeriods.EventsSync < minEventSync {
return fmt.Errorf("EventsSync must be >= %d. Actual is: %d", minEventSync, cfg.TaskPeriods.EventsSync)
}
if cfg.TaskPeriods.LatencySync < minTelemetrySync {
return fmt.Errorf("LatencySync must be >= %d. Actual is: %d", minTelemetrySync, cfg.TaskPeriods.LatencySync)
}
if cfg.TaskPeriods.GaugeSync < minTelemetrySync {
return fmt.Errorf("GaugeSync must be >= %d. Actual is: %d", minTelemetrySync, cfg.TaskPeriods.GaugeSync)
}
if cfg.TaskPeriods.CounterSync < minTelemetrySync {
return fmt.Errorf("CounterSync must be >= %d. Actual is: %d", minTelemetrySync, cfg.TaskPeriods.CounterSync)
if cfg.TaskPeriods.TelemetrySync < minTelemetrySync {
return fmt.Errorf("TelemetrySync must be >= %d. Actual is: %d", minTelemetrySync, cfg.TaskPeriods.TelemetrySync)
}
if cfg.Advanced.SegmentWorkers <= 0 {
return errors.New("Number of workers for fetching segments MUST be greater than zero")
@@ -248,6 +246,7 @@ func Normalize(apikey string, cfg *SplitSdkConfig) error {
cfg.Advanced.SdkURL = cfg.SplitSyncProxyURL
cfg.Advanced.EventsURL = cfg.SplitSyncProxyURL
cfg.Advanced.StreamingServiceURL = cfg.SplitSyncProxyURL
cfg.Advanced.TelemetryServiceURL = cfg.SplitSyncProxyURL
}
if !cfg.IPAddressesEnabled {

3
vendor/github.com/splitio/go-client/v6/splitio/conf/util.go сгенерированный поставляемый
Просмотреть файл

@@ -42,6 +42,9 @@ func NormalizeSDKConf(sdkConfig AdvancedConfig) conf.AdvancedConfig {
if strings.TrimSpace(sdkConfig.StreamingServiceURL) != "" {
config.StreamingServiceURL = sdkConfig.StreamingServiceURL
}
if strings.TrimSpace(sdkConfig.TelemetryServiceURL) != "" {
config.TelemetryServiceURL = sdkConfig.TelemetryServiceURL
}
config.StreamingEnabled = sdkConfig.StreamingEnabled
return config

2
vendor/github.com/splitio/go-client/v6/splitio/version.go сгенерированный поставляемый
Просмотреть файл

@@ -1,4 +1,4 @@
package splitio
// Version contains a string with the split sdk version
const Version = "6.0.2"
const Version = "6.1.0"