blob: f1798b398ddc14dc5642dddb72835d225c35a3c0 [file] [log] [blame]
Mike Frysingerf8ca5322017-02-07 15:54:20 -05001// Copyright 2017 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This file is meant for debugging use to manually trigger collection of
6// debug logs. Normally this can be done with dbus-send but dbus-send does
7// not support passing file descriptors.
8
9#include <stdio.h>
10#include <stdlib.h>
11
12#include <memory>
13
Qijiang Fan713061e2021-03-08 15:45:12 +090014#include <base/check.h>
Brian Norris793510f2018-04-04 15:47:42 -070015#include <base/command_line.h>
Mike Frysingerf8ca5322017-02-07 15:54:20 -050016#include <base/files/file_path.h>
17#include <base/files/file_util.h>
18#include <base/files/scoped_file.h>
19#include <base/logging.h>
20#include <base/strings/stringprintf.h>
21#include <base/time/time.h>
22#include <brillo/flag_helper.h>
23#include <chromeos/dbus/service_constants.h>
24#include <dbus/bus.h>
Mike Frysingerf8ca5322017-02-07 15:54:20 -050025#include <dbus/message.h>
26#include <dbus/object_proxy.h>
27
28namespace {
29
Mike Frysingerf8ca5322017-02-07 15:54:20 -050030const char kUsage[] =
Tom Hughesd6c2d392020-08-24 18:12:11 -070031 "Developer helper tool for getting extended debug logs from the system."
32 "\n"
33 "\n"
34 "This calls back into debugd using the DumpDebugLogs dbus end point."
35 "\n"
36 "\n"
37 "WARNING: The exact contents of the generated output may vary depending on"
38 "\n"
39 "developers' whims.";
Mike Frysingerf8ca5322017-02-07 15:54:20 -050040
41// Returns a dynamic file name with datestamps in it.
42std::string LogName(bool compress) {
43 base::Time::Exploded now;
44 base::Time::Now().LocalExplode(&now);
45
Tom Hughesd6c2d392020-08-24 18:12:11 -070046 return base::StringPrintf("debug-logs_%04i%02i%02i-%02i%02i%02i.%s", now.year,
47 now.month, now.day_of_month, now.hour, now.minute,
48 now.second, compress ? "tgz" : "tar");
Mike Frysingerf8ca5322017-02-07 15:54:20 -050049}
50
51} // namespace
52
53int main(int argc, char* argv[]) {
54 DEFINE_bool(compress, true, "Compress the tarball");
55 DEFINE_string(output, "", "Where to write the output");
Mike Wiitalaa1b44232019-07-31 13:57:31 -060056 // Because the logs can be huge, we default the timeout_ms flag to 2 minutes.
57 DEFINE_int32(timeout_ms, 120 * 1000,
58 "Time (in ms) to gather logs before timeout");
Mike Frysingerf8ca5322017-02-07 15:54:20 -050059 brillo::FlagHelper::Init(argc, argv, kUsage);
60
Brian Norris793510f2018-04-04 15:47:42 -070061 // Excess arguments may be left around.
62 auto args = base::CommandLine::ForCurrentProcess()->GetArgs();
63 if (!args.empty()) {
64 LOG(ERROR) << "Unexpected arguments (try rerunning with --help):";
65 for (const auto& arg : args)
66 LOG(ERROR) << arg;
67 return EXIT_FAILURE;
68 }
69
Mike Frysingerf8ca5322017-02-07 15:54:20 -050070 base::FilePath output(FLAGS_output);
71 if (output.empty())
72 output = base::FilePath{"/tmp/" + LogName(FLAGS_compress)};
73
74 base::ScopedFILE fp(base::OpenFile(output, "w"));
75 if (fp == nullptr) {
76 PLOG(ERROR) << "Could not write output: " << output.value();
77 return EXIT_FAILURE;
78 }
79
80 // Set up dbus proxy for talking to debugd.
81 dbus::Bus::Options options;
82 options.bus_type = dbus::Bus::SYSTEM;
83 scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
84 CHECK(bus->Connect());
85 dbus::ObjectProxy* debugd_proxy = bus->GetObjectProxy(
Tom Hughesd6c2d392020-08-24 18:12:11 -070086 debugd::kDebugdServiceName, dbus::ObjectPath(debugd::kDebugdServicePath));
Mike Frysingerf8ca5322017-02-07 15:54:20 -050087
88 // Send request for debug logs.
Tom Hughesd6c2d392020-08-24 18:12:11 -070089 dbus::MethodCall method_call(debugd::kDebugdInterface,
90 debugd::kDumpDebugLogs);
Mike Frysingerf8ca5322017-02-07 15:54:20 -050091 dbus::MessageWriter writer(&method_call);
Mike Frysingerf8ca5322017-02-07 15:54:20 -050092 writer.AppendBool(FLAGS_compress);
Eric Caruso0b241882018-04-04 13:43:46 -070093 writer.AppendFileDescriptor(fileno(fp.get()));
Mike Frysingerf8ca5322017-02-07 15:54:20 -050094
95 // Wait for the response and process the result.
96 LOG(INFO) << "Gathering logs, please wait";
97 std::unique_ptr<dbus::Response> response(
Mike Wiitalaa1b44232019-07-31 13:57:31 -060098 debugd_proxy->CallMethodAndBlock(&method_call, FLAGS_timeout_ms));
Mike Frysingerf8ca5322017-02-07 15:54:20 -050099 CHECK(response) << debugd::kDumpDebugLogs << " failed";
100 LOG(INFO) << "Logs saved to " << output.value();
101
102 return EXIT_SUCCESS;
103}