Skip to content

Commit

Permalink
Merge branch 'fix-dashboard' into dependabot/go_modules/golang.org/x/…
Browse files Browse the repository at this point in the history
…crypto-0.17.0
  • Loading branch information
sanzmauro authored Jan 24, 2024
2 parents d5e145f + f86caf9 commit ae3efce
Show file tree
Hide file tree
Showing 20 changed files with 374 additions and 145 deletions.
4 changes: 4 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
5.6.0 (Jan 23, 2024)
- Replaced redis KEYS operation in favor of SCAN.
- Added FlagSets stats into Split dashboard.

5.5.1 (Dec 21, 2023)
- Updated docker images for vulnerability fixes.
- Updated go-split-commons version.
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright © 2023 Split Software, Inc.
Copyright © 2024 Split Software, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.proxy
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build stage
FROM golang:1.21.5-alpine3.19 AS builder
FROM golang:1.21.6-alpine3.19 AS builder

ARG EXTRA_BUILD_ARGS

Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile.synchronizer
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build stage
FROM golang:1.21.5-alpine3.19 AS builder
FROM golang:1.21.6-alpine3.19 AS builder

ARG EXTRA_BUILD_ARGS

Expand Down
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.1
github.com/splitio/go-toolkit/v5 v5.3.2
github.com/splitio/go-split-commons/v5 v5.2.1-0.20240124180131-eaca5ff66bf7
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.1 h1:lLOqNQMdZA5Z7FBBh4YODWdE2QFgxSPMptX9ty14x4c=
github.com/splitio/go-split-commons/v5 v5.1.1/go.mod h1:9vAZrlhKvhensyRC11hyVFdgLIBrkX9D5vdYc9qB13w=
github.com/splitio/go-toolkit/v5 v5.3.2 h1:Yy9YBcHRmK5WVZjeA/klLGEdF38xpsL1ejnC3ro8a2M=
github.com/splitio/go-toolkit/v5 v5.3.2/go.mod h1:xYhUvV1gga9/1029Wbp5pjnR6Cy8nvBpjw99wAbsMko=
github.com/splitio/go-split-commons/v5 v5.2.1-0.20240124180131-eaca5ff66bf7 h1:SDIjinG+Rae5OQWhwLLtpRnvbbWvuuHf0+OOj9hI9ug=
github.com/splitio/go-split-commons/v5 v5.2.1-0.20240124180131-eaca5ff66bf7/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),
}
}
23 changes: 23 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 @@ -34,6 +36,7 @@ func bundleSplitInfo(splitStorage storage.SplitStorageConsumer) []dashboard.Spli
Killed: split.Killed,
DefaultTreatment: split.DefaultTreatment,
Treatments: treatmentsS,
FlagSets: split.Sets,
LastModified: time.Unix(0, split.ChangeNumber*int64(time.Millisecond)).UTC().Format(time.UnixDate),
ChangeNumber: split.ChangeNumber,
})
Expand Down Expand Up @@ -208,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 ae3efce

Please sign in to comment.