blob: d9fcd3b64c3e4029ecf5d8c528a1ec8f88b5bfa4 [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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/fdio.h>
#include <lib/syslog/global.h>
#include <zircon/status.h>
#include <string>
#include "dockyard_proxy.h"
#include "dockyard_proxy_grpc.h"
#include "dockyard_proxy_local.h"
#include "harvester.h"
#include "root_resource.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"
#include "src/lib/syslog/cpp/logger.h"
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(fxb/44) replace wip number with real version number.
constexpr char VERSION_OUTPUT[] =
"System Monitor Harvester 20191211\n"
"- memory_digest\n"
"+ separate cpu and memory gather\n";
// Command line options.
constexpr char COMMAND_LOCAL[] = "local";
constexpr char COMMAND_VERSION[] = "version";
bool use_grpc = true;
// Parse command line.
auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
fxl::SetLogSettingsFromCommandLine(command_line, {"harvester"});
FX_LOGS(INFO) << VERSION_OUTPUT;
if (command_line.HasOption(COMMAND_VERSION)) {
std::cout << VERSION_OUTPUT << std::endl;
exit(EXIT_CODE_OK);
}
if (command_line.HasOption(COMMAND_LOCAL)) {
FX_LOGS(INFO) << "Option: local only, not using transport to Dockyard.";
use_grpc = false;
}
// Set up.
std::unique_ptr<harvester::DockyardProxy> dockyard_proxy;
if (use_grpc) {
const auto& positional_args = command_line.positional_args();
if (positional_args.empty()) {
// TODO(fxb/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(fxb/32): This channel isn't authenticated
// (InsecureChannelCredentials()).
dockyard_proxy =
std::make_unique<harvester::DockyardProxyGrpc>(grpc::CreateChannel(
positional_args[0], grpc::InsecureChannelCredentials()));
if (!dockyard_proxy) {
FX_LOGS(ERROR) << "unable to create dockyard_proxy";
exit(EXIT_CODE_GENERAL_ERROR);
}
harvester::DockyardProxyStatus status = dockyard_proxy->Init();
if (status != harvester::DockyardProxyStatus::OK) {
FX_LOGS(ERROR) << harvester::DockyardErrorString("Init", status);
exit(EXIT_CODE_GENERAL_ERROR);
}
} else {
dockyard_proxy = std::make_unique<harvester::DockyardProxyLocal>();
}
zx_handle_t root_resource;
zx_status_t ret = harvester::GetRootResource(&root_resource);
if (ret != ZX_OK) {
exit(EXIT_CODE_GENERAL_ERROR);
}
// Note: Neither of the following loops are "fast" or "slow" on their own.
// It's just a matter of what we choose to run on them.
// Create a separate loop for quick calls (don't run long running functions on
// this loop).
// The "slow" loop is used for potentially long running calls.
async::Loop slow_calls_loop(&kAsyncLoopConfigAttachToCurrentThread);
async::Loop fast_calls_loop(&kAsyncLoopConfigNoAttachToCurrentThread);
// The loop that runs quick calls is in a separate thread.
zx_status_t status = fast_calls_loop.StartThread("fast-calls-thread");
if (status != ZX_OK) {
FX_LOGS(ERROR) << "fast_calls_loop.StartThread failed " << status;
exit(EXIT_CODE_GENERAL_ERROR);
}
FX_LOGS(INFO) << "main thread " << pthread_self();
harvester::Harvester harvester(root_resource, std::move(dockyard_proxy));
harvester.GatherDeviceProperties();
harvester.GatherFastData(fast_calls_loop.dispatcher());
harvester.GatherSlowData(slow_calls_loop.dispatcher());
// The slow_calls_thread that runs heavier calls takes over this thread.
slow_calls_loop.Run();
fast_calls_loop.Quit();
FX_LOGS(INFO) << "System Monitor Harvester - exiting";
return 0;
}