feat: logs column lock (#3669)
* feat: logs column lock * feat: logs column lock indicator * feat: fix getting values from config * feat: removed unnecessary new linemine
parent
6bc67e97f4
commit
6f0ecdec9b
|
|
@ -464,6 +464,8 @@ You can now override the context portForward default address configuration by se
|
|||
textWrap: false
|
||||
# Autoscroll in logs will be disabled. Default is false.
|
||||
disableAutoscroll: false
|
||||
# Enable column locking when autoscroll is enabled. Default is false.
|
||||
columnLock: false
|
||||
# Toggles log line timestamp info. Default false
|
||||
showTime: false
|
||||
# Provide shell pod customization when nodeShell feature gate is enabled!
|
||||
|
|
@ -1115,6 +1117,7 @@ k9s:
|
|||
sinceSeconds: -1
|
||||
textWrap: false
|
||||
disableAutoscroll: false
|
||||
columnLock: false
|
||||
showTime: false
|
||||
thresholds:
|
||||
cpu:
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@
|
|||
"sinceSeconds": {"type": "integer"},
|
||||
"textWrap": {"type": "boolean"},
|
||||
"disableAutoscroll": {"type": "boolean"},
|
||||
"columnLock": {"type": "boolean"},
|
||||
"showTime": {"type": "boolean"}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ k9s:
|
|||
sinceSeconds: -1
|
||||
textWrap: false
|
||||
disableAutoscroll: false
|
||||
columnLock: false
|
||||
showTime: false
|
||||
thresholds:
|
||||
cpu:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ k9s:
|
|||
sinceSeconds: -1
|
||||
textWrap: false
|
||||
disableAutoscroll: false
|
||||
columnLock: false
|
||||
showTime: false
|
||||
thresholds:
|
||||
cpu:
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ type Logger struct {
|
|||
SinceSeconds int64 `json:"sinceSeconds" yaml:"sinceSeconds"`
|
||||
TextWrap bool `json:"textWrap" yaml:"textWrap"`
|
||||
DisableAutoscroll bool `json:"disableAutoscroll" yaml:"disableAutoscroll"`
|
||||
ColumnLock bool `json:"columnLock" yaml:"columnLock"`
|
||||
ShowTime bool `json:"showTime" yaml:"showTime"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ k9s:
|
|||
sinceSeconds: -1
|
||||
textWrap: false
|
||||
disableAutoscroll: false
|
||||
columnLock: false
|
||||
showTime: false
|
||||
thresholds:
|
||||
cpu:
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ k9s:
|
|||
sinceSeconds: -1
|
||||
textWrap: false
|
||||
disableAutoscroll: false
|
||||
columnLock: false
|
||||
showTime: false
|
||||
thresholds:
|
||||
cpu:
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ k9s:
|
|||
sinceSeconds: -1
|
||||
textWrap: false
|
||||
disableAutoscroll: false
|
||||
columnLock: false
|
||||
showTime: false
|
||||
thresholds:
|
||||
cpu:
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ k9s:
|
|||
sinceSeconds: -1
|
||||
textWrap: false
|
||||
disableAutoscroll: false
|
||||
columnLock: false
|
||||
showTime: false
|
||||
thresholds:
|
||||
cpu:
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ type Log struct {
|
|||
cancelUpdates bool
|
||||
mx sync.Mutex
|
||||
follow bool
|
||||
columnLock bool
|
||||
requestOneRefresh bool
|
||||
}
|
||||
|
||||
|
|
@ -56,13 +57,10 @@ var _ model.Component = (*Log)(nil)
|
|||
|
||||
// NewLog returns a new viewer.
|
||||
func NewLog(gvr *client.GVR, opts *dao.LogOptions) *Log {
|
||||
l := Log{
|
||||
Flex: tview.NewFlex(),
|
||||
model: model.NewLog(gvr, opts, defaultFlushTimeout),
|
||||
follow: true,
|
||||
return &Log{
|
||||
Flex: tview.NewFlex(),
|
||||
model: model.NewLog(gvr, opts, defaultFlushTimeout),
|
||||
}
|
||||
|
||||
return &l
|
||||
}
|
||||
|
||||
func (*Log) SetCommand(*cmd.Interpreter) {}
|
||||
|
|
@ -105,6 +103,9 @@ func (l *Log) Init(ctx context.Context) (err error) {
|
|||
l.model.Init(l.app.factory)
|
||||
l.updateTitle()
|
||||
|
||||
l.follow = !l.app.Config.K9s.Logger.DisableAutoscroll
|
||||
l.columnLock = l.app.Config.K9s.Logger.ColumnLock
|
||||
|
||||
l.model.ToggleShowTimestamp(l.app.Config.K9s.Logger.ShowTime)
|
||||
|
||||
return nil
|
||||
|
|
@ -258,6 +259,7 @@ func (l *Log) bindKeys() {
|
|||
ui.KeyShiftC: ui.NewKeyAction("Clear", l.clearCmd, true),
|
||||
ui.KeyM: ui.NewKeyAction("Mark", l.markCmd, true),
|
||||
ui.KeyS: ui.NewKeyAction("Toggle AutoScroll", l.toggleAutoScrollCmd, true),
|
||||
ui.KeyShiftL: ui.NewKeyAction("Toggle ColumnLock", l.toggleColumnLockCmd, true),
|
||||
ui.KeyF: ui.NewKeyAction("Toggle FullScreen", l.toggleFullScreenCmd, true),
|
||||
ui.KeyT: ui.NewKeyAction("Toggle Timestamp", l.toggleTimestampCmd, true),
|
||||
ui.KeyW: ui.NewKeyAction("Toggle Wrap", l.toggleTextWrapCmd, true),
|
||||
|
|
@ -363,7 +365,12 @@ func (l *Log) Flush(lines [][]byte) {
|
|||
_, _ = l.ansiWriter.Write(lines[i])
|
||||
}
|
||||
if l.follow {
|
||||
l.logs.ScrollToEnd()
|
||||
if l.columnLock {
|
||||
// Enables end tracking without resetting column
|
||||
l.logs.SetScrollable(false).SetScrollable(true)
|
||||
} else {
|
||||
l.logs.ScrollToEnd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -464,7 +471,7 @@ func (l *Log) clearCmd(*tcell.EventKey) *tcell.EventKey {
|
|||
|
||||
func (l *Log) markCmd(*tcell.EventKey) *tcell.EventKey {
|
||||
_, _, w, _ := l.GetRect()
|
||||
_, _ = fmt.Fprintf(l.ansiWriter, "\n[%s:-:b]%s[-:-:-]", l.app.Styles.Views().Log.FgColor.String(), strings.Repeat("-", w-4))
|
||||
_, _ = fmt.Fprintf(l.ansiWriter, "[%s:-:b]%s[-:-:-]\n", l.app.Styles.Views().Log.FgColor.String(), strings.Repeat("-", w-4))
|
||||
l.follow = true
|
||||
|
||||
return nil
|
||||
|
|
@ -507,6 +514,18 @@ func (l *Log) toggleAutoScrollCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (l *Log) toggleColumnLockCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if l.app.InCmdMode() {
|
||||
return evt
|
||||
}
|
||||
|
||||
l.indicator.ToggleColumnLock()
|
||||
l.columnLock = l.indicator.ColumnLock()
|
||||
l.indicator.Refresh()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Log) toggleFullScreenCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if l.app.InCmdMode() {
|
||||
return evt
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ type LogIndicator struct {
|
|||
showTime bool
|
||||
allContainers bool
|
||||
shouldDisplayAllContainers bool
|
||||
columnLock bool
|
||||
}
|
||||
|
||||
// NewLogIndicator returns a new indicator.
|
||||
|
|
@ -38,11 +39,13 @@ func NewLogIndicator(cfg *config.Config, styles *config.Styles, allContainers bo
|
|||
textWrap: cfg.K9s.Logger.TextWrap,
|
||||
showTime: cfg.K9s.Logger.ShowTime,
|
||||
shouldDisplayAllContainers: allContainers,
|
||||
columnLock: cfg.K9s.Logger.ColumnLock,
|
||||
}
|
||||
|
||||
if cfg.K9s.Logger.DisableAutoscroll {
|
||||
l.scrollStatus = 0
|
||||
}
|
||||
|
||||
l.StylesChanged(styles)
|
||||
styles.AddListener(&l)
|
||||
l.SetTextAlign(tview.AlignCenter)
|
||||
|
|
@ -63,6 +66,11 @@ func (l *LogIndicator) AutoScroll() bool {
|
|||
return atomic.LoadInt32(&l.scrollStatus) == 1
|
||||
}
|
||||
|
||||
// ColumnLock reports the current column lock mode.
|
||||
func (l *LogIndicator) ColumnLock() bool {
|
||||
return l.columnLock
|
||||
}
|
||||
|
||||
// Timestamp reports the current timestamp mode.
|
||||
func (l *LogIndicator) Timestamp() bool {
|
||||
return l.showTime
|
||||
|
|
@ -78,6 +86,11 @@ func (l *LogIndicator) FullScreen() bool {
|
|||
return l.fullScreen
|
||||
}
|
||||
|
||||
// ToggleColumnLock toggles the current column lock mode.
|
||||
func (l *LogIndicator) ToggleColumnLock() {
|
||||
l.columnLock = !l.columnLock
|
||||
}
|
||||
|
||||
// ToggleTimestamp toggles the current timestamp mode.
|
||||
func (l *LogIndicator) ToggleTimestamp() {
|
||||
l.showTime = !l.showTime
|
||||
|
|
@ -140,6 +153,12 @@ func (l *LogIndicator) Refresh() {
|
|||
l.indicator = append(l.indicator, fmt.Sprintf(toggleOffFmt, "Autoscroll", spacer)...)
|
||||
}
|
||||
|
||||
if l.ColumnLock() {
|
||||
l.indicator = append(l.indicator, fmt.Sprintf(toggleOnFmt, "ColumnLock", spacer)...)
|
||||
} else {
|
||||
l.indicator = append(l.indicator, fmt.Sprintf(toggleOffFmt, "ColumnLock", spacer)...)
|
||||
}
|
||||
|
||||
if l.FullScreen() {
|
||||
l.indicator = append(l.indicator, fmt.Sprintf(toggleOnFmt, "FullScreen", spacer)...)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ func TestLogIndicatorRefresh(t *testing.T) {
|
|||
e string
|
||||
}{
|
||||
"all-containers": {
|
||||
view.NewLogIndicator(config.NewConfig(nil), defaults, true), "[::b]AllContainers:[gray::d]Off[-::] [::b]Autoscroll:[limegreen::b]On[-::] [::b]FullScreen:[gray::d]Off[-::] [::b]Timestamps:[gray::d]Off[-::] [::b]Wrap:[gray::d]Off[-::]\n",
|
||||
view.NewLogIndicator(config.NewConfig(nil), defaults, true), "[::b]AllContainers:[gray::d]Off[-::] [::b]Autoscroll:[limegreen::b]On[-::] [::b]ColumnLock:[gray::d]Off[-::] [::b]FullScreen:[gray::d]Off[-::] [::b]Timestamps:[gray::d]Off[-::] [::b]Wrap:[gray::d]Off[-::]\n",
|
||||
},
|
||||
"plain": {
|
||||
view.NewLogIndicator(config.NewConfig(nil), defaults, false), "[::b]Autoscroll:[limegreen::b]On[-::] [::b]FullScreen:[gray::d]Off[-::] [::b]Timestamps:[gray::d]Off[-::] [::b]Wrap:[gray::d]Off[-::]\n",
|
||||
view.NewLogIndicator(config.NewConfig(nil), defaults, false), "[::b]Autoscroll:[limegreen::b]On[-::] [::b]ColumnLock:[gray::d]Off[-::] [::b]FullScreen:[gray::d]Off[-::] [::b]Timestamps:[gray::d]Off[-::] [::b]Wrap:[gray::d]Off[-::]\n",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,10 +27,34 @@ func TestLogAutoScroll(t *testing.T) {
|
|||
v.GetModel().Set(ii)
|
||||
v.GetModel().Notify()
|
||||
|
||||
assert.Len(t, v.Hints(), 16)
|
||||
assert.Len(t, v.Hints(), 17)
|
||||
|
||||
v.toggleAutoScrollCmd(nil)
|
||||
assert.Equal(t, "Autoscroll:Off FullScreen:Off Timestamps:Off Wrap:Off", v.Indicator().GetText(true))
|
||||
assert.Equal(t, "Autoscroll:Off ColumnLock:Off FullScreen:Off Timestamps:Off Wrap:Off", v.Indicator().GetText(true))
|
||||
}
|
||||
|
||||
func TestLogColumnLock(t *testing.T) {
|
||||
opts := dao.LogOptions{
|
||||
Path: "fred/p1",
|
||||
Container: "blee",
|
||||
}
|
||||
v := NewLog(client.PodGVR, &opts)
|
||||
require.NoError(t, v.Init(makeContext(t)))
|
||||
|
||||
buff := dao.NewLogItems()
|
||||
for i := range 100 {
|
||||
buff.Add(dao.NewLogItemFromString(fmt.Sprintf("line-%d\n", i)))
|
||||
}
|
||||
v.GetModel().Set(buff)
|
||||
|
||||
v.toggleColumnLockCmd(nil)
|
||||
const column = 2
|
||||
v.Logs().ScrollTo(-1, column)
|
||||
v.toggleAutoScrollCmd(nil)
|
||||
|
||||
r, c := v.Logs().GetScrollOffset()
|
||||
assert.Equal(t, -1, r)
|
||||
assert.Equal(t, column, c)
|
||||
}
|
||||
|
||||
func TestLogViewNav(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue