#new TUI feedback
1 messages ยท Page 1 of 1 (latest)
Goals: keep it light, minimize bells and whistles, low CPU usage. When everything is done, get out of your way and just print Unixy output.
Feels a bit noisier than I'd like, I think mostly due to the addition of the foo.bar.baz. chains, but without them it's not really clear what's actually running.
They can also get pretty long which ain't great.
Also tried rendering those on their own lines, but the verbosity escalates pretty quickly
Seems better with non-dimmed foo.bar.: https://asciinema.org/a/QMHK2Z0BBOkOYS9YURu9jwPIU
Do you have any example of what happens when some failure occurs? I would love to see it treat that part better.
Sure - if you have a specific failure example I'm happy to run it too
Here's a missing flag: https://asciinema.org/a/FV9q3t8dY3m9vmxjx1wRODj3F - I'd say this is better just by being quieter, but it could definitely be more helpful
Error messages when a command fails are still really bad ๐ฌ https://asciinema.org/a/bpHkdtDwFAh3Vfypsm95TDrzM
Changed it to show failed pipelines on exit, and changed the Go SDK to silence the inner error since it will have already manifested itself elsewhere: https://asciinema.org/a/8PPe3AZkhyfoNMEPugwWjxZ7m
Note: this 'show failed pipelines' only applies to top-level pipelines; they won't bubble-up out of context. If the top-level call swallows the error, it won't be shown.
Would be nice to just hide these exec /runtime vertices entirely
Ok, cleaned things up a bit more - thanks for the suggestion @fair frigate, this was a goldmine of things to fix! Now is a great time to focus on error messages.
- Fixed an issue that was causing the API error message to be printed twice
- Replaced split Stdout:/Stderr: with a single combined Output: which should be more grokkable, and looks less cluttered. We've wanted that as an API for a while, it just never got triaged, might add that too now that the plumbing is done.
https://asciinema.org/a/IzDNOR0siq1cQTgiezzrzsBg1
One last update: objects passed as args are now simplified; no more Directory@sha256:...{, it's just rendered inline, looks much better.
Here's dagger up:
https://asciinema.org/a/2c2TTrB7UXhvger48cKxPnMpz
Looking great! Love the errors output. My personal feedback from what I see.
-
The timers on every step(vertex?) is overwhelming. I may only care about the total time (top level timer) and maybe the timer on the current step. Not necessarily parent steps. Maybe showing just seconds instead of seconds and milis my make this better? It's rare that things actually happen in milliseconds in CI/CD pipelines these days for it to matter. Seconds are good enough IMO. When the step stops you can always print the secs & millis.
-
Same as above for the left spinning animations. A lot of things spinning on the output is distracting to me. I am trying to focus on the output which in itself is moving very fast and the animations in my peripheral view are a distraction.
The more complex the pipeline more animation clutter, might actually not be an issue for quick smaller pipelines.
Thanks for the feedback! That's exactly the kinds of things I've been wondering. At one point I just had normal dot symbols for the running steps, but it didn't look quite right either. Will keep messing with it. Agree re: timing fidelity, will mess with that too. All of this noise is especially noticeable for things like dagger up where you intend to leave it running indefinitely.
How's this? https://asciinema.org/a/af2FeHdNJ5LsqotNNpLT7AkGB
- No more spinners
- Removed
[]from the durations so they're less noisy - Truncated durations to tenths of seconds so they're less frantic
Also tried without the timers, but I think I do like having them; otherwise it's hard to tell if something is stuck.
Pushed what I have so far: https://github.com/dagger/dagger/pull/6588
Better!! Much less distraction. When things start up I see a ton of timers still so I can't fully judge by the video. I'll test this myself this week and give more feedback. I think we are getting to a good place. There may be more feedback from other community members.
One thing that's kind of bothering me is there are a lot of flashing logs/info on the screen. I am not referring to the animations but the actual information on the screen. Most of it is flashing too fast for me to gleam what's going on. I know it's by the nature of DAGs and dagger. IDK if there's a good solution either but it's just what I feel. It would be nice to have a "skim" version of the TUI where only the most important pieces are shown. Anything that's going on too fast where it needs to flash for less than a second I don't want to see. Hopefully I'm making sense.
Ha that's also something I tried in an earlier iteration, basically if duration is <100ms don't even show it. Will try bringing that back
I originally wanted to use that heuristic to trim out boring completed steps, current iteration just doesn't show completed things at all
Just to clarify - I think this is maybe fine, but I think we should aim to try and really trim the number of progress events we actually end up getting, so we don't have this problem in the first place.
If the vertex is important, it should be displayed fully (and not go away), if it's not, it should never even be shown on screen (unless it fails). The flicker of "not quite important info" is distracting, and this feels like a bit of a workaround from that.
Just thinking out loud, I could be wrong about that.
I think it looks a lot tidier than what we previously had though
Thanks for the feedback!
I don't think we can determine what's important at event emission time. What's important to see in this TUI isn't the same as what's important to see in Cloud. They're designed with similar principles and may even share code in the future, but the medium for presentation and the way that they're used is different. Definitely don't want to drop valuable info on the floor and make the use case for the data too narrow. Seeing the full trace in all its glory in Cloud is a great way to understand how everything works, and can be a very helpful for advanced use cases like building an SDK.
One constraint we're designing backwards from, and that I agree with, is that we want everything to go away at the end. The only output should be the data or --help text you requested, which should just be printed to stdout/stderr in a nice Unixy format as if none of the complicated TUI output ever happened. Until we get that result, I think it's most important to show whatever you're currently waiting on, which is basically a question of "what's taking time." Today I want to try also showing "what has taken time" so interesting things don't disappear, but if it makes it hard to see what is currently taking time because the scrollback becomes too cluttered, then IMO it's not worth it. Displaying vertexes "fully" is also an expensive decision for the same reason; some of these vertices are function calls with large complicated args, some of them have terminal output, etc.
Deciding what to show based on how long it's taking may sound like a workaround, but it's a pretty solid heuristic for what users will actually care to look at, even in unpredicable scenarios where your pipeline gets stuck somewhere you didn't predict. The worst thing a TUI can do is hang without showing me what it's waiting on, so it's nice that this simple heuristic inherently avoids that issue (as opposed to some system where the user tells us what's important, like withFocus).
wow sorry for the wall of text
Trying this out:
func (row *TraceRow) IsInteresting() bool {
vtx := row.Step.FirstVertex()
if vtx.Error != nil {
// show errors always (TODO: make sure encapsulation is possible)
return true
}
if vtx.Duration() < 100*time.Millisecond {
// ignore fast steps; signal:noise is too poor
return false
}
if row.IsRunning {
// show things once they've been running for a while
return true
}
if vtx.Completed != nil && time.Since(vtx.Completed.AsTime()) < time.Second {
// show things that just completed, to reduce flicker
return true
}
return false
}
A 100ms limit alone doesn't really help with flicker because then you'd just have it for steps that took 101ms. But I still think it's a useful first pass. And then if you combine that with removing things after 1 second instead of immediately, it feels a bit less frantic and doesn't seem to get too crowded.
Here's up: https://asciinema.org/a/z8uVglEOewzvOm9nAgVSlnPh7
Oh this looks significantly better โค๏ธ โค๏ธ โค๏ธ
So, I'm really struggling to explain what it is that still bothers me.
I think I agree that when we hit the end of the command (like running a call), we should collapse to only the result, and not show the logs.
But, while it's running, I think I'd like to preserve a little bit of the previous logs - not everything should disappear. Unfortunately, today I don't think it's very simple to define what these are - but I'd imagine "top-level" operations (that should ideally be at the top of the progress tree) to not disappear:
- Load module "x"
- Running function "y"
- Bringing service "z" up (if using
dagger call ... upor something)
Genuinely not a lot - but I think something like this would help to give context on what's happening at each stage. Something where I can glance back and get a brief idea of what's already been done.
I think 1. this is useful from an overview perspective of what's actually being done, and 2. useful so that users can see that progress is being made - if all the progress vanishes after completing, for a super long build (maybe with a ton of module dependencies, or lots of chained functions), it might not feel clear that progress is actually being made at all.
As a more nitpicky comment - these lines are very long, and not particularly clear ๐ข
I get these are the graphql nested fields, but I would really love to work out how to have something that was a bit more understandable.
At one point I though we could try and get snippets from the language the module is written in? But this doesn't work as soon as you're cross-module, and mixing that up is weird (and also language shouldn't matter really).
Also, off-topic, but I remember a discussion somewhere about changing exec /runtime to be named something better... like the name of the module? That swould go some way I think as well towards making this more readable.
Sorry, this is really unstructured, but I'm still struggling to read this output - I tend to always put dagger into --progress=plain mode (like buildkit as well actually). These are just kinda my guesses for why I think it doesn't clock with me (but I also might not be the intended target audience, so you might want to ignore me ๐)
same ๐
Would love to work that out too ๐ unfortunately don't have any ideas. I already tried rendering them "fully" (i.e. showing them as a stack of chained API calls, recursing into parents etc) but it just makes the output wildly verbose and didn't feel worth it. Thought about just hashing + color-coding their ancestry so it doesn't grow indefinitely, but then that's even less useful. I think a lot of this could actually be fixed by supporting intra-module calls, because then rather than huge chains of APIs you'd just see the small call you made within your own module, like daggerverse.withInitdb or something, and you could tidy up the output by using your API internally.
for comparison, here's how bad it looks without any modules at all; this TUI leans very hard on Zenith function calls to encapsulate progress
Looking pretty awesome! But I agree, as much as possible it'd be great to reduce to higher level concepts like functions from own module, and hide (or collapse in one line) the rest.
Trying another thing:
- No more massive ancestry paths. It just shows the field being selected. Much easier to read.
- Added module names (in magenta). This seems to be high bang-for-your-buck in terms of info conveyed, offsetting the info lost from the previous change.
https://asciinema.org/a/Ee8cnNKErZhXgK5eog2JuSlDg
Feedback re: higher level grouping is heard, but I really want to keep doubling down on function-call-based visualization. It'd be great if in the end that's all we need. For example, I don't want to see Running function unit > bass unit() - I just want to see bass unit() because of course that's what a function call looks like. For other things like module initialization, which definitely contribute a lot of noise, it'd be great if we could push those into an actual function call like init() so it's not anything special either. The end goal here is to not feel the need to annotate our logs with a bunch of extra info, and instead have everything represented as function calls, and get to the point where reading that feels as natural as reading a stack trace (though with 1000x better DX and readability), since both are always representing one thing.
Trying yet another thing:
- Rather than showing the module name, show the receiving type.
https://asciinema.org/a/6WxF1qbwhQXoml38JFs0Q3NWN
love this idea.
like this a lot! I think it makes a lot of sense. One nitpick I have is I still don't see myself paying attention to all the timers. If I can see the current child and total time I'd be happy. I feel like they are a distraction. Also would be nice if the timer text is a different color than the left most orange status dot and string input text color.
Removing the timers is a step too far IMO, but here's a version that makes them always faint, rather than matching the 'running' color cue (yellow).
https://asciinema.org/a/PsY8yWxqi2TFeSvVS6dAKujBW
Curious what others think?
That's better although I can still see/feel movement in my peripheral vision when I'm trying to focus on my logs (in this case 4-6 ticking timers). Do we have to show the millis? Can it just be seconds? I feel like that would be better. Maybe this is some kind of an OCD issue only I have ๐
Trying that now ๐
https://asciinema.org/a/2wJpMD9b0D9xIr7acGTqR4ShB
feels kind of awkward to me lol
I think some kind of animation is important so the user knows it isn't stuck, at least. And making it that slow is almost a different kind of distraction.
hmm, I can see people being confused about the 0s ones too. IDK.. Maybe I'll have to live with the tickers. I need some kind of a distraction free mode (cli option?) that's between this and --silent. Only thing that moves is the log from my function. Which is what I primarily care about. I will look at the other stuff only when something fails.
Definitely something you can keep iterating on based on community feedback also. I like the current iteration much much better than what we had so kudos on that.
Glad you like it overall! And the feedback is totally fair, I appreciate hearing different perspectives on this stuff. Would be worth throwing ideas around for flags. Don't want to go crazy with them, but there's no reason it has to be one-size-fits-all
Woo! This looks so neat now actually โค๏ธ
I still would love if we do more higher level grouping, but yes, this is hard ๐ I'd be happy if we left that to the side for now, and came back and fixed it after getting this in soon ๐
r.e. timers, I think having the point is really important - without it, it feels like things get stuck. maybe that's just learnt behavior from buildkit/etc. There does seem to be a case in the recordings where a timer hits a number and then stops going up - when the job is finished. This definitely feels stuck. Maybe we could highlight the finished timers somehow (removing them entirely would be weird though).
@modest hedge r.e. merging this - i know we want to have this in for v0.9.9.
what's left from your perspective? are we in a good place to merge a first pass later today?
does this rely on a progrock update as well? is this even using progrock anymore?
I see we also add in support for CombinedOutput ๐ looking forward to that!
No progrock update needed, new TUI is all in-repo.
Will aim to get the PR mergeable asap today. Gonna go over all the commands and make sure they behave well. For dagger run I might just keep it using the current TUI since the new one is obviously not as well suited for it (tho it looks much better with the recent changes)
re: timers, how would you rank the different versions shown?
a) 1.1s, yellow running, faint completed: https://asciinema.org/a/6WxF1qbwhQXoml38JFs0Q3NWN
b) 1.1s, faint running, faint completed: https://asciinema.org/a/PsY8yWxqi2TFeSvVS6dAKujBW
c) 1s, faint running, faint completed: https://asciinema.org/a/2wJpMD9b0D9xIr7acGTqR4ShB
a > b > c
After going through all of them again I agree with ^^^ too
Feedback in #daggernauts message re: a handled failure in a function leaking. Going to test it today, wondering if errors created by test suites show.
Just realized the "Not sure if this is covered by the new TUI" above ๐
@modest hedge, can you rebase asap so I can test with Erik's changes to the module commands? There's some conflicts to solve.
Yep this is fixed in the new tui
Getting on it now!
@pine vigil done
Iโm just coming back from PTO and checking out the new TUI on 0.9.11 and one thing I really miss was the behavior of โfocus=false
Especially when things go wrong being able to scroll back through the terminal was super valuable
Welcome back! --debug should help right? Removing need for --focus was a discrete goal