-
Notifications
You must be signed in to change notification settings - Fork 2k
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
cli: stream both stdout and stderr when following an alloc. #16556
Conversation
2ed0349
to
9034430
Compare
This update changes the behaviour when following logs from an allocation, so that both stdout and stderr files streamed when the operator supplies the follow flag. The previous behaviour is held when all other flags and situations are provided.
9034430
to
75c93da
Compare
|
||
// End the streaming | ||
r.Close() | ||
_ = r.Close() |
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.
Not part of this PR, but do we need to close(cancel)
here?
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.
Good spot; I can fix this up in another PR.
Co-authored-by: Luiz Aoqui <[email protected]>
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.
if l.follow && !(l.stderr || l.stdout || l.tail || l.numLines > 0 || l.numBytes > 0) { | ||
if err := l.tailMultipleFiles(client, alloc); err != nil { | ||
l.Ui.Error(fmt.Sprintf("Failed to tail stdout and stderr files: %v", err)) | ||
return 1 | ||
} | ||
} else { |
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.
if l.follow && !(l.stderr || l.stdout || l.tail || l.numLines > 0 || l.numBytes > 0) { | |
if err := l.tailMultipleFiles(client, alloc); err != nil { | |
l.Ui.Error(fmt.Sprintf("Failed to tail stdout and stderr files: %v", err)) | |
return 1 | |
} | |
} else { | |
if l.follow && !(l.stderr || l.stdout || l.tail || l.numLines > 0 || l.numBytes > 0) { | |
if err := l.tailMultipleFiles(client, alloc); err != nil { | |
l.Ui.Error(fmt.Sprintf("Failed to tail stdout and stderr files: %v", err)) | |
return 1 | |
} | |
return 0 | |
} |
By returning early we can remove the else
clause and dedent the rest of the code, which may be nice, but very much a style nit-pick 😄
command/alloc_logs.go
Outdated
r, readErr = l.followFile(client, alloc, follow, task, logType, api.OriginEnd, offset) | ||
r, readErr = l.followFile(client, alloc, l.follow, l.task, logType, api.OriginEnd, offset) | ||
|
||
// If numLines is set, wrap the reader | ||
if numLines != -1 { | ||
r = NewLineLimitReader(r, int(numLines), int(numLines*bytesToLines), 1*time.Second) | ||
if l.numLines != -1 { | ||
r = NewLineLimitReader(r, int(l.numLines), int(l.numLines*bytesToLines), 1*time.Second) | ||
} | ||
|
||
if readErr != nil { | ||
readErr = fmt.Errorf("Error tailing file: %v", readErr) | ||
return fmt.Errorf("error tailing file: %v", readErr) | ||
} | ||
} |
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.
Not part of the PR, but it may be worth flipping the lines to check for readErr != nil
earlier since r
will be nil
stdoutFrames, stdoutErrCh := client.AllocFS().Logs( | ||
alloc, true, l.task, api.FSLogNameStdout, api.OriginEnd, 1, cancel, nil) |
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.
Reading the docs I think passing a ctx.Done()
instead of creating a cancel
channel would work, and it would make the code look more like modern Go.
You can then even pass the context to the function (tailMultipleFiles(ctx, ...)
) and have let the parent Run()
handle the lifecycle of the request, so that things like signal handling are handled outside of these sub-functions.
func (l *AllocLogsCommand) Run(...) {
// ...
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// ...
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
go func() {
for {
select {
case <-signalCh:
return 0
}
}
}()
// ...
tailMultipleFiles(ctx, ...)
// ...
followFile(ctx, ...)
}
func (l *AllocLogsCommand) tailMultipleFiles(ctx ...) error {
// ...
stderrFrames, stderrErrCh := client.AllocFS().Logs(
alloc, true, l.task, api.FSLogNameStderr, api.OriginEnd, 1, ctx.Done(), nil)
// ...
}
Co-authored-by: Luiz Aoqui <[email protected]>
Co-authored-by: Luiz Aoqui <[email protected]>
This update changes the behaviour when following logs from an
allocation, so that both stdout and stderr files streamed when the
operator supplies the follow flag. The previous behaviour is held
when all other flags and situations are provided.
Closes #2123