vim-xcode icon indicating copy to clipboard operation
vim-xcode copied to clipboard

Tail logs after running

Open gfontenot opened this issue 9 years ago • 14 comments

Right now, we're just printing the pid for the app process after running. That's not particularly useful, and I often find myself needing to open Xcode just to use the app in the simulator.

I think there's more we could do here, but for right now, it probably makes sense to at least tail the logs for the simulator wherever we ran the run command. It's at least a more useful default behavior than doing nothing.

gfontenot avatar Jul 19 '16 01:07 gfontenot

Hi @gfontenot, I noticed that the Swift print("something") does not print anything to the system.log at all. Do you know where we can find the output for this?

override func viewDidLoad() {
  super.viewDidLoad()
  print("something")
}

hoang-tran avatar Jul 19 '16 04:07 hoang-tran

Oh, right, I forgot about that. Maybe this isn't what we want to do. I wonder if it'd be a better default to run an lldb session.

gfontenot avatar Jul 19 '16 15:07 gfontenot

I think this PR and https://github.com/gfontenot/vim-xcode/pull/77 are both going to be awesome, but I think we might want to move some of this logic into the vim plugin instead. That way we could have much easier hooks around what to do in these cases. We talked about having this entire integration part in a separate plugin, which I'm not sure makes sense anymore, but I do think it would be nice to be able to customize this the way I wanted to, as far as running them in tmux splits, windows etc.

keith avatar Jul 25 '16 21:07 keith

On the lldb idea here, when launching a process you can pass stdout and stderr file paths:

process launch --stop-at-entry --stdout stdout.log --stderr.log

We would need both of these if for nothing else that Swift's prints end up in stdout and NSLog ends up in stderr

In theory after setting this up we could tail both at once:

tail -f stdout.log stderr.log

keith avatar Jul 29 '16 06:07 keith

I believe this is similar to what Xcode does, as the system.log tailed in this PR has a lot more info than just the specific app's logging.

keith avatar Jul 29 '16 06:07 keith

Also just noticed simctl's --wait-for-debugger/-w flag that might be of some use to us..

keith avatar Jul 29 '16 06:07 keith

So if you change this line:

xcrun simctl launch booted "$app_id"

To

xcrun simctl launch --wait-for-debugger booted "$app_id"

Then the process will launch, seemingly frozen in the foreground of the simulator, and if you then attach a debugger (it seems like there is a timeout for this part too) with something like:

output="$(xcrun simctl launch --wait-for-debugger booted "$app_id")"
pid="$(echo "$output" | cut -d " " -f2)"
lldb -p "$pid"

It launches!

keith avatar Jul 29 '16 06:07 keith

Another possible thing we might able to utilize here is the target.output-path setting. Since we're not explicitly calling process launch we can't inject the file paths for stdout and stderr. It seems like this setting should correspond with those command line arguments

keith avatar Jul 29 '16 07:07 keith

Hmm. So this variable is definitely for this use case, but it seems like setting it after the process is launched, has no effect. Which is kind of our case, since simctl is doing the actual spawning. There must be a way to force a refresh of these file descriptors, but I currently only see that in the python bridge with SetOutputFileHandle (I assuming this would do what we want)

keith avatar Jul 29 '16 07:07 keith

@keith Yeah I did a bunch of experimentation around --wait-for-debugger in #77, but I could never get it to actually attach stdout/stderr to the debugging session, so it didn't seem to solve the problem of seeing print() and NSLog() output.

FWIW, Xcode exhibits this same behaviour when you attach to an app that's already running in the simulator (you don't see stdout/stderr for that process). This makes me think that launching within lldb might be the way to go.

sharplet avatar Jul 29 '16 16:07 sharplet

One possible solution to this would be instead to handle the IO redirection at a lower level. As part of the script launched with lldb you could do something like this:

expr --language c -- (int)close(1)
expr --language c -- (int)close(2)
expr --language c -- (int)open("path/to/stdout", 0x201, 0777)
expr --language c -- (int)open("path/to/stderr", 0x201, 0777)

keith avatar Jul 29 '16 17:07 keith

FWIW this is much easier now with os log

keith avatar May 19 '17 02:05 keith

have a link with more info?

gfontenot avatar May 30 '17 12:05 gfontenot

Hmm. Looks like there's some need for blog posts about this. But a simple example of this is:

$ log stream --predicate "subsystem == 'AppName'"

There are some things with usage about this that you have to handle, like changing the predicate to include more things if you want logs from UIKit and such (you can probably do device to but I haven't looked). But from your app if you log a specific code on launch, you can reset the logs in the terminal, and this command persists across app launches, so you can just run it, and tail logs forever, clearing each relaunch.

keith avatar Jun 03 '17 16:06 keith