Skip to content

Commit 85375d4

Browse files
committed
cvd: Add support for logging to a file
Implement timestamped log file creation for the cvd command. Logs are saved in CvdDir() + "/logs/" with a name like cvd_YYYYMMDD_HHMMSS.ms.log. This ensures logs are preserved across runs. Assisted-by: Jetski <jetski@google.com> Bug: b/507600500
1 parent f2e80f6 commit 85375d4

5 files changed

Lines changed: 113 additions & 4 deletions

File tree

base/cvd/cuttlefish/host/commands/cvd/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ cf_cc_binary(
3535
"//cuttlefish/common/libs/utils:flag_parser",
3636
"//cuttlefish/common/libs/utils:subprocess",
3737
"//cuttlefish/common/libs/utils:tee_logging",
38+
"//cuttlefish/host/commands/cvd/cli:log_files",
3839
"//cuttlefish/host/commands/cvd/utils",
3940
"//cuttlefish/host/commands/cvd/version",
4041
"//cuttlefish/host/libs/vm_manager",

base/cvd/cuttlefish/host/commands/cvd/cli/BUILD.bazel

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ cf_cc_library(
5151
],
5252
)
5353

54+
cf_cc_library(
55+
name = "log_files",
56+
srcs = ["log_files.cpp"],
57+
hdrs = ["log_files.h"],
58+
deps = [
59+
"//cuttlefish/common/libs/utils:files",
60+
"//cuttlefish/host/commands/cvd/utils",
61+
"@abseil-cpp//absl/strings",
62+
],
63+
)
64+
5465
# Commands that may invoke other commands
5566
cf_cc_library(
5667
name = "nesting_commands",
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (C) 2026 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "cuttlefish/host/commands/cvd/cli/log_files.h"
18+
19+
#include <chrono>
20+
#include <iomanip>
21+
#include <iostream>
22+
#include <sstream>
23+
#include <string>
24+
#include <vector>
25+
26+
#include "absl/strings/str_cat.h"
27+
28+
#include "cuttlefish/common/libs/utils/files.h"
29+
#include "cuttlefish/host/commands/cvd/utils/common.h"
30+
31+
namespace cuttlefish {
32+
33+
std::vector<std::string> GetLogFiles() {
34+
std::string log_dir = CvdDir() + "/logs";
35+
if (!EnsureDirectoryExists(log_dir, 0777).ok()) {
36+
std::cerr << "Failed to create log directory: " << log_dir
37+
<< ". Logging to file disabled." << std::endl;
38+
return {};
39+
}
40+
41+
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
42+
std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
43+
std::chrono::milliseconds now_ms =
44+
std::chrono::duration_cast<std::chrono::milliseconds>(
45+
now.time_since_epoch()) %
46+
1000;
47+
48+
std::tm tm_now;
49+
localtime_r(&now_time_t, &tm_now);
50+
51+
std::stringstream ss;
52+
ss << std::put_time(&tm_now, "%Y%m%d_%H%M%S") << "." << std::setfill('0')
53+
<< std::setw(3) << now_ms.count();
54+
return {absl::StrCat(log_dir, "/cvd_", ss.str(), ".log")};
55+
}
56+
57+
} // namespace cuttlefish
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (C) 2026 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <string>
20+
#include <vector>
21+
22+
namespace cuttlefish {
23+
24+
/**
25+
* Returns a vector containing the path to a new timestamped log file for the
26+
* cvd command. The log file is created in CvdDir() + "/logs/" with a name like
27+
* cvd_YYYYMMDD_HHMMSS.ms.log. If the logs directory cannot be created, the
28+
* function returns an empty vector.
29+
*/
30+
std::vector<std::string> GetLogFiles();
31+
32+
} // namespace cuttlefish

base/cvd/cuttlefish/host/commands/cvd/main.cc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,28 @@
2020
#include <time.h>
2121
#include <unistd.h>
2222

23+
#include <chrono>
24+
#include <iomanip>
2325
#include <iostream>
26+
#include <sstream>
2427
#include <string>
2528
#include <string_view>
2629
#include <unordered_map>
2730
#include <vector>
2831

29-
#include <android-base/file.h>
3032
#include "absl/cleanup/cleanup.h"
31-
#include "absl/strings/str_split.h"
32-
#include <fmt/format.h>
3333
#include "absl/log/log.h"
34+
#include "absl/strings/str_cat.h"
35+
#include "absl/strings/str_split.h"
36+
#include "android-base/file.h"
37+
#include "fmt/format.h"
3438

3539
#include "cuttlefish/common/libs/utils/environment.h"
3640
#include "cuttlefish/common/libs/utils/files.h"
3741
#include "cuttlefish/common/libs/utils/flag_parser.h"
3842
#include "cuttlefish/common/libs/utils/subprocess.h"
3943
#include "cuttlefish/common/libs/utils/tee_logging.h"
44+
#include "cuttlefish/host/commands/cvd/cli/log_files.h"
4045
#include "cuttlefish/host/commands/cvd/cvd.h"
4146
#include "cuttlefish/host/commands/cvd/utils/common.h"
4247
#include "cuttlefish/host/commands/cvd/version/version.h"
@@ -216,6 +221,7 @@ bool ValidateHostConfiguration() {
216221
}
217222

218223
} // namespace
224+
219225
} // namespace cuttlefish
220226

221227
int main(int argc, char** argv) {
@@ -228,7 +234,9 @@ int main(int argc, char** argv) {
228234
cuttlefish::MetadataLevel metadata_level =
229235
isatty(0) ? cuttlefish::MetadataLevel::ONLY_MESSAGE
230236
: cuttlefish::MetadataLevel::FULL;
231-
cuttlefish::LogToStderr("", metadata_level, verbosity);
237+
238+
std::vector<std::string> log_files = cuttlefish::GetLogFiles();
239+
cuttlefish::LogToStderrAndFiles(log_files, "", metadata_level, verbosity);
232240

233241
if (!cuttlefish::ValidateHostConfiguration()) {
234242
return -1;

0 commit comments

Comments
 (0)