blob: 203df996a4c91e5b18f2d3c27c3a07f4d8baf019 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <iostream>
#include <map>
#include <set>
#include "garnet/bin/trace2json/convert.h"
#include "src/lib/fxl/command_line.h"
#include "src/lib/fxl/log_settings_command_line.h"
namespace {
const char kHelp[] = "help";
const char kInputFile[] = "input-file";
const char kOutputFile[] = "output-file";
const char kCompressedInput[] = "compressed-input";
const char kCompressedOutput[] = "compressed-output";
std::set<std::string> kKnownOptions = {
kHelp, kInputFile, kOutputFile, kCompressedInput, kCompressedOutput,
};
bool ParseBooleanOption(const fxl::CommandLine& command_line, const char* arg_name,
bool* out_value) {
if (command_line.HasOption(fxl::StringView(arg_name))) {
std::string arg_value;
command_line.GetOptionValue(fxl::StringView(arg_name), &arg_value);
if (arg_value == "" || arg_value == "true") {
*out_value = true;
} else if (arg_value == "false") {
*out_value = false;
} else {
FX_LOGS(ERROR) << "Bad value for --" << arg_name << ", pass true or false";
return false;
}
}
return true;
}
void PrintHelpMessage() {
std::map<std::string, std::string> options = {
{"help", "Print this help message."},
{"input-file=[]",
"Read trace from the specified file. If no file is specified, the input "
"is read from stdin."},
{"output-file=[]",
"Write the converted trace to the specified file. If no file is "
"specified, the output is written to stdout."},
{"compressed-input=[false]", "If true, the input is first gzip-decompressed."},
{"compressed-output=[false]",
"If true, the output is gzip-compressed. Writing compressed output to "
"stdout is not supported, so output-file must be specified."},
};
std::cerr
<< "trace2json [options]: Convert a trace from fxt (Fuchsia trace format) to json (Chrome "
"trace format)."
<< std::endl
<< "Fuchsia trace format: "
"https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/docs/development/tracing/"
"trace-format/"
<< std::endl
<< "Chrome trace format: "
"https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit"
<< std::endl;
for (const auto& option : options) {
std::cerr << " --" << option.first << ": " << option.second << std::endl;
}
}
} // namespace
int main(int argc, char** argv) {
auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
if (!fxl::SetLogSettingsFromCommandLine(command_line)) {
return 1;
}
if (command_line.HasOption(kHelp)) {
PrintHelpMessage();
return 0;
}
bool invalid_options = false;
for (const auto& option : command_line.options()) {
if (kKnownOptions.count(option.name) == 0) {
FX_LOGS(ERROR) << "Unknown option: " << option.name;
invalid_options = true;
}
}
if (command_line.positional_args().size() > 0) {
FX_LOGS(ERROR) << "Unexpected positional arg";
invalid_options = true;
}
if (invalid_options) {
PrintHelpMessage();
return 1;
}
ConvertSettings settings;
if (command_line.HasOption(kInputFile)) {
command_line.GetOptionValue(kInputFile, &settings.input_file_name);
}
if (command_line.HasOption(kOutputFile)) {
command_line.GetOptionValue(kOutputFile, &settings.output_file_name);
}
if (!ParseBooleanOption(command_line, kCompressedInput, &settings.compressed_input)) {
PrintHelpMessage();
return 1;
}
if (!ParseBooleanOption(command_line, kCompressedOutput, &settings.compressed_output)) {
PrintHelpMessage();
return 1;
}
if (!ConvertTrace(settings)) {
return 1;
}
return 0;
}