Skip to content

Commit 89df1e2

Browse files
committed
hide progress dots; show reconnection msg
Fixes #44
1 parent 87b08d8 commit 89df1e2

File tree

4 files changed

+62
-12
lines changed

4 files changed

+62
-12
lines changed

src/pkg/cli/colorizer.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"io"
66
"os"
7+
"regexp"
78

89
"golang.org/x/term"
910
)
@@ -137,3 +138,9 @@ func Error(v ...any) (int, error) {
137138
// }
138139
// return c.color[id]
139140
// }
141+
142+
var ansiRegex = regexp.MustCompile("\x1b(?:\\[[=?]?[0-9;]{0,10}[@-~]|].{0,10}?(?:\x1b\\\\|\x07|$)|[@-Z\\\\^_])")
143+
144+
func StripAnsi(s string) string {
145+
return ansiRegex.ReplaceAllLiteralString(s, "")
146+
}

src/pkg/cli/getServices.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ func GetServices(ctx context.Context, client defangv1connect.FabricControllerCli
1414
return err
1515
}
1616

17-
PrintObject("services", serviceList.Msg)
17+
PrintObject("", serviceList.Msg)
1818
return nil
1919
}

src/pkg/cli/tail.go

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ const (
2323

2424
var (
2525
colorKeyRegex = regexp.MustCompile(`"(?:\\["\\/bfnrt]|[^\x00-\x1f"\\]|\\u[0-9a-fA-F]{4})*"\s*:|[^\x00-\x20"=&?]+=`) // handles JSON, logfmt, and query params
26-
ansiRegex = regexp.MustCompile("\x1b(?:\\[[=?]?[0-9;]*[@-~]|].*?(?:\x1b\\\\|\x07|$)|[@-Z\\\\^_])")
2726
)
2827

2928
// ParseTimeOrDuration parses a time string or duration string (e.g. 1h30m) and returns a time.Time.
@@ -129,27 +128,38 @@ func Tail(ctx context.Context, client defangv1connect.FabricControllerClient, se
129128
// Reconnect on Error: internal: stream error: stream ID 5; INTERNAL_ERROR; received from peer
130129
if code == connect.CodeUnavailable || (code == connect.CodeInternal && !connect.IsWireError(tailClient.Err())) {
131130
Debug(" - Disconnected:", tailClient.Err())
132-
Warn(" ! Reconnecting...")
131+
if !raw {
132+
Fprint(os.Stderr, WarnColor, " ! Reconnecting...\r") // overwritten below
133+
}
133134
time.Sleep(time.Second)
134135
tailClient, err = client.Tail(ctx, connect.NewRequest(&pb.TailRequest{Service: service, Etag: etag, Since: timestamppb.New(since)}))
135-
if err == nil {
136-
skipDuplicate = true
137-
continue
136+
if err != nil {
137+
Debug(" - Reconnect failed:", err)
138+
return err
139+
}
140+
if !raw {
141+
Fprintln(os.Stderr, WarnColor, " ! Reconnected! ")
138142
}
139-
Debug(" - Reconnect failed:", err)
140-
return err
143+
skipDuplicate = true
144+
continue
141145
}
142146

143147
return tailClient.Err() // returns nil on EOF
144148
}
145149
msg := tailClient.Msg()
146150

147-
if DoColor && !DoVerbose && !raw {
151+
// Show a spinner if we're not in raw mode and have a TTY
152+
if !raw && DoColor {
148153
fmt.Printf("%c\r", spinner[spinMe%len(spinner)])
149154
spinMe++
155+
// Replace service progress messages with our own spinner
156+
if isProgressMsg(msg.Entries) {
157+
println("asf")
158+
continue
159+
}
150160
}
151161

152-
isInternal := !strings.HasPrefix(msg.Host, "ip-")
162+
isInternal := !strings.HasPrefix(msg.Host, "ip-") // FIXME: not true for BYOC
153163
for _, e := range msg.Entries {
154164
if !DoVerbose && !e.Stderr && isInternal {
155165
// HACK: skip noisy CI/CD logs (except errors)
@@ -201,13 +211,21 @@ func Tail(ctx context.Context, client defangv1connect.FabricControllerClient, se
201211
}
202212
if DoColor {
203213
if !strings.Contains(line, "\033[") {
204-
line = colorKeyRegex.ReplaceAllString(line, replaceString)
214+
line = colorKeyRegex.ReplaceAllString(line, replaceString) // add some color
205215
}
206216
} else {
207-
line = ansiRegex.ReplaceAllLiteralString(line, "")
217+
line = StripAnsi(line)
208218
}
209219
Println(Reset, line)
210220
}
211221
}
212222
}
213223
}
224+
225+
func isProgressDot(line string) bool {
226+
return len(line) <= 1 || len(StripAnsi(line)) <= 1
227+
}
228+
229+
func isProgressMsg(entries []*pb.LogEntry) bool {
230+
return len(entries) == 0 || (len(entries) == 1 && isProgressDot(entries[0].Message))
231+
}

src/pkg/cli/tail_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package cli
2+
3+
import "testing"
4+
5+
func TestIsProgressDot(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
line string
9+
want bool
10+
}{
11+
{"empty", "", true},
12+
{"dot", ".", true},
13+
{"empty line", "\n", true},
14+
{"ansi dot", "\x1b[1m.\x1b[0m", true},
15+
{"pulumi dot", "\033[38;5;3m.\033[0m", true},
16+
{"not a progress msg", "blah", false},
17+
}
18+
for _, tt := range tests {
19+
t.Run(tt.name, func(t *testing.T) {
20+
if got := isProgressDot(tt.line); got != tt.want {
21+
t.Errorf("isProgressDot() = %v, want %v", got, tt.want)
22+
}
23+
})
24+
}
25+
}

0 commit comments

Comments
 (0)