Skip to content

Feedback/ideas/thoughts #50

Description

@josephrocca

Awesome project! Thanks for your work on this. I'm in the process of attempting to switch from pm2 to pup, and I thought it might be useful to share some thoughts given that it looks like you're heading toward v1.0. Please take each of these suggestions with a grain of salt. And I'll pre-apologise here for any suggestions/thoughts that have stemmed from misunderstandings in the way Pup works.

Confusion around pup run vs pup start and pup terminate vs pup stop - and "apps" vs "ecosystems" vs "processes"

Intuitively, here's how I think pup should work:

  1. Install pup
  2. Enable it on startup with sudo pup startup enable or something
  3. Create a pup.json file in your app/server directory
  4. Run pup start in the same directory to start app (and causes pup to track that config file - e.g. for startup stuff)
  5. To stop, run pup stop in that directory (or run pup stop the-app-id), and it stops all the processes for that app/ecosystem (and untracks config file)

Controlling individual processes within an app is something that should be possible, but (at least in my experience) is not as common, so it should not use up the precious/intuitive start and stop commands. By far the most common commands I use with pm2 are start/stop/restart/logs, and they all apply to apps, not processes within an app.

I think this is the most important change that should be made for v1.0. If the current CLI design decisions were made to support more complex use cases that I'm not considering here, then I think "simple things should be simple, complex things should be possible" might be worth applying here. Need to avoid making simple things unsimple in order to make complex things simple-ish. Instead, move the burden to people doing complex things, because there are far fewer of them, and they (basically by definition) have the time + skill to go a little deeper in the config docs, or whatever.

The other huge advantage of this is that I think 90% of people will be migrating here from pm2, and IIUC this is basically how pm2 does it: https://pm2.keymetrics.io/docs/usage/application-declaration/ It's much easier to adopt new software if things work just like you expect - both intuitively, and from experience with related, popular software. Diverging from that is a cost that would need to give significant returns to be justified (Deno team realized this recently with deno install, for example). It's probably only worth diverging from pm2 in aspects where it's kinda confusing/bad.

Also perhaps worth mentioning: With the current CLI commands, I'm not actually sure how I'm supposed to use pup run, since it runs in the foreground instead of starting all the app's processes in the background like I expected. Also, when I try exiting with Ctrl+C, sometimes it hangs:

joe@test:~/app$ pup run
2024-04-11T07:15:50.617Z [LOG] [core:processes] Process 'app' loaded
2024-04-11T07:15:50.617Z [LOG] [app:starting] Process starting, reason: autostart
2024-04-11T07:15:50.651Z [LOG] [app:stdout] Listening on http://localhost:80/
2024-04-11T07:15:50.656Z [LOG] [app:stdout] HTTP server running. Access it at: http://localhost:80/
^C2024-04-11T07:16:00.685Z [LOG] [core:terminate] Termination requested
2024-04-11T07:16:00.689Z [LOG] [app:block] Process blocked, reason: terminating
2024-04-11T07:16:00.690Z [INFO] [core:cleanup] /home/joe/app/.pup.jsonc-tmp removed.
2024-04-11T07:16:00.687Z [LOG] [app:errored] Process exited with error: Error: Exited with code: 130
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C

and I need to close the terminal to actually stop it. Other times it exits fine. But in both cases the pup status tells me No running instance found..

Where is Pup's "ground truth" for config?

IIUC, the pm2 save command snapshots the configs and uses that saved snapshot to e.g. determine whether an app should start on machine startup. I'm wondering how pup handles this? The pm2 save command was always a little bit confusing/annoying to me. Ideally, in my mind, pup would use the actual config files in the app directories as ground truth. So pup start would just add that config file's path to pup's internal "known config files" list, which it uses at machine startup to fetch the actual config file contents, and determine whether the app should be started. And I think pup stop should remove the config file from pup's internal "known config files" list.

There are tradeoffs here, but I think I would prefer if pup held as little "internal state" as possible - so I can just e.g. edit the config file and run pup restart in the same directory, and I know that I'm editing the actual "ground truth" that Pup is using.

I think there's a temptation here to, for example, not bundle pup's untracking of a config file with stop-ing the app because that's not always what would be desirable - but I'd appeal to the "simple things should be simple" principle again here - it's easy to add some extra (more "granular") commands like pup track and pup untrack, or whatever, which can be used in cases where devs are heading off the beaten path.

Document a few of the most common/useful commands in readme

E.g. pup status, pup logs - a quick dot-point list of these in the readme as part of the "quick start" would have been handy for me to quickly get the rough idea. And maybe add a final dot point linking them to e.g. https://github.com/Hexagon/pup/blob/main/docs/src/usage/index.md for the rest of the commands.

Document configuration defaults

This page: https://pup.56k.guru/usage/configuration/#general should have the defaults for all options documented. This one is pretty important I think. It'd also be worth mentioning a few of the most important defaults in the readme I think.

Related: I love opinionated defaults that make it easy for people to get started, but I'm a little bit weary of "overly specific" defaults like watcher.exts = ["ts", "tsx", "js", "jsx", "json"] which might not be very future proof. E.g. could probably add yaml, json5, etc. to that - there's a long tail. It might be best to just watch all extensions by default, but I'm not confident what the best approach is here. Current defaults are not unreasonable, but worth thinking about in terms of forward compatibility and future breaking changes.

pup logs should stream by default

I use pm2 logs <all|app-id> on a daily basis - it's very handy to have logs streaming in my console as I'm coding, so I can e.g. see errors during startup after saving the file, or see live logs on a production server.

Can console.warn be made orange in logs?

I've wished for a long time that pm2 did this. It sounds like a small thing, but I really appreciate that Chrome's devtools does this when I'm remotely inspecting a Deno/Node process. I just wish it were possible for terminal logs to make a visual distinction between warnings and errors. That said, I'm guessing it might not be possible due to console.warn maybe just being a stderr log without any distinction from console.error at the level at which pup "sees" those logs.

A log file with errors and normal logs interspersed

Another annoying thing with pm2 is that (AFAIK) I'm not able to see a log file that has errors and logs interspersed. The reason this is annoying is because the logs that came before an error are often quite relevant to the cause of the error. So, while debugging, I end up needing to switch back and forth between them and rely on timestamps for aligning them.

Switch from JSONC to JSON5, or support both

I hadn't heard of JSONC before - maybe I'm just out of the loop on that. I have used JSON5 before though, and seems to be more commonly used?

JSON5 is nice because you don't need quotes around keys like with JS POJO declarations - makes config files really clean.

Move .pup.jsonc-tmp, .pup.jsonc-data, etc. into .pup

This reduces clutter - especially if more pup-related files are needed in the app directory in the future.

Densify pup status, add colors for skimming, and num restarts + uptime

For pup status, "number of restarts" and "uptime" would be handy, and pm2-style density with skimmable (green=good) would be awesome:

image

Rather than having a separator between rows, I mean. I also think pm2 status could be made a lot more dense - e.g. by using emojis (which work fine in terminal, of course) for boolean/enum fields like status, watch, etc. The denser the better imo.

Also, I think pm2's "cpu" column is kind of useless since IIUC it's the CPU usage at that exact instant - it'd be much more useful for me to see average or total CPU usage over the last 30 minutes, or something.


Please don't feel the need to reply to all/any of the above points. I just hope that these thoughts have been at least somewhat useful. Thanks again for all your work on this!

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions