blob: b5be1ef56ed857c6401add7623ccc80a5912e82f [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 <fcntl.h>
#include <fuchsia/sysinfo/c/fidl.h>
#include <grpc++/grpc++.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/fdio.h>
#include <lib/zx/channel.h>
#include <lib/zx/time.h>
#include <zircon/status.h>
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include "dockyard_proxy.h"
#include "dockyard_proxy_grpc.h"
#include "dockyard_proxy_local.h"
#include "harvester.h"
#include "src/lib/fxl/command_line.h"
#include "src/lib/fxl/log_settings_command_line.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/strings/string_number_conversions.h"
namespace {
zx_status_t get_root_resource(zx_handle_t* root_resource) {
const char* sysinfo = "/dev/misc/sysinfo";
int fd = open(sysinfo, O_RDWR);
if (fd < 0) {
FXL_LOG(ERROR) << "Cannot open sysinfo: " << strerror(errno);
return ZX_ERR_NOT_FOUND;
}
zx::channel channel;
zx_status_t status =
fdio_get_service_handle(fd, channel.reset_and_get_address());
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Cannot obtain sysinfo channel: "
<< zx_status_get_string(status);
return status;
}
zx_status_t fidl_status = fuchsia_sysinfo_DeviceGetRootResource(
channel.get(), &status, root_resource);
if (fidl_status != ZX_OK) {
FXL_LOG(ERROR) << "Cannot obtain root resource: "
<< zx_status_get_string(fidl_status);
return fidl_status;
} else if (status != ZX_OK) {
FXL_LOG(ERROR) << "Cannot obtain root resource: "
<< zx_status_get_string(status);
return status;
}
return ZX_OK;
}
} // namespace
int main(int argc, char** argv) {
constexpr int EXIT_CODE_OK = 0;
// A broad 'something went wrong' error.
constexpr int EXIT_CODE_GENERAL_ERROR = 1;
// The wip number is incremented arbitrarily.
// TODO(smbug.com/44) replace wip number with real version number.
constexpr char VERSION_OUTPUT[] = "System Monitor Harvester - wip 11";
// Command line options.
constexpr char COMMAND_INSPECT[] = "inspect";
constexpr char COMMAND_UPDATE_PERIOD[] = "msec-update-period";
constexpr char COMMAND_LOCAL[] = "local";
constexpr char COMMAND_VERSION[] = "version";
bool use_grpc = true;
int cycle_msec_period = 100;
// Parse command line.
FXL_LOG(INFO) << VERSION_OUTPUT;
auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
if (!fxl::SetLogSettingsFromCommandLine(command_line)) {
exit(EXIT_CODE_GENERAL_ERROR);
}
if (command_line.HasOption(COMMAND_VERSION)) {
std::cout << VERSION_OUTPUT << std::endl;
exit(EXIT_CODE_OK);
}
if (command_line.HasOption(COMMAND_LOCAL)) {
FXL_LOG(INFO) << "Option: local only, not using transport to Dockyard.";
use_grpc = false;
}
if (command_line.HasOption(COMMAND_INSPECT)) {
FXL_LOG(INFO) << "Enabled component framework inspection (wip)";
// TODO(smbug.com/43): actually do component framework inspection.
}
if (command_line.HasOption(COMMAND_UPDATE_PERIOD)) {
std::string update_period;
command_line.GetOptionValue(COMMAND_UPDATE_PERIOD, &update_period);
if (!fxl::StringToNumberWithError(update_period, &cycle_msec_period)) {
std::cerr << "Error: Unable to parse `--" << COMMAND_UPDATE_PERIOD
<< "` value of \"" << update_period << "\"" << std::endl;
exit(EXIT_CODE_GENERAL_ERROR);
}
}
FXL_LOG(INFO) << "Gathering data every " << cycle_msec_period << " msec.";
// Set up.
std::unique_ptr<harvester::DockyardProxy> dockyard_proxy;
if (use_grpc) {
const auto& positional_args = command_line.positional_args();
if (positional_args.size() < 1) {
// TODO(smbug.com/30): Adhere to CLI tool requirements for --help.
std::cerr << "Please specify an IP:Port, such as localhost:50051"
<< std::endl;
exit(EXIT_CODE_GENERAL_ERROR);
}
// TODO(smbug.com/32): This channel isn't authenticated
// (InsecureChannelCredentials()).
dockyard_proxy =
std::make_unique<harvester::DockyardProxyGrpc>(grpc::CreateChannel(
positional_args[0], grpc::InsecureChannelCredentials()));
if (!dockyard_proxy ||
dockyard_proxy->Init() != harvester::DockyardProxyStatus::OK) {
exit(EXIT_CODE_GENERAL_ERROR);
}
} else {
dockyard_proxy = std::make_unique<harvester::DockyardProxyLocal>();
}
zx_handle_t root_resource;
zx_status_t ret = get_root_resource(&root_resource);
if (ret != ZX_OK) {
exit(EXIT_CODE_GENERAL_ERROR);
}
async::Loop loop(&kAsyncLoopConfigAttachToThread);
harvester::Harvester harvester(zx::msec(cycle_msec_period), root_resource,
loop.dispatcher(), std::move(dockyard_proxy));
harvester.GatherData();
loop.Run();
FXL_LOG(INFO) << "System Monitor Harvester - exiting";
return 0;
}