blob: f8fb8f90699480b000fe90806b344f23214ba18c [file] [log] [blame]
// Copyright 2018 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.
#ifndef COBALT_SRC_LIB_CLEARCUT_UPLOADER_H_
#define COBALT_SRC_LIB_CLEARCUT_UPLOADER_H_
#include <chrono>
#include <memory>
#include <vector>
#include "src/lib/clearcut/clearcut.pb.h"
#include "src/lib/util/clock.h"
#include "src/lib/util/sleeper.h"
#include "src/logger/internal_metrics.h"
#include "src/public/lib/http_client.h"
#include "src/public/lib/status.h"
#include "src/public/lib/statusor/statusor.h"
#include "third_party/abseil-cpp/absl/strings/escaping.h"
namespace cobalt::lib::clearcut {
static const int32_t kFuchsiaClientType = 17;
static const int32_t kMaxRetries = 8; // Wait between tries: 0.25s 0.5.s 1s 2s 4s 8s 16s
static const int64_t kInitialBackoffMillis = 250;
// An interface used by cobalt::uploader::ShippingManager for uploading data to clearcut.
class ClearcutUploaderInterface {
public:
virtual ~ClearcutUploaderInterface() = default;
// Uploads the |log_request| with retries.
virtual Status UploadEvents(LogRequest *log_request, int32_t max_retries) = 0;
// Uploads the |log_request| with kMaxRetries retries.
Status UploadEvents(LogRequest *log_request) { return UploadEvents(log_request, kMaxRetries); }
// Resets the internal metrics to use the provided logger.
void ResetInternalMetrics(logger::InternalMetrics *internal_metrics = nullptr) {
internal_metrics_.reset(internal_metrics);
}
[[nodiscard]] const logger::InternalMetrics *internal_metrics() const {
return internal_metrics_.get();
}
protected:
// NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
logger::InternalMetricsPtr internal_metrics_;
};
// A ClearcutUploader sends events to clearcut using the given HTTPClient.
//
// Note: This class is not threadsafe.
class ClearcutUploader : public ClearcutUploaderInterface {
public:
// url: The URL of the Clearcut server to which POST requests should be sent.
//
// client: An implementation of HTTPClient to use.
//
// upload_timeout_millis: If a positive value is specified then this number of milliseconds
// will be used as the HTTP request timeout. Otherwise no timeout will be used.
//
// initial_backoff_millis: The initial value to use for exponential backoff, in milliseconds.
// This is used when the ClearcutUploader retries on failures. Optionally override the default.
// Mostly useful for tests.
//
// steady_clock: Optionally replace the system steady clock. Mostly useful for tests.
//
// sleeper: Optionally replace the system sleep. Mostly useful for tests.
ClearcutUploader(std::string url, std::unique_ptr<HTTPClient> client,
int64_t upload_timeout_millis = 0,
int64_t initial_backoff_millis = kInitialBackoffMillis,
std::unique_ptr<cobalt::util::SteadyClockInterface> steady_clock =
std::make_unique<cobalt::util::SteadyClock>(),
std::unique_ptr<cobalt::util::SleeperInterface> sleeper =
std::make_unique<cobalt::util::Sleeper>());
Status UploadEvents(LogRequest *log_request, int32_t max_retries) override;
private:
// Tries once to upload |log_request|.
Status TryUploadEvents(LogRequest *log_request, std::chrono::steady_clock::time_point deadline);
const std::string url_;
const std::unique_ptr<HTTPClient> client_;
const std::chrono::milliseconds upload_timeout_;
const std::chrono::milliseconds initial_backoff_;
const std::unique_ptr<cobalt::util::SteadyClockInterface> steady_clock_;
const std::unique_ptr<cobalt::util::SleeperInterface> sleeper_;
friend class UploaderTest;
// When we get a next_request_wait_millis from the clearcut server, we set
// this value to now() + next_request_wait_millis.
std::chrono::steady_clock::time_point pause_uploads_until_;
};
} // namespace cobalt::lib::clearcut
#endif // COBALT_SRC_LIB_CLEARCUT_UPLOADER_H_