Home | History | Annotate | Download | only in uploader
      1 /*
      2  * Copyright (C) 2015 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 #include "uploader/metrics_log_base.h"
     18 
     19 #include "base/build_time.h"
     20 #include "base/metrics/histogram_base.h"
     21 #include "base/metrics/histogram_samples.h"
     22 #include "uploader/metrics_hashes.h"
     23 #include "uploader/proto/histogram_event.pb.h"
     24 #include "uploader/proto/system_profile.pb.h"
     25 #include "uploader/proto/user_action_event.pb.h"
     26 
     27 using base::Histogram;
     28 using base::HistogramBase;
     29 using base::HistogramSamples;
     30 using base::SampleCountIterator;
     31 using base::Time;
     32 using base::TimeDelta;
     33 using metrics::HistogramEventProto;
     34 using metrics::SystemProfileProto;
     35 using metrics::UserActionEventProto;
     36 
     37 namespace metrics {
     38 namespace {
     39 
     40 // Any id less than 16 bytes is considered to be a testing id.
     41 bool IsTestingID(const std::string& id) {
     42   return id.size() < 16;
     43 }
     44 
     45 }  // namespace
     46 
     47 MetricsLogBase::MetricsLogBase(const std::string& client_id,
     48                                int session_id,
     49                                LogType log_type,
     50                                const std::string& version_string)
     51     : num_events_(0),
     52       locked_(false),
     53       log_type_(log_type) {
     54   DCHECK_NE(NO_LOG, log_type);
     55   if (IsTestingID(client_id))
     56     uma_proto_.set_client_id(0);
     57   else
     58     uma_proto_.set_client_id(Hash(client_id));
     59 
     60   uma_proto_.set_session_id(session_id);
     61   uma_proto_.mutable_system_profile()->set_build_timestamp(GetBuildTime());
     62   uma_proto_.mutable_system_profile()->set_app_version(version_string);
     63 }
     64 
     65 MetricsLogBase::~MetricsLogBase() {}
     66 
     67 // static
     68 uint64_t MetricsLogBase::Hash(const std::string& value) {
     69   uint64_t hash = metrics::HashMetricName(value);
     70 
     71   // The following log is VERY helpful when folks add some named histogram into
     72   // the code, but forgot to update the descriptive list of histograms.  When
     73   // that happens, all we get to see (server side) is a hash of the histogram
     74   // name.  We can then use this logging to find out what histogram name was
     75   // being hashed to a given MD5 value by just running the version of Chromium
     76   // in question with --enable-logging.
     77   VLOG(1) << "Metrics: Hash numeric [" << value << "]=[" << hash << "]";
     78 
     79   return hash;
     80 }
     81 
     82 // static
     83 int64_t MetricsLogBase::GetBuildTime() {
     84   static int64_t integral_build_time = 0;
     85   if (!integral_build_time) {
     86     Time time = base::GetBuildTime();
     87     integral_build_time = static_cast<int64_t>(time.ToTimeT());
     88   }
     89   return integral_build_time;
     90 }
     91 
     92 // static
     93 int64_t MetricsLogBase::GetCurrentTime() {
     94   return (base::TimeTicks::Now() - base::TimeTicks()).InSeconds();
     95 }
     96 
     97 void MetricsLogBase::CloseLog() {
     98   DCHECK(!locked_);
     99   locked_ = true;
    100 }
    101 
    102 void MetricsLogBase::GetEncodedLog(std::string* encoded_log) {
    103   DCHECK(locked_);
    104   uma_proto_.SerializeToString(encoded_log);
    105 }
    106 
    107 void MetricsLogBase::RecordUserAction(const std::string& key) {
    108   DCHECK(!locked_);
    109 
    110   UserActionEventProto* user_action = uma_proto_.add_user_action_event();
    111   user_action->set_name_hash(Hash(key));
    112   user_action->set_time(GetCurrentTime());
    113 
    114   ++num_events_;
    115 }
    116 
    117 void MetricsLogBase::RecordHistogramDelta(const std::string& histogram_name,
    118                                           const HistogramSamples& snapshot) {
    119   DCHECK(!locked_);
    120   DCHECK_NE(0, snapshot.TotalCount());
    121 
    122   // We will ignore the MAX_INT/infinite value in the last element of range[].
    123 
    124   HistogramEventProto* histogram_proto = uma_proto_.add_histogram_event();
    125   histogram_proto->set_name_hash(Hash(histogram_name));
    126   histogram_proto->set_sum(snapshot.sum());
    127 
    128   for (scoped_ptr<SampleCountIterator> it = snapshot.Iterator(); !it->Done();
    129        it->Next()) {
    130     HistogramBase::Sample min;
    131     HistogramBase::Sample max;
    132     HistogramBase::Count count;
    133     it->Get(&min, &max, &count);
    134     HistogramEventProto::Bucket* bucket = histogram_proto->add_bucket();
    135     bucket->set_min(min);
    136     bucket->set_max(max);
    137     bucket->set_count(count);
    138   }
    139 
    140   // Omit fields to save space (see rules in histogram_event.proto comments).
    141   for (int i = 0; i < histogram_proto->bucket_size(); ++i) {
    142     HistogramEventProto::Bucket* bucket = histogram_proto->mutable_bucket(i);
    143     if (i + 1 < histogram_proto->bucket_size() &&
    144         bucket->max() == histogram_proto->bucket(i + 1).min()) {
    145       bucket->clear_max();
    146     } else if (bucket->max() == bucket->min() + 1) {
    147       bucket->clear_min();
    148     }
    149   }
    150 }
    151 
    152 }  // namespace metrics
    153