Skip to content

Commit

Permalink
Merge pull request #261 from splitio/SDKS-7838-cached-flag-sets
Browse files Browse the repository at this point in the history
SDKS-7838 Show Cached flag sets
  • Loading branch information
sanzmauro authored Jan 11, 2024
2 parents 5e0177b + 1b14fcc commit 7324197
Show file tree
Hide file tree
Showing 14 changed files with 338 additions and 127 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ require (
github.com/gin-gonic/gin v1.9.1
github.com/google/uuid v1.3.0
github.com/splitio/gincache v1.0.1
github.com/splitio/go-split-commons/v5 v5.1.2-0.20240108145819-63cfece95155
github.com/splitio/go-toolkit/v5 v5.3.3-0.20240108144147-a36a17c46788
github.com/splitio/go-split-commons/v5 v5.2.0
github.com/splitio/go-toolkit/v5 v5.4.0
github.com/stretchr/testify v1.8.4
go.etcd.io/bbolt v1.3.6
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,10 @@ github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUA
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/splitio/gincache v1.0.1 h1:dLYdANY/BqH4KcUMCe/LluLyV5WtuE/LEdQWRE06IXU=
github.com/splitio/gincache v1.0.1/go.mod h1:CcgJDSM9Af75kyBH0724v55URVwMBuSj5x1eCWIOECY=
github.com/splitio/go-split-commons/v5 v5.1.2-0.20240108145819-63cfece95155 h1:SecApJYs4oumtZMIBwnE2DFyImlwiuswXIdZDaW42uE=
github.com/splitio/go-split-commons/v5 v5.1.2-0.20240108145819-63cfece95155/go.mod h1:sdXeIX4UdBf+EPdVAdBC+f2RuFUh/44bqHlTLy3rH/I=
github.com/splitio/go-toolkit/v5 v5.3.3-0.20240108144147-a36a17c46788 h1:URrg0BcgUzFE4pAacFlrWiTrmEdH4SY03XXLLWVtqLc=
github.com/splitio/go-toolkit/v5 v5.3.3-0.20240108144147-a36a17c46788/go.mod h1:xYhUvV1gga9/1029Wbp5pjnR6Cy8nvBpjw99wAbsMko=
github.com/splitio/go-split-commons/v5 v5.2.0 h1:1P66JdUV1Fj1DUeWU1rwkeObqinl9AecRxDsktBsx0g=
github.com/splitio/go-split-commons/v5 v5.2.0/go.mod h1:m1Od/jxiSUJXpdbRvRxTaKeSAdQVem5AZr7AjI4xXn8=
github.com/splitio/go-toolkit/v5 v5.4.0 h1:g5WFpRhQomnXCmvfsNOWV4s5AuUrWIZ+amM68G8NBKM=
github.com/splitio/go-toolkit/v5 v5.4.0/go.mod h1:xYhUvV1gga9/1029Wbp5pjnR6Cy8nvBpjw99wAbsMko=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
Expand Down
Binary file added main
Binary file not shown.
1 change: 1 addition & 0 deletions splitio/admin/controllers/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,6 @@ func (c *DashboardController) gatherStats() *dashboard.GlobalStats {
LoggedErrors: errorCount,
LoggedMessages: errorMessages,
Uptime: int64(c.runtime.Uptime().Seconds()),
FlagSets: getFlagSetsInfo(c.storages.SplitStorage),
}
}
22 changes: 22 additions & 0 deletions splitio/admin/controllers/helpers.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package controllers

import (
"sort"
"strings"
"time"

"github.com/splitio/go-split-commons/v5/storage"
Expand Down Expand Up @@ -209,6 +211,26 @@ func getEventsSize(eventStorage storage.EventMultiSdkConsumer) int64 {
return eventStorage.Count()
}

func getFlagSetsInfo(splitsStorage storage.SplitStorage) []dashboard.FlagSetsSummary {
flagSetNames := splitsStorage.GetAllFlagSetNames()

summaries := make([]dashboard.FlagSetsSummary, 0, len(flagSetNames))
featureFlagsBySets := splitsStorage.GetNamesByFlagSets(flagSetNames)

for key, featureFlags := range featureFlagsBySets {
summaries = append(summaries, dashboard.FlagSetsSummary{
Name: key,
FeatureFlagsAssociated: int64(len(featureFlags)),
FeatureFlags: strings.Join(featureFlags, ", "),
})
}
sort.Slice(summaries, func(i, j int) bool {
return summaries[j].Name > summaries[i].Name
})

return summaries
}

func getImpressionSize(impressionStorage storage.ImpressionMultiSdkConsumer) int64 {
if impressionStorage == nil {
return 0
Expand Down
13 changes: 10 additions & 3 deletions splitio/admin/controllers/observability.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ import (
"github.com/gin-gonic/gin"
)

type ObservabilityDto struct {
ActiveSplits []string `json:"activeSplits"`
ActiveSegments map[string]int `json:"activeSegments"`
ActiveFlagSets []string `json:"activeFlagSets"`
}

// ObservabilityController interface is used to have a single constructor that returns the apropriate controller
type ObservabilityController interface {
Register(gin.IRouter)
Expand All @@ -30,9 +36,10 @@ func (c *SyncObservabilityController) Register(router gin.IRouter) {
}

func (c *SyncObservabilityController) observability(ctx *gin.Context) {
ctx.JSON(200, gin.H{
"activeSplits": c.splits.SplitNames(),
"activeSegments": c.segments.NamesAndCount(),
ctx.JSON(200, ObservabilityDto{
ActiveSplits: c.splits.SplitNames(),
ActiveSegments: c.segments.NamesAndCount(),
ActiveFlagSets: c.splits.GetAllFlagSetNames(),
})
}

Expand Down
131 changes: 131 additions & 0 deletions splitio/admin/controllers/observability_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package controllers

import (
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"testing"

"github.com/gin-gonic/gin"
"github.com/splitio/go-split-commons/v5/dtos"
"github.com/splitio/go-split-commons/v5/storage/mocks"
"github.com/splitio/go-toolkit/v5/datastructures/set"
"github.com/splitio/go-toolkit/v5/logging"
adminCommon "github.com/splitio/split-synchronizer/v5/splitio/admin/common"
"github.com/splitio/split-synchronizer/v5/splitio/provisional/observability"
)

func TestSyncObservabilityEndpoint(t *testing.T) {
logger := logging.NewLogger(nil)

extSplitStorage := &extMockSplitStorage{
&mocks.MockSplitStorage{
SplitNamesCall: func() []string {
return []string{"split1", "split2", "split3"}
},
SegmentNamesCall: func() *set.ThreadUnsafeSet {
return set.NewSet("segment1")
},
GetAllFlagSetNamesCall: func() []string {
return []string{"fSet1", "fSet2"}
},
},
nil,
}

extSegmentStorage := &extMockSegmentStorage{
MockSegmentStorage: &mocks.MockSegmentStorage{},
SizeCall: func(name string) (int, error) {
switch name {
case "segment1":
return 10, nil
case "segment2":
return 20, nil
}
return 0, nil
},
}

oSplitStorage, err := observability.NewObservableSplitStorage(extSplitStorage, logger)
if err != nil {
t.Error(err)
return
}

oSegmentStorage, err := observability.NewObservableSegmentStorage(logger, extSplitStorage, extSegmentStorage)
if err != nil {
t.Error(err)
return
}

storages := adminCommon.Storages{
SplitStorage: oSplitStorage,
SegmentStorage: oSegmentStorage,
}

ctrl, err := NewObservabilityController(false, logger, storages)

if err != nil {
t.Error(err)
return
}

resp := httptest.NewRecorder()
ctx, router := gin.CreateTestContext(resp)
ctrl.Register(router)

ctx.Request, _ = http.NewRequest(http.MethodGet, "/observability", nil)
router.ServeHTTP(resp, ctx.Request)

if resp.Code != 200 {
t.Error("hay crap.")
}

body, err := io.ReadAll(resp.Body)
if err != nil {
t.Error(err)
return
}

var result ObservabilityDto
if err := json.Unmarshal(body, &result); err != nil {
t.Error("there should be no error ", err)
}

if len(result.ActiveFlagSets) != 2 {
t.Errorf("Active flag sets should be 2. Actual %d", len(result.ActiveFlagSets))
}

if len(result.ActiveSplits) != 3 {
t.Errorf("Active splits should be 3. Actual %d", len(result.ActiveSplits))
}

if len(result.ActiveSegments) != 1 {
t.Errorf("Active segments should be 1. Actual %d", len(result.ActiveSegments))
}
}

// TODO: should unify this classes
type extMockSplitStorage struct {
*mocks.MockSplitStorage
UpdateWithErrorsCall func([]dtos.SplitDTO, []dtos.SplitDTO, int64) error
}

func (e *extMockSplitStorage) UpdateWithErrors(toAdd []dtos.SplitDTO, toRemove []dtos.SplitDTO, cn int64) error {
return e.UpdateWithErrorsCall(toAdd, toRemove, cn)
}

type extMockSegmentStorage struct {
*mocks.MockSegmentStorage
UpdateWithSummaryCall func(string, *set.ThreadUnsafeSet, *set.ThreadUnsafeSet, int64) (int, int, error)
SizeCall func(string) (int, error)
}

func (e *extMockSegmentStorage) UpdateWithSummary(name string, toAdd *set.ThreadUnsafeSet, toRemove *set.ThreadUnsafeSet, till int64) (added int, removed int, err error) {
return e.UpdateWithSummaryCall(name, toAdd, toRemove, till)
}

func (e *extMockSegmentStorage) Size(name string) (int, error) {
return e.SizeCall(name)
}
Loading

0 comments on commit 7324197

Please sign in to comment.