From 41ef641977306cc3f318e9ef4708c140f6bc7c3c Mon Sep 17 00:00:00 2001 From: Mauro Antonio Sanz Date: Mon, 29 Jan 2024 12:58:49 -0300 Subject: [PATCH] adding flagset info in proxy mode --- splitio/admin/controllers/observability.go | 1 + .../admin/controllers/observability_test.go | 98 ++++++++++++++++++- .../admin/views/dashboard/datainspector.go | 10 +- splitio/admin/views/dashboard/stats.go | 10 +- splitio/proxy/storage/splits.go | 12 +-- splitio/proxy/storage/splits_test.go | 64 ++++++++++++ 6 files changed, 177 insertions(+), 18 deletions(-) diff --git a/splitio/admin/controllers/observability.go b/splitio/admin/controllers/observability.go index d4ae8a75..db6cfc5b 100644 --- a/splitio/admin/controllers/observability.go +++ b/splitio/admin/controllers/observability.go @@ -60,6 +60,7 @@ func (c *ProxyObservabilityController) observability(ctx *gin.Context) { ctx.JSON(200, gin.H{ "activeSplits": c.splits.SplitNames(), "activeSegments": c.segments.NamesAndCount(), + "activeFlagSets": c.splits.GetAllFlagSetNames(), "proxyEndpointStats": c.telemetry.TimeslicedReport(), "proxyEndpointStatsTotal": c.telemetry.TotalMetricsReport(), }) diff --git a/splitio/admin/controllers/observability_test.go b/splitio/admin/controllers/observability_test.go index 0a0d8512..a8e58b73 100644 --- a/splitio/admin/controllers/observability_test.go +++ b/splitio/admin/controllers/observability_test.go @@ -14,6 +14,7 @@ import ( "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" + "github.com/splitio/split-synchronizer/v5/splitio/proxy/storage" ) func TestSyncObservabilityEndpoint(t *testing.T) { @@ -79,7 +80,7 @@ func TestSyncObservabilityEndpoint(t *testing.T) { router.ServeHTTP(resp, ctx.Request) if resp.Code != 200 { - t.Error("hay crap.") + t.Errorf("Something went wrong. Status Code %v", resp.Code) } body, err := io.ReadAll(resp.Body) @@ -129,3 +130,98 @@ func (e *extMockSegmentStorage) UpdateWithSummary(name string, toAdd *set.Thread func (e *extMockSegmentStorage) Size(name string) (int, error) { return e.SizeCall(name) } + +func TestProxyObservabilityEndpoint(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 + } + + localTelemetryStorage := storage.NewTimeslicedProxyEndpointTelemetry( + storage.NewProxyTelemetryFacade(), + 50, + 5, + ) + + storages := adminCommon.Storages{ + SplitStorage: oSplitStorage, + SegmentStorage: oSegmentStorage, + LocalTelemetryStorage: localTelemetryStorage, + } + + ctrl, err := NewObservabilityController(true, 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.Errorf("Something went wrong. Status Code %v", resp.Code) + } + + 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)) + } +} diff --git a/splitio/admin/views/dashboard/datainspector.go b/splitio/admin/views/dashboard/datainspector.go index 6081b894..68059130 100644 --- a/splitio/admin/views/dashboard/datainspector.go +++ b/splitio/admin/views/dashboard/datainspector.go @@ -126,13 +126,9 @@ const dataInspector = ` - {{if .ProxyMode}} - - {{else}} - - - - {{end}} + + + diff --git a/splitio/admin/views/dashboard/stats.go b/splitio/admin/views/dashboard/stats.go index 914b525d..770a7a94 100644 --- a/splitio/admin/views/dashboard/stats.go +++ b/splitio/admin/views/dashboard/stats.go @@ -43,18 +43,24 @@ const cards = `
{{if .ProxyMode}} -
+

Cached Feature Flags

-
+

Cached Segments

+
+
+

Cached Flag Sets

+

+
+
{{else}}
diff --git a/splitio/proxy/storage/splits.go b/splitio/proxy/storage/splits.go index 4214dd52..1fed1965 100644 --- a/splitio/proxy/storage/splits.go +++ b/splitio/proxy/storage/splits.go @@ -173,17 +173,13 @@ func (p *ProxySplitStorageImpl) Count() int { } // GetNamesByFlagSets implements storage.SplitStorage -func (*ProxySplitStorageImpl) GetNamesByFlagSets(sets []string) map[string][]string { - // NOTE: This method is NOT used by the proxy. - // we need to revisit our interfaces so that we're not obliged to do this smeely empty impls. - return nil +func (p *ProxySplitStorageImpl) GetNamesByFlagSets(sets []string) map[string][]string { + return p.snapshot.GetNamesByFlagSets(sets) } // GetAllFlagSetNames implements storage.SplitStorage -func (*ProxySplitStorageImpl) GetAllFlagSetNames() []string { - // NOTE: This method is NOT used by the proxy. - // we need to revisit our interfaces so that we're not obliged to do this smeely empty impls. - return nil +func (p *ProxySplitStorageImpl) GetAllFlagSetNames() []string { + return p.snapshot.GetAllFlagSetNames() } func (p *ProxySplitStorageImpl) setStartingPoint(cn int64) { diff --git a/splitio/proxy/storage/splits_test.go b/splitio/proxy/storage/splits_test.go index af33e016..12fbefea 100644 --- a/splitio/proxy/storage/splits_test.go +++ b/splitio/proxy/storage/splits_test.go @@ -183,3 +183,67 @@ func TestSplitStorageWithFlagsets(t *testing.T) { {Name: "f2", ChangeNumber: 2, Status: "ACTIVE", Sets: []string{"s2", "s3"}}, }, res.Splits) } + +func TestGetNamesByFlagSets(t *testing.T) { + dbw, err := persistent.NewBoltWrapper(persistent.BoltInMemoryMode, nil) + if err != nil { + t.Error("error creating bolt wrapper: ", err) + } + + logger := logging.NewLogger(nil) + + splitC := persistent.NewSplitChangesCollection(dbw, logger) + flags := []dtos.SplitDTO{ + {Name: "f0", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_1", "set2"}}, + {Name: "f1", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_1"}}, + {Name: "f2", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set2"}}, + {Name: "f3", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_1", "set2"}}, + {Name: "f4", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_1", "set6"}}, + {Name: "f5", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_5", "set6"}}, + } + splitC.Update(flags, nil, 0) + + pss := NewProxySplitStorage(dbw, logger, flagsets.NewFlagSetFilter(nil), true) + + namesBySets := pss.GetNamesByFlagSets([]string{"set_1", "set2"}) + + if len(namesBySets) != 2 { + t.Errorf("namesBySets len should be 3. Actual %v", len(namesBySets)) + } + + if len(namesBySets["set_1"]) != 4 { + t.Errorf("set_1 len should be 4. Actual %v", len(namesBySets["set_1"])) + } + + if len(namesBySets["set2"]) != 3 { + t.Errorf("set2 len should be 3. Actual %v", len(namesBySets["set2"])) + } +} + +func TestGetAllFlagSetNames(t *testing.T) { + dbw, err := persistent.NewBoltWrapper(persistent.BoltInMemoryMode, nil) + if err != nil { + t.Error("error creating bolt wrapper: ", err) + } + + logger := logging.NewLogger(nil) + + splitC := persistent.NewSplitChangesCollection(dbw, logger) + flags := []dtos.SplitDTO{ + {Name: "f0", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_1", "set2"}}, + {Name: "f1", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_1"}}, + {Name: "f2", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set2"}}, + {Name: "f3", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_1", "set2"}}, + {Name: "f4", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_1", "set6"}}, + {Name: "f5", ChangeNumber: 0, Status: "ACTIVE", TrafficTypeName: "ttt", Sets: []string{"set_5", "set6"}}, + } + splitC.Update(flags, nil, 0) + + pss := NewProxySplitStorage(dbw, logger, flagsets.NewFlagSetFilter(nil), true) + + setNames := pss.GetAllFlagSetNames() + + if len(setNames) != 4 { + t.Errorf("setNames len should be 4. Actual %v", len(setNames)) + } +}
 Flag SetTotal Feature Flags AssociatedFeature FlagsFlag SetTotal Feature Flags AssociatedFeature Flags