Skip to content
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

Add --read-logs-from for asynchronous log output #227

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

9999years
Copy link
Member

Because ghciwatch reads ghci's output and expects it to be structured in a standard way, it can't cope with programs that output to stdout (or stderr) asynchronously (see ndmitchell/ghcid#137).

To make this easier for frameworks that output logs (like Yesod), we should have an option to read logs asynchronously from a file. If provided, writes to the given file will show up in ghciwatch's output (but not ghci's output).

Copy link

linear bot commented May 1, 2024

@github-actions github-actions bot added the patch Bug fixes or non-functional changes label May 1, 2024
@9999years 9999years marked this pull request as ready for review May 1, 2024 23:32
@9999years 9999years force-pushed the rebeccat/dux-2225-read-logs-from-file branch from 794954c to ba003e7 Compare May 1, 2024 23:33
Comment on lines +117 to +119
// TODO: Lock stdout here and for ghci output.
let _ = stdout.write_all(line.as_bytes()).await;
let _ = stdout.write_all(b"\n").await;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a pretty big "TODO". std::io::Stdout is globally synchronized, but tokio::io::Stdout is not, so this could lead to interleaved output.

AFAICT there's no easy solution for this. The tokio devs suggested creating a task to manage stdout and sending it messages (strings to write) over a channel, which is reasonable enough, but then I'll have to write an adapter to implement std::io::Write by sending messages to an async channel.

Comment on lines +52 to +56
ReadLogsFrom {
shutdown: handle,
path,
}
.run()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a blocker, but it wasn't clear to me why this is split up as a struct and a method on that struct (i.e. ReadLogsFrom { shutdown: handle, path }.run()) and not combined into a single function (i.e. readLogsFrom(handle, path))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple reasons why I chose to implement it like this:

  • Struct+method is a lot easier to split up to deal with complex logic.
  • Methods don't have named parameters, so when there's a lot of state to pass in, using a struct is a lot clearer (and lower-overhead than defining builders).
  • Most of the async tasks in ghciwatch are structured like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
patch Bug fixes or non-functional changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants