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

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

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 сгенерированный поставляемый
Просмотреть файл

@@ -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 сгенерированный поставляемый
Просмотреть файл

@@ -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
}