blob: 208a6418849ba7780a693642378796fa0817b791 [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 "src/developer/forensics/feedback_data/annotations/channel_provider.h"
#include "src/developer/forensics/feedback_data/annotations/types.h"
#include "src/developer/forensics/feedback_data/annotations/utils.h"
#include "src/developer/forensics/feedback_data/constants.h"
#include "src/developer/forensics/utils/errors.h"
#include "src/developer/forensics/utils/fidl/channel_provider_ptr.h"
namespace forensics {
namespace feedback_data {
namespace {
const AnnotationKeys kSupportedAnnotations = {
kAnnotationSystemUpdateChannelCurrent,
kAnnotationSystemUpdateChannelTarget,
};
using AnnotationPair = std::pair<std::string, AnnotationOr>;
AnnotationPair MakeAnnotationPair(const std::string& key,
const ::fpromise::result<std::string, Error>& result) {
AnnotationOr annotation =
(result.is_ok()) ? AnnotationOr(result.value()) : AnnotationOr(result.error());
return std::make_pair(key, std::move(annotation));
}
} // namespace
ChannelProvider::ChannelProvider(async_dispatcher_t* dispatcher,
std::shared_ptr<sys::ServiceDirectory> services,
cobalt::Logger* cobalt)
: dispatcher_(dispatcher), services_(services), cobalt_(cobalt) {}
::fpromise::promise<Annotations> ChannelProvider::GetAnnotations(zx::duration timeout,
const AnnotationKeys& allowlist) {
const AnnotationKeys annotations_to_get = RestrictAllowlist(allowlist, kSupportedAnnotations);
std::vector<::fpromise::promise<AnnotationPair>> annotation_promises;
if (annotations_to_get.find(kAnnotationSystemUpdateChannelCurrent) != annotations_to_get.end()) {
annotation_promises.push_back(
fidl::GetCurrentChannel(dispatcher_, services_, fit::Timeout(timeout))
.then([](const ::fpromise::result<std::string, Error>& result) {
return ::fpromise::ok(
MakeAnnotationPair(kAnnotationSystemUpdateChannelCurrent, result));
}));
}
if (annotations_to_get.find(kAnnotationSystemUpdateChannelTarget) != annotations_to_get.end()) {
annotation_promises.push_back(
fidl::GetTargetChannel(dispatcher_, services_, fit::Timeout(timeout))
.then([](const ::fpromise::result<std::string, Error>& result) {
return ::fpromise::ok(
MakeAnnotationPair(kAnnotationSystemUpdateChannelTarget, result));
}));
}
return ::fpromise::join_promise_vector(std::move(annotation_promises))
.and_then([cobalt = cobalt_](std::vector<::fpromise::result<AnnotationPair>>& results)
-> ::fpromise::result<Annotations> {
Annotations annotations;
for (auto& result : results) {
annotations.insert(std::move(result).value());
}
bool found_timeout{false};
for (const auto& [_, v] : annotations) {
found_timeout |= (!v.HasValue() && v.Error() == Error::kTimeout);
}
if (found_timeout) {
cobalt->LogOccurrence(cobalt::TimedOutData::kChannel);
}
return ::fpromise::ok(std::move(annotations));
});
}
} // namespace feedback_data
} // namespace forensics