Skip to content

Commit

Permalink
Merge pull request #294 from splitio/ls-proxy-dashboard
Browse files Browse the repository at this point in the history
Dashboard implementation
  • Loading branch information
sanzmauro authored Nov 28, 2024
2 parents 01f80b1 + bf938f0 commit 7d8ee9e
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 63 deletions.
36 changes: 19 additions & 17 deletions splitio/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,24 @@ const baseShutdownPath = "/shutdown"

// Options encapsulates dependencies & config options for the Admin server
type Options struct {
Host string
Port int
Name string
Proxy bool
Username string
Password string
Logger logging.LoggerInterface
Storages adminCommon.Storages
ImpressionsEvCalc evcalc.Monitor
EventsEvCalc evcalc.Monitor
Runtime common.Runtime
HcAppMonitor application.MonitorIterface
HcServicesMonitor services.MonitorIterface
Snapshotter cstorage.Snapshotter
TLS *tls.Config
FullConfig interface{}
FlagSpecVersion string
Host string
Port int
Name string
Proxy bool
Username string
Password string
Logger logging.LoggerInterface
Storages adminCommon.Storages
ImpressionsEvCalc evcalc.Monitor
EventsEvCalc evcalc.Monitor
Runtime common.Runtime
HcAppMonitor application.MonitorIterface
HcServicesMonitor services.MonitorIterface
Snapshotter cstorage.Snapshotter
TLS *tls.Config
FullConfig interface{}
FlagSpecVersion string
LargeSegmentVersion string
}

type AdminServer struct {
Expand Down Expand Up @@ -68,6 +69,7 @@ func NewServer(options *Options) (*AdminServer, error) {
options.Runtime,
options.HcAppMonitor,
options.FlagSpecVersion,
options.LargeSegmentVersion,
)
if err != nil {
return nil, fmt.Errorf("error instantiating dashboard controller: %w", err)
Expand Down
42 changes: 23 additions & 19 deletions splitio/admin/controllers/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ import (

// DashboardController contains handlers for rendering the dashboard and its associated FE queries
type DashboardController struct {
title string
proxy bool
logger logging.LoggerInterface
storages adminCommon.Storages
layout *template.Template
impressionsEvCalc evcalc.Monitor
eventsEvCalc evcalc.Monitor
runtime common.Runtime
appMonitor application.MonitorIterface
FlagSpecVersion string
title string
proxy bool
logger logging.LoggerInterface
storages adminCommon.Storages
layout *template.Template
impressionsEvCalc evcalc.Monitor
eventsEvCalc evcalc.Monitor
runtime common.Runtime
appMonitor application.MonitorIterface
FlagSpecVersion string
LargeSegmentVersion string
}

// NewDashboardController instantiates a new dashboard controller
Expand All @@ -43,18 +44,20 @@ func NewDashboardController(
runtime common.Runtime,
appMonitor application.MonitorIterface,
flagSpecVersion string,
largeSegmentVersion string,
) (*DashboardController, error) {

toReturn := &DashboardController{
title: name,
proxy: proxy,
logger: logger,
runtime: runtime,
storages: storages,
eventsEvCalc: eventsEvCalc,
impressionsEvCalc: impressionEvCalc,
appMonitor: appMonitor,
FlagSpecVersion: flagSpecVersion,
title: name,
proxy: proxy,
logger: logger,
runtime: runtime,
storages: storages,
eventsEvCalc: eventsEvCalc,
impressionsEvCalc: impressionEvCalc,
appMonitor: appMonitor,
FlagSpecVersion: flagSpecVersion,
LargeSegmentVersion: largeSegmentVersion,
}

var err error
Expand Down Expand Up @@ -146,6 +149,7 @@ func (c *DashboardController) gatherStats() *dashboard.GlobalStats {
return &dashboard.GlobalStats{
FeatureFlags: bundleSplitInfo(c.storages.SplitStorage),
Segments: bundleSegmentInfo(c.storages.SplitStorage, c.storages.SegmentStorage),
LargeSegments: bundleLargeSegmentInfo(c.storages.SplitStorage, c.storages.LargeSegmentStorage),
Latencies: bundleProxyLatencies(c.storages.LocalTelemetryStorage),
BackendLatencies: bundleLocalSyncLatencies(c.storages.LocalTelemetryStorage),
ImpressionsQueueSize: getImpressionSize(c.storages.ImpressionStorage),
Expand Down
24 changes: 24 additions & 0 deletions splitio/admin/controllers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,30 @@ func bundleSplitInfo(splitStorage storage.SplitStorageConsumer) []dashboard.Spli
return summaries
}

func bundleLargeSegmentInfo(splitStorage storage.SplitStorage, lsStorage storage.LargeSegmentStorageConsumer) []dashboard.LargeSegmentSummary {
if lsStorage == nil {
return []dashboard.LargeSegmentSummary{}
}

lsNames := splitStorage.LargeSegmentNames()

toReturn := make([]dashboard.LargeSegmentSummary, 0, lsNames.Size())
for _, name := range lsNames.List() {
strName, ok := name.(string)
if !ok {
continue
}
cn := lsStorage.ChangeNumber(strName)
toReturn = append(toReturn, dashboard.LargeSegmentSummary{
Name: strName,
TotalKeys: lsStorage.TotalKeys(strName),
LastModified: time.Unix(0, cn*int64(time.Millisecond)).UTC().Format(time.UnixDate),
})
}

return toReturn
}

func bundleSegmentInfo(splitStorage storage.SplitStorage, segmentStorage storage.SegmentStorageConsumer) []dashboard.SegmentSummary {
names := splitStorage.SegmentNames()
summaries := make([]dashboard.SegmentSummary, 0, names.Size())
Expand Down
36 changes: 36 additions & 0 deletions splitio/admin/views/dashboard/datainspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ const dataInspector = `
 Segments
</a>
</li>
{{if .ProxyMode}}
<li role="presentation" class="">
<a href="#large-segments-data" aria-controls="profile" role="tab" data-toggle="tab">
<span class="glyphicon" style="vertical-align:bottom" aria-hidden="true">
<svg fill="none" height="24" viewBox="0 0 25 24" width="25" xmlns="http://www.w3.org/2000/svg">
<path d="M9.34835 6.34835C10.0516 5.64509 11.0054 5.25 12 5.25C12.9946 5.25 13.9484 5.64509 14.6517 6.34835C15.3549 7.05161 15.75 8.00544 15.75 9C15.75 9.99456 15.3549 10.9484 14.6517 11.6517C14.5961 11.7072 14.539 11.7608 14.4804 11.8125C15.0632 12.0912 15.6003 12.4686 16.0659 12.9341C17.1442 14.0125 17.75 15.475 17.75 17V18C17.75 18.4142 17.4142 18.75 17 18.75C16.5858 18.75 16.25 18.4142 16.25 18V17C16.25 15.8728 15.8022 14.7918 15.0052 13.9948C14.2082 13.1978 13.1272 12.75 12 12.75C10.8728 12.75 9.79183 13.1978 8.9948 13.9948C8.19777 14.7918 7.75 15.8728 7.75 17V18C7.75 18.4142 7.41421 18.75 7 18.75C6.58579 18.75 6.25 18.4142 6.25 18V17C6.25 15.475 6.8558 14.0125 7.93414 12.9341C8.39965 12.4686 8.93677 12.0912 9.5196 11.8125C9.46102 11.7608 9.4039 11.7072 9.34835 11.6517C8.64509 10.9484 8.25 9.99456 8.25 9C8.25 8.00544 8.64509 7.05161 9.34835 6.34835ZM12 6.75C11.4033 6.75 10.831 6.98705 10.409 7.40901C9.98705 7.83097 9.75 8.40326 9.75 9C9.75 9.59674 9.98705 10.169 10.409 10.591C10.831 11.0129 11.4033 11.25 12 11.25C12.5967 11.25 13.169 11.0129 13.591 10.591C14.0129 10.169 14.25 9.59674 14.25 9C14.25 8.40326 14.0129 7.83097 13.591 7.40901C13.169 6.98705 12.5967 6.75 12 6.75ZM2.05546 10.0555C2.57118 9.53973 3.27065 9.25 4 9.25C4.72935 9.25 5.42882 9.53973 5.94454 10.0555C6.46027 10.5712 6.75 11.2707 6.75 12C6.75 12.7293 6.46027 13.4288 5.94454 13.9445C5.42882 14.4603 4.72935 14.75 4 14.75C3.40326 14.75 2.83097 14.9871 2.40901 15.409C1.98705 15.831 1.75 16.4033 1.75 17V18C1.75 18.4142 1.41421 18.75 1 18.75C0.585786 18.75 0.25 18.4142 0.25 18V17C0.25 16.0054 0.645088 15.0516 1.34835 14.3483C1.53727 14.1594 1.74427 13.9927 1.96529 13.85C1.50608 13.345 1.25 12.6857 1.25 12C1.25 11.2707 1.53973 10.5712 2.05546 10.0555ZM4 10.75C3.66848 10.75 3.35054 10.8817 3.11612 11.1161C2.8817 11.3505 2.75 11.6685 2.75 12C2.75 12.3315 2.8817 12.6495 3.11612 12.8839C3.35054 13.1183 3.66848 13.25 4 13.25C4.33152 13.25 4.64946 13.1183 4.88388 12.8839C5.1183 12.6495 5.25 12.3315 5.25 12C5.25 11.6685 5.1183 11.3505 4.88388 11.1161C4.64946 10.8817 4.33152 10.75 4 10.75ZM18.0555 10.0555C18.5712 9.53973 19.2707 9.25 20 9.25C20.7293 9.25 21.4288 9.53973 21.9445 10.0555C22.4603 10.5712 22.75 11.2707 22.75 12C22.75 12.6857 22.4939 13.345 22.0347 13.85C22.2557 13.9928 22.4627 14.1594 22.6517 14.3483C23.3549 15.0516 23.75 16.0054 23.75 17V18C23.75 18.4142 23.4142 18.75 23 18.75C22.5858 18.75 22.25 18.4142 22.25 18V17C22.25 16.4033 22.0129 15.831 21.591 15.409C21.169 14.9871 20.5967 14.75 20 14.75C19.2707 14.75 18.5712 14.4603 18.0555 13.9445C17.5397 13.4288 17.25 12.7293 17.25 12C17.25 11.2707 17.5397 10.5712 18.0555 10.0555ZM20 13.25C20.3315 13.25 20.6495 13.1183 20.8839 12.8839C21.1183 12.6495 21.25 12.3315 21.25 12C21.25 11.6685 21.1183 11.3505 20.8839 11.1161C20.6495 10.8817 20.3315 10.75 20 10.75C19.6685 10.75 19.3505 10.8817 19.1161 11.1161C18.8817 11.3505 18.75 11.6685 18.75 12C18.75 12.3315 18.8817 12.6495 19.1161 12.8839C19.3505 13.1183 19.6685 13.25 20 13.25Z" fill-rule="evenodd" clip-rule="evenodd" fill="currentColor"></path>
</svg>
</span>
&nbsp;Large Segments
</a>
</li>
{{end}}
<li role="presentation" class="">
<a href="#flag-sets-data" aria-controls="profile" role="tab" data-toggle="tab">
<span class="glyphicon" style="vertical-align:bottom" aria-hidden="true">
Expand Down Expand Up @@ -118,6 +130,30 @@ const dataInspector = `
</div>
</div>
{{if .ProxyMode}}
<!-- LARGE SEGMENTS DATA -->
<div role="tabpanel" class="tab-pane" id="large-segments-data">
<div class="row">
<div class="col-md-12">
<div class="bg-primary metricBox">
<!-- <h4>Large Segments in proxy</h4> -->
<table id="large_segment_rows" class="table table-condensed table-hover">
<thead>
<tr>
<th>Large Segment</th>
<th>Total Keys</th>
<th>Last Modified</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
{{end}}
<!-- FLAG SETS DATA -->
<div role="tabpanel" class="tab-pane" id="flag-sets-data">
<div class="row">
Expand Down
16 changes: 16 additions & 0 deletions splitio/admin/views/dashboard/js.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,26 @@ const mainScript = `
'</tr>';
}
function formatLargeSegment(segment) {
return '<tr>' +
'<td>' + segment.name + '</td>' +
'<td>' + segment.totalKeys + '</td>' +
'<td>' + segment.cn + '</td>' +
'</tr>';
}
function updateSegments(segments) {
const formatted = segments.map(formatSegment).join('\n');
$('#segment_rows tbody').empty();
$('#segment_rows tbody').append(formatted);
};
function updateLargeSegments(segments) {
const formatted = segments.map(formatLargeSegment).join('\n');
$('#large_segment_rows tbody').empty();
$('#large_segment_rows tbody').append(formatted);
};
function updateMetricCards(stats) {
$('#impressions_queue_value_section').html(stats.impressionsQueueSize);
$('#impressions_lambda_section').html(stats.impressionsLambda);
Expand All @@ -333,6 +347,7 @@ const mainScript = `
$('#backend_total_requests').html(stats.backendTotalRequests);
$('#feature_flags_number').html(stats.featureFlags.length);
$('#segments_number').html(stats.segments.length);
$('#large_segments_number').html(stats.largesegments.length);
$('#flag_sets_number').html(stats.flagSets.length);
$('#impressions_queue_value').html(stats.impressionsQueueSize);
$('#events_queue_value').html(stats.eventsQueueSize);
Expand Down Expand Up @@ -427,6 +442,7 @@ const mainScript = `
updateMetricCards(stats)
updateFeatureFlags(stats.featureFlags);
updateSegments(stats.segments);
updateLargeSegments(stats.largesegments);
updateLogEntries(stats.loggedMessages);
updateFlagSets(stats.flagSets)
Expand Down
60 changes: 34 additions & 26 deletions splitio/admin/views/dashboard/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,36 +76,38 @@ const main = `

// RootObject is the main/root object used to render the dashboard
type RootObject struct {
DashboardTitle string
Version string
ProxyMode bool
RefreshTime int64
Stats GlobalStats `json:"stats"`
Health application.HealthDto `json:"health"`
ServicesHealth services.HealthDto `json:"servicesHealth"`
FlagSpecVersion string
DashboardTitle string
Version string
ProxyMode bool
RefreshTime int64
Stats GlobalStats `json:"stats"`
Health application.HealthDto `json:"health"`
ServicesHealth services.HealthDto `json:"servicesHealth"`
FlagSpecVersion string
LargeSegmentVersion string
}

// GlobalStats runtime stats used to render the dashboard
type GlobalStats struct {
BackendTotalRequests int64 `json:"backendTotalRequests"`
RequestsOk int64 `json:"requestsOk"`
RequestsErrored int64 `json:"requestsErrored"`
BackendRequestsOk int64 `json:"backendRequestsOk"`
BackendRequestsErrored int64 `json:"backendRequestsErrored"`
SdksTotalRequests int64 `json:"sdksTotalRequests"`
LoggedErrors int64 `json:"loggedErrors"`
LoggedMessages []string `json:"loggedMessages"`
FeatureFlags []SplitSummary `json:"featureFlags"`
Segments []SegmentSummary `json:"segments"`
Latencies []ChartJSData `json:"latencies"`
BackendLatencies []ChartJSData `json:"backendLatencies"`
ImpressionsQueueSize int64 `json:"impressionsQueueSize"`
ImpressionsLambda float64 `json:"impressionsLambda"`
EventsQueueSize int64 `json:"eventsQueueSize"`
EventsLambda float64 `json:"eventsLambda"`
Uptime int64 `json:"uptime"`
FlagSets []FlagSetsSummary `json:"flagSets"`
BackendTotalRequests int64 `json:"backendTotalRequests"`
RequestsOk int64 `json:"requestsOk"`
RequestsErrored int64 `json:"requestsErrored"`
BackendRequestsOk int64 `json:"backendRequestsOk"`
BackendRequestsErrored int64 `json:"backendRequestsErrored"`
SdksTotalRequests int64 `json:"sdksTotalRequests"`
LoggedErrors int64 `json:"loggedErrors"`
LoggedMessages []string `json:"loggedMessages"`
FeatureFlags []SplitSummary `json:"featureFlags"`
Segments []SegmentSummary `json:"segments"`
LargeSegments []LargeSegmentSummary `json:"largesegments"`
Latencies []ChartJSData `json:"latencies"`
BackendLatencies []ChartJSData `json:"backendLatencies"`
ImpressionsQueueSize int64 `json:"impressionsQueueSize"`
ImpressionsLambda float64 `json:"impressionsLambda"`
EventsQueueSize int64 `json:"eventsQueueSize"`
EventsLambda float64 `json:"eventsLambda"`
Uptime int64 `json:"uptime"`
FlagSets []FlagSetsSummary `json:"flagSets"`
}

// SplitSummary encapsulates a minimalistic view of feature flag properties to be presented in the dashboard
Expand All @@ -129,6 +131,12 @@ type SegmentSummary struct {
LastModified string `json:"cn"`
}

type LargeSegmentSummary struct {
Name string `json:"name"`
TotalKeys int `json:"totalKeys"`
LastModified string `json:"cn"`
}

// SegmentKeySummary encapsulates basic information associated to the key in proxy mode
// (fields other than name are empty when running as producer
type SegmentKeySummary struct {
Expand Down
8 changes: 7 additions & 1 deletion splitio/admin/views/dashboard/stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,18 @@ const cards = `
<h1 id="feature_flags_number" class="centerText"></h1>
</div>
</div>
<div class="col-md-4">
<div class="col-md-2">
<div class="gray2Box metricBox">
<h4>Cached Segments</h4>
<h1 id="segments_number" class="centerText"></h1>
</div>
</div>
<div class="col-md-2">
<div class="gray2Box metricBox">
<h4>Cached Large Segments</h4>
<h1 id="large_segments_number" class="centerText"></h1>
</div>
</div>
<div class="col-md-4">
<div class="gray2Box metricBox">
<h4>Cached Flag Sets</h4>
Expand Down

0 comments on commit 7d8ee9e

Please sign in to comment.