blob: f4b62b70962e4703d7c51d1840c9ed767e615f4d [file] [log] [blame]
// Copyright 2022 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 "src/lib/metrics_buffer/metrics_impl.h"
#include <fidl/fuchsia.metrics/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/fidl/cpp/wire/channel.h>
#include "src/lib/metrics_buffer/log.h"
namespace cobalt {
using fuchsia_metrics::MetricEventLogger;
using fuchsia_metrics::MetricEventLoggerFactory;
using MetricsResult = ::fit::result<fidl::internal::ErrorsInImpl<fuchsia_metrics::Error>>;
MetricsImpl::MetricsImpl(async_dispatcher_t* dispatcher,
fidl::ClientEnd<fuchsia_io::Directory> directory, uint32_t project_id)
: project_id_(project_id), dispatcher_(dispatcher), directory_(std::move(directory)) {}
void MetricsImpl::LogMetricEvents(std::vector<fuchsia_metrics::MetricEvent> events) {
// failure to post intentionally drops events
(void)async::PostTask(dispatcher_, [this, events = std::move(events)] {
if (!EnsureConnected()) {
// drop events
return;
}
(*logger_)->LogMetricEvents({events}).Then([](MetricsResult result) {
if (result.is_error() && result.error_value().is_framework_error()) {
LOG(INFO, "LogMetricEvents failed (async): %s",
result.error_value().FormatDescription().c_str());
// A later call to LogMetricEvents will notice that the logger_ server end closed.
}
// drop events
});
});
}
// "Ensure" but only to the extent we can ensure without forcing a round-trip. If this returns true,
// the logger_.has_value() and is_valid(), at least until the caller returns back to the dispatcher.
bool MetricsImpl::EnsureConnected() {
if (logger_.has_value() && logger_->is_valid()) {
return true;
}
Connect();
return logger_.has_value() && logger_->is_valid();
}
void MetricsImpl::Connect() {
logger_factory_.reset();
logger_.reset();
auto logger_factory_result =
component::ConnectAt<fuchsia_metrics::MetricEventLoggerFactory>(directory_);
if (!logger_factory_result.is_ok()) {
LOG(INFO, "!logger_factory_result.is_ok() - %s", logger_factory_result.status_string());
return;
}
auto logger_factory = fidl::Client(std::move(logger_factory_result.value()), dispatcher_);
auto logger_endpoints = fidl::CreateEndpoints<fuchsia_metrics::MetricEventLogger>();
if (!logger_endpoints.is_ok()) {
LOG(INFO, "!logger_endpoints.is_ok() - %s", logger_endpoints.status_string());
return;
}
fuchsia_metrics::MetricEventLoggerFactoryCreateMetricEventLoggerRequest request;
fuchsia_metrics::ProjectSpec project_spec;
project_spec.project_id() = project_id_;
request.project_spec() = std::move(project_spec);
request.logger() = std::move(logger_endpoints->server);
logger_factory->CreateMetricEventLogger(std::move(request)).Then([](MetricsResult result) {
if (result.is_error()) {
LOG(INFO, "CreateMetricEventLogger failed (async): %s",
result.error_value().FormatDescription().c_str());
// A later call to LogMetricEvents will notice that the logger_ server end closed.
}
});
logger_factory_ = std::move(logger_factory);
logger_ = fidl::Client(std::move(logger_endpoints->client), dispatcher_);
}
} // namespace cobalt