Skip to content

Commit

Permalink
Remove logs scrolling while printing
Browse files Browse the repository at this point in the history
  • Loading branch information
mszostok committed Jul 13, 2023
1 parent 7a8b838 commit 5ce09dc
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 99 deletions.
2 changes: 0 additions & 2 deletions cmd/cli/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ func NewInstall() *cobra.Command {
flags := installCmd.Flags()

kubex.RegisterKubeconfigFlag(flags)
flags.BoolVar(&opts.LogsReportTimestamp, "logs-report-timestamp", false, "Print timestamp prefix to the Botkube logs entries")
flags.IntVar(&opts.LogsScrollingHeight, "logs-scrolling-height", 10, "")
flags.DurationVar(&opts.Timeout, "timeout", 10*time.Minute, `Maximum time during which the Botkube installation is being watched, where "0" means "infinite". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`)
flags.BoolVarP(&opts.Watch, "watch", "w", true, "Watches the status of the Botkube installation until it finish or the defined `--timeout` occurs.")

Expand Down
10 changes: 4 additions & 6 deletions internal/cli/install/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@ const (

// Config holds parameters for Botkube installation on cluster.
type Config struct {
Kubeconfig string
HelmParams helm.Config
LogsReportTimestamp bool
LogsScrollingHeight int
Watch bool
Timeout time.Duration
Kubeconfig string
HelmParams helm.Config
Watch bool
Timeout time.Duration
}
12 changes: 7 additions & 5 deletions internal/cli/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,21 +109,20 @@ func Install(ctx context.Context, w io.Writer, k8sCfg *kubex.ConfigWithMeta, opt
return fmt.Errorf("Timed out waiting for Pod")
}

messages := make(chan []byte, opts.LogsScrollingHeight)
messages := make(chan []byte, 100)
streamLogCtx, cancelStreamLogs := context.WithCancel(context.Background())
defer cancelStreamLogs()
parallel.Go(func() error {
defer close(messages)
return logs.StartsLogsStreaming(streamLogCtx, clientset, opts.HelmParams.Namespace, podName, messages)
})

logsPrinter := logs.NewFixedHeightPrinter(
opts.LogsScrollingHeight,
logsPrinter := logs.NewPrinter(
podName,
)

parallel.Go(func() error {
logsPrinter.Start(ctxWithTimeout)
logsPrinter.Start(ctxWithTimeout, status)
return nil
})
parallel.Go(func() error {
Expand Down Expand Up @@ -158,7 +157,10 @@ func Install(ctx context.Context, w io.Writer, k8sCfg *kubex.ConfigWithMeta, opt

err = parallel.Wait()
if err != nil {
printFailedInstallMessage(opts.HelmParams.Version, opts.HelmParams.Namespace, podName, w)
err := printFailedInstallMessage(opts.HelmParams.Version, opts.HelmParams.Namespace, podName, w)
if err != nil {
return err
}
return err
}

Expand Down
102 changes: 23 additions & 79 deletions internal/cli/install/logs/printer.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
package logs

import (
"bytes"
"context"
"fmt"
"os"
"strings"
"time"

"github.com/charmbracelet/log"
charmlog "github.com/charmbracelet/log"
"github.com/morikuni/aec"
"github.com/muesli/termenv"
"github.com/muesli/reflow/indent"

"github.com/kubeshop/botkube/internal/cli"
"github.com/kubeshop/botkube/internal/cli/printer"
)

type FixedHeightPrinter struct {
height int
logsBuffer []string
podPhase string
type Printer struct {
podName string
newLog chan string
newPodPhase chan string
Expand All @@ -29,115 +24,64 @@ type FixedHeightPrinter struct {
logger *log.Logger
}

func NewFixedHeightPrinter(height int, name string) *FixedHeightPrinter {
return &FixedHeightPrinter{
height: height,
logsBuffer: []string{},
func NewPrinter(podName string) *Printer {
return &Printer{
newLog: make(chan string, 10),
newPodPhase: make(chan string, 10),
stop: make(chan struct{}),
logger: log.NewWithOptions(os.Stdout, log.Options{
Formatter: log.TextFormatter,
}),
podName: name,
podName: podName,
parser: JSONParser{},
}
}

func (f *FixedHeightPrinter) Start(ctx context.Context) {
refreshDuration := 100 * time.Millisecond
idleDelay := time.NewTimer(refreshDuration)
defer idleDelay.Stop()
func (f *Printer) Start(ctx context.Context, status *printer.StatusPrinter) {
status.InfoWithBody("Streaming logs...", indent.String(fmt.Sprintf("Pod: %s", f.podName), 4))
fmt.Println()

buff := bytes.Buffer{}
status := printer.NewStatus(&buff, "")
status.Step("Streaming logs...")
termenv.SaveCursorPosition()
for {
f.printData(buff.String() + "\n") // it's without new line when it's in progress
idleDelay.Reset(refreshDuration)

select {
case <-f.stop:
status.End(true)
termenv.RestoreCursorPosition()
f.printStatusHeader(buff.String())
f.printLogs(true)
fmt.Println()
return
case <-ctx.Done():
status.End(false)
termenv.RestoreCursorPosition()

f.printStatusHeader(buff.String())
f.printLogs(true)
fmt.Println()
status.Infof("Requested logs streaming cancel...")
return
case <-idleDelay.C:
case entry := <-f.newLog:
f.logsBuffer = append(f.logsBuffer, entry)
if len(f.logsBuffer) > f.height {
//now we need to simulate scrolling, so all lines are moved N-1, where the first line is just removed.
f.logsBuffer = f.logsBuffer[1:]
}
case podPhase := <-f.newPodPhase:
f.podPhase = podPhase
f.printLogs(entry)
}

Check failure on line 54 in internal/cli/install/logs/printer.go

View workflow job for this annotation

GitHub Actions / Lint Go code

unnecessary trailing newline (whitespace)
fmt.Print(aec.Up(uint(f.height + 4)))
}
}

func (f *FixedHeightPrinter) printData(header string) {
f.printStatusHeader(header)
f.printLogs(false)
}
func (f *FixedHeightPrinter) printStatusHeader(step string) {
fmt.Println(step)
fmt.Printf(" Pods: %s Phase: %s\n", f.podName, f.podPhase)
fmt.Println()
}

func (f *FixedHeightPrinter) UpdatePodPhase(phase string) {
func (f *Printer) UpdatePodPhase(phase string) {
select {
case f.newPodPhase <- phase:
default:
}
}

func (f *FixedHeightPrinter) printLogs(skip bool) {
wroteLines := 0
for _, item := range f.logsBuffer {
fields, lvl := f.parser.ParseLineIntoCharm(item)
if fields == nil {
wroteLines++
f.printLogLine(item)
continue
}
if lvl == charmlog.DebugLevel && !cli.VerboseMode.IsEnabled() {
continue
}
wroteLines++
fmt.Print(aec.EraseLine(aec.EraseModes.Tail))
fmt.Print(aec.Column(6))
f.logger.With(fields...).Print(nil)
}

if skip {
func (f *Printer) printLogs(item string) {
fields, lvl := f.parser.ParseLineIntoCharm(item)
if fields == nil {
f.printLogLine(item)
return
}
for i := wroteLines; i < f.height; i++ {
f.printLogLine("\n")
if lvl == charmlog.DebugLevel && !cli.VerboseMode.IsEnabled() {
return
}
fmt.Print(aec.EraseLine(aec.EraseModes.Tail))
fmt.Print(aec.Column(6))
f.logger.With(fields...).Print(nil)
}

func (f *FixedHeightPrinter) printLogLine(line string) {
fmt.Print(aec.EraseLine(aec.EraseModes.Tail))
func (f *Printer) printLogLine(line string) {
fmt.Print(aec.Column(6))
fmt.Print(line)
}

func (f *FixedHeightPrinter) AppendLogEntry(entry string) {
func (f *Printer) AppendLogEntry(entry string) {
if strings.TrimSpace(entry) == "" {
return
}
Expand All @@ -147,6 +91,6 @@ func (f *FixedHeightPrinter) AppendLogEntry(entry string) {
}
}

func (f *FixedHeightPrinter) Stop() {
func (f *Printer) Stop() {
close(f.stop)
}
14 changes: 7 additions & 7 deletions internal/cli/printer/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ func NewStatus(w io.Writer, header string) *StatusPrinter {
st := &StatusPrinter{
w: w,
}
//if cli.IsSmartTerminal(w) {
st.durationSprintf = color.New(color.Faint, color.Italic).Sprintf
st.spinner = NewDynamicSpinner(w)
//} else {
// st.durationSprintf = fmt.Sprintf
// st.spinner = NewStaticSpinner(w)
//}
if cli.IsSmartTerminal(w) {
st.durationSprintf = color.New(color.Faint, color.Italic).Sprintf
st.spinner = NewDynamicSpinner(w)
} else {
st.durationSprintf = fmt.Sprintf
st.spinner = NewStaticSpinner(w)
}

return st
}
Expand Down

0 comments on commit 5ce09dc

Please sign in to comment.