| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // The bootstat command provides options to persist boot events with the current |
| // timestamp, dump the persisted events, and log all events to EventLog to be |
| // uploaded to Android log storage via Tron. |
| |
| //#define LOG_TAG "bootstat" |
| |
| #include <unistd.h> |
| #include <cstddef> |
| #include <cstdio> |
| #include <memory> |
| #include <string> |
| #include <android-base/logging.h> |
| #include <log/log.h> |
| #include "boot_event_record_store.h" |
| #include "event_log_list_builder.h" |
| |
| namespace { |
| |
| // Builds an EventLog buffer named |event| containing |data| and writes |
| // the log into the Tron histogram logs. |
| void LogBootEvent(const std::string& event, int32_t data) { |
| LOG(INFO) << "Logging boot time: " << event << " " << data; |
| |
| EventLogListBuilder log_builder; |
| log_builder.Append(event); |
| log_builder.Append(data); |
| |
| std::unique_ptr<uint8_t[]> log; |
| size_t size; |
| log_builder.Release(&log, &size); |
| |
| android_bWriteLog(HISTOGRAM_LOG_TAG, log.get(), size); |
| } |
| |
| // Scans the boot event record store for record files and logs each boot event |
| // via EventLog. |
| void LogBootEvents() { |
| BootEventRecordStore boot_event_store; |
| |
| auto events = boot_event_store.GetAllBootEvents(); |
| for (auto i = events.cbegin(); i != events.cend(); ++i) { |
| LogBootEvent(i->first, i->second); |
| } |
| } |
| |
| void PrintBootEvents() { |
| printf("Boot events:\n"); |
| printf("------------\n"); |
| |
| BootEventRecordStore boot_event_store; |
| auto events = boot_event_store.GetAllBootEvents(); |
| for (auto i = events.cbegin(); i != events.cend(); ++i) { |
| printf("%s\t%d\n", i->first.c_str(), i->second); |
| } |
| } |
| |
| void ShowHelp(const char *cmd) { |
| fprintf(stderr, "Usage: %s [options]\n", cmd); |
| fprintf(stderr, |
| "options include:\n" |
| " -d Dump the boot event records to the console.\n" |
| " -h Show this help.\n" |
| " -l Log all metrics to logstorage.\n" |
| " -r Record the timestamp of a named boot event.\n"); |
| } |
| |
| // Constructs a readable, printable string from the givencommand line |
| // arguments. |
| std::string GetCommandLine(int argc, char **argv) { |
| std::string cmd; |
| for (int i = 0; i < argc; ++i) { |
| cmd += argv[i]; |
| cmd += " "; |
| } |
| |
| return cmd; |
| } |
| |
| } // namespace |
| |
| int main(int argc, char **argv) { |
| android::base::InitLogging(argv); |
| |
| const std::string cmd_line = GetCommandLine(argc, argv); |
| LOG(INFO) << "Service started: " << cmd_line; |
| |
| int opt = 0; |
| while ((opt = getopt(argc, argv, "hlpr:")) != -1) { |
| switch (opt) { |
| case 'h': { |
| ShowHelp(argv[0]); |
| break; |
| } |
| |
| case 'l': { |
| LogBootEvents(); |
| break; |
| } |
| |
| case 'p': { |
| PrintBootEvents(); |
| break; |
| } |
| |
| case 'r': { |
| // |optarg| is an external variable set by getopt representing |
| // the option argument. |
| const char* event = optarg; |
| |
| BootEventRecordStore boot_event_store; |
| boot_event_store.AddBootEvent(event); |
| break; |
| } |
| |
| default: { |
| DCHECK_EQ(opt, '?'); |
| |
| // |optopt| is an external variable set by getopt representing |
| // the value of the invalid option. |
| LOG(ERROR) << "Invalid option: " << optopt; |
| ShowHelp(argv[0]); |
| return EXIT_FAILURE; |
| } |
| } |
| } |
| |
| return 0; |
| } |