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 #define DEBUG false // STOPSHIP if true 18 #include "Log.h" 19 20 #include "EventMetricProducer.h" 21 #include "stats_util.h" 22 #include "stats_log_util.h" 23 24 #include <limits.h> 25 #include <stdlib.h> 26 27 using android::util::FIELD_COUNT_REPEATED; 28 using android::util::FIELD_TYPE_BOOL; 29 using android::util::FIELD_TYPE_FLOAT; 30 using android::util::FIELD_TYPE_INT32; 31 using android::util::FIELD_TYPE_INT64; 32 using android::util::FIELD_TYPE_STRING; 33 using android::util::FIELD_TYPE_MESSAGE; 34 using android::util::ProtoOutputStream; 35 using std::map; 36 using std::string; 37 using std::unordered_map; 38 using std::vector; 39 40 namespace android { 41 namespace os { 42 namespace statsd { 43 44 // for StatsLogReport 45 const int FIELD_ID_ID = 1; 46 const int FIELD_ID_EVENT_METRICS = 4; 47 const int FIELD_ID_IS_ACTIVE = 14; 48 // for EventMetricDataWrapper 49 const int FIELD_ID_DATA = 1; 50 // for EventMetricData 51 const int FIELD_ID_ELAPSED_TIMESTAMP_NANOS = 1; 52 const int FIELD_ID_ATOMS = 2; 53 54 EventMetricProducer::EventMetricProducer(const ConfigKey& key, const EventMetric& metric, 55 const int conditionIndex, 56 const sp<ConditionWizard>& wizard, 57 const int64_t startTimeNs) 58 : MetricProducer(metric.id(), key, startTimeNs, conditionIndex, wizard) { 59 if (metric.links().size() > 0) { 60 for (const auto& link : metric.links()) { 61 Metric2Condition mc; 62 mc.conditionId = link.condition(); 63 translateFieldMatcher(link.fields_in_what(), &mc.metricFields); 64 translateFieldMatcher(link.fields_in_condition(), &mc.conditionFields); 65 mMetric2ConditionLinks.push_back(mc); 66 } 67 mConditionSliced = true; 68 } 69 mProto = std::make_unique<ProtoOutputStream>(); 70 VLOG("metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(), 71 (long long)mBucketSizeNs, (long long)mTimeBaseNs); 72 } 73 74 EventMetricProducer::~EventMetricProducer() { 75 VLOG("~EventMetricProducer() called"); 76 } 77 78 void EventMetricProducer::dropDataLocked(const int64_t dropTimeNs) { 79 mProto->clear(); 80 StatsdStats::getInstance().noteBucketDropped(mMetricId); 81 } 82 83 void EventMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition, 84 const int64_t eventTime) { 85 } 86 87 std::unique_ptr<std::vector<uint8_t>> serializeProtoLocked(ProtoOutputStream& protoOutput) { 88 size_t bufferSize = protoOutput.size(); 89 90 std::unique_ptr<std::vector<uint8_t>> buffer(new std::vector<uint8_t>(bufferSize)); 91 92 size_t pos = 0; 93 sp<android::util::ProtoReader> reader = protoOutput.data(); 94 while (reader->readBuffer() != NULL) { 95 size_t toRead = reader->currentToRead(); 96 std::memcpy(&((*buffer)[pos]), reader->readBuffer(), toRead); 97 pos += toRead; 98 reader->move(toRead); 99 } 100 101 return buffer; 102 } 103 104 void EventMetricProducer::clearPastBucketsLocked(const int64_t dumpTimeNs) { 105 mProto->clear(); 106 } 107 108 void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs, 109 const bool include_current_partial_bucket, 110 const bool erase_data, 111 const DumpLatency dumpLatency, 112 std::set<string> *str_set, 113 ProtoOutputStream* protoOutput) { 114 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId); 115 protoOutput->write(FIELD_TYPE_BOOL | FIELD_ID_IS_ACTIVE, isActiveLocked()); 116 if (mProto->size() <= 0) { 117 return; 118 } 119 120 size_t bufferSize = mProto->size(); 121 VLOG("metric %lld dump report now... proto size: %zu ", 122 (long long)mMetricId, bufferSize); 123 std::unique_ptr<std::vector<uint8_t>> buffer = serializeProtoLocked(*mProto); 124 125 protoOutput->write(FIELD_TYPE_MESSAGE | FIELD_ID_EVENT_METRICS, 126 reinterpret_cast<char*>(buffer.get()->data()), buffer.get()->size()); 127 128 if (erase_data) { 129 mProto->clear(); 130 } 131 } 132 133 void EventMetricProducer::onConditionChangedLocked(const bool conditionMet, 134 const int64_t eventTime) { 135 VLOG("Metric %lld onConditionChanged", (long long)mMetricId); 136 mCondition = conditionMet ? ConditionState::kTrue : ConditionState::kFalse; 137 } 138 139 void EventMetricProducer::onMatchedLogEventInternalLocked( 140 const size_t matcherIndex, const MetricDimensionKey& eventKey, 141 const ConditionKey& conditionKey, bool condition, 142 const LogEvent& event) { 143 if (!condition) { 144 return; 145 } 146 147 uint64_t wrapperToken = 148 mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA); 149 const int64_t elapsedTimeNs = truncateTimestampIfNecessary( 150 event.GetTagId(), event.GetElapsedTimestampNs()); 151 mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS, (long long) elapsedTimeNs); 152 153 uint64_t eventToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOMS); 154 event.ToProto(*mProto); 155 mProto->end(eventToken); 156 mProto->end(wrapperToken); 157 } 158 159 size_t EventMetricProducer::byteSizeLocked() const { 160 return mProto->bytesWritten(); 161 } 162 163 } // namespace statsd 164 } // namespace os 165 } // namespace android 166