Skip to content

Commit 88290d5

Browse files
committed
Added rule-based segments in the dashboard
1 parent 8fd26d7 commit 88290d5

7 files changed

Lines changed: 191 additions & 24 deletions

File tree

splitio/admin/controllers/dashboard.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ func (c *DashboardController) gatherStats() *dashboard.GlobalStats {
150150
FeatureFlags: bundleSplitInfo(c.storages.SplitStorage),
151151
Segments: bundleSegmentInfo(c.storages.SplitStorage, c.storages.SegmentStorage),
152152
LargeSegments: bundleLargeSegmentInfo(c.storages.SplitStorage, c.storages.LargeSegmentStorage),
153+
RuleBasedSegments: bundleRuleBasedInfo(c.storages.SplitStorage, c.storages.RuleBasedSegmentsStorage),
153154
Latencies: bundleProxyLatencies(c.storages.LocalTelemetryStorage),
154155
BackendLatencies: bundleLocalSyncLatencies(c.storages.LocalTelemetryStorage),
155156
ImpressionsQueueSize: getImpressionSize(c.storages.ImpressionStorage),

splitio/admin/controllers/helpers.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,45 @@ func bundleSegmentInfo(splitStorage storage.SplitStorage, segmentStorage storage
108108
return summaries
109109
}
110110

111+
func bundleRuleBasedInfo(splitStorage storage.SplitStorage, ruleBasedSegmentStorage storage.RuleBasedSegmentStorageConsumer) []dashboard.RuleBasedSegmentSummary {
112+
113+
names := splitStorage.RuleBasedSegmentNames()
114+
summaries := make([]dashboard.RuleBasedSegmentSummary, 0, names.Size())
115+
116+
for _, name := range names.List() {
117+
strName, ok := name.(string)
118+
if !ok {
119+
continue
120+
}
121+
ruleBased, err := ruleBasedSegmentStorage.GetRuleBasedSegmentByName(strName)
122+
123+
if err != nil {
124+
continue
125+
}
126+
excluededSegments := make([]dashboard.ExcluededSegments, 0, len(ruleBased.Excluded.Segments))
127+
for _, excludedSegment := range ruleBased.Excluded.Segments {
128+
excluededSegments = append(excluededSegments, dashboard.ExcluededSegments{
129+
Name: excludedSegment.Name,
130+
Type: excludedSegment.Type,
131+
})
132+
}
133+
134+
if ruleBased.Excluded.Keys == nil {
135+
ruleBased.Excluded.Keys = make([]string, 0)
136+
}
137+
138+
summaries = append(summaries, dashboard.RuleBasedSegmentSummary{
139+
Name: ruleBased.Name,
140+
Active: ruleBased.Status == "ACTIVE",
141+
ExcludedKeys: ruleBased.Excluded.Keys,
142+
ExcluededSegments: excluededSegments,
143+
LastModified: time.Unix(0, ruleBased.ChangeNumber*int64(time.Millisecond)).UTC().Format(time.UnixDate),
144+
ChangeNumber: ruleBased.ChangeNumber,
145+
})
146+
}
147+
return summaries
148+
}
149+
111150
func bundleSegmentKeysInfo(name string, segmentStorage storage.SegmentStorageConsumer) []dashboard.SegmentKeySummary {
112151

113152
keys := segmentStorage.Keys(name)

splitio/admin/views/dashboard/datainspector.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ const dataInspector = `
3838
</a>
3939
</li>
4040
{{end}}
41+
<li role="presentation" class="">
42+
<a href="#rule-based-segments-data" aria-controls="rule-based" role="tab" data-toggle="tab">
43+
<span class="glyphicon" style="vertical-align:bottom" aria-hidden="true">
44+
<svg fill="none" height="24" width="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
45+
<path
46+
d="M6 4C5.44772 4 5 4.44772 5 5V9C5 9.55228 5.44772 10 6 10H10C10.5523 10 11 9.55228 11 9V8H13V11H10V13H13V16H11V15C11 14.4477 10.5523 14 10 14H6C5.44772 14 5 14.4477 5 15V19C5 19.5523 5.44772 20 6 20H10C10.5523 20 11 19.5523 11 19V18H13V20H18C18.5523 20 19 19.5523 19 19V15C19 14.4477 18.5523 14 18 14H15V10H18C18.5523 10 19 9.55228 19 9V5C19 4.44772 18.5523 4 18 4H13V6H11V5C11 4.44772 10.5523 4 10 4H6Z"
47+
fill="currentColor"
48+
/>
49+
</svg>
50+
</span>
51+
&nbsp;Rule-based Segments
52+
</a>
53+
</li>
4154
<li role="presentation" class="">
4255
<a href="#flag-sets-data" aria-controls="profile" role="tab" data-toggle="tab">
4356
<span class="glyphicon" style="vertical-align:bottom" aria-hidden="true">
@@ -154,6 +167,50 @@ const dataInspector = `
154167
</div>
155168
{{end}}
156169
170+
<!-- RULE-BASED SEGMENT DATA -->
171+
<div role="tabpanel" class="tab-pane" id="rule-based-segments-data">
172+
<div class="row">
173+
<div class="col-md-12">
174+
<div class="bg-primary metricBox">
175+
<!-- <h4>Rule-based Segments in proxy</h4> -->
176+
<div class="row">
177+
<div class="col-md-4 col-md-offset-8">
178+
<div class="input-group">
179+
<input type="text" id="filterRuleBasedSegmentNameInput" class="form-control" placeholder="Filter by Rule-based Segment name">
180+
<span class="input-group-btn">
181+
<button class="btn btn-default" type="button" onclick="javascript:filterRuleBasedSegments();">
182+
<span class="glyphicon glyphicon-filter" aria-hidden="true"></span>
183+
</button>
184+
<button class="btn btn-default" type="button" onclick="javascript:resetFilterRuleBasedSegments();">
185+
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
186+
</button>
187+
</span>
188+
</div>
189+
</div>
190+
</div>
191+
<div class="row">
192+
<div class="col-md-12">
193+
<table id="rule_based_segment_rows" class="table table-condensed table-hover">
194+
<thead>
195+
<tr>
196+
<th>Rule-based segment</th>
197+
<th>Status</th>
198+
<th>Excluded Keys</th>
199+
<th>Excluded segments</th>
200+
<th>Last Modified</th>
201+
</tr>
202+
</thead>
203+
<tbody>
204+
</tbody>
205+
</table>
206+
</div>
207+
</div>
208+
</div>
209+
</div>
210+
</div>
211+
</div>
212+
213+
157214
<!-- FLAG SETS DATA -->
158215
<div role="tabpanel" class="tab-pane" id="flag-sets-data">
159216
<div class="row">

splitio/admin/views/dashboard/js.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,23 @@ const mainScript = `
8686
}
8787
});
8888
}
89+
90+
function resetFilterRuleBasedSegments(){
91+
$("tr.ruleBasedItem").removeClass("filterDisplayNone");
92+
$("#filterRuleBasedSegmentNameInput").val("");
93+
}
94+
95+
function filterRuleBasedSegments(){
96+
$("tr.ruleBasedItem").removeClass("filterDisplayNone");
97+
var filter = $("#filterRuleBasedSegmentNameInput").val();
98+
$("tr.ruleBasedItem").each(function() {
99+
$this = $(this);
100+
var ruleBasedName = $this.find("span.ruleBasedItemName").html();
101+
if (ruleBasedName.indexOf(filter.trim()) == -1) {
102+
$this.addClass("filterDisplayNone");
103+
}
104+
});
105+
}
89106
90107
$(function () {
91108
$('[data-toggle="tooltip"]').tooltip()
@@ -255,6 +272,42 @@ const mainScript = `
255272
}
256273
};
257274
275+
function formatRuleBasedSegment(ruleBasedSegment) {
276+
var excludedSegments = Array.isArray(ruleBasedSegment.excludedSegments)
277+
? ruleBasedSegment.excludedSegments
278+
: [];
279+
280+
var excludedSegmentsHtml = excludedSegments.length
281+
? excludedSegments.map(function(seg, i) {
282+
var segName = seg && seg.name ? seg.name : 'Unnamed';
283+
var segType = seg && seg.type ? seg.type : 'Unknown';
284+
var separator = i < excludedSegments.length - 1 ? ', ' : '';
285+
return '<span>' + segName + ' (' + segType + ')</span>' + separator;
286+
}).join('')
287+
: '—';
288+
289+
return (
290+
'<tr class="ruleBasedItem">' +
291+
'<td><span class="ruleBasedItemName">' + ruleBasedSegment.name + '</span></td>' +
292+
(ruleBasedSegment.active
293+
? '<td class="">ACTIVE</td>'
294+
: '<td class="danger">ARCHIVED</td>') +
295+
'<td>' + (ruleBasedSegment.excludedKeys || '') + '</td>' +
296+
'<td>' + excludedSegmentsHtml + '</td>' +
297+
'<td>' + (ruleBasedSegment.cn || '') + '</td>' +
298+
'</tr>\n'
299+
);
300+
}
301+
302+
function updateRuleBasedSegments(ruleBasedSegments) {
303+
ruleBasedSegments.sort((a, b) => parseFloat(b.changeNumber) - parseFloat(a.changeNumber));
304+
const formatted = ruleBasedSegments.map(formatRuleBasedSegment).join('\n');
305+
if (document.getElementById('filterRuleBasedSegmentNameInput').value.length == 0) {
306+
$('#rule_based_segment_rows tbody').empty();
307+
$('#rule_based_segment_rows tbody').append(formatted);
308+
}
309+
};
310+
258311
function formatFlagSet(flagSet) {
259312
return (
260313
'<tr class="flagSetItem">' +
@@ -443,6 +496,7 @@ const mainScript = `
443496
updateFeatureFlags(stats.featureFlags);
444497
updateSegments(stats.segments);
445498
updateLargeSegments(stats.largesegments);
499+
updateRuleBasedSegments(stats.rulebasedsegments)
446500
updateLogEntries(stats.loggedMessages);
447501
updateFlagSets(stats.flagSets)
448502

splitio/admin/views/dashboard/main.go

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,25 +89,26 @@ type RootObject struct {
8989

9090
// GlobalStats runtime stats used to render the dashboard
9191
type GlobalStats struct {
92-
BackendTotalRequests int64 `json:"backendTotalRequests"`
93-
RequestsOk int64 `json:"requestsOk"`
94-
RequestsErrored int64 `json:"requestsErrored"`
95-
BackendRequestsOk int64 `json:"backendRequestsOk"`
96-
BackendRequestsErrored int64 `json:"backendRequestsErrored"`
97-
SdksTotalRequests int64 `json:"sdksTotalRequests"`
98-
LoggedErrors int64 `json:"loggedErrors"`
99-
LoggedMessages []string `json:"loggedMessages"`
100-
FeatureFlags []SplitSummary `json:"featureFlags"`
101-
Segments []SegmentSummary `json:"segments"`
102-
LargeSegments []LargeSegmentSummary `json:"largesegments"`
103-
Latencies []ChartJSData `json:"latencies"`
104-
BackendLatencies []ChartJSData `json:"backendLatencies"`
105-
ImpressionsQueueSize int64 `json:"impressionsQueueSize"`
106-
ImpressionsLambda float64 `json:"impressionsLambda"`
107-
EventsQueueSize int64 `json:"eventsQueueSize"`
108-
EventsLambda float64 `json:"eventsLambda"`
109-
Uptime int64 `json:"uptime"`
110-
FlagSets []FlagSetsSummary `json:"flagSets"`
92+
BackendTotalRequests int64 `json:"backendTotalRequests"`
93+
RequestsOk int64 `json:"requestsOk"`
94+
RequestsErrored int64 `json:"requestsErrored"`
95+
BackendRequestsOk int64 `json:"backendRequestsOk"`
96+
BackendRequestsErrored int64 `json:"backendRequestsErrored"`
97+
SdksTotalRequests int64 `json:"sdksTotalRequests"`
98+
LoggedErrors int64 `json:"loggedErrors"`
99+
LoggedMessages []string `json:"loggedMessages"`
100+
FeatureFlags []SplitSummary `json:"featureFlags"`
101+
Segments []SegmentSummary `json:"segments"`
102+
LargeSegments []LargeSegmentSummary `json:"largesegments"`
103+
RuleBasedSegments []RuleBasedSegmentSummary `json:"rulebasedsegments"`
104+
Latencies []ChartJSData `json:"latencies"`
105+
BackendLatencies []ChartJSData `json:"backendLatencies"`
106+
ImpressionsQueueSize int64 `json:"impressionsQueueSize"`
107+
ImpressionsLambda float64 `json:"impressionsLambda"`
108+
EventsQueueSize int64 `json:"eventsQueueSize"`
109+
EventsLambda float64 `json:"eventsLambda"`
110+
Uptime int64 `json:"uptime"`
111+
FlagSets []FlagSetsSummary `json:"flagSets"`
111112
}
112113

113114
// SplitSummary encapsulates a minimalistic view of feature flag properties to be presented in the dashboard
@@ -137,6 +138,20 @@ type LargeSegmentSummary struct {
137138
LastModified string `json:"cn"`
138139
}
139140

141+
type RuleBasedSegmentSummary struct {
142+
Name string `json:"name"`
143+
Active bool `json:"active"`
144+
ExcludedKeys []string `json:"excludedKeys"`
145+
ExcluededSegments []ExcluededSegments `json:"excludedSegments"`
146+
LastModified string `json:"cn"`
147+
ChangeNumber int64 `json:"changeNumber"`
148+
}
149+
150+
type ExcluededSegments struct {
151+
Name string `json:"name"`
152+
Type string `json:"type"`
153+
}
154+
140155
// SegmentKeySummary encapsulates basic information associated to the key in proxy mode
141156
// (fields other than name are empty when running as producer
142157
type SegmentKeySummary struct {

splitio/commitversion.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ This file is created automatically, please do not edit
55
*/
66

77
// CommitVersion is the version of the last commit previous to release
8-
const CommitVersion = "514a95c"
8+
const CommitVersion = "8fd26d7"

splitio/proxy/initialization.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,11 @@ func Start(logger logging.LoggerInterface, cfg *pconf.Main) error {
208208

209209
rtm := common.NewRuntime(false, syncManager, logger, "Split Proxy", nil, nil, appMonitor, servicesMonitor)
210210
storages := adminCommon.Storages{
211-
SplitStorage: splitStorage,
212-
SegmentStorage: segmentStorage,
213-
LocalTelemetryStorage: localTelemetryStorage,
214-
LargeSegmentStorage: largeSegmentStorage,
211+
SplitStorage: splitStorage,
212+
SegmentStorage: segmentStorage,
213+
LocalTelemetryStorage: localTelemetryStorage,
214+
LargeSegmentStorage: largeSegmentStorage,
215+
RuleBasedSegmentsStorage: ruleBasedStorage,
215216
}
216217

217218
// --------------------------- ADMIN DASHBOARD ------------------------------

0 commit comments

Comments
 (0)