blob: 36cd7ee958345c2cabf1fdad1f17307100faa474 [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.
// This file declares objects which are used to carry the output of the cobalt
// client library. The ValuePart, ObservationPart and Observation objects
// correspond to the identically-named protobuf messages found in
// observation.proto.
#ifndef COBALT_CLIENT_COLLECTION_OBSERVATION_H_
#define COBALT_CLIENT_COLLECTION_OBSERVATION_H_
#include <functional>
#include <map>
#include <string>
#include <vector>
namespace cobalt {
namespace client {
// An UndoFunction is called to indicate a collection attempt has failed and
// must be undone.
typedef std::function<void()> UndoFunction;
// The value of a MetricPart to be sent to Cobalt.
// The value and type of a ValuePart cannot be changed.
class ValuePart {
public:
// Returns an integer value part.
static const ValuePart MakeInt(int64_t value) {
Value val;
val.int_value = value;
return ValuePart(INT, val);
}
// Returns a double value part.
static const ValuePart MakeDouble(double value) {
Value val;
val.double_value = value;
return ValuePart(DOUBLE, val);
}
// Returns a distribution value part.
static const ValuePart MakeDistribution(
const std::map<uint32_t, int64_t>& value) {
Value val;
val.distribution =
new std::map<uint32_t, int64_t>(value.begin(), value.end());
return ValuePart(DISTRIBUTION, val);
}
enum Type {
INT,
DOUBLE,
DISTRIBUTION,
};
// Returns the type of the value part.
Type Which() const { return type_; }
// Returns true if the value part is an integer.
bool IsIntValue() const { return type_ == INT; }
// Returns true if the value part is a double.
bool IsDoubleValue() const { return type_ == DOUBLE; }
// Returns true if the value part is a distribution.
bool IsDistribution() const { return type_ == DISTRIBUTION; }
// Returns the integer value of an integer value part. If the value part is
// not an integer, the behavior is undefined.
int64_t GetIntValue() const { return value_.int_value; }
// Returns the double value of a double value part. If the value part is
// not a double, the behavior is undefined.
double GetDoubleValue() const { return value_.double_value; }
// Returns the distribution value of a distribution value part. If the value
// part is not a distribution, the behavior is undefined.
const std::map<uint32_t, int64_t>& GetDistribution() const {
return *value_.distribution;
}
~ValuePart() {
if (IsDistribution()) {
delete value_.distribution;
}
}
ValuePart(const ValuePart& value)
: type_(value.type_), value_(value.CopyValue()) {}
private:
union Value {
int64_t int_value;
double double_value;
// This is deleted in the constructor.
std::map<uint32_t, int64_t>* distribution;
};
const Value CopyValue() const {
Value value = value_;
if (IsDistribution()) {
// If we're copying a distribution, we have to copy the map.
value.distribution = new std::map<uint32_t, int64_t>(
value_.distribution->begin(), value_.distribution->end());
}
return value;
}
ValuePart(Type type, Value value)
: type_(type), value_(value) {}
Type type_;
Value value_;
};
// An ObservationPart represents a collected observation part. It currently
// only supports integers.
struct ObservationPart {
ObservationPart(std::string part_name, uint32_t encoding_id, ValuePart value,
UndoFunction undo)
: part_name(part_name),
encoding_id(encoding_id),
value(value),
undo(undo) {}
std::string part_name;
uint32_t encoding_id;
ValuePart value;
// Calling undo will undo the collection of the metric part.
// TODO(azani): Maybe make private.
UndoFunction undo;
};
// An Observation represents a collected observation to be sent to Cobalt.
struct Observation {
uint32_t metric_id;
std::vector<ObservationPart> parts;
// Calling undo will undo the collection of the metric including its parts.
UndoFunction undo;
};
} // namespace client
} // namespace cobalt
#endif // COBALT_CLIENT_COLLECTION_OBSERVATION_H_