-
Notifications
You must be signed in to change notification settings - Fork 407
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
pkg: simplify the display logs #10662
Conversation
Thanks. It's good that you managed to use the existing process code to do this. |
otherlibs/stdune/src/user_message.ml
Outdated
@@ -226,13 +228,24 @@ let pp { loc; paragraphs; hints; annots = _ } = | |||
(Pp.textf "File %S, %s, characters %d-%d:" start.pos_fname lnum start_c stop_c)) | |||
:: paragraphs | |||
in | |||
let paragraphs = List.append headers paragraphs in |
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.
does that yield to double printing of headers in some cases?
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.
It works the same as with the loc
argument (heavily inspired). It means if someone executes the print_headers
and the then uses pp
, it will print it twice, yes.
However, this is exactly what could happen with loc
as the Dune_console
print the loc
before calling User_message.print
too (here). If you stick with pp
or Console.print_user_message
you won't have any duplication.
otherlibs/stdune/src/user_message.ml
Outdated
Pp.vbox (Pp.concat_map paragraphs ~sep:Pp.nop ~f:(fun pp -> Pp.seq pp Pp.cut)) | ||
;; | ||
|
||
let print ?(config = Print_config.default) t = | ||
Ansi_color.print (Pp.map_tags (pp t) ~f:config) | ||
;; | ||
|
||
let print_headers ?(config = Print_config.default) t = | ||
let headers = Pp.concat_map t.headers ~sep:Pp.nop ~f:(fun pp -> Pp.seq pp Pp.cut) in |
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.
Pp.nop
is the default value of ~sep
(here and below)
src/dune_rules/pkg_rules.ml
Outdated
: ?accepted_exit_codes:int Predicate.t | ||
-> ?pkg_name:Dune_lang.Package_name.t |
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.
we avoid optional arguments in new code - you can make accepted_exit_codes
a labelled argument and pkg_name
an option.
src/dune_rules/pkg_rules.ml
Outdated
raise (User_error.E msg) | ||
| true, Display.Verbose -> | ||
let error = read t in | ||
if has_output error |
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 has_output error | |
if not (String.is_empty error) |
src/dune_rules/pkg_rules.ml
Outdated
let v ?(accepted_exit_codes = exit_code_zero) ?pkg_name suffix = | ||
let fn = Temp.create File ~prefix ~suffix in |
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 think we can improve the resource management here:
v
kinds of sound like a constructor (we tend to use thecreate
name for this), but it's actually opening a file.- if you can restructure that to a "context manager" this will be easier to reason about. something like
val with_ : ?accepted_exit_codes -> ?pkg_name -> string -> f:(t -> 'a) -> 'a
, a bit likeIn_channel.with_open
. that way you don't have to deal withstate
,close
etc.
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, the
v
is an oldIrmin
habits... - It would make the code much simpler! Thanks
src/dune_rules/pkg_rules.ml
Outdated
content | ||
| Closed -> | ||
raise | ||
(User_error.E |
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.
This part is likely to go away but we prefer Code_error.raise
for this kind of defensive check
src/dune_rules/pkg_rules.ml
Outdated
| Some pkg_name -> | ||
let pkg_name = Dune_pkg.Package_name.to_string pkg_name in | ||
Pp.( | ||
tag report_style (text "<><><>") |
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.
no need to mimic what opam is doing here. this clutters output and is less accessible than just printing the error message.
Thanks, the However,
IMHO, we need a kind of separation between the parsed packages because otherwise users might struggle to parse the logs. I can suggest something lighter like Few questions about the tests:
|
Let me clarify a bit what I mean:
|
Thanks for the clarifications! 🙏
You are totally right. I'll add some of the corrections and add the tests then to help with the discussion.
Sorry, my mistake: I still confuse the toolchain part and the packages part 😅 It's about suppressing the logs when building packages when there are no error, display only errors if we are in non-verbose and displaying all of them (warning in this case) when we are in verbose mode.
I'm not sure to fully understand the point here. In the PR you linked, it seems that it's using To be fair, the |
that's to avoid dependency cycles, this is indeed a context name. |
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.
This is a good starting point! Happy to see it land soon.
I am a bit torn on including Loc.t
as a value into the Spec
. Usually we deal with them by having Loc.t * 'a
types where 'a
is the value the Loc.t
is related to. I've looked at some other action specs and the other Spec
s don't include Loc
s, maybe someone can pitch in how to do that in the best way?
src/dune_rules/pkg_rules.ml
Outdated
} | ||
|
||
let prefix = "dune-pkg" | ||
let exit_code_zero = Predicate.create (fun x -> x = 0) |
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.
You can also use Int.equal 0
here.
src/dune_rules/pkg_rules.ml
Outdated
|
||
type t = | ||
{ pkg_name : Dune_pkg.Package_name.t option | ||
; fn : Dpath.t |
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.
fn
is a bit of a poor name, as it reminds me more of "function" than filename
.
src/dune_rules/pkg_rules.ml
Outdated
@@ -652,7 +759,7 @@ module Run_with_path = struct | |||
|
|||
let is_useful_to ~memoize:_ = true | |||
|
|||
let encode { prog; args; ocamlfind_destdir } path _ : Dune_lang.t = | |||
let encode { prog; args; ocamlfind_destdir; _ } path _ : Dune_lang.t = |
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 would suggest to specifically state the arguments that are being _
'ed in such cases; otherwise you opt out of useful compiler errors that will tell you that you haven't dealt with an argument. Even if the case you have now might be legit, it will make it harder for future modifications.
(But in any case I believe pkg_name
should also be encoded)
2b52da0
to
7588712
Compare
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 was thinking of this and this is not a blocker but I thought it could be nice to have. But it can happen in a future PR as well.
7588712
to
85e516d
Compare
src/dune_rules/pkg_rules.ml
Outdated
;; | ||
end | ||
|
||
let action prog args ~ocamlfind_destdir = | ||
let action ~loc ?pkg_name prog args ~ocamlfind_destdir = |
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.
No optional arguments please
If this PR is adding a file that isn't a target of a rule, what prevents the file from being deleted by dune in subsequent runs during stale artifact deletion? |
I would suggest that you try to accomplish what your PR needs without this change. Such headers are not transmitted through RPC nor are they interpreted by any of the editors. This makes our editor integration incomplete. It seems like a rather general feature, but I can't find a use for it anywhere else in the codebase. |
Hi @rgrinberg,
The file is added temporary to get all the error logs of one process in the same file and avoid interleaving. Consequently, it is deleted as soon as the process finishes.
Yes, I understand and agree with you! I'm wondering if the |
b3c4ffb
to
63c8b7b
Compare
I removed the It should be much simpler to review now, as it temporarily redirects the errors in a file and displays them or not, depending on the result of the command. |
src/dune_rules/pkg_rules.ml
Outdated
let pp_pkg = | ||
let pkg_name = Dune_pkg.Package_name.to_string (fst t.pkg) in | ||
if is_critical | ||
then Pp.textf "Package %s fails to build" pkg_name |
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.
then Pp.textf "Package %s fails to build" pkg_name | |
then Pp.textf "Package %s failed to build" pkg_name |
src/dune_rules/pkg_rules.ml
Outdated
let pkg_name = Dune_pkg.Package_name.to_string (fst t.pkg) in | ||
if is_critical | ||
then Pp.textf "Package %s fails to build" pkg_name | ||
else Pp.textf "Package %s prints some errors" pkg_name |
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.
These are not necessarily errors, right?
else Pp.textf "Package %s prints some errors" pkg_name | |
else Pp.textf "Package %s output" pkg_name |
src/dune_rules/pkg_rules.ml
Outdated
if not (String.is_empty error) | ||
then ( | ||
let msg = error_msg ~is_critical:false t error in | ||
Console.print_user_message msg) |
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 sure what the difference is but I think we often use
Console.print_user_message msg) | |
User_message.print msg) |
src/dune_rules/pkg_rules.ml
Outdated
result | ||
;; | ||
|
||
let error_msg ~is_critical t error = |
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.
the is_critical
bool is a bit weird, I wonder if that would be clearer to pass the message instead
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.
This issue is that in one case it's a Warning
and in another one it's an Error
. We need to stick to the behaviour in Process
and raise only on critical error. I can change it by adding a kind
instead of is_critical
using variant.
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.
Ah ok I missed that part. My main issue was the critical
bit, indeed. What you're suggesting is fine by me, but as a final suggestion, maybe we can use User_warning.emit
and the is_error
flag, with just Logs for package X
as message in both cases. I wonder if that would be enough?
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.
As it would display Error
and Warning
in front of the message, I think this is enough for now 👍
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.
This PR breaks some other tests (which relied on the fact that the output was always printed). Could you go and fix them? I assume that requires passing --verbose
to where this is necessary.
> (build | ||
> (progn | ||
> (run echo "Success!") | ||
> (run true))) |
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.
This is not necessary, echo will already return 0.
@Leonidas-from-XIV, I'm not sure about the path I should take with this. Indeed, if I add a verbose flag, the tests would pass, but the logging result is pretty big... Is it OK to do so? |
You could prefix the tests to output a specific output and do |
919dda4
to
57933f1
Compare
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'll give others a chance to review. This is good to go from me.
To make it easy to fix the tests, you could add restore the old behavior with |
Thanks, @rgrinberg! |
e55994a
to
7a01a8e
Compare
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.
Changed make to make
, but if there is a different way to do that in .t
files please let me know, and I'll fix it.
f1bec1d
to
0362b79
Compare
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.
The implementation looks good, but I'm concerned with the changes in tests TBH.
The problem isn't really the diff size, but rather that what we're testing doesn't match the reality (real build instructions don't write to files; they output on stdout and stderr).
Since it looks like --display verbose
is too verbose, I suggest starting with INSIDE_DUNE
so that we can at least land this PR. (I can offer you guidance about how to pretend we're not INSIDE_DUNE
to write build-package-logs.t
)
Then, in a future PR, we can see how we can make better tests. The pain we're seeing is because we're testing through too many layers, so maybe we could try to define a helper executable that directly executes a package build, or something like that.
I'd say the opposite, real build instructions write to files and all output to stdout is a side-effect (or execute commands based on filters). In the case of |
I agree with @Leonidas-from-XIV: in the "real build instruction" we write to files (many times it's just a call to |
Let me clarify what I meant; there are some packages where
Yes, that's what I was suggesting; we disagree on the intermediate step. If you use |
Out of curiosity, is it a test that I updated? 😕 Considering your comment, if we have some packages relying on
Technically, the changes are already here: it would be changing them once now ^^ Joke aside, I don't mind removing them: my only concern here is that we would put |
Ultimately, you'll be maintaining those tests, so if you're more comfortable with that approach, that's fine by me. |
0362b79
to
11c3ff7
Compare
After an offline discussion with @emillon, I agree with his suggestion of adding a flag for printing the output when present, This way, it provides access to the output when building packages without making I'll open a new one with the @emillon @Leonidas-from-XIV, I let you merge if this is good for you this way. |
56575c9
to
83e4693
Compare
@emillon @Leonidas-from-XIV |
83e4693
to
881cd42
Compare
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.
Thanks. You can accept the env var directly in the cmdliner term to simplify the setup and reduce the diff again.
Please add a changelog entry as well.
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.
Looks good to me, can be (squashed &) merged if tests pass.
I'll cleanup the diff and merge. Thanks! |
test/blackbox-tests/test-cases/pkg/pin-stanza/update-non-dune-local-pin.t
Show resolved
Hide resolved
Only logs the standard output when the command fails or the user explicitly requests it. Add new flag `--debug-package-logs`, which force dune to display the stdout logs when dealing with package management. Signed-off-by: Etienne Marais <[email protected]> Signed-off-by: Christine Rose <[email protected]> Signed-off-by: Etienne Millon <[email protected]>
989f7f7
to
29ae7b9
Compare
Hi,
This PR is an attempt to make the toolchain logs less verbose. As the packages are evaluated as common rules, they printed a lot of lots. To overcome such behavior, the idea is to redirect the error logs into a file and print them in case of errors.
This PR is structured in 3 parts:
User_message
module to embeddedheaders
. This information is printed before any other logs. It allows displaying the name of the package or a piece of information to give a bit of context. Maybe, this part is too much for this PR. I can either extract it or remove it.package name
and thelocation
to the function in charge of handling it.Output
module to sink the error logs into a file and display them as : Error if it fails and, warning if the command succeeds, but in verbose mode.Note that I'm not award of most of the functionalities provided by the dune helper modules (
Stdune
,User_message
, etc). So, feel free to suggest better implementation if it can improve the readability and fit better in the dune codebase! 🙏Closes tarides/team-build-system#30