summaryrefslogtreecommitdiff
path: root/cmds/statsd/src/logd/LogEvent.h
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2020-08-31 21:21:38 -0700
committerXin Li <delphij@google.com>2020-08-31 21:21:38 -0700
commit628590d7ec80e10a3fc24b1c18a1afb55cca10a8 (patch)
tree4b1c3f52d86d7fb53afbe9e9438468588fa489f8 /cmds/statsd/src/logd/LogEvent.h
parentb11b8ec3aec8bb42f2c07e1c5ac7942da293baa8 (diff)
parentd2d3a20624d968199353ccf6ddbae6f3ac39c9af (diff)
Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)
Bug: 166295507 Merged-In: I3d92a6de21a938f6b352ec26dc23420c0fe02b27 Change-Id: Ifdb80563ef042738778ebb8a7581a97c4e3d96e2
Diffstat (limited to 'cmds/statsd/src/logd/LogEvent.h')
-rw-r--r--cmds/statsd/src/logd/LogEvent.h278
1 files changed, 185 insertions, 93 deletions
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index e1b5a0b8f0f5..a5f24603585a 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -18,9 +18,7 @@
#include "FieldValue.h"
-#include <android/os/StatsLogEventWrapper.h>
#include <android/util/ProtoOutputStream.h>
-#include <log/log_read.h>
#include <private/android_logger.h>
#include <string>
@@ -30,75 +28,39 @@ namespace android {
namespace os {
namespace statsd {
-struct AttributionNodeInternal {
- void set_uid(int32_t id) {
- mUid = id;
- }
-
- void set_tag(const std::string& value) {
- mTag = value;
- }
-
- int32_t uid() const {
- return mUid;
- }
-
- const std::string& tag() const {
- return mTag;
- }
-
- int32_t mUid;
- std::string mTag;
-};
-
struct InstallTrainInfo {
int64_t trainVersionCode;
std::string trainName;
int32_t status;
std::vector<int64_t> experimentIds;
+ bool requiresStaging;
+ bool rollbackEnabled;
+ bool requiresLowLatencyMonitor;
};
/**
- * Wrapper for the log_msg structure.
+ * This class decodes the structured, serialized encoding of an atom into a
+ * vector of FieldValues.
*/
class LogEvent {
public:
/**
- * Read a LogEvent from a log_msg.
- */
- explicit LogEvent(log_msg& msg);
-
- /**
- * Creates LogEvent from StatsLogEventWrapper.
- */
- static void createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
- std::vector<std::shared_ptr<LogEvent>>& logEvents);
-
- /**
- * Construct one LogEvent from a StatsLogEventWrapper with the i-th work chain. -1 if no chain.
- */
- explicit LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex);
-
- /**
- * Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
+ * \param uid user id of the logging caller
+ * \param pid process id of the logging caller
*/
- explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs);
-
- // For testing. The timestamp is used as both elapsed real time and logd timestamp.
- explicit LogEvent(int32_t tagId, int64_t timestampNs);
-
- // For testing. The timestamp is used as both elapsed real time and logd timestamp.
- explicit LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid);
+ explicit LogEvent(int32_t uid, int32_t pid);
/**
- * Constructs a KeyValuePairsAtom LogEvent from value maps.
+ * Parses the atomId, timestamp, and vector of values from a buffer
+ * containing the StatsEvent/AStatsEvent encoding of an atom.
+ *
+ * \param buf a buffer that begins at the start of the serialized atom (it
+ * should not include the android_log_header_t or the StatsEventTag)
+ * \param len size of the buffer
+ *
+ * \return success of the initialization
*/
- explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
- int32_t uid,
- const std::map<int32_t, int32_t>& int_map,
- const std::map<int32_t, int64_t>& long_map,
- const std::map<int32_t, std::string>& string_map,
- const std::map<int32_t, float>& float_map);
+ bool parseBuffer(uint8_t* buf, size_t len);
// Constructs a BinaryPushStateChanged LogEvent from API call.
explicit LogEvent(const std::string& trainName, int64_t trainVersionCode, bool requiresStaging,
@@ -108,7 +70,7 @@ public:
explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
const InstallTrainInfo& installTrainInfo);
- ~LogEvent();
+ ~LogEvent() {}
/**
* Get the timestamp associated with this event.
@@ -121,9 +83,17 @@ public:
*/
inline int GetTagId() const { return mTagId; }
- inline uint32_t GetUid() const {
- return mLogUid;
- }
+ /**
+ * Get the uid of the logging client.
+ * Returns -1 if the uid is unknown/has not been set.
+ */
+ inline int32_t GetUid() const { return mLogUid; }
+
+ /**
+ * Get the pid of the logging client.
+ * Returns -1 if the pid is unknown/has not been set.
+ */
+ inline int32_t GetPid() const { return mLogPid; }
/**
* Get the nth value, starting at 1.
@@ -136,24 +106,7 @@ public:
const char* GetString(size_t key, status_t* err) const;
bool GetBool(size_t key, status_t* err) const;
float GetFloat(size_t key, status_t* err) const;
-
- /**
- * Write test data to the LogEvent. This can only be used when the LogEvent is constructed
- * using LogEvent(tagId, timestampNs). You need to call init() before you can read from it.
- */
- bool write(uint32_t value);
- bool write(int32_t value);
- bool write(uint64_t value);
- bool write(int64_t value);
- bool write(const std::string& value);
- bool write(float value);
- bool write(const std::vector<AttributionNodeInternal>& nodes);
- bool write(const AttributionNodeInternal& node);
- bool writeKeyValuePairs(int32_t uid,
- const std::map<int32_t, int32_t>& int_map,
- const std::map<int32_t, int64_t>& long_map,
- const std::map<int32_t, std::string>& string_map,
- const std::map<int32_t, float>& float_map);
+ std::vector<uint8_t> GetStorage(size_t key, status_t* err) const;
/**
* Return a string representation of this event.
@@ -166,12 +119,6 @@ public:
void ToProto(android::util::ProtoOutputStream& out) const;
/**
- * Used with the constructor where tag is passed in. Converts the log_event_list to read mode
- * and prepares the list for reading.
- */
- void init();
-
- /**
* Set elapsed timestamp if the original timestamp is missing.
*/
void setElapsedTimestampNs(int64_t timestampNs) {
@@ -197,39 +144,184 @@ public:
return &mValues;
}
+ // Default value = false
+ inline bool shouldTruncateTimestamp() const {
+ return mTruncateTimestamp;
+ }
+
+ // Returns the index of the uid field within the FieldValues vector if the
+ // uid exists. If there is no uid field, returns -1.
+ //
+ // If the index within the atom definition is desired, do the following:
+ // int vectorIndex = LogEvent.getUidFieldIndex();
+ // if (vectorIndex != -1) {
+ // FieldValue& v = LogEvent.getValues()[vectorIndex];
+ // int atomIndex = v.mField.getPosAtDepth(0);
+ // }
+ // Note that atomIndex is 1-indexed.
+ inline int getUidFieldIndex() {
+ return static_cast<int>(mUidFieldIndex);
+ }
+
+ // Returns whether this LogEvent has an AttributionChain.
+ // If it does and indexRange is not a nullptr, populate indexRange with the start and end index
+ // of the AttributionChain within mValues.
+ bool hasAttributionChain(std::pair<int, int>* indexRange = nullptr) const;
+
+ // Returns the index of the exclusive state field within the FieldValues vector if
+ // an exclusive state exists. If there is no exclusive state field, returns -1.
+ //
+ // If the index within the atom definition is desired, do the following:
+ // int vectorIndex = LogEvent.getExclusiveStateFieldIndex();
+ // if (vectorIndex != -1) {
+ // FieldValue& v = LogEvent.getValues()[vectorIndex];
+ // int atomIndex = v.mField.getPosAtDepth(0);
+ // }
+ // Note that atomIndex is 1-indexed.
+ inline int getExclusiveStateFieldIndex() const {
+ return static_cast<int>(mExclusiveStateFieldIndex);
+ }
+
+ // If a reset state is not sent in the StatsEvent, returns -1. Note that a
+ // reset state is sent if and only if a reset should be triggered.
+ inline int getResetState() const {
+ return mResetState;
+ }
+
inline LogEvent makeCopy() {
return LogEvent(*this);
}
+ template <class T>
+ status_t updateValue(size_t key, T& value, Type type) {
+ int field = getSimpleField(key);
+ for (auto& fieldValue : mValues) {
+ if (fieldValue.mField.getField() == field) {
+ if (fieldValue.mValue.getType() == type) {
+ fieldValue.mValue = Value(value);
+ return OK;
+ } else {
+ return BAD_TYPE;
+ }
+ }
+ }
+ return BAD_INDEX;
+ }
+
+ bool isValid() const {
+ return mValid;
+ }
+
private:
/**
* Only use this if copy is absolutely needed.
*/
- LogEvent(const LogEvent&);
+ LogEvent(const LogEvent&) = default;
+
+ void parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
+ void parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
+ void parseString(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
+ void parseFloat(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
+ void parseBool(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
+ void parseByteArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
+ void parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
+ void parseAttributionChain(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations);
+
+ void parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex = -1);
+ void parseIsUidAnnotation(uint8_t annotationType);
+ void parseTruncateTimestampAnnotation(uint8_t annotationType);
+ void parsePrimaryFieldAnnotation(uint8_t annotationType);
+ void parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType, int firstUidInChainIndex);
+ void parseExclusiveStateAnnotation(uint8_t annotationType);
+ void parseTriggerStateResetAnnotation(uint8_t annotationType);
+ void parseStateNestedAnnotation(uint8_t annotationType);
+ bool checkPreviousValueType(Type expected);
+
+ /**
+ * The below two variables are only valid during the execution of
+ * parseBuffer. There are no guarantees about the state of these variables
+ * before/after.
+ */
+ uint8_t* mBuf;
+ uint32_t mRemainingLen; // number of valid bytes left in the buffer being parsed
+
+ bool mValid = true; // stores whether the event we received from the socket is valid
/**
- * Parses a log_msg into a LogEvent object.
+ * Side-effects:
+ * If there is enough space in buffer to read value of type T
+ * - move mBuf past the value that was just read
+ * - decrement mRemainingLen by size of T
+ * Else
+ * - set mValid to false
*/
- void init(android_log_context context);
+ template <class T>
+ T readNextValue() {
+ T value;
+ if (mRemainingLen < sizeof(T)) {
+ mValid = false;
+ value = 0; // all primitive types can successfully cast 0
+ } else {
+ // When alignof(T) == 1, hopefully the compiler can optimize away
+ // this conditional as always true.
+ if ((reinterpret_cast<uintptr_t>(mBuf) % alignof(T)) == 0) {
+ // We're properly aligned, and can safely make this assignment.
+ value = *((T*)mBuf);
+ } else {
+ // We need to use memcpy. It's slower, but safe.
+ memcpy(&value, mBuf, sizeof(T));
+ }
+ mBuf += sizeof(T);
+ mRemainingLen -= sizeof(T);
+ }
+ return value;
+ }
+
+ template <class T>
+ void addToValues(int32_t* pos, int32_t depth, T& value, bool* last) {
+ Field f = Field(mTagId, pos, depth);
+ // do not decorate last position at depth 0
+ for (int i = 1; i < depth; i++) {
+ if (last[i]) f.decorateLastPos(i);
+ }
+
+ Value v = Value(value);
+ mValues.push_back(FieldValue(f, v));
+ }
+
+ uint8_t getTypeId(uint8_t typeInfo);
+ uint8_t getNumAnnotations(uint8_t typeInfo);
// The items are naturally sorted in DFS order as we read them. this allows us to do fast
// matching.
std::vector<FieldValue> mValues;
- // This field is used when statsD wants to create log event object and write fields to it. After
- // calling init() function, this object would be destroyed to save memory usage.
- // When the log event is created from log msg, this field is never initiated.
- android_log_context mContext = NULL;
-
// The timestamp set by the logd.
int64_t mLogdTimestampNs;
// The elapsed timestamp set by statsd log writer.
int64_t mElapsedTimestampNs;
- int mTagId;
+ // The atom tag of the event (defaults to 0 if client does not
+ // appropriately set the atom id).
+ int mTagId = 0;
+
+ // The uid of the logging client (defaults to -1).
+ int32_t mLogUid = -1;
+
+ // The pid of the logging client (defaults to -1).
+ int32_t mLogPid = -1;
+
+ // Annotations
+ bool mTruncateTimestamp = false;
+ int mResetState = -1;
- uint32_t mLogUid;
+ // Indexes within the FieldValue vector can be stored in 7 bits because
+ // that's the assumption enforced by the encoding used in FieldValue.
+ int8_t mUidFieldIndex = -1;
+ int8_t mAttributionChainStartIndex = -1;
+ int8_t mAttributionChainEndIndex = -1;
+ int8_t mExclusiveStateFieldIndex = -1;
};
void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds, std::vector<uint8_t>* protoOut);