blob: 3f10a6b742a174e077c33c2a2efcf86cc25bd404 [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 LIB_COBALT_CPP_COBALT_LOGGER_IMPL_H_
#define LIB_COBALT_CPP_COBALT_LOGGER_IMPL_H_
#include "garnet/public/lib/cobalt/cpp/cobalt_logger.h"
#include <fuchsia/cobalt/cpp/fidl.h>
#include <lib/backoff/exponential_backoff.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/fit/function.h>
#include <lib/fxl/logging.h>
#include <zx/time.h>
namespace cobalt {
class Event {
public:
Event(uint32_t metric_id) : metric_id_(metric_id) {}
virtual ~Event() = default;
virtual void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) = 0;
uint32_t metric_id() const { 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_,
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
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_,
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
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_,
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
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_,
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
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_,
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
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 StringUsedEvent : public Event {
public:
StringUsedEvent(uint32_t metric_id, const std::string& s)
: Event(metric_id), s_(s) {}
void Log(fuchsia::cobalt::LoggerPtr* logger,
fit::function<void(fuchsia::cobalt::Status)> callback) {
(*logger)->LogString(
metric_id(), s_,
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
const std::string& s() const { return s_; }
private:
const std::string s_;
};
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_,
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
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 Event {
public:
EndTimerEvent(const std::string& timer_id, uint64_t timestamp,
uint32_t timeout_s)
: Event(0),
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_,
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
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;
FXL_CHECK(fidl::Clone(histogram_, &histogram) == ZX_OK);
(*logger)->LogIntHistogram(
metric_id(), event_code_, component_, std::move(histogram),
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
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;
FXL_CHECK(fidl::Clone(event_values_, &event_values) == ZX_OK);
(*logger)->LogCustomEvent(
metric_id(), std::move(event_values),
[callback = callback.share()](fuchsia::cobalt::Status status) {
callback(status);
});
}
const std::vector<fuchsia::cobalt::CustomEventValue>& event_values() const {
return event_values_;
}
private:
const std::vector<fuchsia::cobalt::CustomEventValue> event_values_;
};
class CobaltLoggerImpl : public CobaltLogger {
public:
CobaltLoggerImpl(async_dispatcher_t* dispatcher,
component::StartupContext* context,
fuchsia::cobalt::ProjectProfile profile);
~CobaltLoggerImpl() 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 LogString(uint32_t metric_id, const std::string& s) 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;
private:
void ConnectToCobaltApplication();
fuchsia::cobalt::ProjectProfile CloneProjectProfile();
void OnConnectionError();
void LogEventOnMainThread(std::unique_ptr<Event> event);
void SendEvents();
void OnTransitFail();
void LogEventCallback(const Event* event, fuchsia::cobalt::Status status);
void LogEvent(std::unique_ptr<Event> event);
backoff::ExponentialBackoff backoff_;
async_dispatcher_t* const dispatcher_;
component::StartupContext* context_;
fuchsia::cobalt::LoggerPtr logger_;
const fuchsia::cobalt::ProjectProfile profile_;
std::set<std::unique_ptr<Event>> events_to_send_;
std::set<std::unique_ptr<Event>> events_in_transit_;
FXL_DISALLOW_COPY_AND_ASSIGN(CobaltLoggerImpl);
};
} // namespace cobalt
#endif // LIB_COBALT_CPP_COBALT_LOGGER_IMPL_H_