Giter Site home page Giter Site logo

deref / exo Goto Github PK

View Code? Open in Web Editor NEW
402.0 5.0 14.0 19.42 MB

A process manager & log viewer for dev

Home Page: https://exo.deref.io

License: Apache License 2.0

Go 72.66% Shell 0.32% HCL 1.39% HTML 0.05% CSS 2.31% Svelte 17.17% TypeScript 5.66% JavaScript 0.14% Makefile 0.10% Dockerfile 0.01% Procfile 0.01% CUE 0.18%
procfile supervisor process-manager logs gui docker-compose compose

exo's Introduction

exo: a process manager & log viewer for dev

exo- prefix – external; from outside.

The Exo GUI

Features

  • Procfile and Docker Compose compatible process manager.
  • Terminal commands and browser-based-GUI for all functionality.
  • Multiplexed, colorizing log tailing. Toggle visibility of individual logs.
  • Dynamic process supervision: create, start, stop, restart, delete.

Getting Started

Install Exo:

curl -sL https://exo.deref.io/install | bash

If you prefer package managers or manual installation, see the install docs for details, including uninstall instructions.

Navigate to your code directory and then launch the Exo gui:

exo gui

To use exo as a drop-in replacement for foreman or docker-compose, use run instead:

exo run

This will work automatically with your Procfile, compose.yaml, or similarly named manifest files. The run command also accepts an explicit filename, if you have multiple configurations to choose from.

For more, checkout the Exo documentation, watch some videos or consult the builtin help by running exo help.


Support

Feel free to open an issue, tweet at us, start a discussion, or pop-in to our #exo Slack channel.

Telemetry

exo collects limited and anonymous telemetry data by default. This behavior can be disabled by adding the following setting to your exo config (located at ~/.exo/config.toml by default):

[telemetry]
disable: true

exo's People

Contributors

balupton avatar benelgar avatar brandonbloom avatar jrysana avatar kendru avatar logoff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

exo's Issues

[FEATURE] Support config profiles

Is your feature request related to a problem? Please describe.
When I am developing exo, I constantly have to switch my client config in config.toml to point between the default installed version and the development version.

Describe the solution you'd like
I would like the exo cli to be aware of config profiles. exo profiles ls should display the available profiles with an * next to my current profile, and exo profiles use <profile-name> should set my current profile to <profile-name>. exo profiles create <profile-name> should create a new profile and set it as my default profile.

Describe alternatives you've considered

  • Use environment variables to override the server URL. cons: it is too easy to forget to set the environment variable before running the command or forget that you have an override exported in your shell; your environment is not persistent.

Additional context
This feature may make more sense after we have to ability to update config from the cli, since creating a profile would probably just entail creating a new, empty TOML file that still must be edited by hand.

[FEATURE] Some exo/system events should appear in the log

Is your feature request related to a problem? Please describe.

When processes start, stop, exit, etc, it's not obvious in the logs.

Describe the solution you'd like

There should be a log stream for system events like this, which appear in the aggregate log stream.

self-update fails with release/bundled build

image

from exod.log:

2021/07/28 14:55:37 error processing request: running update script: fork/exec /var/folders/cn/q2gg_ww95f5249g5xtfm4jp40000gn/T/example827031344: no such file or directory
2021/07/28 14:56:38 error processing request: running update script: fork/exec /var/folders/cn/q2gg_ww95f5249g5xtfm4jp40000gn/T/example214949991: no such file or directory

via @siggisim

[BUG] Command sequences are not appropriately escaped when tailing logs

Describe the bug
When logs from multiple processes are multiplexed in the terminal a process can interfere with the logs of another process. For instance, if process A emits \u001b[1mhello\nbye\u001b[0m, equivalent to:

hello
bye

and process B emits oh no\n, the output in the terminal can look like this:

13:38:26 hello
13:38:26 oh no
13:38:26 bye

Here the output of process B is incorrectly bold, as is the timestamp prefix added by exo.

[BUG] Timestamps are wrong (timezone/hours offset)

Describe the bug
In my actual local time, it is 12:38. The logs from tick correctly show this time, but the timestamps we create on the far left shows 4:38, an incorrect time.

Expected behavior
Our timestamps === actual user local time.

Screenshots
image

System Info:

  • OS: Windows (WSL Ubuntu)
  • Component: GUI
  • Version: Dev (>2021.07.30)

[BUG] Initial logs are missing from exo run

Describe the bug
When using exo run the first few seconds of logs are missing.

To Reproduce
Steps to reproduce the behavior:

  1. Create a docker compose file like this:
services:
  test:
    image: bash
    command: "bash -c 'i=0; while true; do echo $((i++)); sleep 1; done'"
  1. Witness this behaviour:
❯ dexo run docker-compose.y*
GUI available at: http://localhost:4001/#/workspaces/hk6vv1fe87qsjqn7kbb8ywaanr
Job URL: http://localhost:4001/#/jobs/t9sayfxh6031e8tjrk9f0pxq88
applying  success
  └─ updating test  success
16:08:15 test 3

16:08:16 test 4

Notice that the first log line printed is "3" when it should have been "0".

[FEATURE] Filterable logs

Is your feature request related to a problem? Please describe.
When I have a large volume of logs, and I am looking for a particular string, I cannot do this easily with exo.

Describe the solution you'd like
I would like the log viewer to include a filter button. Clicking on this button should bring up a text box that I can type in to filter the logs. As I type, the logs are filtered to only those that contain the string that I have entered (case insensitive).

Describe alternatives you've considered
Go back to logging to a file then searching with grep. 😢

Stop button in the UI has different behavior than `Ctrl+C`-ing the same process

Not sure if this is intentional or not, but it leads to some annoying behavior when developing.

When I run exo run tools/goreman/procfiles/Procfile.rexec with this procfile in our repo: https://github.com/buildbuddy-io/buildbuddy

app: bazel run enterprise/server -- --config_file=enterprise/config/buildbuddy.local.yaml
exec: bazel run enterprise/server/cmd/executor:executor -- --monitoring_port=9091 --executor.docker_socket=
redis: redis-server

And hit stop in the UI on exec, I get no logs about a shutdown. When I hit play again - the error message

07:05:47  exec 2021/08/02 14:05:47.344 FTL listen tcp 0.0.0.0:9091: bind: address already in use

This leads me to believe the server that bazel run spun up was never killed.

When I run the same exec process on it's own in a terminal and hit Ctrl+C, I get the following logs:

^CCaught interrupt signal; shutting down...
2021/08/02 14:13:04.832 INF Stopping queue processing, machine is shutting down. name=rN5IABEi
2021/08/02 14:13:04.861 INF Graceful stop of executor succeeded.
Server "prod-buildbuddy-executor" stopped.

And don't get the port collision error when I start it again.

My workaround for now is to hit Ctrl+C on exo run tools/goreman/procfiles/Procfile.rexec, which solves the issue - but means I have to restart all 3 processes.

Handle stopping logio and supervised processes

When we stop a process, we send SIGKILL to the logio process, orphaning the supervised process (and not stopping it). Instead, we should send a SIGTERM to logio, indicating that it should gracefully stop its child process, wait for termination, then stop itself. Configurable timeouts should be used in both exo and the supervisor, after which the child process should be killed. @BenElgar let me know if you have questions.

[BUG] Choke on badly named docker compose services

Describe the bug

Service named with an underscore fails as invalid component name.

This is the same problem as #72

Expected behavior

We should apply the same solution as we did for procfiles. See this PR and the highlighted line in particular:

https://github.com/deref/exo/pull/73/files#diff-d25b12dec6f33085b7526cc93449e046c919e5705e416eb816d79292961f0f91R41

Note that I'd argue that underscores should be rejected by docker compose itself, especially given what the spec says about aliases and hostnames for links.

Containers for the linked service MUST be reachable at a hostname identical to the alias, or the service name if no alias was specified.

Implement `exo feedback` command

  1. Create command: exo feedback
  2. This command should open the default editor with a temporary file.
  3. When this file is saved, a message is sent to Deref with the feedback.

[BUG] Procfile export order & ports

Describe the bug

Exporting a procfile does not preserve procfile order, and includes redundant PORT variables.

diff --git a/Procfile b/Procfile
index bd49e77..2903ab6 100644
--- a/Procfile
+++ b/Procfile
@@ -1,3 +1,3 @@
-server: ./script/dev-server.sh
-gui: ./script/dev-gui.sh
-storybook: ./script/storybook.sh
+gui: PORT=5100 ./script/dev-gui.sh
+server: PORT=5000 ./script/dev-server.sh
+storybook: PORT=5200 ./script/storybook.sh

To Reproduce

On current main, just do exo apply Procfile and you'll immediately see an "out of date" warning in the GUI. Press "export" then, get diff above.

Expected behavior

  1. If the PORT would be redundant from the implicit port order in the procfile, we should omit the PORT=whatever from the exported service lines in the outputted procfile.

  2. Somehow, we should preserve the order of entries in the procfile. Not sure how this should work, maybe some kind of metadata on the components. Like procfile:index=2 or whatever & then a best-effort stable sort used in export? Open to other ideas too.

[BUG] Unclear that anything is happening in the UI when docker images are building

Describe the bug
The UI doesn't show any processes or inform you that anything is happening when a docker image is building.

To Reproduce
Steps to reproduce the behavior:

  1. Run exo run docker-compose.yaml for a docker compose file for which you don't have any cached docker images
  2. Observe in the UI that the workspace is created with no components

Expected behavior
A loading bar or spinner should be displayed

[BUG] exo run handles lots of output poorly

Describe the bug
If a command outputs a vast amount of logs exo run doesn't appear able to stop.

To Reproduce
Steps to reproduce the behavior:

  1. Create a docker compose that looks like this:
services:
  busy:
    image: bash
    command: "bash -c 'while true; do echo hello; done'"
  1. Send a SIGINT or SIGTERM to the exo run process
  2. Witness as nothing happens

Expected behavior
The workspace should stop, terminating the container.

My assumption is that this happens because of the very large amount of output that the script generates.

[FEATURE] Component dependencies

compose files supports a depends_on option, documented here: https://docs.docker.com/compose/compose-file/compose-file-v3/#depends_on and here: https://github.com/compose-spec/compose-spec/blob/master/spec.md#depends_on

As of 8c40b56 we load compose files and ignore this configuration. Ignoring this configuration is reasonable, since well-behaved services need to fail gracefully if their dependencies are temporarily unavailable. There is prior art for this as well, since depends_on is not supported in Docker's Swarm mode.

However, we may want dependencies for other reasons. For instance, interactive start operations should also start their dependencies by default.

If we do support depends_on, we should do so in a more general way, as this affects orchestration in exo beyond just docker.

  • We should implement proper yaml unmarshalling for both the short and long syntax of compose. See the other examples, such as PortMapping and Dictionary in that package.
  • During the compose.Convert process, we should produce dependencies in whatever way we model that in the exo manifest. Lots of design work needed here, but I have some ideas worth discussing.

[FEATURE]: Environment file handling

Two main formats to support, in order of priority:

  1. .env - simple key/value pairs (trivially safe)
  2. .envrc - scripts as defined by https://direnv.net/ – naive handling would be risky, running arbitrary code in a directory. have to consider security threat model.

An enviornment file should be loaded prior to any process start, etc. The workspace configuration screen should have some UI for inspecting/editing these files too.

If an environment file changes (or some other way to detect env changes?), that should invalidate the spec for anything that depends on the environment (when we have a dependency system, at least). That is, we might want to cause an update or even a destroy/recreate for some component.

docker-compose supports an --env-file cli command. we should consider when/how env impacts individual commands, profiles, etc.

Also consider secrets.

upgrading doesn't restart daemon

I think two things have to happen:

  1. need to run exo exit if exo is on the path
  2. the ensureDaemon health check should validate the version matches correctly

[BUG] Log pages load very slowly in wrong order in the UI

If you view a process that has lots of logs it will load the logs forwards from the first line. This can be very slow if there are many thousands of lines of logs. Instead I'd propose that we load the most recent logs and then page backwards.

[FEATURE] Git branch display/switch

Is your feature request related to a problem? Please describe.
I love using exo for logs and process management, but I find that I constantly go to my terminal to check what branch I have checked out with Git.

Describe the solution you'd like
I would love to have my current git branch displayed in some status area (like in VSCode). When I click on this, I would like to see a list of branches that I have checked out locally, and if I click on one, I would like to change to that branch. If there are changes preventing me from switching branches, it would be fine to show an error message.

Describe alternatives you've considered
Going back and forth between exo and my terminal 🙃

Additional context
N/A

[FEATURE] builtin file watcher

The current one has a lots of problems, starting a list:

  • Doesn't ignore changes to *.swp files.
  • Sometimes fails to restart after errors.
  • Some graceful shutdown problem. e.g. go run leaves behind binaries (h/t @BenElgar)

Perhaps more importantly, builtin file watcher support would be a welcome feature! Once we have custom exo manifests, we could add watch configuration for each service/process/container. Exo would then automatically restart processes via the control interface when things change.

[BUG] Unclear that error has occurred in UI

Describe the bug
When an exo run command fails it is unclear that this has happened in the UI.

To Reproduce
Steps to reproduce the behavior:

  1. Create a docker-compose file with an error, e.g.
services:
  alpine:
    image: "alpine"
    command: "notacommand"

That will give an error like the following in the server but no error in the UI.

19:47:31 server 2021/08/06 18:47:31 starting container "73d8bd1d97b21c1c00d94a9b9b83fbc985829e3045597e8af9c223fd15f2cbf3": Error response from daemon: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "notacommand": executable file not found in $PATH: unknown

Expected behavior
Some error message in the UI

[FEATURE] "smart case" string filtering

Is your feature request related to a problem? Please describe.

When filtering logs, I usually want to search case insensitive, but sometimes I want to search case-sensitive.

Describe the solution you'd like

See "smartcase" in vim:
https://vim.fandom.com/wiki/Searching

I always have this on by default. Basically, if you search for an all-lowercase string, then the search is case insensitive. If there are any uppercase characters, then the search is case sensitive.

Describe alternatives you've considered

Providing some UI or search/filter directives for toggling case sensitivity on and off. I think that should probably happen first: some more general work to improve filtering/querying expression.

PORT environment variable should not be set by default

When starting a new process imported from a Procfile, exo automatically injects a PORT environment variable into the new process. This can have unintended consequences. For example, my application relies on a config file to specify the port, but it allows PORT to override this value. I expect that if I do not set this environment variable in a Procfile, .envrc, or similar that it will not be set magically.

[FEATURE] bash completions

This should already be possible as part of the Cobra feature set, but we should figure out how to automate this as part of the install process.

[BUG] Logs are truncated

Describe the bug
Long log lines are truncated and/or split across lines.

To Reproduce
Steps to reproduce the behaviour:

  1. Create a docker-compose.yaml like so:
services:
  web:
    image: bash
    command: "printf '.%.0s' {1..9000}"
  1. Run it with exo run docker-compose.yaml

Expected behaviour
One log line printed with 9000 dots on one line in both the UI and the CLI. Instead what happens is that some smaller number of dots is printed in the UI (this seems to be consistently 8080) and none are printed in the CLI.

If the 9000 is increased to a much larger number the dots appear to get split across multiple lines in the UI but still don't sum to the correct number.

[BUG] exo run doesn't make clear that a service has failed to start

When an exo run command fails it is unclear that this has happened in the UI.

To Reproduce
Steps to reproduce the behavior:

  1. Create a docker-compose file with an error, e.g.
services:
  alpine:
    image: "alpine"
    command: "notacommand"
  1. Run exo run docker-compose.yml
    This will output something equivalent to the following and not stop:
❯ dexo run docker-compose.yml
GUI available at: http://localhost:4000/#/workspaces/hah3yrwaa4mz7zp1sj275y5wkm

Expected behavior
Terminate the exo run with a non-zero status code or at least output an error message on stderr.

[BUG] Ignoring `CMD` value in docker images

Describe the bug
If a docker-compose file doesn't specify a command it won't work with exo run.

To Reproduce
Steps to reproduce the behavior:

  1. Create a dockerfile that specifies a command, e.g.
FROM alpine
CMD ["sleep", "infinity"]
  1. Create a docker-compose that references it and doesn't include a command:
services:
  alpine:
    build: .
  1. Run exo run docker-compose.yml, which will give something like:
❯ dexo run docker-compose.yml
GUI available at: http://localhost:4000/#/workspaces/sfbbetx0x4y6bwf8keb9xv0mem
Error: applying manifest: internal server error
applying manifest: internal server error

In the server logs one sees:

20:00:39 server 2021/08/06 19:00:39 http 20b8fkx46p0y8zpfw8w0480e40: error processing request: adding "alpine": creating container: Error response from daemon: No command specified

Expected behavior
The compose file to run.

[BUG] Log output without a newline on the end never gets flushed.

I did a fmt.Printf("blah") (note: no \n) and then no other log messages happened. No log messages got produced. This seems reasonable, but maybe we should have a timeout on individual log messages, and split them, so that no one else winds up in this confused position?

cd/command chaining not supported in Procfile

Foreman now supports cd and command chaining within a Procfile, e.g.:

gui: cd gui && npm i && npm run dev

Exo does not allow this behviour. The workaround is the following:

gui: sh -c 'cd gui && npm i && npm run dev'

if component spec is invalid, create still succeeds

If you click "Create Process" twice in a row:

image

image

Need either/both of earlier spec validation and an "error/invalid" state for components, so that creation will succeed and the component can then be edited after creation. The latter seems more robust.

[FEATURE] set docker labels

Is your feature request related to a problem? Please describe.

When something goes wrong between docker & exo, it may be difficult to figure out what docker resources need cleanup.

Describe the solution you'd like

labels/tags/annotations are the standard tool in cloud-computing world for this, and docker is no different. Docker compose sets a com.docker.compose.project on every resource it creates and we should do the same.

Every container, network, and volume we create should get at least these two labels set:

  1. io.deref.exo.workspace - id string
  2. io.deref.exo.component - id string

Other labels that docker compose sets are worth studying and considering which apply to exo:

LABEL_CONTAINER_NUMBER = 'com.docker.compose.container-number'
LABEL_ONE_OFF = 'com.docker.compose.oneoff'
LABEL_PROJECT = 'com.docker.compose.project'
LABEL_WORKING_DIR = 'com.docker.compose.project.working_dir'
LABEL_CONFIG_FILES = 'com.docker.compose.project.config_files'
LABEL_ENVIRONMENT_FILE = 'com.docker.compose.project.environment_file'
LABEL_SERVICE = 'com.docker.compose.service'
LABEL_NETWORK = 'com.docker.compose.network'
LABEL_VERSION = 'com.docker.compose.version'
LABEL_SLUG = 'com.docker.compose.slug'
LABEL_VOLUME = 'com.docker.compose.volume'
LABEL_CONFIG_HASH = 'com.docker.compose.config-hash'

Beyond labels, we should probably produce better friendly names. Compose uses some code like this:

def build_container_name(project, service, number, slug=None):
    bits = [project.lstrip('-_'), service]
    if slug:
        bits.extend(['run', truncate_id(slug)])
    else:
        bits.append(str(number))
    return '_'.join(bits)

[BUG] `dexo exit` does not exit the dev daemon

Describe the bug
When using the dexo exit command, it should exit the dev process. It currently exits the installed instance rather than the dev one.

To Reproduce
Steps to reproduce the behavior:

  1. cd to the repo root directory
  2. Run exo run, then press Ctl+C to stop the logs process.
  3. Verify that the dev server is running: dexo status
  4. Run dexo exit

Expected behavior
After exiting, dexo status should indicate that the dev server is no longer running.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.