blob: 5122aa674857ce11e88a68daf1a3ef0d2e5a4f7b [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 SRC_LIB_COBALT_CPP_COBALT_LOGGER_IMPL_H_
#define SRC_LIB_COBALT_CPP_COBALT_LOGGER_IMPL_H_
#include <fuchsia/cobalt/cpp/fidl.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/fit/function.h>
#include <lib/zx/time.h>
#include <set>
#include "src/lib/backoff/exponential_backoff.h"
#include "src/lib/cobalt/cpp/cobalt_logger.h"
#include "src/lib/fxl/logging.h"
namespace cobalt {
class BaseEvent {
public:
BaseEvent() {}
virtual ~BaseEvent() = default;
virtual void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) = 0;
virtual uint32_t metric_id() const { return 0; }
};
class Event : public BaseEvent {
public:
Event(uint32_t metric_id) : BaseEvent(), metric_id_(metric_id) {}
virtual ~Event() = default;
uint32_t metric_id() const override { return metric_id_; }
private:
const uint32_t metric_id_;
};
class OccurrenceEvent : public Event {
public:
OccurrenceEvent(uint32_t metric_id, uint32_t event_code)
: Event(metric_id), event_code_(event_code) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
(*logger)->LogEvent(metric_id(), event_code_, std::move(callback));
}
uint32_t event_code() const { return event_code_; }
private:
const uint32_t event_code_;
};
class CountEvent : public Event {
public:
CountEvent(uint32_t metric_id, uint32_t event_code, const std::string& component,
int64_t period_duration_micros, int64_t count)
: Event(metric_id),
event_code_(event_code),
component_(component),
period_duration_micros_(period_duration_micros),
count_(count) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
(*logger)->LogEventCount(metric_id(), event_code_, component_, period_duration_micros_, count_,
std::move(callback));
}
uint32_t event_code() const { return event_code_; }
const std::string& component() const { return component_; }
int64_t period_duration_micros() const { return period_duration_micros_; }
int64_t count() const { return count_; }
private:
const uint32_t event_code_;
const std::string component_;
const int64_t period_duration_micros_;
const int64_t count_;
};
class ElapsedTimeEvent : public Event {
public:
ElapsedTimeEvent(uint32_t metric_id, uint32_t event_code, const std::string& component,
int64_t elapsed_micros)
: Event(metric_id),
event_code_(event_code),
component_(component),
elapsed_micros_(elapsed_micros) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
(*logger)->LogElapsedTime(metric_id(), event_code_, component_, elapsed_micros_,
std::move(callback));
}
uint32_t event_code() const { return event_code_; }
const std::string& component() const { return component_; }
int64_t elapsed_micros() const { return elapsed_micros_; }
private:
const uint32_t event_code_;
const std::string component_;
const int64_t elapsed_micros_;
};
class FrameRateEvent : public Event {
public:
FrameRateEvent(uint32_t metric_id, uint32_t event_code, const std::string& component, float fps)
: Event(metric_id), event_code_(event_code), component_(component), fps_(fps) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
(*logger)->LogFrameRate(metric_id(), event_code_, component_, fps_, std::move(callback));
}
uint32_t event_code() const { return event_code_; }
const std::string& component() const { return component_; }
float fps() const { return fps_; }
private:
const uint32_t event_code_;
const std::string component_;
const float fps_;
};
class MemoryUsageEvent : public Event {
public:
MemoryUsageEvent(uint32_t metric_id, uint32_t event_code, const std::string& component,
int64_t bytes)
: Event(metric_id), event_code_(event_code), component_(component), bytes_(bytes) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
(*logger)->LogMemoryUsage(metric_id(), event_code_, component_, bytes_, std::move(callback));
}
uint32_t event_code() const { return event_code_; }
const std::string& component() const { return component_; }
int64_t bytes() const { return bytes_; }
private:
const uint32_t event_code_;
const std::string component_;
const int64_t bytes_;
};
class StartTimerEvent : public Event {
public:
StartTimerEvent(uint32_t metric_id, uint32_t event_code, const std::string& component,
const std::string& timer_id, uint64_t timestamp, uint32_t timeout_s)
: Event(metric_id),
event_code_(event_code),
component_(component),
timer_id_(timer_id),
timestamp_(timestamp),
timeout_s_(timeout_s) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
(*logger)->StartTimer(metric_id(), event_code_, component_, timer_id_, timestamp_, timeout_s_,
std::move(callback));
}
uint32_t event_code() const { return event_code_; }
const std::string& component() const { return component_; }
const std::string& timer_id() const { return timer_id_; }
uint64_t timestamp() const { return timestamp_; }
uint32_t timeout_s() const { return timeout_s_; }
private:
const uint32_t event_code_;
const std::string component_;
const std::string timer_id_;
const uint64_t timestamp_;
const uint32_t timeout_s_;
};
class EndTimerEvent : public BaseEvent {
public:
EndTimerEvent(const std::string& timer_id, uint64_t timestamp, uint32_t timeout_s)
: BaseEvent(), timer_id_(timer_id), timestamp_(timestamp), timeout_s_(timeout_s) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
(*logger)->EndTimer(timer_id_, timestamp_, timeout_s_, std::move(callback));
}
const std::string& timer_id() const { return timer_id_; }
uint64_t timestamp() const { return timestamp_; }
uint32_t timeout_s() const { return timeout_s_; }
private:
const std::string timer_id_;
const uint64_t timestamp_;
const uint32_t timeout_s_;
};
class IntHistogramEvent : public Event {
public:
IntHistogramEvent(uint32_t metric_id, uint32_t event_code, const std::string& component,
std::vector<fuchsia::cobalt::HistogramBucket> histogram)
: Event(metric_id),
event_code_(event_code),
component_(component),
histogram_(std::move(histogram)) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
std::vector<fuchsia::cobalt::HistogramBucket> histogram;
FX_CHECK(fidl::Clone(histogram_, &histogram) == ZX_OK);
(*logger)->LogIntHistogram(metric_id(), event_code_, component_, std::move(histogram),
std::move(callback));
}
uint32_t event_code() const { return event_code_; }
const std::string& component() const { return component_; }
const std::vector<fuchsia::cobalt::HistogramBucket>& histogram() const { return histogram_; }
private:
const uint32_t event_code_;
const std::string component_;
const std::vector<fuchsia::cobalt::HistogramBucket> histogram_;
};
class CustomEvent : public Event {
public:
CustomEvent(uint32_t metric_id, std::vector<fuchsia::cobalt::CustomEventValue> event_values)
: Event(metric_id), event_values_(std::move(event_values)) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
std::vector<fuchsia::cobalt::CustomEventValue> event_values;
FX_CHECK(fidl::Clone(event_values_, &event_values) == ZX_OK);
(*logger)->LogCustomEvent(metric_id(), std::move(event_values), std::move(callback));
}
const std::vector<fuchsia::cobalt::CustomEventValue>& event_values() const {
return event_values_;
}
private:
const std::vector<fuchsia::cobalt::CustomEventValue> event_values_;
};
class CobaltEvent : public Event {
public:
CobaltEvent(fuchsia::cobalt::CobaltEvent event)
: Event(event.metric_id), event_(std::move(event)) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
fuchsia::cobalt::CobaltEvent event;
FX_CHECK(fidl::Clone(event_, &event) == ZX_OK);
(*logger)->LogCobaltEvent(std::move(event), std::move(callback));
}
private:
const fuchsia::cobalt::CobaltEvent event_;
};
class CobaltEvents : public BaseEvent {
public:
CobaltEvents(std::vector<fuchsia::cobalt::CobaltEvent> events)
: BaseEvent(), events_(std::move(events)) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
std::vector<fuchsia::cobalt::CobaltEvent> events;
FX_CHECK(fidl::Clone(events_, &events) == ZX_OK);
(*logger)->LogCobaltEvents(std::move(events), std::move(callback));
}
private:
const std::vector<fuchsia::cobalt::CobaltEvent> events_;
};
class BaseCobaltLoggerImpl : public CobaltLogger {
public:
BaseCobaltLoggerImpl(async_dispatcher_t* dispatcher, uint32_t project_id);
~BaseCobaltLoggerImpl() override;
void LogEvent(uint32_t metric_id, uint32_t event_code) override;
void LogEventCount(uint32_t metric_id, uint32_t event_code, const std::string& component,
zx::duration period_duration, int64_t count) override;
void LogElapsedTime(uint32_t metric_id, uint32_t event_code, const std::string& component,
zx::duration elapsed_time) override;
void LogFrameRate(uint32_t metric_id, uint32_t event_code, const std::string& component,
float fps) override;
void LogMemoryUsage(uint32_t metric_id, uint32_t event_code, const std::string& component,
int64_t bytes) override;
void StartTimer(uint32_t metric_id, uint32_t event_code, const std::string& component,
const std::string& timer_id, zx::time timestamp, zx::duration timeout) override;
void EndTimer(const std::string& timer_id, zx::time timestamp, zx::duration timeout) override;
void LogIntHistogram(uint32_t metric_id, uint32_t event_code, const std::string& component,
std::vector<fuchsia::cobalt::HistogramBucket> histogram) override;
void LogCustomEvent(uint32_t metric_id,
std::vector<fuchsia::cobalt::CustomEventValue> event_values) override;
virtual void LogCobaltEvent(fuchsia::cobalt::CobaltEvent event) override;
virtual void LogCobaltEvents(std::vector<fuchsia::cobalt::CobaltEvent> event) override;
protected:
void ConnectToCobaltApplication();
virtual fidl::InterfacePtr<fuchsia::cobalt::LoggerFactory> ConnectToLoggerFactory() = 0;
private:
std::function<void(fuchsia::cobalt::Status)> CreateLoggerCallback(const std::string& method_name);
void OnConnectionError();
void LogEventOnMainThread(std::unique_ptr<BaseEvent> event);
void SendEvents();
void OnTransitFail();
void LogEventCallback(const BaseEvent* event, fuchsia::cobalt::Status status);
void LogEvent(std::unique_ptr<BaseEvent> event);
backoff::ExponentialBackoff backoff_;
async_dispatcher_t* const dispatcher_;
fuchsia::cobalt::LoggerFactoryPtr logger_factory_;
fuchsia::cobalt::LoggerPtr logger_;
// Because logger_ is bound in the contructor we need to keep track of whether or not the remote
// server is ready.
bool logger_ready_ = false;
// project ID to use when connecting to Cobalt with CreateLoggerFromProjectId().
const uint32_t project_id_;
std::set<std::unique_ptr<BaseEvent>> events_to_send_;
std::set<std::unique_ptr<BaseEvent>> events_in_transit_;
FXL_DISALLOW_COPY_AND_ASSIGN(BaseCobaltLoggerImpl);
};
class CobaltLoggerImpl : public BaseCobaltLoggerImpl {
public:
// Use this version of the constructor in order to connect to the Cobalt
// application via CreateLoggerFromProjectId().
CobaltLoggerImpl(async_dispatcher_t* dispatcher, std::shared_ptr<sys::ServiceDirectory> services,
uint32_t project_id);
~CobaltLoggerImpl() override{};
protected:
virtual fidl::InterfacePtr<fuchsia::cobalt::LoggerFactory> ConnectToLoggerFactory() override;
private:
std::shared_ptr<sys::ServiceDirectory> services_;
FXL_DISALLOW_COPY_AND_ASSIGN(CobaltLoggerImpl);
};
} // namespace cobalt
#endif // SRC_LIB_COBALT_CPP_COBALT_LOGGER_IMPL_H_