blob: 6c43f833b9cd1aba65c38e99da8c5d6f0920edcc [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
Brian Norris793510f2018-04-04 15:47:42 -070014#include <base/command_line.h>
Mike Frysingerf8ca5322017-02-07 15:54:20 -050015#include <base/files/file_path.h>
16#include <base/files/file_util.h>
17#include <base/files/scoped_file.h>
18#include <base/logging.h>
19#include <base/strings/stringprintf.h>
20#include <base/time/time.h>
21#include <brillo/flag_helper.h>
22#include <chromeos/dbus/service_constants.h>
23#include <dbus/bus.h>
Mike Frysingerf8ca5322017-02-07 15:54:20 -050024#include <dbus/message.h>
25#include <dbus/object_proxy.h>
26
27namespace {
28
29// Because the logs can be huge, we set the D-Bus timeout to 2 minutes.
30const int kDBusTimeoutMS = 120 * 1000;
31
32const char kUsage[] =
33 "Developer helper tool for getting extended debug logs from the system."
34 "\n"
35 "\n"
Brian Norrisca4fc042018-04-03 00:24:26 -070036 "This calls back into debugd using the DumpDebugLogs dbus end point."
37 "\n"
38 "\n"
39 "WARNING: The exact contents of the generated output may vary depending on"
40 "\n"
41 "developers' whims.";
Mike Frysingerf8ca5322017-02-07 15:54:20 -050042
43// Returns a dynamic file name with datestamps in it.
44std::string LogName(bool compress) {
45 base::Time::Exploded now;
46 base::Time::Now().LocalExplode(&now);
47
48 return base::StringPrintf(
49 "debug-logs_%04i%02i%02i-%02i%02i%02i.%s",
50 now.year, now.month, now.day_of_month, now.hour, now.minute, now.second,
51 compress ? "tgz" : "tar");
52}
53
54} // namespace
55
56int main(int argc, char* argv[]) {
57 DEFINE_bool(compress, true, "Compress the tarball");
58 DEFINE_string(output, "", "Where to write the output");
59 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(
86 debugd::kDebugdServiceName,
87 dbus::ObjectPath(debugd::kDebugdServicePath));
88
89 // Send request for debug logs.
90 dbus::MethodCall method_call(
91 debugd::kDebugdInterface,
92 debugd::kDumpDebugLogs);
93 dbus::MessageWriter writer(&method_call);
Mike Frysingerf8ca5322017-02-07 15:54:20 -050094 writer.AppendBool(FLAGS_compress);
Eric Caruso0b241882018-04-04 13:43:46 -070095 writer.AppendFileDescriptor(fileno(fp.get()));
Mike Frysingerf8ca5322017-02-07 15:54:20 -050096
97 // Wait for the response and process the result.
98 LOG(INFO) << "Gathering logs, please wait";
99 std::unique_ptr<dbus::Response> response(
100 debugd_proxy->CallMethodAndBlock(
101 &method_call, kDBusTimeoutMS));
102 CHECK(response) << debugd::kDumpDebugLogs << " failed";
103 LOG(INFO) << "Logs saved to " << output.value();
104
105 return EXIT_SUCCESS;
106}