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 27using android::util::FIELD_COUNT_REPEATED; 28using android::util::FIELD_TYPE_BOOL; 29using android::util::FIELD_TYPE_FLOAT; 30using android::util::FIELD_TYPE_INT32; 31using android::util::FIELD_TYPE_INT64; 32using android::util::FIELD_TYPE_STRING; 33using android::util::FIELD_TYPE_MESSAGE; 34using android::util::ProtoOutputStream; 35using std::map; 36using std::string; 37using std::unordered_map; 38using std::vector; 39 40namespace android { 41namespace os { 42namespace statsd { 43 44// for StatsLogReport 45const int FIELD_ID_ID = 1; 46const int FIELD_ID_EVENT_METRICS = 4; 47// for EventMetricDataWrapper 48const int FIELD_ID_DATA = 1; 49// for EventMetricData 50const int FIELD_ID_ELAPSED_TIMESTAMP_NANOS = 1; 51const int FIELD_ID_ATOMS = 2; 52const int FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS = 3; 53 54EventMetricProducer::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 74EventMetricProducer::~EventMetricProducer() { 75 VLOG("~EventMetricProducer() called"); 76} 77 78void EventMetricProducer::dropDataLocked(const int64_t dropTimeNs) { 79 mProto->clear(); 80} 81 82void EventMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition, 83 const int64_t eventTime) { 84} 85 86std::unique_ptr<std::vector<uint8_t>> serializeProtoLocked(ProtoOutputStream& protoOutput) { 87 size_t bufferSize = protoOutput.size(); 88 89 std::unique_ptr<std::vector<uint8_t>> buffer(new std::vector<uint8_t>(bufferSize)); 90 91 size_t pos = 0; 92 auto it = protoOutput.data(); 93 while (it.readBuffer() != NULL) { 94 size_t toRead = it.currentToRead(); 95 std::memcpy(&((*buffer)[pos]), it.readBuffer(), toRead); 96 pos += toRead; 97 it.rp()->move(toRead); 98 } 99 100 return buffer; 101} 102 103void EventMetricProducer::clearPastBucketsLocked(const int64_t dumpTimeNs) { 104 mProto->clear(); 105} 106 107void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs, 108 const bool include_current_partial_bucket, 109 std::set<string> *str_set, 110 ProtoOutputStream* protoOutput) { 111 if (mProto->size() <= 0) { 112 return; 113 } 114 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId); 115 116 size_t bufferSize = mProto->size(); 117 VLOG("metric %lld dump report now... proto size: %zu ", 118 (long long)mMetricId, bufferSize); 119 std::unique_ptr<std::vector<uint8_t>> buffer = serializeProtoLocked(*mProto); 120 121 protoOutput->write(FIELD_TYPE_MESSAGE | FIELD_ID_EVENT_METRICS, 122 reinterpret_cast<char*>(buffer.get()->data()), buffer.get()->size()); 123 124 mProto->clear(); 125} 126 127void EventMetricProducer::onConditionChangedLocked(const bool conditionMet, 128 const int64_t eventTime) { 129 VLOG("Metric %lld onConditionChanged", (long long)mMetricId); 130 mCondition = conditionMet; 131} 132 133void EventMetricProducer::onMatchedLogEventInternalLocked( 134 const size_t matcherIndex, const MetricDimensionKey& eventKey, 135 const ConditionKey& conditionKey, bool condition, 136 const LogEvent& event) { 137 if (!condition) { 138 return; 139 } 140 141 uint64_t wrapperToken = 142 mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA); 143 const bool truncateTimestamp = 144 android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.find(event.GetTagId()) == 145 android::util::AtomsInfo::kNotTruncatingTimestampAtomWhiteList.end(); 146 if (truncateTimestamp) { 147 mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS, 148 (long long)truncateTimestampNsToFiveMinutes(event.GetElapsedTimestampNs())); 149 mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS, 150 (long long)truncateTimestampNsToFiveMinutes(getWallClockNs())); 151 } else { 152 mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS, 153 (long long)event.GetElapsedTimestampNs()); 154 mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS, 155 (long long)getWallClockNs()); 156 } 157 158 uint64_t eventToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOMS); 159 event.ToProto(*mProto); 160 mProto->end(eventToken); 161 mProto->end(wrapperToken); 162} 163 164size_t EventMetricProducer::byteSizeLocked() const { 165 return mProto->bytesWritten(); 166} 167 168} // namespace statsd 169} // namespace os 170} // namespace android 171