Skip to content

Commit 3398c8b

Browse files
committed
Add colors to cvd monitor
- Introduce component-aware syntax highlighting and coloring for logcat, kernel, launcher, and log_tee streams in `cvd monitor`. - Colorize timestamps, subsystem tags, PIDs/TIDs, and verbosity levels to improve log readability and debugging efficiency. - Restructure log monitoring logic into decoupled structured parsing and formatting pipelines within a new `commands/monitor/` package. - Add comprehensive unit tests for parsing and formatting across all supported log stream formats. Assisted-by: Jetski Bug: b/513710219
1 parent 1f0353b commit 3398c8b

30 files changed

Lines changed: 1531 additions & 187 deletions

base/cvd/cuttlefish/common/libs/utils/tee_logging.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ std::string StderrOutputGenerator(const struct tm& now, int pid, uint64_t tid,
165165
return output_string;
166166
}
167167

168-
// TODO(schuffelen): Do something less primitive.
168+
} // namespace
169+
169170
std::string StripColorCodes(const std::string& str) {
170171
std::stringstream sstream;
171172
bool in_color_code = false;
@@ -183,8 +184,6 @@ std::string StripColorCodes(const std::string& str) {
183184
return sstream.str();
184185
}
185186

186-
} // namespace
187-
188187
SeverityTarget SeverityTarget::FromFile(const std::string& path,
189188
MetadataLevel metadata_level,
190189
LogSeverity severity) {

base/cvd/cuttlefish/common/libs/utils/tee_logging.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ enum class LogSeverity : int {
4040
std::string FromSeverity(LogSeverity severity);
4141
Result<LogSeverity> ToSeverity(const std::string& value);
4242

43+
std::string StripColorCodes(const std::string& str);
44+
4345
LogSeverity ConsoleSeverity();
4446
LogSeverity LogFileSeverity();
4547

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ cf_cc_library(
130130
"//cuttlefish/host/commands/cvd/cli/commands:lint",
131131
"//cuttlefish/host/commands/cvd/cli/commands:login",
132132
"//cuttlefish/host/commands/cvd/cli/commands:logs",
133-
"//cuttlefish/host/commands/cvd/cli/commands:monitor",
134133
"//cuttlefish/host/commands/cvd/cli/commands:power_btn",
135134
"//cuttlefish/host/commands/cvd/cli/commands:powerwash",
136135
"//cuttlefish/host/commands/cvd/cli/commands:remove",
@@ -143,6 +142,7 @@ cf_cc_library(
143142
"//cuttlefish/host/commands/cvd/cli/commands:status",
144143
"//cuttlefish/host/commands/cvd/cli/commands:stop",
145144
"//cuttlefish/host/commands/cvd/cli/commands:version",
145+
"//cuttlefish/host/commands/cvd/cli/commands/monitor:command_handler",
146146
"//cuttlefish/host/commands/cvd/cli/parser:load_config_cc_proto",
147147
"//cuttlefish/host/commands/cvd/cli/parser:load_configs_parser",
148148
"//cuttlefish/host/commands/cvd/cli/selector:creation_analyzer",

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

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
load("//cuttlefish/bazel:rules.bzl", "cf_cc_library", "cf_cc_test")
1+
load("//cuttlefish/bazel:rules.bzl", "cf_cc_library")
22

33
package(
44
default_visibility = ["//:android_cuttlefish"],
@@ -246,41 +246,6 @@ cf_cc_library(
246246
],
247247
)
248248

249-
cf_cc_library(
250-
name = "monitor",
251-
srcs = ["monitor.cpp"],
252-
hdrs = ["monitor.h"],
253-
deps = [
254-
"//cuttlefish/common/libs/fs",
255-
"//cuttlefish/common/libs/utils:flag_parser",
256-
"//cuttlefish/host/commands/cvd/cli:command_request",
257-
"//cuttlefish/host/commands/cvd/cli:types",
258-
"//cuttlefish/host/commands/cvd/cli:utils",
259-
"//cuttlefish/host/commands/cvd/cli/commands:command_handler",
260-
"//cuttlefish/host/commands/cvd/cli/selector",
261-
"//cuttlefish/host/commands/cvd/instances",
262-
"//cuttlefish/host/commands/cvd/instances:instance_manager",
263-
"//cuttlefish/host/libs/log_names",
264-
"//cuttlefish/result",
265-
"//libbase",
266-
"@abseil-cpp//absl/log:check",
267-
"@abseil-cpp//absl/strings",
268-
"@abseil-cpp//absl/strings:cord",
269-
"@fmt",
270-
],
271-
)
272-
273-
cf_cc_test(
274-
name = "monitor_test",
275-
srcs = ["monitor_test.cpp"],
276-
deps = [
277-
":monitor",
278-
"//cuttlefish/common/libs/fs",
279-
"//cuttlefish/result:result_matchers",
280-
"@abseil-cpp//absl/strings",
281-
],
282-
)
283-
284249
cf_cc_library(
285250
name = "power_btn",
286251
srcs = ["power_btn.cpp"],
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
load("//cuttlefish/bazel:rules.bzl", "cf_cc_library", "cf_cc_test")
2+
3+
package(
4+
default_visibility = ["//cuttlefish/host/commands/cvd/cli:__subpackages__"],
5+
)
6+
7+
cf_cc_library(
8+
name = "ansi_codes",
9+
srcs = ["ansi_codes.cc"],
10+
hdrs = ["ansi_codes.h"],
11+
clang_format_enabled = True,
12+
deps = [
13+
"@abseil-cpp//absl/strings",
14+
],
15+
)
16+
17+
cf_cc_library(
18+
name = "command_handler",
19+
srcs = ["command_handler.cc"],
20+
hdrs = ["command_handler.h"],
21+
clang_format_enabled = True,
22+
deps = [
23+
":ansi_codes",
24+
":display",
25+
"//cuttlefish/common/libs/fs",
26+
"//cuttlefish/common/libs/utils:flag_parser",
27+
"//cuttlefish/host/commands/cvd/cli:command_request",
28+
"//cuttlefish/host/commands/cvd/cli:types",
29+
"//cuttlefish/host/commands/cvd/cli:utils",
30+
"//cuttlefish/host/commands/cvd/cli/commands:command_handler",
31+
"//cuttlefish/host/commands/cvd/cli/selector",
32+
"//cuttlefish/host/commands/cvd/instances",
33+
"//cuttlefish/host/commands/cvd/instances:instance_manager",
34+
"//cuttlefish/host/libs/log_names",
35+
"//cuttlefish/result",
36+
"//libbase",
37+
"@abseil-cpp//absl/strings",
38+
],
39+
)
40+
41+
cf_cc_library(
42+
name = "display",
43+
srcs = ["display.cc"],
44+
hdrs = ["display.h"],
45+
clang_format_enabled = True,
46+
deps = [
47+
":kernel",
48+
":launcher",
49+
":log_tee",
50+
":logcat",
51+
":truncate",
52+
"//cuttlefish/common/libs/fs",
53+
"//cuttlefish/common/libs/utils:environment",
54+
"//cuttlefish/common/libs/utils:tee_logging",
55+
"//cuttlefish/host/libs/log_names",
56+
"//cuttlefish/result",
57+
"@abseil-cpp//absl/log:check",
58+
"@abseil-cpp//absl/strings",
59+
"@abseil-cpp//absl/strings:cord",
60+
],
61+
)
62+
63+
cf_cc_test(
64+
name = "display_test",
65+
srcs = ["display_test.cc"],
66+
clang_format_enabled = True,
67+
deps = [
68+
":display",
69+
"//cuttlefish/common/libs/fs",
70+
"//cuttlefish/result:result_matchers",
71+
"@abseil-cpp//absl/strings",
72+
],
73+
)
74+
75+
cf_cc_library(
76+
name = "kernel",
77+
srcs = ["kernel.cc"],
78+
hdrs = ["kernel.h"],
79+
clang_format_enabled = True,
80+
deps = [
81+
":ansi_codes",
82+
"//cuttlefish/result",
83+
"@abseil-cpp//absl/strings",
84+
],
85+
)
86+
87+
cf_cc_test(
88+
name = "kernel_test",
89+
srcs = ["kernel_test.cc"],
90+
clang_format_enabled = True,
91+
deps = [
92+
":kernel",
93+
"//cuttlefish/result:result_matchers",
94+
],
95+
)
96+
97+
cf_cc_library(
98+
name = "launcher",
99+
srcs = ["launcher.cc"],
100+
hdrs = ["launcher.h"],
101+
clang_format_enabled = True,
102+
deps = [
103+
":ansi_codes",
104+
":verbosity",
105+
"//cuttlefish/result",
106+
"@abseil-cpp//absl/strings",
107+
],
108+
)
109+
110+
cf_cc_test(
111+
name = "launcher_test",
112+
srcs = ["launcher_test.cc"],
113+
clang_format_enabled = True,
114+
deps = [
115+
":launcher",
116+
"//cuttlefish/result:result_matchers",
117+
],
118+
)
119+
120+
cf_cc_library(
121+
name = "log_tee",
122+
srcs = ["log_tee.cc"],
123+
hdrs = ["log_tee.h"],
124+
clang_format_enabled = True,
125+
deps = [
126+
":ansi_codes",
127+
":verbosity",
128+
"//cuttlefish/result",
129+
"@abseil-cpp//absl/strings",
130+
],
131+
)
132+
133+
cf_cc_test(
134+
name = "log_tee_test",
135+
srcs = ["log_tee_test.cc"],
136+
clang_format_enabled = True,
137+
deps = [
138+
":log_tee",
139+
"//cuttlefish/result:result_matchers",
140+
],
141+
)
142+
143+
cf_cc_library(
144+
name = "logcat",
145+
srcs = ["logcat.cc"],
146+
hdrs = ["logcat.h"],
147+
clang_format_enabled = True,
148+
deps = [
149+
":ansi_codes",
150+
":verbosity",
151+
"//cuttlefish/result",
152+
"@abseil-cpp//absl/strings",
153+
],
154+
)
155+
156+
cf_cc_library(
157+
name = "truncate",
158+
srcs = ["truncate.cc"],
159+
hdrs = ["truncate.h"],
160+
clang_format_enabled = True,
161+
deps = [
162+
":ansi_codes",
163+
"@abseil-cpp//absl/strings",
164+
],
165+
)
166+
167+
cf_cc_test(
168+
name = "truncate_test",
169+
srcs = ["truncate_test.cc"],
170+
clang_format_enabled = True,
171+
deps = [
172+
":ansi_codes",
173+
":truncate",
174+
"@abseil-cpp//absl/strings",
175+
],
176+
)
177+
178+
cf_cc_test(
179+
name = "logcat_test",
180+
srcs = ["logcat_test.cc"],
181+
clang_format_enabled = True,
182+
deps = [
183+
":logcat",
184+
"//cuttlefish/result:result_matchers",
185+
],
186+
)
187+
188+
cf_cc_library(
189+
name = "verbosity",
190+
srcs = ["verbosity.cc"],
191+
hdrs = ["verbosity.h"],
192+
clang_format_enabled = True,
193+
deps = [
194+
":ansi_codes",
195+
],
196+
)
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+
#include "cuttlefish/host/commands/cvd/cli/commands/monitor/ansi_codes.h"
18+
19+
#include <string>
20+
21+
#include "absl/strings/str_cat.h"
22+
23+
namespace cuttlefish {
24+
25+
bool IsCsiFinalByte(char c) {
26+
auto uc = static_cast<unsigned char>(c);
27+
return uc >= '@' && uc <= '~';
28+
}
29+
30+
std::string AnsiCursorUp(int n) { return absl::StrCat("\033[", n, "A"); }
31+
32+
} // namespace cuttlefish
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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 <string_view>
21+
22+
namespace cuttlefish {
23+
24+
inline constexpr std::string_view kAnsiCsi = "\033[";
25+
inline constexpr std::string_view kAnsiReset = "\033[0m";
26+
inline constexpr std::string_view kAnsiRed = "\033[0;31m";
27+
inline constexpr std::string_view kAnsiGreen = "\033[0;32m";
28+
inline constexpr std::string_view kAnsiYellow = "\033[0;33m";
29+
inline constexpr std::string_view kAnsiCyan = "\033[0;36m";
30+
inline constexpr std::string_view kAnsiWhite = "\033[0;37m";
31+
inline constexpr std::string_view kAnsiClearScreenAfterCursor = "\033[J";
32+
33+
// CSI final bytes are in the range 0x40–0x7E (ASCII @ to ~).
34+
bool IsCsiFinalByte(char c);
35+
36+
std::string AnsiCursorUp(int n);
37+
38+
} // namespace cuttlefish

0 commit comments

Comments
 (0)