Home | History | Annotate | Download | only in metrics
      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