/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "FieldValue.h" #include <android/frameworks/stats/1.0/types.h> #include <android/os/StatsLogEventWrapper.h> #include <android/util/ProtoOutputStream.h> #include <log/log_event_list.h> #include <log/log_read.h> #include <private/android_logger.h> #include <utils/Errors.h> #include <string> #include <vector> using namespace android::frameworks::stats::V1_0; 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; }; /** * Wrapper for the log_msg structure. */ 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. */ 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); /** * Constructs a KeyValuePairsAtom LogEvent from value maps. */ 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); // Constructs a BinaryPushStateChanged LogEvent from API call. explicit LogEvent(const std::string& trainName, int64_t trainVersionCode, bool requiresStaging, bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state, const std::vector<uint8_t>& experimentIds, int32_t userId); explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs, const VendorAtom& vendorAtom); explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs, const InstallTrainInfo& installTrainInfo); ~LogEvent(); /** * Get the timestamp associated with this event. */ inline int64_t GetLogdTimestampNs() const { return mLogdTimestampNs; } inline int64_t GetElapsedTimestampNs() const { return mElapsedTimestampNs; } /** * Get the tag for this event. */ inline int GetTagId() const { return mTagId; } inline uint32_t GetUid() const { return mLogUid; } /** * Get the nth value, starting at 1. * * Returns BAD_INDEX if the index is larger than the number of elements. * Returns BAD_TYPE if the index is available but the data is the wrong type. */ int64_t GetLong(size_t key, status_t* err) const; int GetInt(size_t key, status_t* err) const; 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); /** * Return a string representation of this event. */ std::string ToString() const; /** * Write this object to a ProtoOutputStream. */ 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) { mElapsedTimestampNs = timestampNs; } /** * Set the timestamp if the original logd timestamp is missing. */ void setLogdWallClockTimestampNs(int64_t timestampNs) { mLogdTimestampNs = timestampNs; } inline int size() const { return mValues.size(); } const std::vector<FieldValue>& getValues() const { return mValues; } std::vector<FieldValue>* getMutableValues() { return &mValues; } inline LogEvent makeCopy() { return LogEvent(*this); } private: /** * Only use this if copy is absolutely needed. */ LogEvent(const LogEvent&); /** * Parses a log_msg into a LogEvent object. */ void init(android_log_context context); // 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; uint32_t mLogUid; }; void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds, std::vector<uint8_t>* protoOut); } // namespace statsd } // namespace os } // namespace android