MM-34932: Bump dependencies (#17708)
https://mattermost.atlassian.net/browse/MM-34932 ```release-note NONE ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
fff09bf210
Коммит
3299a72adb
115
vendor/github.com/splitio/go-client/v6/splitio/client/client.go
сгенерированный
поставляемый
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
сгенерированный
поставляемый
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
сгенерированный
поставляемый
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
сгенерированный
поставляемый
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
сгенерированный
поставляемый
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
сгенерированный
поставляемый
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
сгенерированный
поставляемый
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
сгенерированный
поставляемый
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"
|
||||
|
||||
8
vendor/github.com/splitio/go-split-commons/v3/conf/conf.go
сгенерированный
поставляемый
8
vendor/github.com/splitio/go-split-commons/v3/conf/conf.go
сгенерированный
поставляемый
@@ -54,10 +54,11 @@ type TaskPeriods struct {
|
||||
SplitSync int
|
||||
SegmentSync int
|
||||
ImpressionSync int
|
||||
GaugeSync int
|
||||
CounterSync int
|
||||
LatencySync int
|
||||
GaugeSync int // deprecated
|
||||
CounterSync int // deprecated
|
||||
LatencySync int // deprecated
|
||||
EventsSync int
|
||||
TelemetrySync int
|
||||
}
|
||||
|
||||
// AdvancedConfig exposes more configurable parameters that can be used to further tailor the sdk to the user's needs
|
||||
@@ -70,6 +71,7 @@ type AdvancedConfig struct {
|
||||
SegmentWorkers int
|
||||
SdkURL string
|
||||
EventsURL string
|
||||
TelemetryServiceURL string
|
||||
EventsBulkSize int64
|
||||
EventsQueueSize int
|
||||
ImpressionsQueueSize int
|
||||
|
||||
2
vendor/github.com/splitio/go-split-commons/v3/conf/defaults.go
сгенерированный
поставляемый
2
vendor/github.com/splitio/go-split-commons/v3/conf/defaults.go
сгенерированный
поставляемый
@@ -15,6 +15,7 @@ const (
|
||||
defaultEventsURL = "https://events.split.io/api"
|
||||
defaultSdkURL = "https://sdk.split.io/api"
|
||||
defaultStreamingServiceURL = "https://streaming.split.io/sse"
|
||||
defaultTelemetryServiceURL = "https://telemetry.split.io/api/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -48,5 +49,6 @@ func GetDefaultAdvancedConfig() AdvancedConfig {
|
||||
EventsURL: defaultEventsURL,
|
||||
SdkURL: defaultSdkURL,
|
||||
StreamingServiceURL: defaultStreamingServiceURL,
|
||||
TelemetryServiceURL: defaultTelemetryServiceURL,
|
||||
}
|
||||
}
|
||||
|
||||
132
vendor/github.com/splitio/go-split-commons/v3/dtos/metrics.go
сгенерированный
поставляемый
132
vendor/github.com/splitio/go-split-commons/v3/dtos/metrics.go
сгенерированный
поставляемый
@@ -1,132 +0,0 @@
|
||||
package dtos
|
||||
|
||||
// LatenciesDTO struct mapping latencies post
|
||||
type LatenciesDTO struct {
|
||||
MetricName string `json:"name"`
|
||||
Latencies []int64 `json:"latencies"`
|
||||
}
|
||||
|
||||
// CounterDTO struct mapping counts post
|
||||
type CounterDTO struct {
|
||||
MetricName string `json:"name"`
|
||||
Count int64 `json:"delta"`
|
||||
}
|
||||
|
||||
// GaugeDTO struct mapping gauges post
|
||||
type GaugeDTO struct {
|
||||
MetricName string `json:"name"`
|
||||
Gauge float64 `json:"value"`
|
||||
}
|
||||
|
||||
const maxBuckets = 23
|
||||
|
||||
// LatencyDataBulk holds all latencies fetched from storage sorted properly.
|
||||
type LatencyDataBulk struct {
|
||||
data map[string]map[string]map[string][]int64
|
||||
}
|
||||
|
||||
// PutLatency adds a new latency to the structure
|
||||
func (l *LatencyDataBulk) PutLatency(sdk string, machineIP string, metricName string, bucketNumber int, value int64) {
|
||||
|
||||
if _, ok := l.data[sdk]; !ok {
|
||||
l.data[sdk] = make(map[string]map[string][]int64)
|
||||
}
|
||||
|
||||
if _, ok := l.data[sdk][machineIP]; !ok {
|
||||
l.data[sdk][machineIP] = make(map[string][]int64)
|
||||
}
|
||||
|
||||
if _, ok := l.data[sdk][machineIP][metricName]; !ok {
|
||||
l.data[sdk][machineIP][metricName] = make([]int64, maxBuckets)
|
||||
}
|
||||
|
||||
l.data[sdk][machineIP][metricName][bucketNumber] = value
|
||||
}
|
||||
|
||||
// ForEach iterates thru all latencies
|
||||
func (l *LatencyDataBulk) ForEach(callback func(string, string, map[string][]int64)) {
|
||||
for sdk, byIP := range l.data {
|
||||
for ip, byName := range byIP {
|
||||
callback(sdk, ip, byName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewLatencyDataBulk creates a new Latency holding structure
|
||||
func NewLatencyDataBulk() *LatencyDataBulk {
|
||||
return &LatencyDataBulk{
|
||||
data: make(map[string]map[string]map[string][]int64),
|
||||
}
|
||||
}
|
||||
|
||||
// CounterDataBulk holds all counters fetched from storage sorted properly.
|
||||
type CounterDataBulk struct {
|
||||
data map[string]map[string]map[string]int64
|
||||
}
|
||||
|
||||
// PutCounter adds a counter to the structure
|
||||
func (l *CounterDataBulk) PutCounter(sdk string, machineIP string, metricName string, value int64) {
|
||||
|
||||
if _, ok := l.data[sdk]; !ok {
|
||||
l.data[sdk] = make(map[string]map[string]int64)
|
||||
}
|
||||
|
||||
if _, ok := l.data[sdk][machineIP]; !ok {
|
||||
l.data[sdk][machineIP] = make(map[string]int64)
|
||||
}
|
||||
|
||||
l.data[sdk][machineIP][metricName] = value
|
||||
}
|
||||
|
||||
// ForEach iterates thru all counters
|
||||
func (l *CounterDataBulk) ForEach(callback func(string, string, map[string]int64)) {
|
||||
for sdk, byIP := range l.data {
|
||||
for ip, byName := range byIP {
|
||||
callback(sdk, ip, byName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewCounterDataBulk creates a new Counter holding structure
|
||||
func NewCounterDataBulk() *CounterDataBulk {
|
||||
return &CounterDataBulk{
|
||||
data: make(map[string]map[string]map[string]int64),
|
||||
}
|
||||
}
|
||||
|
||||
// GaugeDataBulk holds all gauges fetched from storage sorted properly.
|
||||
type GaugeDataBulk struct {
|
||||
data map[string]map[string]map[string]float64
|
||||
}
|
||||
|
||||
// PutGauge adds a gauge to the structure
|
||||
func (l *GaugeDataBulk) PutGauge(sdk string, machineIP string, metricName string, value float64) {
|
||||
|
||||
if _, ok := l.data[sdk]; !ok {
|
||||
l.data[sdk] = make(map[string]map[string]float64)
|
||||
}
|
||||
|
||||
if _, ok := l.data[sdk][machineIP]; !ok {
|
||||
l.data[sdk][machineIP] = make(map[string]float64)
|
||||
}
|
||||
|
||||
l.data[sdk][machineIP][metricName] = value
|
||||
}
|
||||
|
||||
// ForEach iterates thru all gauges
|
||||
func (l *GaugeDataBulk) ForEach(callback func(string, string, string, float64)) {
|
||||
for sdk, byIP := range l.data {
|
||||
for ip, byName := range byIP {
|
||||
for name, value := range byName {
|
||||
callback(sdk, ip, name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewGaugeDataBulk creates a new Gauge holding structure
|
||||
func NewGaugeDataBulk() *GaugeDataBulk {
|
||||
return &GaugeDataBulk{
|
||||
data: make(map[string]map[string]map[string]float64),
|
||||
}
|
||||
}
|
||||
126
vendor/github.com/splitio/go-split-commons/v3/dtos/telemetry.go
сгенерированный
поставляемый
Обычный файл
126
vendor/github.com/splitio/go-split-commons/v3/dtos/telemetry.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,126 @@
|
||||
package dtos
|
||||
|
||||
// LastSynchronization struct
|
||||
type LastSynchronization struct {
|
||||
Splits int64 `json:"sp,omitempty"`
|
||||
Segments int64 `json:"se,omitempty"`
|
||||
Impressions int64 `json:"im,omitempty"`
|
||||
ImpressionsCount int64 `json:"ic,omitempty"`
|
||||
Events int64 `json:"ev,omitempty"`
|
||||
Token int64 `json:"to,omitempty"`
|
||||
Telemetry int64 `json:"te,omitempty"`
|
||||
}
|
||||
|
||||
// HTTPErrors struct
|
||||
type HTTPErrors struct {
|
||||
Splits map[int]int64 `json:"sp,omitempty"`
|
||||
Segments map[int]int64 `json:"se,omitempty"`
|
||||
Impressions map[int]int64 `json:"im,omitempty"`
|
||||
ImpressionsCount map[int]int64 `json:"ic,omitempty"`
|
||||
Events map[int]int64 `json:"ev,omitempty"`
|
||||
Token map[int]int64 `json:"to,omitempty"`
|
||||
Telemetry map[int]int64 `json:"te,omitempty"`
|
||||
}
|
||||
|
||||
// HTTPLatencies struct
|
||||
type HTTPLatencies struct {
|
||||
Splits []int64 `json:"sp,omitempty"`
|
||||
Segments []int64 `json:"se,omitempty"`
|
||||
Impressions []int64 `json:"im,omitempty"`
|
||||
ImpressionsCount []int64 `json:"ic,omitempty"`
|
||||
Events []int64 `json:"ev,omitempty"`
|
||||
Token []int64 `json:"to,omitempty"`
|
||||
Telemetry []int64 `json:"te,omitempty"`
|
||||
}
|
||||
|
||||
// MethodLatencies struct
|
||||
type MethodLatencies struct {
|
||||
Treatment []int64 `json:"t,omitempty"`
|
||||
Treatments []int64 `json:"ts,omitempty"`
|
||||
TreatmentWithConfig []int64 `json:"tc,omitempty"`
|
||||
TreatmentsWithConfig []int64 `json:"tcs,omitempty"`
|
||||
Track []int64 `json:"tr,omitempty"`
|
||||
}
|
||||
|
||||
// MethodExceptions struct
|
||||
type MethodExceptions struct {
|
||||
Treatment int64 `json:"t,omitempty"`
|
||||
Treatments int64 `json:"ts,omitempty"`
|
||||
TreatmentWithConfig int64 `json:"tc,omitempty"`
|
||||
TreatmentsWithConfig int64 `json:"tcs,omitempty"`
|
||||
Track int64 `json:"tr,omitempty"`
|
||||
}
|
||||
|
||||
// StreamingEvent struct
|
||||
type StreamingEvent struct {
|
||||
Type int `json:"e,omitempty"`
|
||||
Data int64 `json:"d,omitempty"`
|
||||
Timestamp int64 `json:"t,omitempty"`
|
||||
}
|
||||
|
||||
// TelemetryQueueObject struct mapping telemetry
|
||||
type TelemetryQueueObject struct {
|
||||
Metadata Metadata `json:"m"`
|
||||
Config Config `json:"t"`
|
||||
}
|
||||
|
||||
// Rates struct
|
||||
type Rates struct {
|
||||
Splits int64 `json:"sp,omitempty"`
|
||||
Segments int64 `json:"se,omitempty"`
|
||||
Impressions int64 `json:"im,omitempty"`
|
||||
Events int64 `json:"ev,omitempty"`
|
||||
Telemetry int64 `json:"te,omitempty"`
|
||||
}
|
||||
|
||||
// URLOverrides struct
|
||||
type URLOverrides struct {
|
||||
Sdk bool `json:"s,omitempty"`
|
||||
Events bool `json:"e,omitempty"`
|
||||
Auth bool `json:"a,omitempty"`
|
||||
Stream bool `json:"st,omitempty"`
|
||||
Telemetry bool `json:"t,omitempty"`
|
||||
}
|
||||
|
||||
// Config data for initial configs metrics
|
||||
type Config struct {
|
||||
OperationMode int `json:"oM,omitempty"`
|
||||
StreamingEnabled bool `json:"sE,omitempty"`
|
||||
Storage string `json:"st,omitempty"`
|
||||
Rates *Rates `json:"rR,omitempty"`
|
||||
URLOverrides *URLOverrides `json:"uO,omitempty"`
|
||||
ImpressionsQueueSize int64 `json:"iQ,omitempty"`
|
||||
EventsQueueSize int64 `json:"eQ,omitempty"`
|
||||
ImpressionsMode int `json:"iM,omitempty"`
|
||||
ImpressionsListenerEnabled bool `json:"iL,omitempty"`
|
||||
HTTPProxyDetected bool `json:"hP,omitempty"`
|
||||
ActiveFactories int64 `json:"aF,omitempty"`
|
||||
RedundantFactories int64 `json:"rF,omitempty"`
|
||||
TimeUntilReady int64 `json:"tR,omitempty"`
|
||||
BurTimeouts int64 `json:"bT,omitempty"`
|
||||
NonReadyUsages int64 `json:"nR,omitempty"`
|
||||
Integrations []string `json:"i,omitempty"`
|
||||
Tags []string `json:"t,omitempty"`
|
||||
}
|
||||
|
||||
// Stats data sent by sdks pereiodically
|
||||
type Stats struct {
|
||||
LastSynchronizations *LastSynchronization `json:"lS,omitempty"`
|
||||
MethodLatencies *MethodLatencies `json:"mL,omitempty"`
|
||||
MethodExceptions *MethodExceptions `json:"mE,omitempty"`
|
||||
HTTPErrors *HTTPErrors `json:"hE,omitempty"`
|
||||
HTTPLatencies *HTTPLatencies `json:"hL,omitempty"`
|
||||
TokenRefreshes int64 `json:"tR,omitempty"`
|
||||
AuthRejections int64 `json:"aR,omitempty"`
|
||||
ImpressionsQueued int64 `json:"iQ,omitempty"`
|
||||
ImpressionsDeduped int64 `json:"iDe,omitempty"`
|
||||
ImpressionsDropped int64 `json:"iDr,omitempty"`
|
||||
SplitCount int64 `json:"spC,omitempty"`
|
||||
SegmentCount int64 `json:"seC,omitempty"`
|
||||
SegmentKeyCount int64 `json:"skC,omitempty"`
|
||||
SessionLengthMs int64 `json:"sL,omitempty"`
|
||||
EventsQueued int64 `json:"eQ,omitempty"`
|
||||
EventsDropped int64 `json:"eD,omitempty"`
|
||||
StreamingEvents []StreamingEvent `json:"sE,omitempty"`
|
||||
Tags []string `json:"t,omitempty"`
|
||||
}
|
||||
7
vendor/github.com/splitio/go-split-commons/v3/provisional/impmanager.go
сгенерированный
поставляемый
7
vendor/github.com/splitio/go-split-commons/v3/provisional/impmanager.go
сгенерированный
поставляемый
@@ -5,6 +5,8 @@ import (
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-split-commons/v3/util"
|
||||
)
|
||||
|
||||
@@ -22,10 +24,11 @@ type ImpressionManagerImpl struct {
|
||||
shouldAddPreviousTime bool
|
||||
isOptimized bool
|
||||
listenerEnabled bool
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// NewImpressionManager creates new ImpManager
|
||||
func NewImpressionManager(managerConfig conf.ManagerConfig, impressionCounter *ImpressionsCounter) (ImpressionManager, error) {
|
||||
func NewImpressionManager(managerConfig conf.ManagerConfig, impressionCounter *ImpressionsCounter, runtimeTelemetry storage.TelemetryRuntimeProducer) (ImpressionManager, error) {
|
||||
impressionObserver, err := NewImpressionObserver(lastSeenCacheSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -37,6 +40,7 @@ func NewImpressionManager(managerConfig conf.ManagerConfig, impressionCounter *I
|
||||
shouldAddPreviousTime: util.ShouldAddPreviousTime(managerConfig),
|
||||
isOptimized: impressionCounter != nil && util.ShouldBeOptimized(managerConfig),
|
||||
listenerEnabled: managerConfig.ListenerEnabled,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
|
||||
return impManager, nil
|
||||
@@ -72,5 +76,6 @@ func (i *ImpressionManagerImpl) ProcessImpressions(impressions []dtos.Impression
|
||||
forLog, forListener = i.processImpression(impression, forLog, forListener)
|
||||
}
|
||||
|
||||
i.runtimeTelemetry.RecordImpressionsStats(telemetry.ImpressionsDeduped, int64(len(impressions)-len(forLog)))
|
||||
return forLog, forListener
|
||||
}
|
||||
|
||||
14
vendor/github.com/splitio/go-split-commons/v3/push/constants.go
сгенерированный
поставляемый
14
vendor/github.com/splitio/go-split-commons/v3/push/constants.go
сгенерированный
поставляемый
@@ -1,14 +0,0 @@
|
||||
package push
|
||||
|
||||
const (
|
||||
workerStatusIdle = iota
|
||||
workerStatusRunning
|
||||
workerStatusShuttingDown
|
||||
)
|
||||
|
||||
const (
|
||||
pushManagerStatusIdle = iota
|
||||
pushManagerStatusInitializing
|
||||
pushManagerStatusRunning
|
||||
pushManagerStatusShuttingDown
|
||||
)
|
||||
46
vendor/github.com/splitio/go-split-commons/v3/push/manager.go
сгенерированный
поставляемый
46
vendor/github.com/splitio/go-split-commons/v3/push/manager.go
сгенерированный
поставляемый
@@ -11,6 +11,8 @@ import (
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-split-commons/v3/service/api/sse"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-toolkit/v4/common"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
"github.com/splitio/go-toolkit/v4/struct/traits/lifecycle"
|
||||
@@ -48,13 +50,9 @@ type ManagerImpl struct {
|
||||
feedback FeedbackLoop
|
||||
nextRefresh *time.Timer
|
||||
refreshTokenMutex sync.Mutex
|
||||
/*
|
||||
running *gtSync.AtomicBool
|
||||
status int32
|
||||
shutdownWaiter chan struct{}
|
||||
*/
|
||||
lifecycle lifecycle.Manager
|
||||
logger logging.LoggerInterface
|
||||
lifecycle lifecycle.Manager
|
||||
logger logging.LoggerInterface
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// FeedbackLoop is a type alias for the type of chan that must be supplied for push status tobe propagated
|
||||
@@ -67,6 +65,9 @@ func NewManager(
|
||||
cfg *conf.AdvancedConfig,
|
||||
feedbackLoop chan<- int64,
|
||||
authAPI service.AuthClient,
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer,
|
||||
metadata dtos.Metadata,
|
||||
clientKey *string,
|
||||
) (*ManagerImpl, error) {
|
||||
|
||||
processor, err := NewProcessor(cfg.SplitUpdateQueueSize, cfg.SegmentUpdateQueueSize, synchronizer, logger)
|
||||
@@ -74,7 +75,7 @@ func NewManager(
|
||||
return nil, fmt.Errorf("error instantiating processor: %w", err)
|
||||
}
|
||||
|
||||
statusTracker := NewStatusTracker(logger)
|
||||
statusTracker := NewStatusTracker(logger, runtimeTelemetry)
|
||||
parser := &NotificationParserImpl{
|
||||
logger: logger,
|
||||
onSplitUpdate: processor.ProcessSplitChangeUpdate,
|
||||
@@ -86,13 +87,14 @@ func NewManager(
|
||||
}
|
||||
|
||||
manager := &ManagerImpl{
|
||||
authAPI: authAPI,
|
||||
sseClient: sse.NewStreamingClient(cfg, logger),
|
||||
statusTracker: statusTracker,
|
||||
feedback: feedbackLoop,
|
||||
processor: processor,
|
||||
parser: parser,
|
||||
logger: logger,
|
||||
authAPI: authAPI,
|
||||
sseClient: sse.NewStreamingClient(cfg, logger, metadata, clientKey),
|
||||
statusTracker: statusTracker,
|
||||
feedback: feedbackLoop,
|
||||
processor: processor,
|
||||
parser: parser,
|
||||
logger: logger,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
manager.lifecycle.Setup()
|
||||
return manager, nil
|
||||
@@ -135,21 +137,29 @@ func (m *ManagerImpl) StopWorkers() {
|
||||
}
|
||||
|
||||
func (m *ManagerImpl) performAuthentication() (*dtos.Token, *int64) {
|
||||
before := time.Now()
|
||||
token, err := m.authAPI.Authenticate()
|
||||
if err != nil {
|
||||
if errType, ok := err.(dtos.HTTPError); ok {
|
||||
m.runtimeTelemetry.RecordSyncError(telemetry.TokenSync, errType.Code)
|
||||
if errType.Code >= http.StatusInternalServerError {
|
||||
m.logger.Error(fmt.Sprintf("Error authenticating: %s", err.Error()))
|
||||
return nil, common.Int64Ref(StatusRetryableError)
|
||||
}
|
||||
if errType.Code == http.StatusUnauthorized {
|
||||
m.runtimeTelemetry.RecordAuthRejections() // Only 401
|
||||
}
|
||||
return nil, common.Int64Ref(StatusNonRetryableError) // 400, 401, etc
|
||||
}
|
||||
// Not an HTTP eerror, most likely a tcp/bad connection. Should retry
|
||||
// Not an HTTP error, most likely a tcp/bad connection. Should retry
|
||||
return nil, common.Int64Ref(StatusRetryableError)
|
||||
}
|
||||
m.runtimeTelemetry.RecordSyncLatency(telemetry.TokenSync, time.Since(before).Nanoseconds())
|
||||
if !token.PushEnabled {
|
||||
return nil, common.Int64Ref(StatusNonRetryableError)
|
||||
}
|
||||
m.runtimeTelemetry.RecordTokenRefreshes()
|
||||
m.runtimeTelemetry.RecordSuccessfulSync(telemetry.TokenSync, time.Now().UTC().UnixNano()/int64(time.Millisecond))
|
||||
return token, nil
|
||||
}
|
||||
|
||||
@@ -199,6 +209,8 @@ func (m *ManagerImpl) triggerConnectionFlow() {
|
||||
m.logger.Warning("Failed to calculate next token expiration time. Defaulting to 50 minutes")
|
||||
when = 50 * time.Minute
|
||||
}
|
||||
// Tracking TOKEN_REFRESHES
|
||||
m.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeTokenRefresh, when.Milliseconds()))
|
||||
m.withRefreshTokenLock(func() {
|
||||
m.nextRefresh = time.AfterFunc(when, func() {
|
||||
m.logger.Info("Refreshing SSE auth token.")
|
||||
@@ -206,6 +218,8 @@ func (m *ManagerImpl) triggerConnectionFlow() {
|
||||
m.Start()
|
||||
})
|
||||
})
|
||||
// Tracking CONNECTION_ESTABLISHED
|
||||
m.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeSSEConnectionEstablished, 0))
|
||||
m.feedback <- StatusUp
|
||||
case sse.StatusConnectionFailed:
|
||||
m.lifecycle.AbnormalShutdown()
|
||||
|
||||
26
vendor/github.com/splitio/go-split-commons/v3/push/statustracker.go
сгенерированный
поставляемый
26
vendor/github.com/splitio/go-split-commons/v3/push/statustracker.go
сгенерированный
поставляемый
@@ -4,10 +4,17 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-toolkit/v4/common"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
const (
|
||||
pri = "control_pri"
|
||||
sec = "control_sec"
|
||||
)
|
||||
|
||||
// StatusTracker keeps track of the status of the push subsystem and generates appropriate status change notifications.
|
||||
type StatusTracker interface {
|
||||
HandleOccupancy(*OccupancyMessage) *int64
|
||||
@@ -28,6 +35,7 @@ type StatusTrackerImpl struct {
|
||||
lastControlMessage string
|
||||
lastStatusPropagated int64
|
||||
shutdownExpected bool
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// NotifySSEShutdownExpected should be called when we are forcefully closing the SSE client
|
||||
@@ -41,7 +49,7 @@ func (p *StatusTrackerImpl) NotifySSEShutdownExpected() {
|
||||
func (p *StatusTrackerImpl) Reset() {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
p.occupancy = map[string]int64{"control_pri": 2, "control_sec": 2}
|
||||
p.occupancy = map[string]int64{pri: 2, sec: 2}
|
||||
p.lastControlMessage = ControlTypeStreamingEnabled
|
||||
p.lastStatusPropagated = StatusUp
|
||||
p.shutdownExpected = false
|
||||
@@ -63,6 +71,13 @@ func (p *StatusTrackerImpl) HandleOccupancy(message *OccupancyMessage) (newStatu
|
||||
|
||||
p.lastOccupancyTimestamp = message.Timestamp()
|
||||
p.occupancy[channel] = message.Publishers()
|
||||
// Tracking OccupancyEvent
|
||||
switch channel {
|
||||
case pri:
|
||||
p.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeOccupancyPri, message.Publishers()))
|
||||
case sec:
|
||||
p.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeOccupancySec, message.Publishers()))
|
||||
}
|
||||
return p.updateStatus()
|
||||
}
|
||||
|
||||
@@ -77,6 +92,9 @@ func (p *StatusTrackerImpl) HandleAblyError(errorEvent *AblyError) (newStatus *i
|
||||
// Regardless of whether the error is retryable or not, we're going to close the connection
|
||||
p.shutdownExpected = true
|
||||
|
||||
// Tracking ABLY_ERROR
|
||||
p.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeAblyError, int64(errorEvent.Code())))
|
||||
|
||||
if errorEvent.IsRetryable() {
|
||||
p.logger.Info("Received retryable error message. Restarting SSE connection with backoff")
|
||||
return p.propagateStatus(StatusRetryableError)
|
||||
@@ -109,14 +127,16 @@ func (p *StatusTrackerImpl) HandleDisconnection() *int64 {
|
||||
p.mutex.Lock()
|
||||
defer p.mutex.Unlock()
|
||||
if !p.shutdownExpected {
|
||||
p.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeConnectionError, telemetry.NonRequested))
|
||||
return p.propagateStatus(StatusRetryableError)
|
||||
}
|
||||
p.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeConnectionError, telemetry.Requested))
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewStatusTracker returns a new StatusTracker
|
||||
func NewStatusTracker(logger logging.LoggerInterface) *StatusTrackerImpl {
|
||||
tracker := &StatusTrackerImpl{logger: logger}
|
||||
func NewStatusTracker(logger logging.LoggerInterface, runtimeTelemetry storage.TelemetryRuntimeProducer) *StatusTrackerImpl {
|
||||
tracker := &StatusTrackerImpl{logger: logger, runtimeTelemetry: runtimeTelemetry}
|
||||
tracker.Reset()
|
||||
return tracker
|
||||
}
|
||||
|
||||
10
vendor/github.com/splitio/go-split-commons/v3/service/api/client.go
сгенерированный
поставляемый
10
vendor/github.com/splitio/go-split-commons/v3/service/api/client.go
сгенерированный
поставляемый
@@ -30,7 +30,6 @@ type Client interface {
|
||||
type HTTPClient struct {
|
||||
url string
|
||||
httpClient *http.Client
|
||||
headers map[string]string
|
||||
logger logging.LoggerInterface
|
||||
apikey string
|
||||
metadata dtos.Metadata
|
||||
@@ -44,8 +43,7 @@ func NewHTTPClient(
|
||||
logger logging.LoggerInterface,
|
||||
metadata dtos.Metadata,
|
||||
) Client {
|
||||
var timeout int
|
||||
timeout = cfg.HTTPTimeout
|
||||
timeout := cfg.HTTPTimeout
|
||||
client := &http.Client{Timeout: time.Duration(timeout) * time.Second}
|
||||
return &HTTPClient{
|
||||
url: endpoint,
|
||||
@@ -66,11 +64,9 @@ func (c *HTTPClient) Get(service string, headers map[string]string) ([]byte, err
|
||||
c.logger.Debug("Authorization [ApiKey]: ", logging.ObfuscateAPIKey(authorization))
|
||||
req.Header.Add("Accept-Encoding", "gzip")
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
req.Header.Add("SplitSDKVersion", c.metadata.SDKVersion)
|
||||
req.Header.Add("SplitSDKMachineName", c.metadata.MachineName)
|
||||
req.Header.Add("SplitSDKMachineIP", c.metadata.MachineIP)
|
||||
parsedHeaders := AddMetadataToHeaders(c.metadata, headers, nil)
|
||||
|
||||
for headerName, headerValue := range headers {
|
||||
for headerName, headerValue := range parsedHeaders {
|
||||
req.Header.Add(headerName, headerValue)
|
||||
}
|
||||
|
||||
|
||||
32
vendor/github.com/splitio/go-split-commons/v3/service/api/helpers.go
сгенерированный
поставляемый
Обычный файл
32
vendor/github.com/splitio/go-split-commons/v3/service/api/helpers.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,32 @@
|
||||
package api
|
||||
|
||||
import "github.com/splitio/go-split-commons/v3/dtos"
|
||||
|
||||
const (
|
||||
splitSDKVersion = "SplitSDKVersion"
|
||||
splitSDKMachineName = "SplitSDKMachineName"
|
||||
splitSDKMachineIP = "SplitSDKMachineIP"
|
||||
splitSDKClientKey = "SplitSDKClientKey"
|
||||
|
||||
unknown = "unknown"
|
||||
na = "NA"
|
||||
)
|
||||
|
||||
// AddMetadataToHeaders adds metadata in headers
|
||||
func AddMetadataToHeaders(metadata dtos.Metadata, extraHeaders map[string]string, clientKey *string) map[string]string {
|
||||
headers := make(map[string]string)
|
||||
headers[splitSDKVersion] = metadata.SDKVersion
|
||||
if metadata.MachineName != na && metadata.MachineName != unknown {
|
||||
headers[splitSDKMachineName] = metadata.MachineName
|
||||
}
|
||||
if metadata.MachineIP != na && metadata.MachineIP != unknown {
|
||||
headers[splitSDKMachineIP] = metadata.MachineIP
|
||||
}
|
||||
for header, value := range extraHeaders {
|
||||
headers[header] = value
|
||||
}
|
||||
if clientKey != nil {
|
||||
headers[splitSDKClientKey] = *clientKey
|
||||
}
|
||||
return headers
|
||||
}
|
||||
15
vendor/github.com/splitio/go-split-commons/v3/service/api/http_fetchers.go
сгенерированный
поставляемый
15
vendor/github.com/splitio/go-split-commons/v3/service/api/http_fetchers.go
сгенерированный
поставляемый
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
@@ -41,12 +42,7 @@ type HTTPSplitFetcher struct {
|
||||
}
|
||||
|
||||
// NewHTTPSplitFetcher instantiates and return an HTTPSplitFetcher
|
||||
func NewHTTPSplitFetcher(
|
||||
apikey string,
|
||||
cfg conf.AdvancedConfig,
|
||||
logger logging.LoggerInterface,
|
||||
metadata dtos.Metadata,
|
||||
) *HTTPSplitFetcher {
|
||||
func NewHTTPSplitFetcher(apikey string, cfg conf.AdvancedConfig, logger logging.LoggerInterface, metadata dtos.Metadata) service.SplitFetcher {
|
||||
return &HTTPSplitFetcher{
|
||||
httpFetcherBase: httpFetcherBase{
|
||||
client: NewHTTPClient(apikey, cfg, cfg.SdkURL, logger, metadata),
|
||||
@@ -79,12 +75,7 @@ type HTTPSegmentFetcher struct {
|
||||
}
|
||||
|
||||
// NewHTTPSegmentFetcher instantiates and returns a new HTTPSegmentFetcher.
|
||||
func NewHTTPSegmentFetcher(
|
||||
apikey string,
|
||||
cfg conf.AdvancedConfig,
|
||||
logger logging.LoggerInterface,
|
||||
metadata dtos.Metadata,
|
||||
) *HTTPSegmentFetcher {
|
||||
func NewHTTPSegmentFetcher(apikey string, cfg conf.AdvancedConfig, logger logging.LoggerInterface, metadata dtos.Metadata) service.SegmentFetcher {
|
||||
return &HTTPSegmentFetcher{
|
||||
httpFetcherBase: httpFetcherBase{
|
||||
client: NewHTTPClient(apikey, cfg, cfg.SdkURL, logger, metadata),
|
||||
|
||||
149
vendor/github.com/splitio/go-split-commons/v3/service/api/http_recorders.go
сгенерированный
поставляемый
149
vendor/github.com/splitio/go-split-commons/v3/service/api/http_recorders.go
сгенерированный
поставляемый
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
@@ -15,20 +16,7 @@ type httpRecorderBase struct {
|
||||
|
||||
// RecordRaw records raw data
|
||||
func (h *httpRecorderBase) RecordRaw(url string, data []byte, metadata dtos.Metadata, extraHeaders map[string]string) error {
|
||||
headers := make(map[string]string)
|
||||
headers["SplitSDKVersion"] = metadata.SDKVersion
|
||||
if metadata.MachineName != "NA" && metadata.MachineName != "unknown" {
|
||||
headers["SplitSDKMachineName"] = metadata.MachineName
|
||||
}
|
||||
if metadata.MachineIP != "NA" && metadata.MachineIP != "unknown" {
|
||||
headers["SplitSDKMachineIP"] = metadata.MachineIP
|
||||
}
|
||||
if extraHeaders != nil {
|
||||
for header, value := range extraHeaders {
|
||||
headers[header] = value
|
||||
}
|
||||
}
|
||||
return h.client.Post(url, data, headers)
|
||||
return h.client.Post(url, data, AddMetadataToHeaders(metadata, extraHeaders, nil))
|
||||
}
|
||||
|
||||
// HTTPImpressionRecorder is a struct responsible for submitting impression bulks to the backend
|
||||
@@ -74,11 +62,7 @@ func (i *HTTPImpressionRecorder) RecordImpressionsCount(pf dtos.ImpressionsCount
|
||||
}
|
||||
|
||||
// NewHTTPImpressionRecorder instantiates an HTTPImpressionRecorder
|
||||
func NewHTTPImpressionRecorder(
|
||||
apikey string,
|
||||
cfg conf.AdvancedConfig,
|
||||
logger logging.LoggerInterface,
|
||||
) *HTTPImpressionRecorder {
|
||||
func NewHTTPImpressionRecorder(apikey string, cfg conf.AdvancedConfig, logger logging.LoggerInterface) service.ImpressionsRecorder {
|
||||
client := NewHTTPClient(apikey, cfg, cfg.EventsURL, logger, dtos.Metadata{})
|
||||
return &HTTPImpressionRecorder{
|
||||
httpRecorderBase: httpRecorderBase{
|
||||
@@ -88,77 +72,6 @@ func NewHTTPImpressionRecorder(
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPMetricsRecorder is a struct responsible for submitting metrics (latency, gauge, counters) to the backend
|
||||
type HTTPMetricsRecorder struct {
|
||||
httpRecorderBase
|
||||
}
|
||||
|
||||
// RecordCounters method submits counter metrics to the backend
|
||||
func (m *HTTPMetricsRecorder) RecordCounters(counters []dtos.CounterDTO, metadata dtos.Metadata) error {
|
||||
data, err := json.Marshal(counters)
|
||||
if err != nil {
|
||||
m.logger.Error("Error marshaling JSON", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.RecordRaw("/metrics/counters", data, metadata, nil)
|
||||
if err != nil {
|
||||
m.logger.Error("Error posting counters", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecordLatencies method submits latency metrics to the backend
|
||||
func (m *HTTPMetricsRecorder) RecordLatencies(latencies []dtos.LatenciesDTO, metadata dtos.Metadata) error {
|
||||
data, err := json.Marshal(latencies)
|
||||
if err != nil {
|
||||
m.logger.Error("Error marshaling JSON", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.RecordRaw("/metrics/times", data, metadata, nil)
|
||||
if err != nil {
|
||||
m.logger.Error("Error posting latencies", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecordGauge method submits gauge metrics to the backend
|
||||
func (m *HTTPMetricsRecorder) RecordGauge(gauge dtos.GaugeDTO, metadata dtos.Metadata) error {
|
||||
data, err := json.Marshal(gauge)
|
||||
if err != nil {
|
||||
m.logger.Error("Error marshaling JSON", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.RecordRaw("/metrics/gauge", data, metadata, nil)
|
||||
if err != nil {
|
||||
m.logger.Error("Error posting gauges", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewHTTPMetricsRecorder instantiates an HTTPMetricsRecorder
|
||||
func NewHTTPMetricsRecorder(
|
||||
apikey string,
|
||||
cfg conf.AdvancedConfig,
|
||||
logger logging.LoggerInterface,
|
||||
) *HTTPMetricsRecorder {
|
||||
client := NewHTTPClient(apikey, cfg, cfg.EventsURL, logger, dtos.Metadata{})
|
||||
return &HTTPMetricsRecorder{
|
||||
httpRecorderBase: httpRecorderBase{
|
||||
client: client,
|
||||
logger: logger,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPEventsRecorder is a struct responsible for submitting events bulks to the backend
|
||||
type HTTPEventsRecorder struct {
|
||||
httpRecorderBase
|
||||
@@ -182,11 +95,7 @@ func (i *HTTPEventsRecorder) Record(events []dtos.EventDTO, metadata dtos.Metada
|
||||
}
|
||||
|
||||
// NewHTTPEventsRecorder instantiates an HTTPEventsRecorder
|
||||
func NewHTTPEventsRecorder(
|
||||
apikey string,
|
||||
cfg conf.AdvancedConfig,
|
||||
logger logging.LoggerInterface,
|
||||
) *HTTPEventsRecorder {
|
||||
func NewHTTPEventsRecorder(apikey string, cfg conf.AdvancedConfig, logger logging.LoggerInterface) service.EventsRecorder {
|
||||
client := NewHTTPClient(apikey, cfg, cfg.EventsURL, logger, dtos.Metadata{})
|
||||
return &HTTPEventsRecorder{
|
||||
httpRecorderBase: httpRecorderBase{
|
||||
@@ -195,3 +104,53 @@ func NewHTTPEventsRecorder(
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// HTTPTelemetryRecorder is a struct responsible for submitting telemetry to the backend
|
||||
type HTTPTelemetryRecorder struct {
|
||||
httpRecorderBase
|
||||
}
|
||||
|
||||
// NewHTTPTelemetryRecorder instantiates an HTTPTelemetryRecorder
|
||||
func NewHTTPTelemetryRecorder(apikey string, cfg conf.AdvancedConfig, logger logging.LoggerInterface) service.TelemetryRecorder {
|
||||
client := NewHTTPClient(apikey, cfg, cfg.TelemetryServiceURL, logger, dtos.Metadata{})
|
||||
return &HTTPTelemetryRecorder{
|
||||
httpRecorderBase: httpRecorderBase{
|
||||
client: client,
|
||||
logger: logger,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// RecordConfig method submits config
|
||||
func (m *HTTPTelemetryRecorder) RecordConfig(config dtos.Config, metadata dtos.Metadata) error {
|
||||
data, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
m.logger.Error("Error marshaling JSON", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.RecordRaw("/metrics/config", data, metadata, nil)
|
||||
if err != nil {
|
||||
m.logger.Error("Error posting config", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecordStats method submits stats
|
||||
func (m *HTTPTelemetryRecorder) RecordStats(stats dtos.Stats, metadata dtos.Metadata) error {
|
||||
data, err := json.Marshal(stats)
|
||||
if err != nil {
|
||||
m.logger.Error("Error marshaling JSON", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.RecordRaw("/metrics/usage", data, metadata, nil)
|
||||
if err != nil {
|
||||
m.logger.Error("Error posting usage", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
35
vendor/github.com/splitio/go-split-commons/v3/service/api/split.go
сгенерированный
поставляемый
Обычный файл
35
vendor/github.com/splitio/go-split-commons/v3/service/api/split.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,35 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
// SplitAPI struct for fetchers and recorders
|
||||
type SplitAPI struct {
|
||||
AuthClient service.AuthClient
|
||||
SplitFetcher service.SplitFetcher
|
||||
SegmentFetcher service.SegmentFetcher
|
||||
ImpressionRecorder service.ImpressionsRecorder
|
||||
EventRecorder service.EventsRecorder
|
||||
TelemetryRecorder service.TelemetryRecorder
|
||||
}
|
||||
|
||||
// NewSplitAPI creates new splitAPI
|
||||
func NewSplitAPI(
|
||||
apikey string,
|
||||
conf conf.AdvancedConfig,
|
||||
logger logging.LoggerInterface,
|
||||
metadata dtos.Metadata,
|
||||
) *SplitAPI {
|
||||
return &SplitAPI{
|
||||
AuthClient: NewAuthAPIClient(apikey, conf, logger, metadata),
|
||||
SplitFetcher: NewHTTPSplitFetcher(apikey, conf, logger, metadata),
|
||||
SegmentFetcher: NewHTTPSegmentFetcher(apikey, conf, logger, metadata),
|
||||
ImpressionRecorder: NewHTTPImpressionRecorder(apikey, conf, logger),
|
||||
EventRecorder: NewHTTPEventsRecorder(apikey, conf, logger),
|
||||
TelemetryRecorder: NewHTTPTelemetryRecorder(apikey, conf, logger),
|
||||
}
|
||||
}
|
||||
10
vendor/github.com/splitio/go-split-commons/v3/service/api/sse/client.go
сгенерированный
поставляемый
10
vendor/github.com/splitio/go-split-commons/v3/service/api/sse/client.go
сгенерированный
поставляемый
@@ -5,6 +5,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service/api"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
"github.com/splitio/go-toolkit/v4/sse"
|
||||
"github.com/splitio/go-toolkit/v4/struct/traits/lifecycle"
|
||||
@@ -28,6 +30,8 @@ type StreamingClientImpl struct {
|
||||
sseClient *sse.Client
|
||||
logger logging.LoggerInterface
|
||||
lifecycle lifecycle.Manager
|
||||
metadata dtos.Metadata
|
||||
clientKey *string
|
||||
}
|
||||
|
||||
// Status constants
|
||||
@@ -42,12 +46,14 @@ const (
|
||||
type IncomingMessage = sse.RawEvent
|
||||
|
||||
// NewStreamingClient creates new SSE Client
|
||||
func NewStreamingClient(cfg *conf.AdvancedConfig, logger logging.LoggerInterface) *StreamingClientImpl {
|
||||
func NewStreamingClient(cfg *conf.AdvancedConfig, logger logging.LoggerInterface, metadata dtos.Metadata, clientKey *string) *StreamingClientImpl {
|
||||
sseClient, _ := sse.NewClient(cfg.StreamingServiceURL, keepAlive, logger)
|
||||
|
||||
client := &StreamingClientImpl{
|
||||
sseClient: sseClient,
|
||||
logger: logger,
|
||||
metadata: metadata,
|
||||
clientKey: clientKey,
|
||||
}
|
||||
client.lifecycle.Setup()
|
||||
return client
|
||||
@@ -72,7 +78,7 @@ func (s *StreamingClientImpl) ConnectStreaming(token string, streamingStatus cha
|
||||
return
|
||||
}
|
||||
firstEventReceived := gtSync.NewAtomicBool(false)
|
||||
out := s.sseClient.Do(params, func(m IncomingMessage) {
|
||||
out := s.sseClient.Do(params, api.AddMetadataToHeaders(s.metadata, nil, s.clientKey), func(m IncomingMessage) {
|
||||
if firstEventReceived.TestAndSet() && !m.IsError() {
|
||||
streamingStatus <- StatusFirstEventOk
|
||||
}
|
||||
|
||||
9
vendor/github.com/splitio/go-split-commons/v3/service/interfaces.go
сгенерированный
поставляемый
9
vendor/github.com/splitio/go-split-commons/v3/service/interfaces.go
сгенерированный
поставляемый
@@ -25,11 +25,10 @@ type ImpressionsRecorder interface {
|
||||
RecordImpressionsCount(pf dtos.ImpressionsCountDTO, metadata dtos.Metadata) error
|
||||
}
|
||||
|
||||
// MetricsRecorder interface to be implemented by Metrics loggers
|
||||
type MetricsRecorder interface {
|
||||
RecordLatencies(latencies []dtos.LatenciesDTO, metadata dtos.Metadata) error
|
||||
RecordCounters(counters []dtos.CounterDTO, metadata dtos.Metadata) error
|
||||
RecordGauge(gauge dtos.GaugeDTO, metadata dtos.Metadata) error
|
||||
// TelemetryRecorder interface to be implemented by Telemetry loggers
|
||||
type TelemetryRecorder interface {
|
||||
RecordConfig(config dtos.Config, metadata dtos.Metadata) error
|
||||
RecordStats(stats dtos.Stats, metadata dtos.Metadata) error
|
||||
}
|
||||
|
||||
// EventsRecorder interface to post events
|
||||
|
||||
35
vendor/github.com/splitio/go-split-commons/v3/service/split.go
сгенерированный
поставляемый
35
vendor/github.com/splitio/go-split-commons/v3/service/split.go
сгенерированный
поставляемый
@@ -1,35 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service/api"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
// SplitAPI struct for fetchers and recorders
|
||||
type SplitAPI struct {
|
||||
AuthClient AuthClient
|
||||
SplitFetcher SplitFetcher
|
||||
SegmentFetcher SegmentFetcher
|
||||
ImpressionRecorder ImpressionsRecorder
|
||||
EventRecorder EventsRecorder
|
||||
MetricRecorder MetricsRecorder
|
||||
}
|
||||
|
||||
// NewSplitAPI creates new splitAPI
|
||||
func NewSplitAPI(
|
||||
apikey string,
|
||||
conf conf.AdvancedConfig,
|
||||
logger logging.LoggerInterface,
|
||||
metadata dtos.Metadata,
|
||||
) *SplitAPI {
|
||||
return &SplitAPI{
|
||||
AuthClient: api.NewAuthAPIClient(apikey, conf, logger, metadata),
|
||||
SplitFetcher: api.NewHTTPSplitFetcher(apikey, conf, logger, metadata),
|
||||
SegmentFetcher: api.NewHTTPSegmentFetcher(apikey, conf, logger, metadata),
|
||||
ImpressionRecorder: api.NewHTTPImpressionRecorder(apikey, conf, logger),
|
||||
EventRecorder: api.NewHTTPEventsRecorder(apikey, conf, logger),
|
||||
MetricRecorder: api.NewHTTPMetricsRecorder(apikey, conf, logger),
|
||||
}
|
||||
}
|
||||
44
vendor/github.com/splitio/go-split-commons/v3/storage/inmemory/helpers.go
сгенерированный
поставляемый
Обычный файл
44
vendor/github.com/splitio/go-split-commons/v3/storage/inmemory/helpers.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,44 @@
|
||||
package inmemory
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// ErrorOutOfBounds err
|
||||
var ErrorOutOfBounds error = errors.New("out of bounds")
|
||||
|
||||
// AtomicInt64Slice var
|
||||
type AtomicInt64Slice []int64
|
||||
|
||||
// NewAtomicInt64Slice create slice
|
||||
func NewAtomicInt64Slice(size int64) (AtomicInt64Slice, error) {
|
||||
if size <= 0 {
|
||||
return nil, fmt.Errorf("invalid array size: %d", size)
|
||||
}
|
||||
return make([]int64, size), nil
|
||||
}
|
||||
|
||||
// Incr increments inx count
|
||||
func (a AtomicInt64Slice) Incr(index int) {
|
||||
atomic.AddInt64(&a[index], 1)
|
||||
}
|
||||
|
||||
// FetchAndClearOne returns previous and reset
|
||||
func (a AtomicInt64Slice) FetchAndClearOne(index int) (int64, error) {
|
||||
if index >= len(a) || index < 0 {
|
||||
return 0, ErrorOutOfBounds
|
||||
}
|
||||
|
||||
return atomic.SwapInt64(&a[index], 0), nil
|
||||
}
|
||||
|
||||
// FetchAndClearAll returns all and reset
|
||||
func (a AtomicInt64Slice) FetchAndClearAll() []int64 {
|
||||
toRet := make([]int64, len(a))
|
||||
for index := 0; index < len(a); index++ {
|
||||
toRet[index] = atomic.SwapInt64(&a[index], 0)
|
||||
}
|
||||
return toRet
|
||||
}
|
||||
@@ -86,3 +86,14 @@ func (m *MMSegmentStorage) Update(name string, toAdd *set.ThreadUnsafeSet, toRem
|
||||
|
||||
// CountRemovedKeys method
|
||||
func (m *MMSegmentStorage) CountRemovedKeys(segmentName string) int64 { return 0 }
|
||||
|
||||
// SegmentKeysCount
|
||||
func (m *MMSegmentStorage) SegmentKeysCount() int64 {
|
||||
m.mutex.RLock()
|
||||
defer m.mutex.RUnlock()
|
||||
var toReturn int64 = 0
|
||||
for _, keys := range m.data {
|
||||
toReturn = toReturn + int64(keys.Size())
|
||||
}
|
||||
return toReturn
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
@@ -13,13 +15,14 @@ import (
|
||||
const MaxAccumulatedBytes = 5 * 1024 * 1024
|
||||
|
||||
// NewMQEventsStorage returns an instance of MQEventsStorage
|
||||
func NewMQEventsStorage(queueSize int, isFull chan string, logger logging.LoggerInterface) *MQEventsStorage {
|
||||
func NewMQEventsStorage(queueSize int, isFull chan string, logger logging.LoggerInterface, runtimeTelemetry storage.TelemetryRuntimeProducer) *MQEventsStorage {
|
||||
return &MQEventsStorage{
|
||||
queue: list.New(),
|
||||
size: queueSize,
|
||||
mutexQueue: &sync.Mutex{},
|
||||
fullChan: isFull,
|
||||
logger: logger,
|
||||
queue: list.New(),
|
||||
size: queueSize,
|
||||
mutexQueue: &sync.Mutex{},
|
||||
fullChan: isFull,
|
||||
logger: logger,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +39,7 @@ type MQEventsStorage struct {
|
||||
mutexQueue *sync.Mutex
|
||||
fullChan chan string //only write channel
|
||||
logger logging.LoggerInterface
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
func (s *MQEventsStorage) sendSignalIsFull() {
|
||||
@@ -55,12 +59,14 @@ func (s *MQEventsStorage) Push(event dtos.EventDTO, size int) error {
|
||||
defer s.mutexQueue.Unlock()
|
||||
|
||||
if s.queue.Len()+1 > s.size {
|
||||
s.runtimeTelemetry.RecordEventsStats(telemetry.EventsDropped, 1)
|
||||
s.sendSignalIsFull()
|
||||
return ErrorMaxSizeReached
|
||||
}
|
||||
|
||||
// Add element
|
||||
s.queue.PushBack(eventWrapper{event: event, size: size})
|
||||
s.runtimeTelemetry.RecordEventsStats(telemetry.EventsQueued, 1)
|
||||
s.accumulatedBytes += size
|
||||
if s.queue.Len() == s.size || s.accumulatedBytes >= MaxAccumulatedBytes {
|
||||
s.sendSignalIsFull()
|
||||
@@ -5,27 +5,31 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
// NewMQImpressionsStorage returns an instance of MQEventsStorage
|
||||
func NewMQImpressionsStorage(queueSize int, isFull chan<- string, logger logging.LoggerInterface) *MQImpressionsStorage {
|
||||
func NewMQImpressionsStorage(queueSize int, isFull chan<- string, logger logging.LoggerInterface, runtimeTelemetry storage.TelemetryRuntimeProducer) *MQImpressionsStorage {
|
||||
return &MQImpressionsStorage{
|
||||
queue: list.New(),
|
||||
size: queueSize,
|
||||
mutexQueue: &sync.Mutex{},
|
||||
fullChan: isFull,
|
||||
logger: logger,
|
||||
queue: list.New(),
|
||||
size: queueSize,
|
||||
mutexQueue: &sync.Mutex{},
|
||||
fullChan: isFull,
|
||||
logger: logger,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
}
|
||||
|
||||
// MQImpressionsStorage in memory events storage
|
||||
type MQImpressionsStorage struct {
|
||||
queue *list.List
|
||||
size int
|
||||
mutexQueue *sync.Mutex
|
||||
fullChan chan<- string //only write channel
|
||||
logger logging.LoggerInterface
|
||||
queue *list.List
|
||||
size int
|
||||
mutexQueue *sync.Mutex
|
||||
fullChan chan<- string //only write channel
|
||||
logger logging.LoggerInterface
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
func (s *MQImpressionsStorage) sendSignalIsFull() {
|
||||
@@ -59,13 +63,18 @@ func (s *MQImpressionsStorage) LogImpressions(impressions []dtos.Impression) err
|
||||
s.mutexQueue.Lock()
|
||||
defer s.mutexQueue.Unlock()
|
||||
|
||||
impressionsToAdd := len(impressions)
|
||||
|
||||
for _, impression := range impressions {
|
||||
if s.queue.Len()+1 > s.size {
|
||||
s.sendSignalIsFull()
|
||||
s.runtimeTelemetry.RecordImpressionsStats(telemetry.ImpressionsDropped, int64(impressionsToAdd))
|
||||
return ErrorMaxSizeReached
|
||||
}
|
||||
// Add element
|
||||
s.queue.PushBack(impression)
|
||||
s.runtimeTelemetry.RecordImpressionsStats(telemetry.ImpressionsQueued, 1)
|
||||
impressionsToAdd--
|
||||
|
||||
if s.queue.Len() == s.size {
|
||||
s.sendSignalIsFull()
|
||||
480
vendor/github.com/splitio/go-split-commons/v3/storage/inmemory/telemetry.go
сгенерированный
поставляемый
Обычный файл
480
vendor/github.com/splitio/go-split-commons/v3/storage/inmemory/telemetry.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,480 @@
|
||||
package inmemory
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
constants "github.com/splitio/go-split-commons/v3/telemetry"
|
||||
)
|
||||
|
||||
type latencies struct {
|
||||
// MethodLatencies
|
||||
treatment AtomicInt64Slice
|
||||
treatments AtomicInt64Slice
|
||||
treatmentWithConfig AtomicInt64Slice
|
||||
treatmentsWithConfig AtomicInt64Slice
|
||||
track AtomicInt64Slice
|
||||
|
||||
// HTTPLatencies
|
||||
splits AtomicInt64Slice
|
||||
segments AtomicInt64Slice
|
||||
impressions AtomicInt64Slice
|
||||
impressionsCount AtomicInt64Slice
|
||||
events AtomicInt64Slice
|
||||
telemetry AtomicInt64Slice
|
||||
token AtomicInt64Slice
|
||||
}
|
||||
|
||||
type counters struct {
|
||||
// Evaluation Counters
|
||||
treatment int64
|
||||
treatments int64
|
||||
treatmentWithConfig int64
|
||||
treatmentsWithConfig int64
|
||||
track int64
|
||||
|
||||
// Push Counters
|
||||
authRejections int64
|
||||
tokenRefreshes int64
|
||||
|
||||
// Factory Counters
|
||||
burTimeouts int64
|
||||
nonReadyUsages int64
|
||||
}
|
||||
|
||||
type records struct {
|
||||
// Impressions Data
|
||||
impressionsQueued int64
|
||||
impressionsDropped int64
|
||||
impressionsDeduped int64
|
||||
|
||||
// Events Data
|
||||
eventsQueued int64
|
||||
eventsDropped int64
|
||||
|
||||
// LastSynchronization
|
||||
splits int64
|
||||
segments int64
|
||||
impressions int64
|
||||
impressionsCount int64
|
||||
events int64
|
||||
token int64
|
||||
telemetry int64
|
||||
|
||||
// SDK
|
||||
session int64
|
||||
}
|
||||
|
||||
// TelemetryStorage In Memory Telemetry Storage struct
|
||||
type TelemetryStorage struct {
|
||||
counters counters
|
||||
httpErrors dtos.HTTPErrors
|
||||
mutexHTTPErrors sync.RWMutex
|
||||
latencies latencies
|
||||
records records
|
||||
streamingEvents []dtos.StreamingEvent // Max Length 20
|
||||
mutexStreamingEvents sync.RWMutex
|
||||
tags []string
|
||||
mutexTags sync.RWMutex
|
||||
}
|
||||
|
||||
// NewTelemetryStorage builds in memory telemetry storage
|
||||
func NewTelemetryStorage() (storage.TelemetryStorage, error) {
|
||||
treatmentLatencies, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
treatmentWithConfigLatencies, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
treatmentsLatencies, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
treatmentsWithConfigLatencies, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
track, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
|
||||
splits, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
segments, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
impressions, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
impressionsCount, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
events, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
telemetry, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
token, err := NewAtomicInt64Slice(constants.LatencyBucketCount)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create InMemory Storage, %w", err)
|
||||
}
|
||||
|
||||
return &TelemetryStorage{
|
||||
counters: counters{},
|
||||
httpErrors: dtos.HTTPErrors{
|
||||
Splits: make(map[int]int64),
|
||||
Segments: make(map[int]int64),
|
||||
Impressions: make(map[int]int64),
|
||||
ImpressionsCount: make(map[int]int64),
|
||||
Events: make(map[int]int64),
|
||||
Token: make(map[int]int64),
|
||||
Telemetry: make(map[int]int64),
|
||||
},
|
||||
mutexHTTPErrors: sync.RWMutex{},
|
||||
latencies: latencies{
|
||||
treatment: treatmentLatencies,
|
||||
treatmentWithConfig: treatmentWithConfigLatencies,
|
||||
treatments: treatmentsLatencies,
|
||||
treatmentsWithConfig: treatmentsWithConfigLatencies,
|
||||
track: track,
|
||||
|
||||
splits: splits,
|
||||
segments: segments,
|
||||
impressions: impressions,
|
||||
impressionsCount: impressionsCount,
|
||||
events: events,
|
||||
token: token,
|
||||
telemetry: telemetry,
|
||||
},
|
||||
records: records{},
|
||||
streamingEvents: make([]dtos.StreamingEvent, 0, constants.MaxStreamingEvents),
|
||||
mutexStreamingEvents: sync.RWMutex{},
|
||||
tags: make([]string, 0, constants.MaxTags),
|
||||
mutexTags: sync.RWMutex{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TELEMETRY STORAGE PRODUCER
|
||||
|
||||
func (i *TelemetryStorage) RecordConfigData(configData dtos.Config) error {
|
||||
// No-Op. Config Data will be sent directly to Split Servers. No need to store.
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecordLatency stores latency for method
|
||||
func (i *TelemetryStorage) RecordLatency(method string, latency int64) {
|
||||
bucket := constants.Bucket(latency)
|
||||
switch method {
|
||||
case constants.Treatment:
|
||||
i.latencies.treatment.Incr(bucket)
|
||||
case constants.Treatments:
|
||||
i.latencies.treatments.Incr(bucket)
|
||||
case constants.TreatmentWithConfig:
|
||||
i.latencies.treatmentWithConfig.Incr(bucket)
|
||||
case constants.TreatmentsWithConfig:
|
||||
i.latencies.treatmentsWithConfig.Incr(bucket)
|
||||
case constants.Track:
|
||||
i.latencies.track.Incr(bucket)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordException stores exceptions for method
|
||||
func (i *TelemetryStorage) RecordException(method string) {
|
||||
switch method {
|
||||
case constants.Treatment:
|
||||
atomic.AddInt64(&i.counters.treatment, 1)
|
||||
case constants.Treatments:
|
||||
atomic.AddInt64(&i.counters.treatments, 1)
|
||||
case constants.TreatmentWithConfig:
|
||||
atomic.AddInt64(&i.counters.treatmentWithConfig, 1)
|
||||
case constants.TreatmentsWithConfig:
|
||||
atomic.AddInt64(&i.counters.treatmentsWithConfig, 1)
|
||||
case constants.Track:
|
||||
atomic.AddInt64(&i.counters.track, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordImpressionsStats records impressions by type
|
||||
func (i *TelemetryStorage) RecordImpressionsStats(dataType int, count int64) {
|
||||
switch dataType {
|
||||
case constants.ImpressionsDropped:
|
||||
atomic.AddInt64(&i.records.impressionsDropped, count)
|
||||
case constants.ImpressionsDeduped:
|
||||
atomic.AddInt64(&i.records.impressionsDeduped, count)
|
||||
case constants.ImpressionsQueued:
|
||||
atomic.AddInt64(&i.records.impressionsQueued, count)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordEventsStats recirds events by type
|
||||
func (i *TelemetryStorage) RecordEventsStats(dataType int, count int64) {
|
||||
switch dataType {
|
||||
case constants.EventsDropped:
|
||||
atomic.AddInt64(&i.records.eventsDropped, count)
|
||||
case constants.EventsQueued:
|
||||
atomic.AddInt64(&i.records.eventsQueued, count)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordSuccessfulSync records sync for resource
|
||||
func (i *TelemetryStorage) RecordSuccessfulSync(resource int, timestamp int64) {
|
||||
switch resource {
|
||||
case constants.SplitSync:
|
||||
atomic.StoreInt64(&i.records.splits, timestamp)
|
||||
case constants.SegmentSync:
|
||||
atomic.StoreInt64(&i.records.segments, timestamp)
|
||||
case constants.ImpressionSync:
|
||||
atomic.StoreInt64(&i.records.impressions, timestamp)
|
||||
case constants.ImpressionCountSync:
|
||||
atomic.StoreInt64(&i.records.impressionsCount, timestamp)
|
||||
case constants.EventSync:
|
||||
atomic.StoreInt64(&i.records.events, timestamp)
|
||||
case constants.TelemetrySync:
|
||||
atomic.StoreInt64(&i.records.telemetry, timestamp)
|
||||
case constants.TokenSync:
|
||||
atomic.StoreInt64(&i.records.token, timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *TelemetryStorage) createOrUpdate(status int, item map[int]int64) {
|
||||
if item == nil {
|
||||
item[status] = 1
|
||||
return
|
||||
}
|
||||
item[status]++
|
||||
}
|
||||
|
||||
// RecordSyncError records http error
|
||||
func (i *TelemetryStorage) RecordSyncError(resource int, status int) {
|
||||
i.mutexHTTPErrors.Lock()
|
||||
defer i.mutexHTTPErrors.Unlock()
|
||||
switch resource {
|
||||
case constants.SplitSync:
|
||||
i.createOrUpdate(status, i.httpErrors.Splits)
|
||||
case constants.SegmentSync:
|
||||
i.createOrUpdate(status, i.httpErrors.Segments)
|
||||
case constants.ImpressionSync:
|
||||
i.createOrUpdate(status, i.httpErrors.Impressions)
|
||||
case constants.ImpressionCountSync:
|
||||
i.createOrUpdate(status, i.httpErrors.ImpressionsCount)
|
||||
case constants.EventSync:
|
||||
i.createOrUpdate(status, i.httpErrors.Events)
|
||||
case constants.TelemetrySync:
|
||||
i.createOrUpdate(status, i.httpErrors.Telemetry)
|
||||
case constants.TokenSync:
|
||||
i.createOrUpdate(status, i.httpErrors.Token)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordSyncLatency records http error
|
||||
func (i *TelemetryStorage) RecordSyncLatency(resource int, latency int64) {
|
||||
bucket := constants.Bucket(latency)
|
||||
switch resource {
|
||||
case constants.SplitSync:
|
||||
i.latencies.splits.Incr(bucket)
|
||||
case constants.SegmentSync:
|
||||
i.latencies.segments.Incr(bucket)
|
||||
case constants.ImpressionSync:
|
||||
i.latencies.impressions.Incr(bucket)
|
||||
case constants.ImpressionCountSync:
|
||||
i.latencies.impressionsCount.Incr(bucket)
|
||||
case constants.EventSync:
|
||||
i.latencies.events.Incr(bucket)
|
||||
case constants.TelemetrySync:
|
||||
i.latencies.telemetry.Incr(bucket)
|
||||
case constants.TokenSync:
|
||||
i.latencies.token.Incr(bucket)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordAuthRejections records auth rejections
|
||||
func (i *TelemetryStorage) RecordAuthRejections() {
|
||||
atomic.AddInt64(&i.counters.authRejections, 1)
|
||||
}
|
||||
|
||||
// RecordTokenRefreshes records token
|
||||
func (i *TelemetryStorage) RecordTokenRefreshes() {
|
||||
atomic.AddInt64(&i.counters.tokenRefreshes, 1)
|
||||
}
|
||||
|
||||
// RecordStreamingEvent appends new streaming event
|
||||
func (i *TelemetryStorage) RecordStreamingEvent(event *dtos.StreamingEvent) {
|
||||
if event == nil {
|
||||
return
|
||||
}
|
||||
i.mutexStreamingEvents.Lock()
|
||||
defer i.mutexStreamingEvents.Unlock()
|
||||
if len(i.streamingEvents) < constants.MaxStreamingEvents {
|
||||
i.streamingEvents = append(i.streamingEvents, *event)
|
||||
}
|
||||
}
|
||||
|
||||
// AddTag adds particular tag
|
||||
func (i *TelemetryStorage) AddTag(tag string) {
|
||||
i.mutexTags.Lock()
|
||||
defer i.mutexTags.Unlock()
|
||||
if len(i.tags) < constants.MaxTags {
|
||||
i.tags = append(i.tags, tag)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordSessionLength records session length
|
||||
func (i *TelemetryStorage) RecordSessionLength(session int64) {
|
||||
atomic.StoreInt64(&i.records.session, session)
|
||||
}
|
||||
|
||||
// RecordNonReadyUsage records non ready usage
|
||||
func (i *TelemetryStorage) RecordNonReadyUsage() {
|
||||
atomic.AddInt64(&i.counters.nonReadyUsages, 1)
|
||||
}
|
||||
|
||||
// RecordBURTimeout records bur timeodout
|
||||
func (i *TelemetryStorage) RecordBURTimeout() {
|
||||
atomic.AddInt64(&i.counters.burTimeouts, 1)
|
||||
}
|
||||
|
||||
// TELEMETRY STORAGE CONSUMER
|
||||
|
||||
// PopLatencies gets and clears method latencies
|
||||
func (i *TelemetryStorage) PopLatencies() dtos.MethodLatencies {
|
||||
return dtos.MethodLatencies{
|
||||
Treatment: i.latencies.treatment.FetchAndClearAll(),
|
||||
Treatments: i.latencies.treatments.FetchAndClearAll(),
|
||||
TreatmentWithConfig: i.latencies.treatmentWithConfig.FetchAndClearAll(),
|
||||
TreatmentsWithConfig: i.latencies.treatmentsWithConfig.FetchAndClearAll(),
|
||||
Track: i.latencies.track.FetchAndClearAll(),
|
||||
}
|
||||
}
|
||||
|
||||
// PopExceptions gets and clears method exceptions
|
||||
func (i *TelemetryStorage) PopExceptions() dtos.MethodExceptions {
|
||||
return dtos.MethodExceptions{
|
||||
Treatment: atomic.SwapInt64(&i.counters.treatment, 0),
|
||||
Treatments: atomic.SwapInt64(&i.counters.treatments, 0),
|
||||
TreatmentWithConfig: atomic.SwapInt64(&i.counters.treatmentWithConfig, 0),
|
||||
TreatmentsWithConfig: atomic.SwapInt64(&i.counters.treatmentsWithConfig, 0),
|
||||
Track: atomic.SwapInt64(&i.counters.track, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// GetImpressionsStats gets impressions by type
|
||||
func (i *TelemetryStorage) GetImpressionsStats(dataType int) int64 {
|
||||
switch dataType {
|
||||
case constants.ImpressionsDropped:
|
||||
return atomic.LoadInt64(&i.records.impressionsDropped)
|
||||
case constants.ImpressionsDeduped:
|
||||
return atomic.LoadInt64(&i.records.impressionsDeduped)
|
||||
case constants.ImpressionsQueued:
|
||||
return atomic.LoadInt64(&i.records.impressionsQueued)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetEventsStats gets events by type
|
||||
func (i *TelemetryStorage) GetEventsStats(dataType int) int64 {
|
||||
switch dataType {
|
||||
case constants.EventsDropped:
|
||||
return atomic.LoadInt64(&i.records.eventsDropped)
|
||||
case constants.EventsQueued:
|
||||
return atomic.LoadInt64(&i.records.eventsQueued)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetLastSynchronization gets last synchronization stats for fetchers and recorders
|
||||
func (i *TelemetryStorage) GetLastSynchronization() dtos.LastSynchronization {
|
||||
return dtos.LastSynchronization{
|
||||
Splits: atomic.LoadInt64(&i.records.splits),
|
||||
Segments: atomic.LoadInt64(&i.records.segments),
|
||||
Impressions: atomic.LoadInt64(&i.records.impressions),
|
||||
ImpressionsCount: atomic.LoadInt64(&i.records.impressionsCount),
|
||||
Events: atomic.LoadInt64(&i.records.events),
|
||||
Telemetry: atomic.LoadInt64(&i.records.telemetry),
|
||||
Token: atomic.LoadInt64(&i.records.token),
|
||||
}
|
||||
}
|
||||
|
||||
// PopHTTPErrors gets http errors
|
||||
func (i *TelemetryStorage) PopHTTPErrors() dtos.HTTPErrors {
|
||||
i.mutexHTTPErrors.Lock()
|
||||
defer i.mutexHTTPErrors.Unlock()
|
||||
toReturn := i.httpErrors
|
||||
i.httpErrors.Splits = make(map[int]int64)
|
||||
i.httpErrors.Segments = make(map[int]int64)
|
||||
i.httpErrors.Impressions = make(map[int]int64)
|
||||
i.httpErrors.ImpressionsCount = make(map[int]int64)
|
||||
i.httpErrors.Events = make(map[int]int64)
|
||||
i.httpErrors.Telemetry = make(map[int]int64)
|
||||
i.httpErrors.Token = make(map[int]int64)
|
||||
return toReturn
|
||||
}
|
||||
|
||||
// PopHTTPLatencies gets http latencies
|
||||
func (i *TelemetryStorage) PopHTTPLatencies() dtos.HTTPLatencies {
|
||||
return dtos.HTTPLatencies{
|
||||
Splits: i.latencies.splits.FetchAndClearAll(),
|
||||
Segments: i.latencies.segments.FetchAndClearAll(),
|
||||
Impressions: i.latencies.impressions.FetchAndClearAll(),
|
||||
ImpressionsCount: i.latencies.impressionsCount.FetchAndClearAll(),
|
||||
Events: i.latencies.events.FetchAndClearAll(),
|
||||
Telemetry: i.latencies.telemetry.FetchAndClearAll(),
|
||||
Token: i.latencies.token.FetchAndClearAll(),
|
||||
}
|
||||
}
|
||||
|
||||
// PopAuthRejections gets total amount of auth rejections
|
||||
func (i *TelemetryStorage) PopAuthRejections() int64 {
|
||||
return atomic.SwapInt64(&i.counters.authRejections, 0)
|
||||
}
|
||||
|
||||
// PopTokenRefreshes gets total amount of token refreshes
|
||||
func (i *TelemetryStorage) PopTokenRefreshes() int64 {
|
||||
return atomic.SwapInt64(&i.counters.tokenRefreshes, 0)
|
||||
}
|
||||
|
||||
// PopStreamingEvents gets streamingEvents data
|
||||
func (i *TelemetryStorage) PopStreamingEvents() []dtos.StreamingEvent {
|
||||
i.mutexStreamingEvents.Lock()
|
||||
defer i.mutexStreamingEvents.Unlock()
|
||||
toReturn := i.streamingEvents
|
||||
i.streamingEvents = make([]dtos.StreamingEvent, 0, constants.MaxStreamingEvents)
|
||||
return toReturn
|
||||
}
|
||||
|
||||
// PopTags gets total amount of tags
|
||||
func (i *TelemetryStorage) PopTags() []string {
|
||||
i.mutexTags.Lock()
|
||||
defer i.mutexTags.Unlock()
|
||||
toReturn := i.tags
|
||||
i.tags = make([]string, 0, constants.MaxTags)
|
||||
return toReturn
|
||||
}
|
||||
|
||||
// GetSessionLength gets session duration
|
||||
func (i *TelemetryStorage) GetSessionLength() int64 {
|
||||
return atomic.LoadInt64(&i.records.session)
|
||||
}
|
||||
|
||||
// GetNonReadyUsages gets non usages on ready
|
||||
func (i *TelemetryStorage) GetNonReadyUsages() int64 {
|
||||
return atomic.LoadInt64(&i.counters.nonReadyUsages)
|
||||
}
|
||||
|
||||
// GetBURTimeouts gets timedouts data
|
||||
func (i *TelemetryStorage) GetBURTimeouts() int64 {
|
||||
return atomic.LoadInt64(&i.counters.burTimeouts)
|
||||
}
|
||||
105
vendor/github.com/splitio/go-split-commons/v3/storage/interfaces.go
сгенерированный
поставляемый
105
vendor/github.com/splitio/go-split-commons/v3/storage/interfaces.go
сгенерированный
поставляемый
@@ -36,6 +36,7 @@ type SegmentStorageConsumer interface {
|
||||
CountRemovedKeys(segmentName string) int64
|
||||
Keys(segmentName string) *set.ThreadUnsafeSet
|
||||
SegmentContainsKey(segmentName string, key string) (bool, error)
|
||||
SegmentKeysCount() int64
|
||||
}
|
||||
|
||||
// ImpressionStorageProducer interface should be impemented by structs that accept incoming impressions
|
||||
@@ -52,25 +53,6 @@ type ImpressionStorageConsumer interface {
|
||||
PopNWithMetadata(n int64) ([]dtos.ImpressionQueueObject, error)
|
||||
}
|
||||
|
||||
// MetricsStorageProducer interface should be impemented by structs that accept incoming metrics
|
||||
type MetricsStorageProducer interface {
|
||||
PutGauge(key string, gauge float64)
|
||||
IncLatency(metricName string, index int)
|
||||
IncCounter(key string)
|
||||
}
|
||||
|
||||
// MetricsStorageConsumer interface should be implemented by structs that offer popping metrics
|
||||
type MetricsStorageConsumer interface {
|
||||
PeekCounters() map[string]int64
|
||||
PeekLatencies() map[string][]int64
|
||||
PopGauges() []dtos.GaugeDTO
|
||||
PopLatencies() []dtos.LatenciesDTO
|
||||
PopCounters() []dtos.CounterDTO
|
||||
PopGaugesWithMetadata() (*dtos.GaugeDataBulk, error)
|
||||
PopLatenciesWithMetadata() (*dtos.LatencyDataBulk, error)
|
||||
PopCountersWithMetadata() (*dtos.CounterDataBulk, error)
|
||||
}
|
||||
|
||||
// EventStorageProducer interface should be implemented by structs that accept incoming events
|
||||
type EventStorageProducer interface {
|
||||
Push(event dtos.EventDTO, size int) error
|
||||
@@ -85,6 +67,79 @@ type EventStorageConsumer interface {
|
||||
PopNWithMetadata(n int64) ([]dtos.QueueStoredEventDTO, error)
|
||||
}
|
||||
|
||||
// TelemetryStorageProducer interface should be implemented by struct that accepts incoming telemetry
|
||||
type TelemetryStorageProducer interface {
|
||||
TelemetryConfigProducer
|
||||
TelemetryEvaluationProducer
|
||||
TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// TelemetryRedisProducer interface redis
|
||||
type TelemetryRedisProducer interface {
|
||||
TelemetryConfigProducer
|
||||
TelemetryEvaluationProducer
|
||||
}
|
||||
|
||||
// TelemetryConfigProducer interface for config data
|
||||
type TelemetryConfigProducer interface {
|
||||
RecordConfigData(configData dtos.Config) error
|
||||
RecordNonReadyUsage()
|
||||
RecordBURTimeout()
|
||||
}
|
||||
|
||||
// TelemetryEvaluationProducer for evaluation
|
||||
type TelemetryEvaluationProducer interface {
|
||||
RecordLatency(method string, latency int64)
|
||||
RecordException(method string)
|
||||
}
|
||||
|
||||
// TelemetryRuntimeProducer for runtime stats
|
||||
type TelemetryRuntimeProducer interface {
|
||||
AddTag(tag string)
|
||||
RecordImpressionsStats(dataType int, count int64)
|
||||
RecordEventsStats(dataType int, count int64)
|
||||
RecordSuccessfulSync(resource int, time int64)
|
||||
RecordSyncError(resource int, status int)
|
||||
RecordSyncLatency(resource int, latency int64)
|
||||
RecordAuthRejections()
|
||||
RecordTokenRefreshes()
|
||||
RecordStreamingEvent(streamingEvent *dtos.StreamingEvent)
|
||||
RecordSessionLength(session int64)
|
||||
}
|
||||
|
||||
// TelemetryStorageConsumer interface should be implemented by structs that offer popping telemetry
|
||||
type TelemetryStorageConsumer interface {
|
||||
TelemetryConfigConsumer
|
||||
TelemetryEvaluationConsumer
|
||||
TelemetryRuntimeConsumer
|
||||
}
|
||||
|
||||
// TelemetryConfigConsumer interface for config data
|
||||
type TelemetryConfigConsumer interface {
|
||||
GetNonReadyUsages() int64
|
||||
GetBURTimeouts() int64
|
||||
}
|
||||
|
||||
// TelemetryEvaluationConsumer for evaluation
|
||||
type TelemetryEvaluationConsumer interface {
|
||||
PopLatencies() dtos.MethodLatencies
|
||||
PopExceptions() dtos.MethodExceptions
|
||||
}
|
||||
|
||||
// TelemetryRuntimeConsumer for runtime stats
|
||||
type TelemetryRuntimeConsumer interface {
|
||||
GetImpressionsStats(dataType int) int64
|
||||
GetEventsStats(dataType int) int64
|
||||
GetLastSynchronization() dtos.LastSynchronization
|
||||
PopHTTPErrors() dtos.HTTPErrors
|
||||
PopHTTPLatencies() dtos.HTTPLatencies
|
||||
PopAuthRejections() int64
|
||||
PopTokenRefreshes() int64
|
||||
PopStreamingEvents() []dtos.StreamingEvent
|
||||
PopTags() []string
|
||||
GetSessionLength() int64
|
||||
}
|
||||
|
||||
// --- Wide Interfaces
|
||||
|
||||
// SplitStorage wraps consumer & producer interfaces
|
||||
@@ -105,14 +160,14 @@ type ImpressionStorage interface {
|
||||
ImpressionStorageProducer
|
||||
}
|
||||
|
||||
// MetricsStorage wraps consumer and producer interfaces
|
||||
type MetricsStorage interface {
|
||||
MetricsStorageConsumer
|
||||
MetricsStorageProducer
|
||||
}
|
||||
|
||||
// EventsStorage wraps consumer and producer interfaces
|
||||
type EventsStorage interface {
|
||||
EventStorageConsumer
|
||||
EventStorageProducer
|
||||
}
|
||||
|
||||
// TelemetryStorage wraps consumer and producer interfaces
|
||||
type TelemetryStorage interface {
|
||||
TelemetryStorageConsumer
|
||||
TelemetryStorageProducer
|
||||
}
|
||||
|
||||
125
vendor/github.com/splitio/go-split-commons/v3/storage/metricWrapper.go
сгенерированный
поставляемый
125
vendor/github.com/splitio/go-split-commons/v3/storage/metricWrapper.go
сгенерированный
поставляемый
@@ -1,125 +0,0 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
// MetricWrapper struct
|
||||
type MetricWrapper struct {
|
||||
Telemetry MetricsStorage
|
||||
LocalTelemetry MetricsStorage
|
||||
logger logging.LoggerInterface
|
||||
}
|
||||
|
||||
const (
|
||||
// SplitChangesCounter counters
|
||||
SplitChangesCounter = iota
|
||||
// SplitChangesLatency latencies
|
||||
SplitChangesLatency
|
||||
// SegmentChangesCounter counters
|
||||
SegmentChangesCounter
|
||||
// SegmentChangesLatency latencies
|
||||
SegmentChangesLatency
|
||||
// TestImpressionsCounter counter
|
||||
TestImpressionsCounter
|
||||
// TestImpressionsLatency latencies
|
||||
TestImpressionsLatency
|
||||
// PostEventsCounter counter
|
||||
PostEventsCounter
|
||||
//PostEventsLatency latencies
|
||||
PostEventsLatency
|
||||
// MySegmentsCounter counters
|
||||
MySegmentsCounter
|
||||
// MySegmentsLatency latencies
|
||||
MySegmentsLatency
|
||||
)
|
||||
|
||||
const (
|
||||
counter = "backend::request.{status}"
|
||||
|
||||
splitChangesCounter = "splitChangeFetcher.status.{status}"
|
||||
splitChangesLatency = "splitChangeFetcher.time"
|
||||
localSplitChangesLatency = "backend::/api/splitChanges"
|
||||
|
||||
segmentChangesCounter = "segmentChangeFetcher.status.{status}"
|
||||
segmentChangesLatency = "segmentChangeFetcher.time"
|
||||
localSegmentChangesLatency = "backend::/api/segmentChanges"
|
||||
|
||||
testImpressionsCounter = "testImpressions.status.{status}"
|
||||
testImpressionsLatency = "testImpressions.time"
|
||||
localTestImpressionsLatency = "backend::/api/testImpressions/bulk"
|
||||
|
||||
postEventsCounter = "events.status.{status}"
|
||||
postEventsLatency = "events.time"
|
||||
localPostEventsLatency = "backend::/api/events/bulk"
|
||||
|
||||
mySegmentsCounter = "mySegments.status.{status}"
|
||||
mySegmentsLatency = "mySegments.time"
|
||||
localMySegmentsLatency = "backend::/api/mySegments"
|
||||
)
|
||||
|
||||
// NewMetricWrapper builds new wrapper
|
||||
func NewMetricWrapper(telemetry MetricsStorage, localTelemetry MetricsStorage, logger logging.LoggerInterface) *MetricWrapper {
|
||||
return &MetricWrapper{
|
||||
LocalTelemetry: localTelemetry,
|
||||
logger: logger,
|
||||
Telemetry: telemetry,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MetricWrapper) getKey(key int) (string, string, error) {
|
||||
switch key {
|
||||
case SplitChangesCounter:
|
||||
return splitChangesCounter, counter, nil
|
||||
case SplitChangesLatency:
|
||||
return splitChangesLatency, localSplitChangesLatency, nil
|
||||
case SegmentChangesCounter:
|
||||
return segmentChangesCounter, counter, nil
|
||||
case SegmentChangesLatency:
|
||||
return segmentChangesLatency, localSegmentChangesLatency, nil
|
||||
case TestImpressionsCounter:
|
||||
return testImpressionsCounter, counter, nil
|
||||
case TestImpressionsLatency:
|
||||
return testImpressionsLatency, localTestImpressionsLatency, nil
|
||||
case PostEventsCounter:
|
||||
return postEventsCounter, counter, nil
|
||||
case PostEventsLatency:
|
||||
return postEventsLatency, localPostEventsLatency, nil
|
||||
case MySegmentsCounter:
|
||||
return mySegmentsCounter, counter, nil
|
||||
case MySegmentsLatency:
|
||||
return mySegmentsLatency, localMySegmentsLatency, nil
|
||||
default:
|
||||
return "", "", errors.New("Key does not exist")
|
||||
}
|
||||
}
|
||||
|
||||
// StoreCounters stores counters
|
||||
func (m *MetricWrapper) StoreCounters(key int, value string) {
|
||||
common, local, err := m.getKey(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if m.LocalTelemetry != nil {
|
||||
m.LocalTelemetry.IncCounter(strings.Replace(local, "{status}", value, 1))
|
||||
}
|
||||
if value == "ok" {
|
||||
value = "200"
|
||||
}
|
||||
m.Telemetry.IncCounter(strings.Replace(common, "{status}", value, 1))
|
||||
}
|
||||
|
||||
// StoreLatencies stores counters
|
||||
func (m *MetricWrapper) StoreLatencies(key int, bucket int) {
|
||||
common, local, err := m.getKey(key)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if m.LocalTelemetry != nil {
|
||||
m.LocalTelemetry.IncLatency(local, bucket)
|
||||
}
|
||||
m.Telemetry.IncLatency(common, bucket)
|
||||
}
|
||||
73
vendor/github.com/splitio/go-split-commons/v3/storage/mocks/metric.go
сгенерированный
поставляемый
73
vendor/github.com/splitio/go-split-commons/v3/storage/mocks/metric.go
сгенерированный
поставляемый
@@ -1,73 +0,0 @@
|
||||
package mocks
|
||||
|
||||
import "github.com/splitio/go-split-commons/v3/dtos"
|
||||
|
||||
// MockMetricStorage is a mocked implementation of Metric Storage
|
||||
type MockMetricStorage struct {
|
||||
IncCounterCall func(key string)
|
||||
IncLatencyCall func(metricName string, index int)
|
||||
PutGaugeCall func(key string, gauge float64)
|
||||
PopGaugesCall func() []dtos.GaugeDTO
|
||||
PopLatenciesCall func() []dtos.LatenciesDTO
|
||||
PopCountersCall func() []dtos.CounterDTO
|
||||
PeekCountersCall func() map[string]int64
|
||||
PeekLatenciesCall func() map[string][]int64
|
||||
PopGaugesWithMetadataCall func() (*dtos.GaugeDataBulk, error)
|
||||
PopCountersWithMetadataCall func() (*dtos.CounterDataBulk, error)
|
||||
PopLatenciesWithMetadataCall func() (*dtos.LatencyDataBulk, error)
|
||||
}
|
||||
|
||||
// IncCounter mock
|
||||
func (m MockMetricStorage) IncCounter(key string) {
|
||||
m.IncCounterCall(key)
|
||||
}
|
||||
|
||||
// IncLatency mock
|
||||
func (m MockMetricStorage) IncLatency(metricName string, index int) {
|
||||
m.IncLatencyCall(metricName, index)
|
||||
}
|
||||
|
||||
// PutGauge mock
|
||||
func (m MockMetricStorage) PutGauge(key string, gauge float64) {
|
||||
m.PutGaugeCall(key, gauge)
|
||||
}
|
||||
|
||||
// PopGauges mock
|
||||
func (m MockMetricStorage) PopGauges() []dtos.GaugeDTO {
|
||||
return m.PopGaugesCall()
|
||||
}
|
||||
|
||||
// PopLatencies mock
|
||||
func (m MockMetricStorage) PopLatencies() []dtos.LatenciesDTO {
|
||||
return m.PopLatenciesCall()
|
||||
}
|
||||
|
||||
// PopCounters mock
|
||||
func (m MockMetricStorage) PopCounters() []dtos.CounterDTO {
|
||||
return m.PopCountersCall()
|
||||
}
|
||||
|
||||
// PeekCounters mock
|
||||
func (m MockMetricStorage) PeekCounters() map[string]int64 {
|
||||
return m.PeekCountersCall()
|
||||
}
|
||||
|
||||
// PeekLatencies mock
|
||||
func (m MockMetricStorage) PeekLatencies() map[string][]int64 {
|
||||
return m.PeekLatenciesCall()
|
||||
}
|
||||
|
||||
// PopGaugesWithMetadata mock
|
||||
func (m MockMetricStorage) PopGaugesWithMetadata() (*dtos.GaugeDataBulk, error) {
|
||||
return m.PopGaugesWithMetadataCall()
|
||||
}
|
||||
|
||||
// PopCountersWithMetadata mock
|
||||
func (m MockMetricStorage) PopCountersWithMetadata() (*dtos.CounterDataBulk, error) {
|
||||
return m.PopCountersWithMetadataCall()
|
||||
}
|
||||
|
||||
// PopLatenciesWithMetadata mock
|
||||
func (m MockMetricStorage) PopLatenciesWithMetadata() (*dtos.LatencyDataBulk, error) {
|
||||
return m.PopLatenciesWithMetadataCall()
|
||||
}
|
||||
5
vendor/github.com/splitio/go-split-commons/v3/storage/mocks/segment.go
сгенерированный
поставляемый
5
vendor/github.com/splitio/go-split-commons/v3/storage/mocks/segment.go
сгенерированный
поставляемый
@@ -10,6 +10,7 @@ type MockSegmentStorage struct {
|
||||
SegmentContainsKeyCall func(segmentName string, key string) (bool, error)
|
||||
SetChangeNumberCall func(segmentName string, till int64) error
|
||||
CountRemovedKeysCall func(segmentName string) int64
|
||||
SegmentKeysCountCall func() int64
|
||||
}
|
||||
|
||||
// ChangeNumber mock
|
||||
@@ -41,3 +42,7 @@ func (m MockSegmentStorage) SetChangeNumber(segmentName string, till int64) erro
|
||||
func (m MockSegmentStorage) CountRemovedKeys(segmentName string) int64 {
|
||||
return m.CountRemovedKeysCall(segmentName)
|
||||
}
|
||||
|
||||
func (m MockSegmentStorage) SegmentKeysCount() int64 {
|
||||
return m.SegmentKeysCountCall()
|
||||
}
|
||||
|
||||
179
vendor/github.com/splitio/go-split-commons/v3/storage/mocks/telemetry.go
сгенерированный
поставляемый
Обычный файл
179
vendor/github.com/splitio/go-split-commons/v3/storage/mocks/telemetry.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,179 @@
|
||||
package mocks
|
||||
|
||||
import "github.com/splitio/go-split-commons/v3/dtos"
|
||||
|
||||
// MockTelemetryStorage is a mocked implementation of Telemetry Storage
|
||||
type MockTelemetryStorage struct {
|
||||
RecordConfigDataCall func(configData dtos.Config) error
|
||||
RecordLatencyCall func(method string, latency int64)
|
||||
RecordExceptionCall func(method string)
|
||||
RecordImpressionsStatsCall func(dataType int, count int64)
|
||||
RecordEventsStatsCall func(dataType int, count int64)
|
||||
RecordSuccessfulSyncCall func(resource int, time int64)
|
||||
RecordSyncErrorCall func(resource int, status int)
|
||||
RecordSyncLatencyCall func(resource int, latency int64)
|
||||
RecordAuthRejectionsCall func()
|
||||
RecordTokenRefreshesCall func()
|
||||
RecordStreamingEventCall func(streamingEvent *dtos.StreamingEvent)
|
||||
AddTagCall func(tag string)
|
||||
RecordSessionLengthCall func(session int64)
|
||||
RecordNonReadyUsageCall func()
|
||||
RecordBURTimeoutCall func()
|
||||
PopLatenciesCall func() dtos.MethodLatencies
|
||||
PopExceptionsCall func() dtos.MethodExceptions
|
||||
GetImpressionsStatsCall func(dataType int) int64
|
||||
GetEventsStatsCall func(dataType int) int64
|
||||
GetLastSynchronizationCall func() dtos.LastSynchronization
|
||||
PopHTTPErrorsCall func() dtos.HTTPErrors
|
||||
PopHTTPLatenciesCall func() dtos.HTTPLatencies
|
||||
PopAuthRejectionsCall func() int64
|
||||
PopTokenRefreshesCall func() int64
|
||||
PopStreamingEventsCall func() []dtos.StreamingEvent
|
||||
PopTagsCall func() []string
|
||||
GetSessionLengthCall func() int64
|
||||
GetNonReadyUsagesCall func() int64
|
||||
GetBURTimeoutsCall func() int64
|
||||
}
|
||||
|
||||
// RecordConfig mock
|
||||
func (m MockTelemetryStorage) RecordConfigData(configData dtos.Config) error {
|
||||
return m.RecordConfigDataCall(configData)
|
||||
}
|
||||
|
||||
// RecordLatency mock
|
||||
func (m MockTelemetryStorage) RecordLatency(method string, latency int64) {
|
||||
m.RecordLatencyCall(method, latency)
|
||||
}
|
||||
|
||||
// RecordException mock
|
||||
func (m MockTelemetryStorage) RecordException(method string) { m.RecordExceptionCall(method) }
|
||||
|
||||
// RecordImpressionsStats mock
|
||||
func (m MockTelemetryStorage) RecordImpressionsStats(dataType int, count int64) {
|
||||
m.RecordImpressionsStatsCall(dataType, count)
|
||||
}
|
||||
|
||||
// RecordEventsStats mock
|
||||
func (m MockTelemetryStorage) RecordEventsStats(dataType int, count int64) {
|
||||
m.RecordEventsStatsCall(dataType, count)
|
||||
}
|
||||
|
||||
// RecordSuccessfulSync mock
|
||||
func (m MockTelemetryStorage) RecordSuccessfulSync(resource int, time int64) {
|
||||
m.RecordSuccessfulSyncCall(resource, time)
|
||||
}
|
||||
|
||||
// RecordSyncError mock
|
||||
func (m MockTelemetryStorage) RecordSyncError(resource int, status int) {
|
||||
m.RecordSyncErrorCall(resource, status)
|
||||
}
|
||||
|
||||
// RecordSyncLatency mock
|
||||
func (m MockTelemetryStorage) RecordSyncLatency(resource int, latency int64) {
|
||||
m.RecordSyncLatencyCall(resource, latency)
|
||||
}
|
||||
|
||||
// RecordAuthRejections mock
|
||||
func (m MockTelemetryStorage) RecordAuthRejections() {
|
||||
m.RecordAuthRejectionsCall()
|
||||
}
|
||||
|
||||
// RecordTokenRefreshes mock
|
||||
func (m MockTelemetryStorage) RecordTokenRefreshes() {
|
||||
m.RecordTokenRefreshesCall()
|
||||
}
|
||||
|
||||
// RecordStreamingEvent mock
|
||||
func (m MockTelemetryStorage) RecordStreamingEvent(streamingEvent *dtos.StreamingEvent) {
|
||||
m.RecordStreamingEventCall(streamingEvent)
|
||||
}
|
||||
|
||||
// AddTag mock
|
||||
func (m MockTelemetryStorage) AddTag(tag string) {
|
||||
m.AddTagCall(tag)
|
||||
}
|
||||
|
||||
// RecordSessionLength mock
|
||||
func (m MockTelemetryStorage) RecordSessionLength(session int64) {
|
||||
m.RecordSessionLengthCall(session)
|
||||
}
|
||||
|
||||
// RecordNonReadyUsage mock
|
||||
func (m MockTelemetryStorage) RecordNonReadyUsage() {
|
||||
m.RecordNonReadyUsageCall()
|
||||
}
|
||||
|
||||
// RecordBURTimeout mock
|
||||
func (m MockTelemetryStorage) RecordBURTimeout() {
|
||||
m.RecordBURTimeoutCall()
|
||||
}
|
||||
|
||||
// PopLatencies mock
|
||||
func (m MockTelemetryStorage) PopLatencies() dtos.MethodLatencies {
|
||||
return m.PopLatenciesCall()
|
||||
}
|
||||
|
||||
//PopExceptions mock
|
||||
func (m MockTelemetryStorage) PopExceptions() dtos.MethodExceptions {
|
||||
return m.PopExceptionsCall()
|
||||
}
|
||||
|
||||
// GetImpressionsStats mock
|
||||
func (m MockTelemetryStorage) GetImpressionsStats(dataType int) int64 {
|
||||
return m.GetImpressionsStatsCall(dataType)
|
||||
}
|
||||
|
||||
// GetEventsStats mock
|
||||
func (m MockTelemetryStorage) GetEventsStats(dataType int) int64 {
|
||||
return m.GetEventsStatsCall(dataType)
|
||||
}
|
||||
|
||||
// GetLastSynchronization mock
|
||||
func (m MockTelemetryStorage) GetLastSynchronization() dtos.LastSynchronization {
|
||||
return m.GetLastSynchronizationCall()
|
||||
}
|
||||
|
||||
// PopHTTPErrors mock
|
||||
func (m MockTelemetryStorage) PopHTTPErrors() dtos.HTTPErrors {
|
||||
return m.PopHTTPErrorsCall()
|
||||
}
|
||||
|
||||
// PopHTTPLatencies mock
|
||||
func (m MockTelemetryStorage) PopHTTPLatencies() dtos.HTTPLatencies {
|
||||
return m.PopHTTPLatenciesCall()
|
||||
}
|
||||
|
||||
// PopAuthRejections mock
|
||||
func (m MockTelemetryStorage) PopAuthRejections() int64 {
|
||||
return m.PopAuthRejectionsCall()
|
||||
}
|
||||
|
||||
// PopTokenRefreshes mock
|
||||
func (m MockTelemetryStorage) PopTokenRefreshes() int64 {
|
||||
return m.PopTokenRefreshesCall()
|
||||
}
|
||||
|
||||
// PopStreamingEvents mock
|
||||
func (m MockTelemetryStorage) PopStreamingEvents() []dtos.StreamingEvent {
|
||||
return m.PopStreamingEventsCall()
|
||||
}
|
||||
|
||||
// PopTags mock
|
||||
func (m MockTelemetryStorage) PopTags() []string {
|
||||
return m.PopTagsCall()
|
||||
}
|
||||
|
||||
// GetSessionLength mock
|
||||
func (m MockTelemetryStorage) GetSessionLength() int64 {
|
||||
return m.GetSessionLengthCall()
|
||||
}
|
||||
|
||||
// GetNonReadyUsages mock
|
||||
func (m MockTelemetryStorage) GetNonReadyUsages() int64 {
|
||||
return m.GetNonReadyUsagesCall()
|
||||
}
|
||||
|
||||
// GetBURTimeouts mock
|
||||
func (m MockTelemetryStorage) GetBURTimeouts() int64 {
|
||||
return m.GetBURTimeoutsCall()
|
||||
}
|
||||
149
vendor/github.com/splitio/go-split-commons/v3/storage/mutexmap/metrics.go
сгенерированный
поставляемый
149
vendor/github.com/splitio/go-split-commons/v3/storage/mutexmap/metrics.go
сгенерированный
поставляемый
@@ -1,149 +0,0 @@
|
||||
package mutexmap
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
)
|
||||
|
||||
// MMMetricsStorage contains an in-memory implementation of Metrics storage
|
||||
type MMMetricsStorage struct {
|
||||
gaugeData map[string]float64
|
||||
gaugeMutex *sync.Mutex
|
||||
counterData map[string]int64
|
||||
countersMutex *sync.RWMutex
|
||||
latenciesData map[string][]int64
|
||||
latenciesMutex *sync.RWMutex
|
||||
}
|
||||
|
||||
// NewMMMetricsStorage instantiates a new MMMetricsStorage
|
||||
func NewMMMetricsStorage() *MMMetricsStorage {
|
||||
return &MMMetricsStorage{
|
||||
counterData: make(map[string]int64),
|
||||
countersMutex: &sync.RWMutex{},
|
||||
gaugeData: make(map[string]float64),
|
||||
gaugeMutex: &sync.Mutex{},
|
||||
latenciesData: make(map[string][]int64),
|
||||
latenciesMutex: &sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
// PutGauge stores a new gauge value for a specific key
|
||||
func (m *MMMetricsStorage) PutGauge(key string, gauge float64) {
|
||||
m.gaugeMutex.Lock()
|
||||
defer m.gaugeMutex.Unlock()
|
||||
m.gaugeData[key] = gauge
|
||||
}
|
||||
|
||||
// PopGauges returns and deletes all gauges currently stored
|
||||
func (m *MMMetricsStorage) PopGauges() []dtos.GaugeDTO {
|
||||
m.gaugeMutex.Lock()
|
||||
defer func() {
|
||||
m.gaugeData = make(map[string]float64)
|
||||
m.gaugeMutex.Unlock()
|
||||
}()
|
||||
|
||||
gauges := make([]dtos.GaugeDTO, 0)
|
||||
for key, gauge := range m.gaugeData {
|
||||
gauges = append(gauges, dtos.GaugeDTO{
|
||||
MetricName: key,
|
||||
Gauge: gauge,
|
||||
})
|
||||
}
|
||||
return gauges
|
||||
}
|
||||
|
||||
// IncCounter increments the counter for a specific key. It initializes it in 1 if it doesn't exist when this function
|
||||
// is called.
|
||||
func (m *MMMetricsStorage) IncCounter(key string) {
|
||||
m.countersMutex.Lock()
|
||||
defer m.countersMutex.Unlock()
|
||||
_, exists := m.counterData[key]
|
||||
if !exists {
|
||||
m.counterData[key] = 1
|
||||
} else {
|
||||
m.counterData[key]++
|
||||
}
|
||||
}
|
||||
|
||||
// PopCounters returns and deletes all the counters stored
|
||||
func (m *MMMetricsStorage) PopCounters() []dtos.CounterDTO {
|
||||
m.countersMutex.Lock()
|
||||
defer func() {
|
||||
m.counterData = make(map[string]int64)
|
||||
m.countersMutex.Unlock()
|
||||
}()
|
||||
|
||||
counters := make([]dtos.CounterDTO, 0)
|
||||
for key, counter := range m.counterData {
|
||||
counters = append(counters, dtos.CounterDTO{
|
||||
MetricName: key,
|
||||
Count: counter,
|
||||
})
|
||||
}
|
||||
return counters
|
||||
}
|
||||
|
||||
// PeekCounters returns Counters
|
||||
func (m *MMMetricsStorage) PeekCounters() map[string]int64 {
|
||||
m.countersMutex.RLock()
|
||||
defer m.countersMutex.RUnlock()
|
||||
return m.counterData
|
||||
}
|
||||
|
||||
// PeekLatencies returns Latencies
|
||||
func (m *MMMetricsStorage) PeekLatencies() map[string][]int64 {
|
||||
m.latenciesMutex.RLock()
|
||||
defer m.latenciesMutex.RUnlock()
|
||||
return m.latenciesData
|
||||
}
|
||||
|
||||
// IncLatency increments the latency for a specific key and bucket. If the key doesn't exist it's initialized to
|
||||
// an empty array of 23 items.
|
||||
func (m *MMMetricsStorage) IncLatency(metricName string, index int) {
|
||||
if index < 0 || index > 22 {
|
||||
return
|
||||
}
|
||||
m.latenciesMutex.Lock()
|
||||
defer m.latenciesMutex.Unlock()
|
||||
_, exists := m.latenciesData[metricName]
|
||||
if !exists {
|
||||
m.latenciesData[metricName] = make([]int64, 23)
|
||||
m.latenciesData[metricName][index] = 1
|
||||
} else {
|
||||
m.latenciesData[metricName][index]++
|
||||
}
|
||||
}
|
||||
|
||||
// PopLatencies Returns and delete all the latencies currently stored
|
||||
func (m *MMMetricsStorage) PopLatencies() []dtos.LatenciesDTO {
|
||||
m.latenciesMutex.Lock()
|
||||
defer func() {
|
||||
m.latenciesData = make(map[string][]int64)
|
||||
m.latenciesMutex.Unlock()
|
||||
}()
|
||||
|
||||
latencies := make([]dtos.LatenciesDTO, 0)
|
||||
for key, latency := range m.latenciesData {
|
||||
latencies = append(latencies, dtos.LatenciesDTO{
|
||||
Latencies: latency,
|
||||
MetricName: key,
|
||||
})
|
||||
}
|
||||
return latencies
|
||||
}
|
||||
|
||||
// PopGaugesWithMetadata mock
|
||||
func (m *MMMetricsStorage) PopGaugesWithMetadata() (*dtos.GaugeDataBulk, error) {
|
||||
panic("Not implemented for inmemory")
|
||||
}
|
||||
|
||||
// PopLatenciesWithMetadata mock
|
||||
func (m *MMMetricsStorage) PopLatenciesWithMetadata() (*dtos.LatencyDataBulk, error) {
|
||||
panic("Not implemented for inmemory")
|
||||
}
|
||||
|
||||
// PopCountersWithMetadata mock
|
||||
func (m *MMMetricsStorage) PopCountersWithMetadata() (*dtos.CounterDataBulk, error) {
|
||||
panic("Not implemented for inmemory")
|
||||
}
|
||||
28
vendor/github.com/splitio/go-split-commons/v3/storage/redis/constants.go
сгенерированный
поставляемый
28
vendor/github.com/splitio/go-split-commons/v3/storage/redis/constants.go
сгенерированный
поставляемый
@@ -1,17 +1,19 @@
|
||||
package redis
|
||||
|
||||
const (
|
||||
redisSplit = "SPLITIO.split.{split}" // split object
|
||||
redisSplitTill = "SPLITIO.splits.till" // last split fetch
|
||||
redisSegment = "SPLITIO.segment.{segment}" // segment object
|
||||
redisSegmentTill = "SPLITIO.segment.{segment}.till" // last segment fetch
|
||||
redisImpressions = "SPLITIO/{sdkVersion}/{instanceId}/impressions.{feature}" // impressions for a feature
|
||||
redisLatency = "SPLITIO/{sdkVersion}/{instanceId}/latency.{metric}.bucket.{bucket}" // latency bucket
|
||||
redisCounter = "SPLITIO/{sdkVersion}/{instanceId}/count.{metric}" // counter
|
||||
redisGauge = "SPLITIO/{sdkVersion}/{instanceId}/gauge.{metric}" // gauge
|
||||
redisEvents = "SPLITIO.events" // events LIST key
|
||||
redisImpressionsQueue = "SPLITIO.impressions" // impressions LIST key
|
||||
redisImpressionsTTL = 60 // impressions default TTL
|
||||
redisTrafficType = "SPLITIO.trafficType.{trafficType}" // traffic Type fetch
|
||||
redisHash = "SPLITIO.hash"
|
||||
redisSplit = "SPLITIO.split.{split}" // split object
|
||||
redisSplitTill = "SPLITIO.splits.till" // last split fetch
|
||||
redisSegment = "SPLITIO.segment.{segment}" // segment object
|
||||
redisSegmentTill = "SPLITIO.segment.{segment}.till" // last segment fetch
|
||||
redisEvents = "SPLITIO.events" // events LIST key
|
||||
redisImpressionsQueue = "SPLITIO.impressions" // impressions LIST key
|
||||
redisImpressionsTTL = 3600 // impressions default TTL
|
||||
redisTrafficType = "SPLITIO.trafficType.{trafficType}" // traffic Type fetch
|
||||
redisHash = "SPLITIO.hash" // hash key
|
||||
redisConfig = "SPLITIO.telemetry.config" // config Key
|
||||
redisConfigTTL = 3600 // config TTL
|
||||
redisLatency = "SPLITIO.telemetry.latencies" // latency Key
|
||||
redisExceptionField = "{sdkVersion}/{machineName}/{machineIP}/{method}" // exception field template
|
||||
redisException = "SPLITIO.telemetry.exceptions" // exception Key
|
||||
redisLatencyField = "{sdkVersion}/{machineName}/{machineIP}/{method}/{bucket}" // latency field template
|
||||
)
|
||||
|
||||
24
vendor/github.com/splitio/go-split-commons/v3/storage/redis/impressions.go
сгенерированный
поставляемый
24
vendor/github.com/splitio/go-split-commons/v3/storage/redis/impressions.go
сгенерированный
поставляемый
@@ -14,23 +14,21 @@ const impressionsTTLRefresh = time.Duration(3600) * time.Second
|
||||
|
||||
// ImpressionStorage is a redis-based implementation of split storage
|
||||
type ImpressionStorage struct {
|
||||
client *redis.PrefixedRedisClient
|
||||
mutex *sync.Mutex
|
||||
logger logging.LoggerInterface
|
||||
redisKey string
|
||||
impressionsTTL time.Duration
|
||||
metadata dtos.Metadata
|
||||
client *redis.PrefixedRedisClient
|
||||
mutex *sync.Mutex
|
||||
logger logging.LoggerInterface
|
||||
redisKey string
|
||||
metadata dtos.Metadata
|
||||
}
|
||||
|
||||
// NewImpressionStorage creates a new RedisSplitStorage and returns a reference to it
|
||||
func NewImpressionStorage(client *redis.PrefixedRedisClient, metadata dtos.Metadata, logger logging.LoggerInterface) *ImpressionStorage {
|
||||
return &ImpressionStorage{
|
||||
client: client,
|
||||
mutex: &sync.Mutex{},
|
||||
logger: logger,
|
||||
redisKey: redisImpressionsQueue,
|
||||
impressionsTTL: redisImpressionsTTL,
|
||||
metadata: metadata,
|
||||
client: client,
|
||||
mutex: &sync.Mutex{},
|
||||
logger: logger,
|
||||
redisKey: redisImpressionsQueue,
|
||||
metadata: metadata,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +81,7 @@ func (r *ImpressionStorage) push(impressions []dtos.ImpressionQueueObject) error
|
||||
// Checks if expiration needs to be set
|
||||
if inserted == int64(len(impressionsJSON)) {
|
||||
r.logger.Debug("Proceeding to set expiration for: ", r.redisKey)
|
||||
result := r.client.Expire(r.redisKey, time.Duration(r.impressionsTTL)*time.Minute)
|
||||
result := r.client.Expire(r.redisKey, time.Duration(redisImpressionsTTL)*time.Second)
|
||||
if result == false {
|
||||
r.logger.Error("Something were wrong setting expiration", errPush)
|
||||
}
|
||||
|
||||
322
vendor/github.com/splitio/go-split-commons/v3/storage/redis/metrics.go
сгенерированный
поставляемый
322
vendor/github.com/splitio/go-split-commons/v3/storage/redis/metrics.go
сгенерированный
поставляемый
@@ -1,322 +0,0 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
"github.com/splitio/go-toolkit/v4/redis"
|
||||
)
|
||||
|
||||
// MetricsStorage is a redis-based implementation of split storage
|
||||
type MetricsStorage struct {
|
||||
client redis.PrefixedRedisClient
|
||||
logger logging.LoggerInterface
|
||||
gaugeSingleTemplate string
|
||||
countersSingleTemplate string
|
||||
latenciesSingleTemplate string
|
||||
gaugeMultiTemplate string
|
||||
countersMultiTemplate string
|
||||
latenciesMultiTemplate string
|
||||
mutex *sync.RWMutex
|
||||
}
|
||||
|
||||
// NewMetricsStorage creates a new RedisSplitStorage and returns a reference to it
|
||||
func NewMetricsStorage(redisClient *redis.PrefixedRedisClient, metadata dtos.Metadata, logger logging.LoggerInterface) *MetricsStorage {
|
||||
// @Todo Split Storages between Go-Client and Redis
|
||||
gaugeSingleTemplate := strings.Replace(redisGauge, "{sdkVersion}", metadata.SDKVersion, 1)
|
||||
gaugeSingleTemplate = strings.Replace(gaugeSingleTemplate, "{instanceId}", metadata.MachineName, 1)
|
||||
countersSingleTemplate := strings.Replace(redisCounter, "{sdkVersion}", metadata.SDKVersion, 1)
|
||||
countersSingleTemplate = strings.Replace(countersSingleTemplate, "{instanceId}", metadata.MachineName, 1)
|
||||
latenciesSingleTemplate := strings.Replace(redisLatency, "{sdkVersion}", metadata.SDKVersion, 1)
|
||||
latenciesSingleTemplate = strings.Replace(latenciesSingleTemplate, "{instanceId}", metadata.MachineName, 1)
|
||||
|
||||
gaugeMultiTemplate := strings.Replace(redisGauge, "{sdkVersion}", "*", 1)
|
||||
gaugeMultiTemplate = strings.Replace(gaugeMultiTemplate, "{instanceId}", "*", 1)
|
||||
gaugeMultiTemplate = strings.Replace(gaugeMultiTemplate, "{metric}", "*", 1)
|
||||
countersMultiTemplate := strings.Replace(redisCounter, "{sdkVersion}", "*", 1)
|
||||
countersMultiTemplate = strings.Replace(countersMultiTemplate, "{instanceId}", "*", 1)
|
||||
countersMultiTemplate = strings.Replace(countersMultiTemplate, "{metric}", "*", 1)
|
||||
latenciesMultiTemplate := strings.Replace(redisLatency, "{sdkVersion}", "*", 1)
|
||||
latenciesMultiTemplate = strings.Replace(latenciesMultiTemplate, "{instanceId}", "*", 1)
|
||||
latenciesMultiTemplate = strings.Replace(latenciesMultiTemplate, "{metric}", "*", 1)
|
||||
latenciesMultiTemplate = strings.Replace(latenciesMultiTemplate, "{bucket}", "*", 1)
|
||||
|
||||
return &MetricsStorage{
|
||||
client: *redisClient,
|
||||
logger: logger,
|
||||
gaugeSingleTemplate: gaugeSingleTemplate,
|
||||
countersSingleTemplate: countersSingleTemplate,
|
||||
latenciesSingleTemplate: latenciesSingleTemplate,
|
||||
gaugeMultiTemplate: gaugeMultiTemplate,
|
||||
countersMultiTemplate: countersMultiTemplate,
|
||||
latenciesMultiTemplate: latenciesMultiTemplate,
|
||||
mutex: &sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
// IncCounter incraeses the count for a specific metric
|
||||
func (r *MetricsStorage) IncCounter(metric string) {
|
||||
keyToIncr := strings.Replace(r.countersSingleTemplate, "{metric}", metric, 1)
|
||||
_, err := r.client.Incr(keyToIncr)
|
||||
if err != nil {
|
||||
r.logger.Error(fmt.Sprintf("Error incrementing counterfor metric \"%s\" in redis: %s", metric, err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
// IncLatency incraeses the latency of a bucket for a specific metric
|
||||
func (r *MetricsStorage) IncLatency(metric string, index int) {
|
||||
keyToIncr := strings.Replace(r.latenciesSingleTemplate, "{metric}", metric, 1)
|
||||
keyToIncr = strings.Replace(keyToIncr, "{bucket}", strconv.FormatInt(int64(index), 10), 1)
|
||||
_, err := r.client.Incr(keyToIncr)
|
||||
if err != nil {
|
||||
r.logger.Error(fmt.Sprintf(
|
||||
"Error incrementing latency bucket %d for metric \"%s\" in redis: %s", index, metric, err.Error(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// PutGauge stores a gauge in redis
|
||||
func (r *MetricsStorage) PutGauge(key string, gauge float64) {
|
||||
keyToStore := strings.Replace(r.gaugeSingleTemplate, "{metric}", key, 1)
|
||||
err := r.client.Set(keyToStore, gauge, 0)
|
||||
if err != nil {
|
||||
r.logger.Error(fmt.Sprintf("Error storing gauge \"%s\" in redis: %s\n", key, err))
|
||||
}
|
||||
}
|
||||
|
||||
// PopCounters some
|
||||
func (r *MetricsStorage) PopCounters() []dtos.CounterDTO {
|
||||
panic("Not implemented for redis")
|
||||
}
|
||||
|
||||
// PopGauges some
|
||||
func (r *MetricsStorage) PopGauges() []dtos.GaugeDTO {
|
||||
panic("Not implemented for redis")
|
||||
}
|
||||
|
||||
// PopLatencies some
|
||||
func (r *MetricsStorage) PopLatencies() []dtos.LatenciesDTO {
|
||||
panic("Not implemented for redis")
|
||||
}
|
||||
|
||||
func (r *MetricsStorage) popByPattern(pattern string, useTransaction bool) (map[string]interface{}, error) {
|
||||
r.mutex.Lock()
|
||||
defer r.mutex.Unlock()
|
||||
keys, err := r.client.Keys(pattern)
|
||||
if err != nil {
|
||||
r.logger.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
return map[string]interface{}{}, nil
|
||||
}
|
||||
|
||||
values, err := r.client.MGet(keys)
|
||||
if err != nil {
|
||||
r.logger.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
_, err = r.client.Del(keys...)
|
||||
if err != nil {
|
||||
// if we failed to delete the keys, log an error and continue working.
|
||||
r.logger.Error(err.Error())
|
||||
}
|
||||
|
||||
toReturn := make(map[string]interface{})
|
||||
for index := range keys {
|
||||
if index >= len(keys) || index >= len(values) {
|
||||
break
|
||||
}
|
||||
toReturn[keys[index]] = values[index]
|
||||
}
|
||||
return toReturn, nil
|
||||
|
||||
}
|
||||
|
||||
func parseIntRedisValue(s interface{}) (int64, error) {
|
||||
asStr, ok := s.(string)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("%+v is not a string", s)
|
||||
}
|
||||
|
||||
asInt64, err := strconv.ParseInt(asStr, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return asInt64, nil
|
||||
}
|
||||
|
||||
func parseFloatRedisValue(s interface{}) (float64, error) {
|
||||
asStr, ok := s.(string)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("%+v is not a string", s)
|
||||
}
|
||||
|
||||
asFloat64, err := strconv.ParseFloat(asStr, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return asFloat64, nil
|
||||
}
|
||||
|
||||
func (r *MetricsStorage) parseLatencyKey(key string) (string, string, string, int, error) {
|
||||
re := regexp.MustCompile(`(\w+.)?SPLITIO\/([^\/]+)\/([^\/]+)\/latency.([^\/]+).bucket.([0-9]*)`)
|
||||
match := re.FindStringSubmatch(key)
|
||||
|
||||
if len(match) < 6 {
|
||||
return "", "", "", 0, fmt.Errorf("Error parsing key %s", key)
|
||||
}
|
||||
|
||||
sdkNameAndVersion := match[2]
|
||||
if sdkNameAndVersion == "" {
|
||||
return "", "", "", 0, fmt.Errorf("Invalid sdk name/version")
|
||||
}
|
||||
|
||||
machineIP := match[3]
|
||||
if machineIP == "" {
|
||||
return "", "", "", 0, fmt.Errorf("Invalid machine IP")
|
||||
}
|
||||
|
||||
metricName := match[4]
|
||||
if metricName == "" {
|
||||
return "", "", "", 0, fmt.Errorf("Invalid feature name")
|
||||
}
|
||||
|
||||
bucketNumber, err := strconv.Atoi(match[5])
|
||||
if err != nil {
|
||||
return "", "", "", 0, fmt.Errorf("Error parsing bucket number: %s", err.Error())
|
||||
}
|
||||
r.logger.Verbose("Impression parsed key", match)
|
||||
|
||||
return sdkNameAndVersion, machineIP, metricName, bucketNumber, nil
|
||||
}
|
||||
|
||||
func (r *MetricsStorage) parseMetricKey(metricType string, key string) (string, string, string, error) {
|
||||
var re = regexp.MustCompile(strings.Replace(
|
||||
`(\w+.)?SPLITIO\/([^\/]+)\/([^\/]+)\/{metricType}.([\s\S]*)`,
|
||||
"{metricType}",
|
||||
metricType,
|
||||
1,
|
||||
))
|
||||
match := re.FindStringSubmatch(key)
|
||||
|
||||
if len(match) < 5 {
|
||||
return "", "", "", fmt.Errorf("Error parsing key %s", key)
|
||||
}
|
||||
|
||||
sdkNameAndVersion := match[2]
|
||||
if sdkNameAndVersion == "" {
|
||||
return "", "", "", fmt.Errorf("Invalid sdk name/version")
|
||||
}
|
||||
|
||||
machineIP := match[3]
|
||||
if machineIP == "" {
|
||||
return "", "", "", fmt.Errorf("Invalid machine IP")
|
||||
}
|
||||
|
||||
metricName := match[4]
|
||||
if metricName == "" {
|
||||
return "", "", "", fmt.Errorf("Invalid feature name")
|
||||
}
|
||||
|
||||
r.logger.Verbose("Impression parsed key", match)
|
||||
|
||||
return sdkNameAndVersion, machineIP, metricName, nil
|
||||
}
|
||||
|
||||
// PopGaugesWithMetadata returns gauges values saved in Redis by SDKs
|
||||
func (r *MetricsStorage) PopGaugesWithMetadata() (*dtos.GaugeDataBulk, error) {
|
||||
data, err := r.popByPattern(r.gaugeMultiTemplate, false)
|
||||
if err != nil {
|
||||
r.logger.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gaugesToReturn := dtos.NewGaugeDataBulk()
|
||||
for key, value := range data {
|
||||
sdkNameAndVersion, machineIP, metricName, err := r.parseMetricKey("gauge", key)
|
||||
if err != nil {
|
||||
r.logger.Error(fmt.Sprintf("Unable to parse key %s. Skipping", key))
|
||||
continue
|
||||
}
|
||||
asFloat, err := parseFloatRedisValue(value)
|
||||
if err != nil {
|
||||
r.logger.Error(fmt.Sprintf("Unable to parse value %+v. Skipping", value))
|
||||
continue
|
||||
}
|
||||
gaugesToReturn.PutGauge(sdkNameAndVersion, machineIP, metricName, asFloat)
|
||||
}
|
||||
|
||||
return gaugesToReturn, nil
|
||||
}
|
||||
|
||||
// PopCountersWithMetadata returns counter values saved in Redis by SDKs
|
||||
func (r *MetricsStorage) PopCountersWithMetadata() (*dtos.CounterDataBulk, error) {
|
||||
data, err := r.popByPattern(r.countersMultiTemplate, false)
|
||||
if err != nil {
|
||||
r.logger.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
countersToReturn := dtos.NewCounterDataBulk()
|
||||
for key, value := range data {
|
||||
sdkNameAndVersion, machineIP, metricName, err := r.parseMetricKey("count", key)
|
||||
if err != nil {
|
||||
r.logger.Error("Unable to parse key %s. Skipping", key)
|
||||
continue
|
||||
}
|
||||
asInt, err := parseIntRedisValue(value)
|
||||
if err != nil {
|
||||
r.logger.Error(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
countersToReturn.PutCounter(sdkNameAndVersion, machineIP, metricName, asInt)
|
||||
}
|
||||
|
||||
return countersToReturn, nil
|
||||
}
|
||||
|
||||
// PopLatenciesWithMetadata returns latency values saved in Redis by SDKs
|
||||
func (r *MetricsStorage) PopLatenciesWithMetadata() (*dtos.LatencyDataBulk, error) {
|
||||
data, err := r.popByPattern(r.latenciesMultiTemplate, false)
|
||||
if err != nil {
|
||||
r.logger.Error(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
latenciesToReturn := dtos.NewLatencyDataBulk()
|
||||
for key, value := range data {
|
||||
value, err := parseIntRedisValue(value)
|
||||
if err != nil {
|
||||
r.logger.Warning(fmt.Sprintf("Unable to parse value of key %s. Skipping", key))
|
||||
continue
|
||||
}
|
||||
sdkNameAndVersion, machineIP, metricName, bucketNumber, err := r.parseLatencyKey(key)
|
||||
if err != nil {
|
||||
r.logger.Warning(fmt.Sprintf("Unable to parse key %s. Skipping", key))
|
||||
continue
|
||||
}
|
||||
latenciesToReturn.PutLatency(sdkNameAndVersion, machineIP, metricName, bucketNumber, value)
|
||||
}
|
||||
r.logger.Verbose(latenciesToReturn)
|
||||
return latenciesToReturn, nil
|
||||
}
|
||||
|
||||
// PeekCounters returns Counters
|
||||
func (r *MetricsStorage) PeekCounters() map[string]int64 {
|
||||
return make(map[string]int64, 0)
|
||||
}
|
||||
|
||||
// PeekLatencies returns Latencies
|
||||
func (r *MetricsStorage) PeekLatencies() map[string][]int64 {
|
||||
return make(map[string][]int64, 0)
|
||||
}
|
||||
6
vendor/github.com/splitio/go-split-commons/v3/storage/redis/segments.go
сгенерированный
поставляемый
6
vendor/github.com/splitio/go-split-commons/v3/storage/redis/segments.go
сгенерированный
поставляемый
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-toolkit/v4/datastructures/set"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
"github.com/splitio/go-toolkit/v4/redis"
|
||||
@@ -19,7 +20,7 @@ type SegmentStorage struct {
|
||||
}
|
||||
|
||||
// NewSegmentStorage creates a new RedisSegmentStorage and returns a reference to it
|
||||
func NewSegmentStorage(redisClient *redis.PrefixedRedisClient, logger logging.LoggerInterface) *SegmentStorage {
|
||||
func NewSegmentStorage(redisClient *redis.PrefixedRedisClient, logger logging.LoggerInterface) storage.SegmentStorage {
|
||||
return &SegmentStorage{
|
||||
client: *redisClient,
|
||||
logger: logger,
|
||||
@@ -98,3 +99,6 @@ func (r *SegmentStorage) SegmentContainsKey(segmentName string, key string) (boo
|
||||
|
||||
// CountRemovedKeys method
|
||||
func (r *SegmentStorage) CountRemovedKeys(segmentName string) int64 { return 0 }
|
||||
|
||||
// SegmentKeysCount method
|
||||
func (r *SegmentStorage) SegmentKeysCount() int64 { return 0 }
|
||||
|
||||
105
vendor/github.com/splitio/go-split-commons/v3/storage/redis/telemetry.go
сгенерированный
поставляемый
Обычный файл
105
vendor/github.com/splitio/go-split-commons/v3/storage/redis/telemetry.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,105 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
"github.com/splitio/go-toolkit/v4/redis"
|
||||
)
|
||||
|
||||
const (
|
||||
sdkVersion = "{sdkVersion}"
|
||||
machineIP = "{machineIP}"
|
||||
machineName = "{machineName}"
|
||||
name = "{method}"
|
||||
bucketName = "{bucket}"
|
||||
)
|
||||
|
||||
// TelemetryStorage is a redis-based implementation of telemetry storage
|
||||
type TelemetryStorage struct {
|
||||
client *redis.PrefixedRedisClient
|
||||
exceptionTemplate string
|
||||
latencyTemplate string
|
||||
logger logging.LoggerInterface
|
||||
metadata dtos.Metadata
|
||||
}
|
||||
|
||||
// NewTelemetryStorage creates a new RedisTelemetryStorage and returns a reference to it
|
||||
func NewTelemetryStorage(redisClient *redis.PrefixedRedisClient, logger logging.LoggerInterface, metadata dtos.Metadata) storage.TelemetryRedisProducer {
|
||||
replacer := strings.NewReplacer(sdkVersion, metadata.SDKVersion, machineName, metadata.MachineName, machineIP, metadata.MachineIP)
|
||||
exceptionTemplate := replacer.Replace(redisExceptionField)
|
||||
latencyTemplate := replacer.Replace(redisLatencyField)
|
||||
|
||||
return &TelemetryStorage{
|
||||
client: redisClient,
|
||||
exceptionTemplate: exceptionTemplate,
|
||||
latencyTemplate: latencyTemplate,
|
||||
logger: logger,
|
||||
metadata: metadata,
|
||||
}
|
||||
}
|
||||
|
||||
// TELEMETRY STORAGE PRODUCER
|
||||
|
||||
// RecordConfigData push config into queue
|
||||
func (t *TelemetryStorage) RecordConfigData(configData dtos.Config) error {
|
||||
jsonData, err := json.Marshal(dtos.TelemetryQueueObject{
|
||||
Metadata: t.metadata,
|
||||
Config: configData,
|
||||
})
|
||||
if err != nil {
|
||||
t.logger.Error("Error encoding impression in json", err.Error())
|
||||
}
|
||||
|
||||
inserted, errPush := t.client.RPush(redisConfig, jsonData)
|
||||
if errPush != nil {
|
||||
t.logger.Error("Something were wrong pushing config data to redis", errPush)
|
||||
return errPush
|
||||
}
|
||||
|
||||
// Checks if expiration needs to be set
|
||||
if inserted == 1 {
|
||||
t.logger.Debug("Proceeding to set expiration for: ", redisConfig)
|
||||
result := t.client.Expire(redisConfig, time.Duration(redisConfigTTL)*time.Second)
|
||||
if !result {
|
||||
t.logger.Error("Something were wrong setting expiration", errPush)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecordLatency stores latency for method
|
||||
func (t *TelemetryStorage) RecordLatency(method string, latency int64) {
|
||||
bucket := telemetry.Bucket(latency)
|
||||
field := strings.Replace(t.latencyTemplate, name, method, 1)
|
||||
field = strings.Replace(field, bucketName, fmt.Sprintf("%d", bucket), 1)
|
||||
_, err := t.client.HIncrBy(redisLatency, field, 1)
|
||||
if err != nil {
|
||||
t.logger.Error("Error recording in redis.", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// RecordException stores exceptions for method
|
||||
func (t *TelemetryStorage) RecordException(method string) {
|
||||
field := strings.Replace(t.exceptionTemplate, name, method, 1)
|
||||
_, err := t.client.HIncrBy(redisException, field, 1)
|
||||
if err != nil {
|
||||
t.logger.Error("Error recording in redis.", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// RecordNonReadyUsage records non ready usage
|
||||
func (t *TelemetryStorage) RecordNonReadyUsage() {
|
||||
// No-Op. Redis is implicitly ready and does not need to wait for anything. Tracking not required.
|
||||
}
|
||||
|
||||
// RecordBURTimeout records bur timeodout
|
||||
func (t *TelemetryStorage) RecordBURTimeout() {
|
||||
// No-Op. Redis is implicitly ready and does not need to block for anything. Tracking not required.
|
||||
}
|
||||
29
vendor/github.com/splitio/go-split-commons/v3/synchronizer/local.go
сгенерированный
поставляемый
29
vendor/github.com/splitio/go-split-commons/v3/synchronizer/local.go
сгенерированный
поставляемый
@@ -1,10 +1,8 @@
|
||||
package synchronizer
|
||||
|
||||
import (
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-split-commons/v3/service/api"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
storageMock "github.com/splitio/go-split-commons/v3/storage/mocks"
|
||||
"github.com/splitio/go-split-commons/v3/synchronizer/worker/split"
|
||||
"github.com/splitio/go-split-commons/v3/tasks"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
@@ -12,30 +10,15 @@ import (
|
||||
|
||||
// Local implements Local Synchronizer
|
||||
type Local struct {
|
||||
splitTasks SplitTasks
|
||||
workers Workers
|
||||
logger logging.LoggerInterface
|
||||
inMememoryFullQueue chan string
|
||||
splitTasks SplitTasks
|
||||
workers Workers
|
||||
logger logging.LoggerInterface
|
||||
}
|
||||
|
||||
// NewLocal creates new Local
|
||||
func NewLocal(
|
||||
period int,
|
||||
splitAPI *service.SplitAPI,
|
||||
splitStorage storage.SplitStorage,
|
||||
logger logging.LoggerInterface,
|
||||
) Synchronizer {
|
||||
metricStorageMock := storageMock.MockMetricStorage{
|
||||
IncCounterCall: func(key string) {},
|
||||
IncLatencyCall: func(metricName string, index int) {},
|
||||
PopCountersCall: func() []dtos.CounterDTO { return make([]dtos.CounterDTO, 0, 0) },
|
||||
PopGaugesCall: func() []dtos.GaugeDTO { return make([]dtos.GaugeDTO, 0, 0) },
|
||||
PopLatenciesCall: func() []dtos.LatenciesDTO { return make([]dtos.LatenciesDTO, 0, 0) },
|
||||
PutGaugeCall: func(key string, gauge float64) {},
|
||||
}
|
||||
metricsWrapper := storage.NewMetricWrapper(metricStorageMock, nil, logger)
|
||||
func NewLocal(period int, splitAPI *api.SplitAPI, splitStorage storage.SplitStorage, logger logging.LoggerInterface, runtimeTelemetry storage.TelemetryRuntimeProducer) Synchronizer {
|
||||
workers := Workers{
|
||||
SplitFetcher: split.NewSplitFetcher(splitStorage, splitAPI.SplitFetcher, metricsWrapper, logger),
|
||||
SplitFetcher: split.NewSplitFetcher(splitStorage, splitAPI.SplitFetcher, logger, runtimeTelemetry),
|
||||
}
|
||||
return &Local{
|
||||
splitTasks: SplitTasks{
|
||||
|
||||
50
vendor/github.com/splitio/go-split-commons/v3/synchronizer/manager.go
сгенерированный
поставляемый
50
vendor/github.com/splitio/go-split-commons/v3/synchronizer/manager.go
сгенерированный
поставляемый
@@ -6,9 +6,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/push"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-toolkit/v4/backoff"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
"github.com/splitio/go-toolkit/v4/struct/traits/lifecycle"
|
||||
@@ -38,15 +40,16 @@ type Manager interface {
|
||||
|
||||
// ManagerImpl struct
|
||||
type ManagerImpl struct {
|
||||
synchronizer Synchronizer
|
||||
logger logging.LoggerInterface
|
||||
config conf.AdvancedConfig
|
||||
pushManager push.Manager
|
||||
managerStatus chan int
|
||||
streamingStatus chan int64
|
||||
operationMode int32
|
||||
lifecycle lifecycle.Manager
|
||||
backoff backoff.Interface
|
||||
synchronizer Synchronizer
|
||||
logger logging.LoggerInterface
|
||||
config conf.AdvancedConfig
|
||||
pushManager push.Manager
|
||||
managerStatus chan int
|
||||
streamingStatus chan int64
|
||||
operationMode int32
|
||||
lifecycle lifecycle.Manager
|
||||
backoff backoff.Interface
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// NewSynchronizerManager creates new sync manager
|
||||
@@ -57,22 +60,29 @@ func NewSynchronizerManager(
|
||||
authClient service.AuthClient,
|
||||
splitStorage storage.SplitStorage,
|
||||
managerStatus chan int,
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer,
|
||||
metadata dtos.Metadata,
|
||||
clientKey *string,
|
||||
) (*ManagerImpl, error) {
|
||||
if managerStatus == nil || cap(managerStatus) < 1 {
|
||||
return nil, errors.New("Status channel cannot be nil nor having capacity")
|
||||
}
|
||||
|
||||
manager := &ManagerImpl{
|
||||
backoff: backoff.New(),
|
||||
synchronizer: synchronizer,
|
||||
logger: logger,
|
||||
config: config,
|
||||
managerStatus: managerStatus,
|
||||
backoff: backoff.New(),
|
||||
synchronizer: synchronizer,
|
||||
logger: logger,
|
||||
config: config,
|
||||
managerStatus: managerStatus,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
manager.lifecycle.Setup()
|
||||
if config.StreamingEnabled {
|
||||
streamingStatus := make(chan int64, 1000)
|
||||
pushManager, err := push.NewManager(logger, synchronizer, &config, streamingStatus, authClient)
|
||||
if clientKey != nil && len(*clientKey) != 4 {
|
||||
return nil, errors.New("invalid ClientKey")
|
||||
}
|
||||
pushManager, err := push.NewManager(logger, synchronizer, &config, streamingStatus, authClient, runtimeTelemetry, metadata, clientKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -182,6 +192,8 @@ func (s *ManagerImpl) pushStatusWatcher() {
|
||||
s.pushManager.Stop()
|
||||
s.synchronizer.SyncAll(false)
|
||||
s.startPolling()
|
||||
// Tracking STREAMING_DISABLED
|
||||
s.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeStreamingStatus, telemetry.StreamingDisabled))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,6 +202,8 @@ func (s *ManagerImpl) pushStatusWatcher() {
|
||||
func (s *ManagerImpl) startPolling() {
|
||||
atomic.StoreInt32(&s.operationMode, Polling)
|
||||
s.synchronizer.StartPeriodicFetching()
|
||||
// Tracking POLLING
|
||||
s.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeSyncMode, telemetry.Polling))
|
||||
}
|
||||
|
||||
func (s *ManagerImpl) stopPolling() {
|
||||
@@ -198,10 +212,16 @@ func (s *ManagerImpl) stopPolling() {
|
||||
|
||||
func (s *ManagerImpl) pauseStreaming() {
|
||||
s.pushManager.StartWorkers()
|
||||
// Tracking STREAMING_PAUSED
|
||||
s.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeStreamingStatus, telemetry.StreamingPaused))
|
||||
}
|
||||
|
||||
func (s *ManagerImpl) enableStreaming() {
|
||||
s.pushManager.StartWorkers()
|
||||
atomic.StoreInt32(&s.operationMode, Streaming)
|
||||
s.backoff.Reset()
|
||||
// Tracking STREAMING
|
||||
s.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeSyncMode, telemetry.Streaming))
|
||||
// Tracking STREAMING_ENABLED
|
||||
s.runtimeTelemetry.RecordStreamingEvent(telemetry.GetStreamingEvent(telemetry.EventTypeStreamingStatus, telemetry.StreamingEnabled))
|
||||
}
|
||||
|
||||
9
vendor/github.com/splitio/go-split-commons/v3/synchronizer/synchronizer.go
сгенерированный
поставляемый
9
vendor/github.com/splitio/go-split-commons/v3/synchronizer/synchronizer.go
сгенерированный
поставляемый
@@ -5,10 +5,10 @@ import (
|
||||
"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/asynctask"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
@@ -27,7 +27,7 @@ type SplitTasks struct {
|
||||
type Workers struct {
|
||||
SplitFetcher split.Updater
|
||||
SegmentFetcher segment.Updater
|
||||
TelemetryRecorder metric.MetricRecorder
|
||||
TelemetryRecorder telemetry.TelemetrySynchronizer
|
||||
ImpressionRecorder impression.ImpressionRecorder
|
||||
EventRecorder event.EventRecorder
|
||||
ImpressionsCountRecorder impressionscount.ImpressionsCountRecorder
|
||||
@@ -62,7 +62,7 @@ func NewSynchronizer(
|
||||
}
|
||||
|
||||
func (s *SynchronizerImpl) dataFlusher() {
|
||||
for true {
|
||||
for {
|
||||
msg := <-s.inMememoryFullQueue
|
||||
switch msg {
|
||||
case "EVENTS_FULL":
|
||||
@@ -71,7 +71,6 @@ func (s *SynchronizerImpl) dataFlusher() {
|
||||
if err != nil {
|
||||
s.logger.Error("Error flushing storage queue", err)
|
||||
}
|
||||
break
|
||||
case "IMPRESSIONS_FULL":
|
||||
s.logger.Debug("FLUSHING storage queue")
|
||||
err := s.workers.ImpressionRecorder.SynchronizeImpressions(s.impressionBulkSize)
|
||||
@@ -137,7 +136,7 @@ func (s *SynchronizerImpl) StopPeriodicDataRecording() {
|
||||
s.splitTasks.ImpressionSyncTask.Stop(true)
|
||||
}
|
||||
if s.splitTasks.TelemetrySyncTask != nil {
|
||||
s.splitTasks.TelemetrySyncTask.Stop(false)
|
||||
s.splitTasks.TelemetrySyncTask.Stop(true)
|
||||
}
|
||||
if s.splitTasks.EventSyncTask != nil {
|
||||
s.splitTasks.EventSyncTask.Stop(true)
|
||||
|
||||
32
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/event/single.go
сгенерированный
поставляемый
32
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/event/single.go
сгенерированный
поставляемый
@@ -2,39 +2,38 @@ package event
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"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"
|
||||
)
|
||||
|
||||
// RecorderSingle struct for event sync
|
||||
type RecorderSingle struct {
|
||||
eventStorage storage.EventStorageConsumer
|
||||
eventRecorder service.EventsRecorder
|
||||
metricsWrapper *storage.MetricWrapper
|
||||
logger logging.LoggerInterface
|
||||
metadata dtos.Metadata
|
||||
eventStorage storage.EventStorageConsumer
|
||||
eventRecorder service.EventsRecorder
|
||||
logger logging.LoggerInterface
|
||||
metadata dtos.Metadata
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// NewEventRecorderSingle creates new event synchronizer for posting events
|
||||
func NewEventRecorderSingle(
|
||||
eventStorage storage.EventStorageConsumer,
|
||||
eventRecorder service.EventsRecorder,
|
||||
metricsWrapper *storage.MetricWrapper,
|
||||
logger logging.LoggerInterface,
|
||||
metadata dtos.Metadata,
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer,
|
||||
) EventRecorder {
|
||||
return &RecorderSingle{
|
||||
eventStorage: eventStorage,
|
||||
eventRecorder: eventRecorder,
|
||||
metricsWrapper: metricsWrapper,
|
||||
logger: logger,
|
||||
metadata: metadata,
|
||||
eventStorage: eventStorage,
|
||||
eventRecorder: eventRecorder,
|
||||
logger: logger,
|
||||
metadata: metadata,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,13 +54,12 @@ func (e *RecorderSingle) SynchronizeEvents(bulkSize int64) error {
|
||||
err = e.eventRecorder.Record(queuedEvents, e.metadata)
|
||||
if err != nil {
|
||||
if httpError, ok := err.(*dtos.HTTPError); ok {
|
||||
e.metricsWrapper.StoreCounters(storage.PostEventsCounter, strconv.Itoa(httpError.Code))
|
||||
e.runtimeTelemetry.RecordSyncError(telemetry.EventSync, httpError.Code)
|
||||
}
|
||||
return err
|
||||
}
|
||||
bucket := util.Bucket(time.Now().Sub(before).Nanoseconds())
|
||||
e.metricsWrapper.StoreLatencies(storage.PostEventsLatency, bucket)
|
||||
e.metricsWrapper.StoreCounters(storage.PostEventsCounter, "ok")
|
||||
e.runtimeTelemetry.RecordSyncLatency(telemetry.EventSync, time.Since(before).Nanoseconds())
|
||||
e.runtimeTelemetry.RecordSuccessfulSync(telemetry.EventSync, time.Now().UTC().UnixNano()/int64(time.Millisecond))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
15
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/impression/single.go
сгенерированный
поставляемый
15
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/impression/single.go
сгенерированный
поставляемый
@@ -2,13 +2,13 @@ package impression
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-split-commons/v3/util"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
@@ -22,20 +22,20 @@ const (
|
||||
type RecorderSingle struct {
|
||||
impressionStorage storage.ImpressionStorageConsumer
|
||||
impressionRecorder service.ImpressionsRecorder
|
||||
metricsWrapper *storage.MetricWrapper
|
||||
logger logging.LoggerInterface
|
||||
metadata dtos.Metadata
|
||||
mode string
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// NewRecorderSingle creates new impression synchronizer for posting impressions
|
||||
func NewRecorderSingle(
|
||||
impressionStorage storage.ImpressionStorageConsumer,
|
||||
impressionRecorder service.ImpressionsRecorder,
|
||||
metricsWrapper *storage.MetricWrapper,
|
||||
logger logging.LoggerInterface,
|
||||
metadata dtos.Metadata,
|
||||
managerConfig conf.ManagerConfig,
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer,
|
||||
) ImpressionRecorder {
|
||||
mode := conf.ImpressionsModeOptimized
|
||||
if !util.ShouldBeOptimized(managerConfig) {
|
||||
@@ -44,10 +44,10 @@ func NewRecorderSingle(
|
||||
return &RecorderSingle{
|
||||
impressionStorage: impressionStorage,
|
||||
impressionRecorder: impressionRecorder,
|
||||
metricsWrapper: metricsWrapper,
|
||||
logger: logger,
|
||||
metadata: metadata,
|
||||
mode: mode,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,13 +96,12 @@ func (i *RecorderSingle) SynchronizeImpressions(bulkSize int64) error {
|
||||
err = i.impressionRecorder.Record(bulkImpressions, i.metadata, map[string]string{splitSDKImpressionsMode: i.mode})
|
||||
if err != nil {
|
||||
if httpError, ok := err.(*dtos.HTTPError); ok {
|
||||
i.metricsWrapper.StoreCounters(storage.TestImpressionsCounter, strconv.Itoa(httpError.Code))
|
||||
i.runtimeTelemetry.RecordSyncError(telemetry.ImpressionSync, httpError.Code)
|
||||
}
|
||||
return err
|
||||
}
|
||||
bucket := util.Bucket(time.Now().Sub(before).Nanoseconds())
|
||||
i.metricsWrapper.StoreLatencies(storage.TestImpressionsLatency, bucket)
|
||||
i.metricsWrapper.StoreCounters(storage.TestImpressionsCounter, "ok")
|
||||
i.runtimeTelemetry.RecordSyncLatency(telemetry.ImpressionSync, time.Since(before).Nanoseconds())
|
||||
i.runtimeTelemetry.RecordSuccessfulSync(telemetry.ImpressionSync, time.Now().UTC().UnixNano()/int64(time.Millisecond))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
20
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/impressionscount/single.go
сгенерированный
поставляемый
20
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/impressionscount/single.go
сгенерированный
поставляемый
@@ -1,9 +1,13 @@
|
||||
package impressionscount
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"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/storage"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
@@ -13,6 +17,7 @@ type RecorderSingle struct {
|
||||
impressionRecorder service.ImpressionsRecorder
|
||||
metadata dtos.Metadata
|
||||
logger logging.LoggerInterface
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// NewRecorderSingle creates new impressionsCount synchronizer for posting impressionsCount
|
||||
@@ -21,12 +26,14 @@ func NewRecorderSingle(
|
||||
impressionRecorder service.ImpressionsRecorder,
|
||||
metadata dtos.Metadata,
|
||||
logger logging.LoggerInterface,
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer,
|
||||
) ImpressionsCountRecorder {
|
||||
return &RecorderSingle{
|
||||
impressionsCounter: impressionsCounter,
|
||||
impressionRecorder: impressionRecorder,
|
||||
metadata: metadata,
|
||||
logger: logger,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,5 +54,16 @@ func (m *RecorderSingle) SynchronizeImpressionsCount() error {
|
||||
pf := dtos.ImpressionsCountDTO{
|
||||
PerFeature: impressionsInTimeFrame,
|
||||
}
|
||||
return m.impressionRecorder.RecordImpressionsCount(pf, m.metadata)
|
||||
|
||||
before := time.Now()
|
||||
err := m.impressionRecorder.RecordImpressionsCount(pf, m.metadata)
|
||||
if err != nil {
|
||||
if httpError, ok := err.(*dtos.HTTPError); ok {
|
||||
m.runtimeTelemetry.RecordSyncError(telemetry.ImpressionCountSync, httpError.Code)
|
||||
}
|
||||
return err
|
||||
}
|
||||
m.runtimeTelemetry.RecordSyncLatency(telemetry.ImpressionCountSync, time.Since(before).Nanoseconds())
|
||||
m.runtimeTelemetry.RecordSuccessfulSync(telemetry.ImpressionCountSync, time.Now().UTC().UnixNano()/int64(time.Millisecond))
|
||||
return nil
|
||||
}
|
||||
|
||||
6
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/metric/interface.go
сгенерированный
поставляемый
6
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/metric/interface.go
сгенерированный
поставляемый
@@ -1,6 +0,0 @@
|
||||
package metric
|
||||
|
||||
// MetricRecorder interface
|
||||
type MetricRecorder interface {
|
||||
SynchronizeTelemetry() error
|
||||
}
|
||||
74
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/metric/single.go
сгенерированный
поставляемый
74
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/metric/single.go
сгенерированный
поставляемый
@@ -1,74 +0,0 @@
|
||||
package metric
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
)
|
||||
|
||||
// RecorderSingle struct for metric sync
|
||||
type RecorderSingle struct {
|
||||
metricStorage storage.MetricsStorageConsumer
|
||||
metricRecorder service.MetricsRecorder
|
||||
metadata dtos.Metadata
|
||||
}
|
||||
|
||||
// NewRecorderSingle creates new metric synchronizer for posting metrics
|
||||
func NewRecorderSingle(
|
||||
metricStorage storage.MetricsStorageConsumer,
|
||||
metricRecorder service.MetricsRecorder,
|
||||
metadata dtos.Metadata,
|
||||
) MetricRecorder {
|
||||
return &RecorderSingle{
|
||||
metricStorage: metricStorage,
|
||||
metricRecorder: metricRecorder,
|
||||
metadata: metadata,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *RecorderSingle) synchronizeLatencies() error {
|
||||
latencies := m.metricStorage.PopLatencies()
|
||||
if len(latencies) > 0 {
|
||||
err := m.metricRecorder.RecordLatencies(latencies, m.metadata)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RecorderSingle) synchronizeGauges() error {
|
||||
var errs []error
|
||||
for _, gauge := range m.metricStorage.PopGauges() {
|
||||
err := m.metricRecorder.RecordGauge(gauge, m.metadata)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return errors.New("Some gauges could not be posted")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RecorderSingle) synchronizeCounters() error {
|
||||
counters := m.metricStorage.PopCounters()
|
||||
if len(counters) > 0 {
|
||||
err := m.metricRecorder.RecordCounters(counters, m.metadata)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SynchronizeTelemetry syncs telemetry
|
||||
func (m *RecorderSingle) SynchronizeTelemetry() error {
|
||||
err := m.synchronizeGauges()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = m.synchronizeLatencies()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.synchronizeCounters()
|
||||
}
|
||||
33
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/segment/segment.go
сгенерированный
поставляемый
33
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/segment/segment.go
сгенерированный
поставляемый
@@ -2,25 +2,24 @@ package segment
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"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/datastructures/set"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
// UpdaterImpl struct for segment sync
|
||||
type UpdaterImpl struct {
|
||||
splitStorage storage.SplitStorageConsumer
|
||||
segmentStorage storage.SegmentStorage
|
||||
segmentFetcher service.SegmentFetcher
|
||||
metricsWrapper *storage.MetricWrapper
|
||||
logger logging.LoggerInterface
|
||||
splitStorage storage.SplitStorageConsumer
|
||||
segmentStorage storage.SegmentStorage
|
||||
segmentFetcher service.SegmentFetcher
|
||||
logger logging.LoggerInterface
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// NewSegmentFetcher creates new segment synchronizer for processing segment updates
|
||||
@@ -28,15 +27,15 @@ func NewSegmentFetcher(
|
||||
splitStorage storage.SplitStorage,
|
||||
segmentStorage storage.SegmentStorage,
|
||||
segmentFetcher service.SegmentFetcher,
|
||||
metricsWrapper *storage.MetricWrapper,
|
||||
logger logging.LoggerInterface,
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer,
|
||||
) Updater {
|
||||
return &UpdaterImpl{
|
||||
splitStorage: splitStorage,
|
||||
segmentStorage: segmentStorage,
|
||||
segmentFetcher: segmentFetcher,
|
||||
metricsWrapper: metricsWrapper,
|
||||
logger: logger,
|
||||
splitStorage: splitStorage,
|
||||
segmentStorage: segmentStorage,
|
||||
segmentFetcher: segmentFetcher,
|
||||
logger: logger,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,16 +82,14 @@ func (s *UpdaterImpl) SynchronizeSegment(name string, till *int64, requestNoCach
|
||||
segmentChanges, err := s.segmentFetcher.Fetch(name, changeNumber, requestNoCache)
|
||||
if err != nil {
|
||||
if httpError, ok := err.(*dtos.HTTPError); ok {
|
||||
s.metricsWrapper.StoreCounters(storage.SegmentChangesCounter, strconv.Itoa(httpError.Code))
|
||||
s.runtimeTelemetry.RecordSyncError(telemetry.SegmentSync, httpError.Code)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
s.runtimeTelemetry.RecordSyncLatency(telemetry.SegmentSync, time.Since(before).Nanoseconds())
|
||||
s.processUpdate(segmentChanges)
|
||||
bucket := util.Bucket(time.Now().Sub(before).Nanoseconds())
|
||||
s.metricsWrapper.StoreLatencies(storage.SegmentChangesLatency, bucket)
|
||||
s.metricsWrapper.StoreCounters(storage.SegmentChangesCounter, "ok")
|
||||
if segmentChanges.Till == segmentChanges.Since || (till != nil && segmentChanges.Till >= *till) {
|
||||
s.runtimeTelemetry.RecordSuccessfulSync(telemetry.SegmentSync, time.Now().UTC().UnixNano()/int64(time.Millisecond))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
30
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/split/split.go
сгенерированный
поставляемый
30
vendor/github.com/splitio/go-split-commons/v3/synchronizer/worker/split/split.go
сгенерированный
поставляемый
@@ -1,13 +1,12 @@
|
||||
package split
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -17,24 +16,24 @@ const (
|
||||
|
||||
// UpdaterImpl struct for split sync
|
||||
type UpdaterImpl struct {
|
||||
splitStorage storage.SplitStorage
|
||||
splitFetcher service.SplitFetcher
|
||||
metricsWrapper *storage.MetricWrapper
|
||||
logger logging.LoggerInterface
|
||||
splitStorage storage.SplitStorage
|
||||
splitFetcher service.SplitFetcher
|
||||
logger logging.LoggerInterface
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// NewSplitFetcher creates new split synchronizer for processing split updates
|
||||
func NewSplitFetcher(
|
||||
splitStorage storage.SplitStorage,
|
||||
splitFetcher service.SplitFetcher,
|
||||
metricsWrapper *storage.MetricWrapper,
|
||||
logger logging.LoggerInterface,
|
||||
) *UpdaterImpl {
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer,
|
||||
) Updater {
|
||||
return &UpdaterImpl{
|
||||
splitStorage: splitStorage,
|
||||
splitFetcher: splitFetcher,
|
||||
metricsWrapper: metricsWrapper,
|
||||
logger: logger,
|
||||
splitStorage: splitStorage,
|
||||
splitFetcher: splitFetcher,
|
||||
logger: logger,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,16 +75,15 @@ func (s *UpdaterImpl) SynchronizeSplits(till *int64, requestNoCache bool) ([]str
|
||||
splits, err := s.splitFetcher.Fetch(changeNumber, requestNoCache)
|
||||
if err != nil {
|
||||
if httpError, ok := err.(*dtos.HTTPError); ok {
|
||||
s.metricsWrapper.StoreCounters(storage.SplitChangesCounter, strconv.Itoa(httpError.Code))
|
||||
s.runtimeTelemetry.RecordSyncError(telemetry.SplitSync, httpError.Code)
|
||||
}
|
||||
return segments, err
|
||||
}
|
||||
s.runtimeTelemetry.RecordSyncLatency(telemetry.SplitSync, time.Since(before).Nanoseconds())
|
||||
s.processUpdate(splits)
|
||||
segments = append(segments, extractSegments(splits)...)
|
||||
bucket := util.Bucket(time.Now().Sub(before).Nanoseconds())
|
||||
s.metricsWrapper.StoreCounters(storage.SplitChangesCounter, "ok")
|
||||
s.metricsWrapper.StoreLatencies(storage.SplitChangesLatency, bucket)
|
||||
if splits.Till == splits.Since || (till != nil && splits.Till >= *till) {
|
||||
s.runtimeTelemetry.RecordSuccessfulSync(telemetry.SplitSync, time.Now().UTC().UnixNano()/int64(time.Millisecond))
|
||||
return segments, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"github.com/splitio/go-split-commons/v3/synchronizer/worker/metric"
|
||||
"github.com/splitio/go-split-commons/v3/telemetry"
|
||||
"github.com/splitio/go-toolkit/v4/asynctask"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
// NewRecordTelemetryTask creates a new telemtry recording task
|
||||
func NewRecordTelemetryTask(
|
||||
recorder metric.MetricRecorder,
|
||||
recorder telemetry.TelemetrySynchronizer,
|
||||
period int,
|
||||
logger logging.LoggerInterface,
|
||||
) *asynctask.AsyncTask {
|
||||
record := func(logger logging.LoggerInterface) error {
|
||||
return recorder.SynchronizeTelemetry()
|
||||
return recorder.SynchronizeStats()
|
||||
}
|
||||
|
||||
onStop := func(l logging.LoggerInterface) {
|
||||
107
vendor/github.com/splitio/go-split-commons/v3/telemetry/constants.go
сгенерированный
поставляемый
Обычный файл
107
vendor/github.com/splitio/go-split-commons/v3/telemetry/constants.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,107 @@
|
||||
package telemetry
|
||||
|
||||
import "github.com/splitio/go-split-commons/v3/conf"
|
||||
|
||||
const (
|
||||
// Treatment getTreatment
|
||||
Treatment = "treatment"
|
||||
// Treatments getTreatments
|
||||
Treatments = "treatments"
|
||||
// TreatmentWithConfig getTreatmentWithConfig
|
||||
TreatmentWithConfig = "treatmentWithConfig"
|
||||
// TreatmentsWithConfig getTreatmentsWithConfig
|
||||
TreatmentsWithConfig = "treatmentsWithConfig"
|
||||
// Track track
|
||||
Track = "track"
|
||||
)
|
||||
|
||||
const (
|
||||
// SplitSync splitChanges
|
||||
SplitSync = iota
|
||||
// SegmentSync segmentChanges
|
||||
SegmentSync
|
||||
// ImpressionSync impressions
|
||||
ImpressionSync
|
||||
// ImpressionCountSync impressionsCount
|
||||
ImpressionCountSync
|
||||
// EventSync events
|
||||
EventSync
|
||||
// TelemetrySync telemetry
|
||||
TelemetrySync
|
||||
// TokenSync auth
|
||||
TokenSync
|
||||
)
|
||||
|
||||
const (
|
||||
// ImpressionsDropped dropped
|
||||
ImpressionsDropped = iota
|
||||
// ImpressionsDeduped deduped
|
||||
ImpressionsDeduped
|
||||
// ImpressionsQueued queued
|
||||
ImpressionsQueued
|
||||
)
|
||||
|
||||
const (
|
||||
// EventsDropped dropped
|
||||
EventsDropped = iota
|
||||
// EventsQueued queued
|
||||
EventsQueued
|
||||
)
|
||||
|
||||
const (
|
||||
// LatencyBucketCount Max buckets
|
||||
LatencyBucketCount = 23
|
||||
// MaxStreamingEvents Max streaming events allowed
|
||||
MaxStreamingEvents = 20
|
||||
// MaxTags Max tags
|
||||
MaxTags = 10
|
||||
)
|
||||
|
||||
const (
|
||||
EventTypeSSEConnectionEstablished = iota * 10
|
||||
EventTypeOccupancyPri
|
||||
EventTypeOccupancySec
|
||||
EventTypeStreamingStatus
|
||||
EventTypeConnectionError
|
||||
EventTypeTokenRefresh
|
||||
EventTypeAblyError
|
||||
EventTypeSyncMode
|
||||
)
|
||||
|
||||
const (
|
||||
StreamingDisabled = iota
|
||||
StreamingEnabled
|
||||
StreamingPaused
|
||||
)
|
||||
|
||||
const (
|
||||
Requested = iota
|
||||
NonRequested
|
||||
)
|
||||
|
||||
const (
|
||||
Streaming = iota
|
||||
Polling
|
||||
)
|
||||
|
||||
const (
|
||||
Standalone = iota
|
||||
Consumer
|
||||
)
|
||||
|
||||
const (
|
||||
ImpressionsModeOptimized = iota
|
||||
ImpressionsModeDebug
|
||||
)
|
||||
|
||||
const (
|
||||
Redis = "redis"
|
||||
Memory = "memory"
|
||||
)
|
||||
|
||||
// InitConfig involves entire config for init
|
||||
type InitConfig struct {
|
||||
AdvancedConfig conf.AdvancedConfig
|
||||
TaskPeriods conf.TaskPeriods
|
||||
ManagerConfig conf.ManagerConfig
|
||||
}
|
||||
42
vendor/github.com/splitio/go-split-commons/v3/telemetry/helpers.go
сгенерированный
поставляемый
Обычный файл
42
vendor/github.com/splitio/go-split-commons/v3/telemetry/helpers.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,42 @@
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
)
|
||||
|
||||
func GetStreamingEvent(eventType int, data int64) *dtos.StreamingEvent {
|
||||
switch eventType {
|
||||
case EventTypeSSEConnectionEstablished, EventTypeOccupancyPri,
|
||||
EventTypeOccupancySec, EventTypeStreamingStatus,
|
||||
EventTypeConnectionError, EventTypeTokenRefresh,
|
||||
EventTypeAblyError, EventTypeSyncMode:
|
||||
return &dtos.StreamingEvent{
|
||||
Type: eventType,
|
||||
Data: data,
|
||||
Timestamp: time.Now().UTC().Unix(),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getURLOverrides(cfg conf.AdvancedConfig) dtos.URLOverrides {
|
||||
defaults := conf.GetDefaultAdvancedConfig()
|
||||
return dtos.URLOverrides{
|
||||
Sdk: cfg.SdkURL != defaults.SdkURL,
|
||||
Events: cfg.EventsURL != defaults.EventsURL,
|
||||
Auth: cfg.AuthServiceURL != defaults.AuthServiceURL,
|
||||
Stream: cfg.StreamingServiceURL != defaults.StreamingServiceURL,
|
||||
Telemetry: cfg.TelemetryServiceURL != defaults.TelemetryServiceURL,
|
||||
}
|
||||
}
|
||||
|
||||
func getRedudantActiveFactories(factoryInstances map[string]int64) int64 {
|
||||
var toReturn int64 = 0
|
||||
for _, instances := range factoryInstances {
|
||||
toReturn = toReturn + instances - 1
|
||||
}
|
||||
return toReturn
|
||||
}
|
||||
7
vendor/github.com/splitio/go-split-commons/v3/telemetry/interface.go
сгенерированный
поставляемый
Обычный файл
7
vendor/github.com/splitio/go-split-commons/v3/telemetry/interface.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,7 @@
|
||||
package telemetry
|
||||
|
||||
// TelemetrySynchronizer interface
|
||||
type TelemetrySynchronizer interface {
|
||||
SynchronizeConfig(cfg InitConfig, timedUntilReady int64, factoryInstances map[string]int64, tags []string)
|
||||
SynchronizeStats() error
|
||||
}
|
||||
135
vendor/github.com/splitio/go-split-commons/v3/telemetry/memory.go
сгенерированный
поставляемый
Обычный файл
135
vendor/github.com/splitio/go-split-commons/v3/telemetry/memory.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,135 @@
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/splitio/go-split-commons/v3/conf"
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/service"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
// RecorderSingle struct for telemetry sync
|
||||
type RecorderSingle struct {
|
||||
telemetryStorage storage.TelemetryStorageConsumer
|
||||
telemetryRecorder service.TelemetryRecorder
|
||||
splitStorage storage.SplitStorageConsumer
|
||||
segmentStorage storage.SegmentStorageConsumer
|
||||
logger logging.LoggerInterface
|
||||
metadata dtos.Metadata
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer
|
||||
}
|
||||
|
||||
// NewTelemetrySynchronizer creates new event synchronizer for posting events
|
||||
func NewTelemetrySynchronizer(
|
||||
telemetryStorage storage.TelemetryStorageConsumer,
|
||||
telemetryRecorder service.TelemetryRecorder,
|
||||
splitStorage storage.SplitStorageConsumer,
|
||||
segmentStorage storage.SegmentStorageConsumer,
|
||||
logger logging.LoggerInterface,
|
||||
metadata dtos.Metadata,
|
||||
runtimeTelemetry storage.TelemetryRuntimeProducer,
|
||||
) TelemetrySynchronizer {
|
||||
return &RecorderSingle{
|
||||
telemetryStorage: telemetryStorage,
|
||||
telemetryRecorder: telemetryRecorder,
|
||||
splitStorage: splitStorage,
|
||||
segmentStorage: segmentStorage,
|
||||
logger: logger,
|
||||
metadata: metadata,
|
||||
runtimeTelemetry: runtimeTelemetry,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *RecorderSingle) buildStats() dtos.Stats {
|
||||
methodLatencies := e.telemetryStorage.PopLatencies()
|
||||
methodExceptions := e.telemetryStorage.PopExceptions()
|
||||
lastSynchronization := e.telemetryStorage.GetLastSynchronization()
|
||||
httpErrors := e.telemetryStorage.PopHTTPErrors()
|
||||
httpLatencies := e.telemetryStorage.PopHTTPLatencies()
|
||||
return dtos.Stats{
|
||||
MethodLatencies: &methodLatencies,
|
||||
MethodExceptions: &methodExceptions,
|
||||
ImpressionsDropped: e.telemetryStorage.GetImpressionsStats(ImpressionsDropped),
|
||||
ImpressionsDeduped: e.telemetryStorage.GetImpressionsStats(ImpressionsDeduped),
|
||||
ImpressionsQueued: e.telemetryStorage.GetImpressionsStats(ImpressionsQueued),
|
||||
EventsQueued: e.telemetryStorage.GetEventsStats(EventsQueued),
|
||||
EventsDropped: e.telemetryStorage.GetEventsStats(EventsDropped),
|
||||
LastSynchronizations: &lastSynchronization,
|
||||
HTTPErrors: &httpErrors,
|
||||
HTTPLatencies: &httpLatencies,
|
||||
SplitCount: int64(len(e.splitStorage.SplitNames())),
|
||||
SegmentCount: int64(e.splitStorage.SegmentNames().Size()),
|
||||
SegmentKeyCount: e.segmentStorage.SegmentKeysCount(),
|
||||
TokenRefreshes: e.telemetryStorage.PopTokenRefreshes(),
|
||||
AuthRejections: e.telemetryStorage.PopAuthRejections(),
|
||||
StreamingEvents: e.telemetryStorage.PopStreamingEvents(),
|
||||
SessionLengthMs: e.telemetryStorage.GetSessionLength(),
|
||||
Tags: e.telemetryStorage.PopTags(),
|
||||
}
|
||||
}
|
||||
|
||||
// SynchronizeStats syncs telemetry stats
|
||||
func (e *RecorderSingle) SynchronizeStats() error {
|
||||
stats := e.buildStats()
|
||||
|
||||
before := time.Now()
|
||||
err := e.telemetryRecorder.RecordStats(stats, e.metadata)
|
||||
if err != nil {
|
||||
if httpError, ok := err.(*dtos.HTTPError); ok {
|
||||
e.runtimeTelemetry.RecordSyncError(TelemetrySync, httpError.Code)
|
||||
}
|
||||
return err
|
||||
}
|
||||
e.runtimeTelemetry.RecordSyncLatency(TelemetrySync, time.Since(before).Nanoseconds())
|
||||
e.runtimeTelemetry.RecordSuccessfulSync(TelemetrySync, time.Now().UTC().UnixNano()/int64(time.Millisecond))
|
||||
return nil
|
||||
}
|
||||
|
||||
// SynchronizeConfig syncs telemetry config
|
||||
func (e *RecorderSingle) SynchronizeConfig(cfg InitConfig, timedUntilReady int64, factoryInstances map[string]int64, tags []string) {
|
||||
urlOverrides := getURLOverrides(cfg.AdvancedConfig)
|
||||
|
||||
impressionsMode := ImpressionsModeOptimized
|
||||
if cfg.ManagerConfig.ImpressionsMode == conf.ImpressionsModeDebug {
|
||||
impressionsMode = ImpressionsModeDebug
|
||||
}
|
||||
|
||||
before := time.Now()
|
||||
err := e.telemetryRecorder.RecordConfig(dtos.Config{
|
||||
OperationMode: Standalone,
|
||||
Storage: Memory,
|
||||
ActiveFactories: int64(len(factoryInstances)),
|
||||
RedundantFactories: getRedudantActiveFactories(factoryInstances),
|
||||
Tags: tags,
|
||||
StreamingEnabled: cfg.AdvancedConfig.StreamingEnabled,
|
||||
Rates: &dtos.Rates{
|
||||
Splits: int64(cfg.TaskPeriods.SplitSync),
|
||||
Segments: int64(cfg.TaskPeriods.SegmentSync),
|
||||
Impressions: int64(cfg.TaskPeriods.ImpressionSync),
|
||||
Events: int64(cfg.TaskPeriods.EventsSync),
|
||||
Telemetry: int64(cfg.TaskPeriods.TelemetrySync),
|
||||
},
|
||||
URLOverrides: &urlOverrides,
|
||||
ImpressionsQueueSize: int64(cfg.AdvancedConfig.ImpressionsQueueSize),
|
||||
EventsQueueSize: int64(cfg.AdvancedConfig.EventsQueueSize),
|
||||
ImpressionsMode: impressionsMode,
|
||||
ImpressionsListenerEnabled: cfg.ManagerConfig.ListenerEnabled,
|
||||
HTTPProxyDetected: len(strings.TrimSpace(os.Getenv("HTTP_PROXY"))) > 0,
|
||||
TimeUntilReady: timedUntilReady,
|
||||
BurTimeouts: e.telemetryStorage.GetBURTimeouts(),
|
||||
NonReadyUsages: e.telemetryStorage.GetNonReadyUsages(),
|
||||
}, e.metadata)
|
||||
if err != nil {
|
||||
e.logger.Error("Could not log config data", err.Error())
|
||||
if httpError, ok := err.(*dtos.HTTPError); ok {
|
||||
e.runtimeTelemetry.RecordSyncError(TelemetrySync, httpError.Code)
|
||||
}
|
||||
return
|
||||
}
|
||||
e.runtimeTelemetry.RecordSyncLatency(TelemetrySync, time.Since(before).Nanoseconds())
|
||||
e.runtimeTelemetry.RecordSuccessfulSync(TelemetrySync, time.Now().UTC().UnixNano()/int64(time.Millisecond))
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package util
|
||||
package telemetry
|
||||
|
||||
var latencyBuckets = [23]float64{
|
||||
1.00,
|
||||
37
vendor/github.com/splitio/go-split-commons/v3/telemetry/redis.go
сгенерированный
поставляемый
Обычный файл
37
vendor/github.com/splitio/go-split-commons/v3/telemetry/redis.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,37 @@
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
"github.com/splitio/go-split-commons/v3/dtos"
|
||||
"github.com/splitio/go-split-commons/v3/storage"
|
||||
"github.com/splitio/go-toolkit/v4/logging"
|
||||
)
|
||||
|
||||
type SynchronizerRedis struct {
|
||||
storage storage.TelemetryConfigProducer
|
||||
logger logging.LoggerInterface
|
||||
}
|
||||
|
||||
func NewSynchronizerRedis(storage storage.TelemetryConfigProducer, logger logging.LoggerInterface) TelemetrySynchronizer {
|
||||
return &SynchronizerRedis{
|
||||
storage: storage,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *SynchronizerRedis) SynchronizeStats() error {
|
||||
// No-Op. Not required for redis. This will be implemented by Synchronizer.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SynchronizerRedis) SynchronizeConfig(cfg InitConfig, timedUntilReady int64, factoryInstances map[string]int64, tags []string) {
|
||||
err := r.storage.RecordConfigData(dtos.Config{
|
||||
OperationMode: Consumer,
|
||||
Storage: Redis,
|
||||
ActiveFactories: int64(len(factoryInstances)),
|
||||
RedundantFactories: getRedudantActiveFactories(factoryInstances),
|
||||
Tags: tags,
|
||||
})
|
||||
if err != nil {
|
||||
r.logger.Error("Could not log config data", err.Error())
|
||||
}
|
||||
}
|
||||
5
vendor/github.com/splitio/go-toolkit/v4/sse/event.go
сгенерированный
поставляемый
5
vendor/github.com/splitio/go-toolkit/v4/sse/event.go
сгенерированный
поставляемый
@@ -58,9 +58,8 @@ type EventBuilder interface {
|
||||
|
||||
// EventBuilderImpl implenets the EventBuilder interface. Used to parse incoming event lines
|
||||
type EventBuilderImpl struct {
|
||||
includesComment bool
|
||||
mutex sync.Mutex
|
||||
lines []string
|
||||
mutex sync.Mutex
|
||||
lines []string
|
||||
}
|
||||
|
||||
// AddLine adds a new line belonging to the currently being processed event
|
||||
|
||||
13
vendor/github.com/splitio/go-toolkit/v4/sse/sse.go
сгенерированный
поставляемый
13
vendor/github.com/splitio/go-toolkit/v4/sse/sse.go
сгенерированный
поставляемый
@@ -14,10 +14,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
statusIdle = iota
|
||||
statusRunning
|
||||
statusShuttingDown
|
||||
|
||||
endOfLineChar = '\n'
|
||||
endOfLineStr = "\n"
|
||||
)
|
||||
@@ -73,7 +69,7 @@ func (l *Client) readEvents(in *bufio.Reader, out chan<- RawEvent) {
|
||||
}
|
||||
|
||||
// Do starts streaming
|
||||
func (l *Client) Do(params map[string]string, callback func(e RawEvent)) error {
|
||||
func (l *Client) Do(params map[string]string, headers map[string]string, callback func(e RawEvent)) error {
|
||||
|
||||
if !l.lifecycle.BeginInitialization() {
|
||||
return ErrNotIdle
|
||||
@@ -89,7 +85,7 @@ func (l *Client) Do(params map[string]string, callback func(e RawEvent)) error {
|
||||
l.lifecycle.ShutdownComplete()
|
||||
}()
|
||||
|
||||
req, err := l.buildCancellableRequest(ctx, params)
|
||||
req, err := l.buildCancellableRequest(ctx, params, headers)
|
||||
if err != nil {
|
||||
return &ErrConnectionFailed{wrapped: fmt.Errorf("error building request: %w", err)}
|
||||
}
|
||||
@@ -157,7 +153,7 @@ func (l *Client) Shutdown(blocking bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Client) buildCancellableRequest(ctx context.Context, params map[string]string) (*http.Request, error) {
|
||||
func (l *Client) buildCancellableRequest(ctx context.Context, params map[string]string, headers map[string]string) (*http.Request, error) {
|
||||
req, err := http.NewRequest("GET", l.url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error instantiating request: %w", err)
|
||||
@@ -168,6 +164,9 @@ func (l *Client) buildCancellableRequest(ctx context.Context, params map[string]
|
||||
for key, value := range params {
|
||||
query.Add(key, value)
|
||||
}
|
||||
for key, value := range headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
req.URL.RawQuery = query.Encode()
|
||||
req.Header.Set("Accept", "text/event-stream")
|
||||
return req, nil
|
||||
|
||||
Ссылка в новой задаче
Block a user