feat(backend): allow configuring defaults for the UI

This commit is contained in:
Łukasz Mierzwa
2019-10-04 23:03:10 +01:00
parent 81ab1029c8
commit d7c15240f1
6 changed files with 125 additions and 1 deletions

View File

@@ -79,10 +79,17 @@ func index(c *gin.Context) {
}
filtersB64 := base64.StdEncoding.EncodeToString(filtersJSON)
defaults, err := json.Marshal(config.Config.UI)
if err != nil {
panic(err)
}
defaultsB64 := base64.StdEncoding.EncodeToString(defaults)
c.HTML(http.StatusOK, "ui/build/index.html", gin.H{
"Version": version,
"SentryDSN": config.Config.Sentry.Public,
"DefaultFilter": filtersB64,
"Defaults": defaultsB64,
})
log.Infof("[%s] %s %s took %s", c.ClientIP(), c.Request.Method, c.Request.RequestURI, time.Since(start))

View File

@@ -615,7 +615,7 @@ sentry:
## Silence form
`silenceForm` section allow customizing silence form behavior.
`silenceForm` section allows customizing silence form behavior.
`author:populate_from_header` subsection allows to configure fetching of author
name used on the silence form from the request header. It can be used with
setups where karma is deployed behind authentication proxy that adds some extra
@@ -660,6 +660,52 @@ silenceForm:
- job
```
## UI defaults
`ui` section allows configuring default values for UI settings controled via the
configuration modal. Those defaults can be overwritten by use via UI controls.
Syntax:
```YAML
ui:
refresh: duration
hideFiltersWhenIdle: bool
colorTitlebar: bool
minimalGroupWidth: integer
alertsPerGroup: integer
collapseGroups: string
```
- `refresh` - default refresh interval, this tells the UI how often karma API
should be queried
- `hideFiltersWhenIdle` - if enabled filter bar will be hidden after some
user inactivity
- `colorTitlebar` - if enabled alert group title bar color will be set to follow
alerts in that group
- `minimalGroupWidth` - minimal width (in pixels) for each alert group rendered
on the grid. This value is used to calculate the number of columns rendered on
the grid.
- `alertsPerGroup` - default number of alerts to show for each group
- `collapseGroups` - controls if alert groups will default to being rendered
expanded or collapsed (only title bar is visible). Valid values:
- expanded - groups are always expanded
- collapsed - groups are always collapsed
- collapsedOnMobile - groups are expanded on desktop and collapsed on mobile
browsers
Defaults:
```YAML
ui:
refresh: 30s
hideFiltersWhenIdle: true
colorTitlebar: false
minimalGroupWidth: 420
alertsPerGroup: 5
collapseGroups: collapsedOnMobile
```
## Customizing karma
In order to keep the core code simple karma doesn't support any way of extending

View File

@@ -57,3 +57,10 @@ silenceForm:
strip:
labels:
- job
ui:
refresh: 30s
hideFiltersWhenIdle: true
colorTitlebar: false
minimalGroupWidth: 420
alertsPerGroup: 5
collapseGroups: collapsedOnMobile

View File

@@ -90,6 +90,13 @@ func init() {
pflag.String("sentry.public", "", "Sentry DSN for Go exceptions")
pflag.String("sentry.private", "", "Sentry DSN for JavaScript exceptions")
pflag.Duration("ui.refresh", time.Second*30, "UI refresh interval")
pflag.Bool("ui.hideFiltersWhenIdle", true, "Hide the filters bar when idle")
pflag.Bool("ui.colorTitlebar", false, "Color alert group titlebar based on alert state")
pflag.Int("ui.minimalGroupWidth", 420, "Minimal width for each alert group on the grid")
pflag.Int("ui.alertsPerGroup", 5, "Default number of alerts to show for each alert group")
pflag.String("ui.collapseGroups", "collapsedOnMobile", "Default state for alert groups")
}
// ReadConfig will read all sources of configuration, merge all keys and
@@ -173,6 +180,12 @@ func (config *configSchema) Read() {
config.SilenceForm.Strip.Labels = v.GetStringSlice("silenceform.strip.labels")
config.SilenceForm.Author.PopulateFromHeader.Header = v.GetString("silenceform.author.populate_from_header.header")
config.SilenceForm.Author.PopulateFromHeader.ValueRegex = v.GetString("silenceform.author.populate_from_header.value_re")
config.UI.Refresh = v.GetDuration("ui.refresh")
config.UI.HideFiltersWhenIdle = v.GetBool("ui.hideFiltersWhenIdle")
config.UI.ColorTitlebar = v.GetBool("ui.colorTitlebar")
config.UI.MinimalGroupWidth = v.GetInt("ui.minimalGroupWidth")
config.UI.AlertsPerGroup = v.GetInt("ui.alertsPerGroup")
config.UI.CollapseGroups = v.GetString("ui.collapseGroups")
if config.SilenceForm.Author.PopulateFromHeader.ValueRegex != "" {
_, err = regexp.Compile(config.SilenceForm.Author.PopulateFromHeader.ValueRegex)
@@ -223,6 +236,10 @@ func (config *configSchema) Read() {
log.Fatalf("Invalid grid.sorting.order value '%s', allowed options: disabled, startsAt, label", config.Grid.Sorting.Order)
}
if !slices.StringInSlice([]string{"expanded", "collapsed", "collapsedOnMobile"}, config.UI.CollapseGroups) {
log.Fatalf("Invalid ui.collapseGroups value '%s', allowed options: expanded, collapsed, collapsedOnMobile", config.UI.CollapseGroups)
}
// FIXME workaround for https://github.com/prymitive/karma/issues/507
// until https://github.com/spf13/viper/pull/635 is merged
// read in raw config file if it's used and override maps where keys are label

View File

@@ -129,6 +129,13 @@ silenceForm:
value_re: ""
strip:
labels: []
ui:
refresh: 30s
hideFiltersWhenIdle: true
colorTitlebar: false
minimalGroupWidth: 420
alertsPerGroup: 5
collapseGroups: collapsedOnMobile
`
configDump, err := yaml.Marshal(Config)
@@ -259,3 +266,35 @@ func TestInvalidSilenceFormRegex(t *testing.T) {
t.Error("Invalid silence form regex didn't cause log.Fatal()")
}
}
func TestInvalidGridSortingOrder(t *testing.T) {
resetEnv()
os.Setenv("GRID_SORTING_ORDER", "foo")
log.SetLevel(log.PanicLevel)
defer func() { log.StandardLogger().ExitFunc = nil }()
var wasFatal bool
log.StandardLogger().ExitFunc = func(int) { wasFatal = true }
Config.Read()
if !wasFatal {
t.Error("Invalid grid.sorting.order value didn't cause log.Fatal()")
}
}
func TestInvalidUICollapseGroups(t *testing.T) {
resetEnv()
os.Setenv("UI_COLLAPSEGROUPS", "foo")
log.SetLevel(log.PanicLevel)
defer func() { log.StandardLogger().ExitFunc = nil }()
var wasFatal bool
log.StandardLogger().ExitFunc = func(int) { wasFatal = true }
Config.Read()
if !wasFatal {
t.Error("Invalid ui.collapseGroups value didn't cause log.Fatal()")
}
}

View File

@@ -105,4 +105,12 @@ type configSchema struct {
Labels []string
}
} `yaml:"silenceForm" mapstructure:"silenceForm"`
UI struct {
Refresh time.Duration
HideFiltersWhenIdle bool `yaml:"hideFiltersWhenIdle" mapstructure:"hideFiltersWhenIdle"`
ColorTitlebar bool `yaml:"colorTitlebar" mapstructure:"colorTitlebar"`
MinimalGroupWidth int `yaml:"minimalGroupWidth" mapstructure:"minimalGroupWidth"`
AlertsPerGroup int `yaml:"alertsPerGroup" mapstructure:"alertsPerGroup"`
CollapseGroups string `yaml:"collapseGroups" mapstructure:"collapseGroups"`
}
}