blob: eec6b94aab28ad12f768e0965a7556a55a074487 [file] [log] [blame]
// Copyright 2020 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/local_aggregation_1_1/backfill_manager.h"
#include <algorithm>
#include <chrono>
#include "src/lib/util/datetime_util.h"
#include "src/local_aggregation_1_1/local_aggregation.pb.h"
#include "src/public/lib/statusor/status_macros.h"
#include "src/public/lib/statusor/statusor.h"
#include "src/registry/metric_definition.pb.h"
namespace cobalt::local_aggregation {
using TimeInfo = util::TimeInfo;
using time_point = std::chrono::system_clock::time_point;
BackfillManager::BackfillManager(uint32_t total_backfill_window)
: backstop_days_(total_backfill_window) {}
lib::statusor::StatusOr<std::vector<TimeInfo>> BackfillManager::CalculateBackfill(
TimeInfo last_time_info, time_point end_time,
const util::CivilTimeConverterInterface& civil_time_converter, const MetricDefinition& metric,
bool is_daily) const {
// Calculate the end day index and hour ID with respect to the time zone specified in `metric`.
CB_ASSIGN_OR_RETURN(TimeInfo end_info,
TimeInfo::FromTimePoint(end_time, civil_time_converter, metric));
// Calculate the backstop day index with respect to the current UTC time. It is not useful to send
// observations for earlier day indices, since the shuffler's lookback period is calculated with
// respect to UTC. Observations with smaller day indices will be dropped.
uint32_t backstop_day_index = util::TimePointToDayIndexUtc(end_time) - backstop_days_;
std::vector<TimeInfo> backfill;
// If calculating backfill for a daily report, select every day index since the last one (or the
// backstop day index, whichever is larger), up to the day index of `end_time` in `metric`'s time
// zone.
//
// If calculating for an hourly report, we need to be more careful, since not all hour IDs are
// valid for a given time zone. For each hour within the backfill period, we need to compute the
// hour ID with respect to `metric`'s time zone as of the beginning of that hour. This accounts
// for the possibility that the UTC offset or DST status may change within the backfill period.
if (is_daily) {
uint32_t start_day_index = std::max(last_time_info.day_index + 1, backstop_day_index);
for (uint32_t i = start_day_index; i < end_info.day_index; ++i) {
backfill.push_back(TimeInfo::FromDayIndex(i));
}
} else {
time_point time = end_time - util::kOneHour;
while (time >= time_point::min()) {
CB_ASSIGN_OR_RETURN(TimeInfo time_info,
TimeInfo::FromTimePoint(time, civil_time_converter, metric));
if (time_info.hour_id <= last_time_info.hour_id || time_info.day_index < backstop_day_index) {
break;
}
backfill.push_back(time_info);
time -= util::kOneHour;
}
std::reverse(backfill.begin(), backfill.end());
}
return backfill;
}
} // namespace cobalt::local_aggregation