Skip to content

Cvd logs subcommand#2498

Open
ser-io wants to merge 6 commits intogoogle:mainfrom
ser-io:cvd-logs-subcommand
Open

Cvd logs subcommand#2498
ser-io wants to merge 6 commits intogoogle:mainfrom
ser-io:cvd-logs-subcommand

Conversation

@ser-io
Copy link
Copy Markdown
Member

@ser-io ser-io commented Apr 30, 2026

No description provided.

@ser-io ser-io force-pushed the cvd-logs-subcommand branch from 346fc80 to ff7c2bb Compare April 30, 2026 21:37
@ser-io ser-io requested review from Databean and jemoreira April 30, 2026 21:37
Comment on lines +55 to +60
Command cat("cat");
cat.AddParameter(filename);
int exit_code = cat.Start().Wait();
CF_EXPECTF(exit_code == 0, "{} {} failed: exited with status {}",
cat.Executable(), filename, exit_code);
return {};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the suggestions in https://clig.dev/#output is

Use a pager (e.g. less) if you are outputting a lot of text. For example, git diff does this by default. Using a pager can be error-prone, so be careful with your implementation such that you don’t make the experience worse for the user. Use a pager only if stdin or stdout is an interactive terminal.

A good sensible set of options to use for less is less -FIRX. This does not page if the content fills one screen, ignores case when you search, enables color and formatting, and leaves the contents on the screen when less quits.

CF_EXPECT(IsDirectory(logs_dir));

if (opts.print_target.empty()) {
return PrintLogsList(logs_dir);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: return CF_EXPECT(PrintLogsList(logs_dir));

otherwise Handle() will not appear in the stack trace.

}

func runCmdWithContextEnv(ctx context.Context, command []string, envvars map[string]string) (string, error) {
func runCmdWithContextEnv(ctx context.Context, command []string, envvars map[string]string) (string, string, error) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe worth returning a structure with fields for stdout and stderr so code isn't reliant on the caller knowing what each string means? It could be reused for RunCmdWithEnv and RunCmd as well.

Comment thread base/cvd/cuttlefish/host/commands/cvd/cli/commands/logs.cpp Outdated

std::cout << "hello, logs\n";
std::string dir = instance.instance_dir();
std::string logs_dir = dir + "/logs";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some logs in the instance dir are symlinks to the assembly dir that may not be created if the instance fails to boot. This code should avoid those symlinks and go for the actual files instead.

There is also fetch.log in the artifacts dir.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I noticed the following log names: assemble_cvd.log and cuttlefish_config.json and fetch.log are symlinks in the instance directory. Created b/509586405 to handle this in a different PR.

std::string dir = instance.instance_dir();
std::string logs_dir = dir + "/logs";

CF_EXPECT(FileExists(logs_dir));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cvd create --nostart && cvd logs is a valid command sequence but the second command will fail with an obscure error message about some directory not existing.

It should print a line informing the user that there are no logs available when no log files are found. If --verbose was given it could list the directories it searched too.

Comment on lines +35 to +36
GflagsCompatFlag("print", print_target),
GflagsCompatFlag("p", print_target),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates two different flags, instead of a single flag with two aliases. Do this instead:

GflagsCompatFlag("print", print_target).Alias({FlagAliasMode::kFlagConsumesFollowing, "-p"}),

std::cout << std::endl;
return {};
};
return WalkDirectory(dir, callback);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use CF_EXPECT on WalkDirectory so this function gets added to the stack trace.

constexpr int kMaxPadding = 30;
std::string basename = android::base::Basename(filename);
std::cout << basename;
std::cout << std::string(std::max(int(kMaxPadding - basename.length()), 1), ' ');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: While the padding might make it look nice for a human it will complicate using this in a script. For example, cvd logs | cut -d" " -f2 can't be used to get the file paths because of the unpredictable number of spaces. You could use padding only if stdout is a terminal, like ls does to determine whether to print one file per line or not.

constexpr int kMaxPadding = 30;
std::string basename = android::base::Basename(filename);
std::cout << basename;
std::cout << std::string(std::max(int(kMaxPadding - basename.length()), 1), ' ');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Assign that expression to a variable to make it more clear what it is.

}

Result<void> PrintLog(const std::string& filename) {
Command cat("cat");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds an implicit dependency between cvd and cat. While it's unlikely cvd will run in a system that doesn't have cat it's still better to not depend on it. The simplest way to implement this in-process is something like:

std::ifstream file("/path/to/file");                                              
CF_EXPECT(file.is_open());
std::cout << file.rdbuf();

If you still think calling cat is preferable for some reason then do a plain exec without fork to at least avoid creating a new process unnecessarily.

}
listedNames = append(listedNames, fields[0])
}
keyExpectedNames := []string{"logcat", "launcher.log", "kernel.log"}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also assemble_cvd.log and fetch.log when launched with cvd load.

@ser-io ser-io force-pushed the cvd-logs-subcommand branch from ff7c2bb to 1177b9c Compare May 4, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants