-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: stream bootloader logs #111
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
package local | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"os" | ||
"path/filepath" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
@@ -27,8 +29,8 @@ import ( | |
"helm.sh/helm/v3/pkg/release" | ||
"helm.sh/helm/v3/pkg/repo" | ||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
eventsv1 "k8s.io/api/events/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
const ( | ||
|
@@ -378,6 +380,63 @@ func (c *Command) watchEvents(ctx context.Context) { | |
} | ||
} | ||
|
||
// 2024-09-10 20:16:24 WARN i.m.s.r.u.Loggers$Slf4JLogger(warn):299 - [273.... | ||
var javaLogRx = regexp.MustCompile(`^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} \x1b\[(?:1;)?\d+m(?P<level>[A-Z]+)\x1b\[m (?P<msg>\S+ - .*)`) | ||
|
||
func (c *Command) streamPodLogs(ctx context.Context, namespace, podName, prefix string, since time.Time) error { | ||
r, err := c.k8s.StreamPodLogs(ctx, airbyteNamespace, airbyteBootloaderPodName, since) | ||
if err != nil { | ||
return err | ||
} | ||
defer r.Close() | ||
|
||
level := pterm.Debug | ||
scanner := bufio.NewScanner(r) | ||
|
||
for scanner.Scan() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we check the state of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think that's necessary. The context is passed to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I proved this to myself. I couldn't think of a nice way to write an actual test for it (since it depends on the real k8s implementation), but I hacked in this code (note
|
||
|
||
// skip java stacktrace noise | ||
if strings.HasPrefix(scanner.Text(), "\tat ") || strings.HasPrefix(scanner.Text(), "\t... ") { | ||
continue | ||
} | ||
|
||
m := javaLogRx.FindSubmatch(scanner.Bytes()) | ||
var msg string | ||
|
||
if m != nil { | ||
msg = string(m[2]) | ||
if string(m[1]) == "ERROR" { | ||
level = pterm.Error | ||
} else { | ||
level = pterm.Debug | ||
} | ||
} else { | ||
msg = scanner.Text() | ||
} | ||
|
||
level.Printfln("%s: %s", prefix, msg) | ||
} | ||
return scanner.Err() | ||
} | ||
|
||
func (c *Command) watchBootloaderLogs(ctx context.Context) { | ||
pterm.Debug.Printfln("start streaming bootloader logs") | ||
since := time.Now() | ||
|
||
for { | ||
// Wait a few seconds on the first iteration, give the bootloaders some time to start. | ||
time.Sleep(5 * time.Second) | ||
|
||
err := c.streamPodLogs(ctx, airbyteNamespace, airbyteBootloaderPodName, "airbyte-bootloader", since) | ||
if err == nil { | ||
break | ||
} else { | ||
pterm.Debug.Printfln("error streaming bootloader logs. will retry: %s", err) | ||
} | ||
} | ||
pterm.Debug.Printfln("done streaming bootloader logs") | ||
} | ||
|
||
// now is used to filter out kubernetes events that happened in the past. | ||
// Kubernetes wants us to use the ResourceVersion on the event watch request itself, but that approach | ||
// is more complicated as it requires determining which ResourceVersion to initially provide. | ||
|
@@ -398,6 +457,8 @@ func (c *Command) handleEvent(ctx context.Context, e *eventsv1.Event) { | |
case strings.EqualFold(e.Type, "normal"): | ||
if strings.EqualFold(e.Reason, "backoff") { | ||
pterm.Warning.Println(e.Note) | ||
} else if e.Reason == "Started" && e.Regarding.Name == "airbyte-abctl-airbyte-bootloader" { | ||
go c.watchBootloaderLogs(ctx) | ||
} else { | ||
pterm.Debug.Println(e.Note) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder how fragile this is. We're likely changing our logging implementation on the platform shortly, and I don't think we have any guarantees that this format won't be modified with that change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, all this log stuff is definitely fragile, but it's better than nothing for now. We need to do some work in the bootloader to make all this stuff clean and easy and stable over time.
And, maybe it's reasonable to say that the current log format should be the standard going forward. It's a very common format. Note that there are actually multiple formats in these logs too, which is annoying.
What's best might be to not parse logs in abctl, but have some other summarized bootloader status.