1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <utils/JenkinsHash.h> 20 #include <vector> 21 #include "FieldValue.h" 22 #include "android-base/stringprintf.h" 23 #include "logd/LogEvent.h" 24 25 namespace android { 26 namespace os { 27 namespace statsd { 28 29 using android::base::StringPrintf; 30 31 struct Metric2Condition { 32 int64_t conditionId; 33 std::vector<Matcher> metricFields; 34 std::vector<Matcher> conditionFields; 35 }; 36 37 class HashableDimensionKey { 38 public: 39 explicit HashableDimensionKey(const std::vector<FieldValue>& values) { 40 mValues = values; 41 } 42 43 HashableDimensionKey() {}; 44 45 HashableDimensionKey(const HashableDimensionKey& that) : mValues(that.getValues()){}; 46 47 inline void addValue(const FieldValue& value) { 48 mValues.push_back(value); 49 } 50 51 inline const std::vector<FieldValue>& getValues() const { 52 return mValues; 53 } 54 55 inline std::vector<FieldValue>* mutableValues() { 56 return &mValues; 57 } 58 59 inline FieldValue* mutableValue(size_t i) { 60 if (i >= 0 && i < mValues.size()) { 61 return &(mValues[i]); 62 } 63 return nullptr; 64 } 65 66 std::string toString() const; 67 68 bool operator==(const HashableDimensionKey& that) const; 69 70 bool operator<(const HashableDimensionKey& that) const; 71 72 bool contains(const HashableDimensionKey& that) const; 73 74 private: 75 std::vector<FieldValue> mValues; 76 }; 77 78 class MetricDimensionKey { 79 public: 80 explicit MetricDimensionKey(const HashableDimensionKey& dimensionKeyInWhat, 81 const HashableDimensionKey& dimensionKeyInCondition) 82 : mDimensionKeyInWhat(dimensionKeyInWhat), 83 mDimensionKeyInCondition(dimensionKeyInCondition) {}; 84 85 MetricDimensionKey(){}; 86 87 MetricDimensionKey(const MetricDimensionKey& that) 88 : mDimensionKeyInWhat(that.getDimensionKeyInWhat()), 89 mDimensionKeyInCondition(that.getDimensionKeyInCondition()) {}; 90 91 MetricDimensionKey& operator=(const MetricDimensionKey& from) = default; 92 93 std::string toString() const; 94 95 inline const HashableDimensionKey& getDimensionKeyInWhat() const { 96 return mDimensionKeyInWhat; 97 } 98 99 inline const HashableDimensionKey& getDimensionKeyInCondition() const { 100 return mDimensionKeyInCondition; 101 } 102 103 inline void setDimensionKeyInCondition(const HashableDimensionKey& key) { 104 mDimensionKeyInCondition = key; 105 } 106 107 bool hasDimensionKeyInCondition() const { 108 return mDimensionKeyInCondition.getValues().size() > 0; 109 } 110 111 bool operator==(const MetricDimensionKey& that) const; 112 113 bool operator<(const MetricDimensionKey& that) const; 114 115 private: 116 HashableDimensionKey mDimensionKeyInWhat; 117 HashableDimensionKey mDimensionKeyInCondition; 118 }; 119 120 android::hash_t hashDimension(const HashableDimensionKey& key); 121 122 /** 123 * Creating HashableDimensionKeys from FieldValues using matcher. 124 * 125 * This function may make modifications to the Field if the matcher has Position=FIRST,LAST or ALL 126 * in it. This is because: for example, when we create dimension from last uid in attribution chain, 127 * In one event, uid 1000 is at position 5 and it's the last 128 * In another event, uid 1000 is at position 6, and it's the last 129 * these 2 events should be mapped to the same dimension. So we will remove the original position 130 * from the dimension key for the uid field (by applying 0x80 bit mask). 131 */ 132 bool filterValues(const std::vector<Matcher>& matcherFields, const std::vector<FieldValue>& values, 133 HashableDimensionKey* output); 134 135 /** 136 * Filter the values from FieldValues using the matchers. 137 * 138 * In contrast to the above function, this function will not do any modification to the original 139 * data. Considering it as taking a snapshot on the atom event. 140 */ 141 void filterGaugeValues(const std::vector<Matcher>& matchers, const std::vector<FieldValue>& values, 142 std::vector<FieldValue>* output); 143 144 void getDimensionForCondition(const std::vector<FieldValue>& eventValues, 145 const Metric2Condition& links, 146 HashableDimensionKey* conditionDimension); 147 148 } // namespace statsd 149 } // namespace os 150 } // namespace android 151 152 namespace std { 153 154 using android::os::statsd::HashableDimensionKey; 155 using android::os::statsd::MetricDimensionKey; 156 157 template <> 158 struct hash<HashableDimensionKey> { 159 std::size_t operator()(const HashableDimensionKey& key) const { 160 return hashDimension(key); 161 } 162 }; 163 164 template <> 165 struct hash<MetricDimensionKey> { 166 std::size_t operator()(const MetricDimensionKey& key) const { 167 android::hash_t hash = hashDimension(key.getDimensionKeyInWhat()); 168 hash = android::JenkinsHashMix(hash, hashDimension(key.getDimensionKeyInCondition())); 169 return android::JenkinsHashWhiten(hash); 170 } 171 }; 172 } // namespace std