Home | History | Annotate | Download | only in metrics
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/metrics/histogram_base.h"
      6 
      7 #include <limits.h>
      8 
      9 #include <memory>
     10 #include <utility>
     11 
     12 #include "base/json/json_string_value_serializer.h"
     13 #include "base/logging.h"
     14 #include "base/metrics/histogram.h"
     15 #include "base/metrics/histogram_samples.h"
     16 #include "base/metrics/sparse_histogram.h"
     17 #include "base/metrics/statistics_recorder.h"
     18 #include "base/pickle.h"
     19 #include "base/process/process_handle.h"
     20 #include "base/strings/stringprintf.h"
     21 #include "base/values.h"
     22 
     23 namespace base {
     24 
     25 std::string HistogramTypeToString(HistogramType type) {
     26   switch (type) {
     27     case HISTOGRAM:
     28       return "HISTOGRAM";
     29     case LINEAR_HISTOGRAM:
     30       return "LINEAR_HISTOGRAM";
     31     case BOOLEAN_HISTOGRAM:
     32       return "BOOLEAN_HISTOGRAM";
     33     case CUSTOM_HISTOGRAM:
     34       return "CUSTOM_HISTOGRAM";
     35     case SPARSE_HISTOGRAM:
     36       return "SPARSE_HISTOGRAM";
     37   }
     38   NOTREACHED();
     39   return "UNKNOWN";
     40 }
     41 
     42 HistogramBase* DeserializeHistogramInfo(PickleIterator* iter) {
     43   int type;
     44   if (!iter->ReadInt(&type))
     45     return NULL;
     46 
     47   switch (type) {
     48     case HISTOGRAM:
     49       return Histogram::DeserializeInfoImpl(iter);
     50     case LINEAR_HISTOGRAM:
     51       return LinearHistogram::DeserializeInfoImpl(iter);
     52     case BOOLEAN_HISTOGRAM:
     53       return BooleanHistogram::DeserializeInfoImpl(iter);
     54     case CUSTOM_HISTOGRAM:
     55       return CustomHistogram::DeserializeInfoImpl(iter);
     56     case SPARSE_HISTOGRAM:
     57       return SparseHistogram::DeserializeInfoImpl(iter);
     58     default:
     59       return NULL;
     60   }
     61 }
     62 
     63 const HistogramBase::Sample HistogramBase::kSampleType_MAX = INT_MAX;
     64 HistogramBase* HistogramBase::report_histogram_ = nullptr;
     65 
     66 HistogramBase::HistogramBase(const std::string& name)
     67     : histogram_name_(name),
     68       flags_(kNoFlags) {}
     69 
     70 HistogramBase::~HistogramBase() {}
     71 
     72 void HistogramBase::CheckName(const StringPiece& name) const {
     73   DCHECK_EQ(histogram_name(), name);
     74 }
     75 
     76 void HistogramBase::SetFlags(int32_t flags) {
     77   HistogramBase::Count old_flags = subtle::NoBarrier_Load(&flags_);
     78   subtle::NoBarrier_Store(&flags_, old_flags | flags);
     79 }
     80 
     81 void HistogramBase::ClearFlags(int32_t flags) {
     82   HistogramBase::Count old_flags = subtle::NoBarrier_Load(&flags_);
     83   subtle::NoBarrier_Store(&flags_, old_flags & ~flags);
     84 }
     85 
     86 void HistogramBase::AddTime(const TimeDelta& time) {
     87   Add(static_cast<Sample>(time.InMilliseconds()));
     88 }
     89 
     90 void HistogramBase::AddBoolean(bool value) {
     91   Add(value ? 1 : 0);
     92 }
     93 
     94 bool HistogramBase::SerializeInfo(Pickle* pickle) const {
     95   if (!pickle->WriteInt(GetHistogramType()))
     96     return false;
     97   return SerializeInfoImpl(pickle);
     98 }
     99 
    100 uint32_t HistogramBase::FindCorruption(
    101     const HistogramSamples& /*samples*/) const {
    102   // Not supported by default.
    103   return NO_INCONSISTENCIES;
    104 }
    105 
    106 void HistogramBase::WriteJSON(std::string* output) const {
    107   Count count;
    108   int64_t sum;
    109   std::unique_ptr<ListValue> buckets(new ListValue());
    110   GetCountAndBucketData(&count, &sum, buckets.get());
    111   std::unique_ptr<DictionaryValue> parameters(new DictionaryValue());
    112   GetParameters(parameters.get());
    113 
    114   JSONStringValueSerializer serializer(output);
    115   DictionaryValue root;
    116   root.SetString("name", histogram_name());
    117   root.SetInteger("count", count);
    118   root.SetDouble("sum", static_cast<double>(sum));
    119   root.SetInteger("flags", flags());
    120   root.Set("params", std::move(parameters));
    121   root.Set("buckets", std::move(buckets));
    122   root.SetInteger("pid", GetCurrentProcId());
    123   serializer.Serialize(root);
    124 }
    125 
    126 // static
    127 void HistogramBase::EnableActivityReportHistogram(
    128     const std::string& process_type) {
    129   DCHECK(!report_histogram_);
    130   size_t existing = StatisticsRecorder::GetHistogramCount();
    131   if (existing != 0) {
    132     DVLOG(1) << existing
    133              << " histograms were created before reporting was enabled.";
    134   }
    135 
    136   std::string name =
    137       "UMA.Histograms.Activity" +
    138       (process_type.empty() ? process_type : "." + process_type);
    139 
    140   // Calling FactoryGet() here rather than using a histogram-macro works
    141   // around some problems with tests that could end up seeing the results
    142   // histogram when not expected due to a bad interaction between
    143   // HistogramTester and StatisticsRecorder.
    144   report_histogram_ = LinearHistogram::FactoryGet(
    145       name, 1, HISTOGRAM_REPORT_MAX, HISTOGRAM_REPORT_MAX + 1,
    146       kUmaTargetedHistogramFlag);
    147   report_histogram_->Add(HISTOGRAM_REPORT_CREATED);
    148 }
    149 
    150 void HistogramBase::FindAndRunCallback(HistogramBase::Sample sample) const {
    151   if ((flags() & kCallbackExists) == 0)
    152     return;
    153 
    154   StatisticsRecorder::OnSampleCallback cb =
    155       StatisticsRecorder::FindCallback(histogram_name());
    156   if (!cb.is_null())
    157     cb.Run(sample);
    158 }
    159 
    160 void HistogramBase::WriteAsciiBucketGraph(double current_size,
    161                                           double max_size,
    162                                           std::string* output) const {
    163   const int k_line_length = 72;  // Maximal horizontal width of graph.
    164   int x_count = static_cast<int>(k_line_length * (current_size / max_size)
    165                                  + 0.5);
    166   int x_remainder = k_line_length - x_count;
    167 
    168   while (0 < x_count--)
    169     output->append("-");
    170   output->append("O");
    171   while (0 < x_remainder--)
    172     output->append(" ");
    173 }
    174 
    175 const std::string HistogramBase::GetSimpleAsciiBucketRange(
    176     Sample sample) const {
    177   std::string result;
    178   if (kHexRangePrintingFlag & flags())
    179     StringAppendF(&result, "%#x", sample);
    180   else
    181     StringAppendF(&result, "%d", sample);
    182   return result;
    183 }
    184 
    185 void HistogramBase::WriteAsciiBucketValue(Count current,
    186                                           double scaled_sum,
    187                                           std::string* output) const {
    188   StringAppendF(output, " (%d = %3.1f%%)", current, current/scaled_sum);
    189 }
    190 
    191 // static
    192 void HistogramBase::ReportHistogramActivity(const HistogramBase& histogram,
    193                                             ReportActivity activity) {
    194   if (!report_histogram_)
    195     return;
    196 
    197   const int32_t flags = histogram.flags_;
    198   HistogramReport report_type = HISTOGRAM_REPORT_MAX;
    199   switch (activity) {
    200     case HISTOGRAM_CREATED:
    201       report_histogram_->Add(HISTOGRAM_REPORT_HISTOGRAM_CREATED);
    202       switch (histogram.GetHistogramType()) {
    203         case HISTOGRAM:
    204           report_type = HISTOGRAM_REPORT_TYPE_LOGARITHMIC;
    205           break;
    206         case LINEAR_HISTOGRAM:
    207           report_type = HISTOGRAM_REPORT_TYPE_LINEAR;
    208           break;
    209         case BOOLEAN_HISTOGRAM:
    210           report_type = HISTOGRAM_REPORT_TYPE_BOOLEAN;
    211           break;
    212         case CUSTOM_HISTOGRAM:
    213           report_type = HISTOGRAM_REPORT_TYPE_CUSTOM;
    214           break;
    215         case SPARSE_HISTOGRAM:
    216           report_type = HISTOGRAM_REPORT_TYPE_SPARSE;
    217           break;
    218       }
    219       report_histogram_->Add(report_type);
    220       if (flags & kIsPersistent)
    221         report_histogram_->Add(HISTOGRAM_REPORT_FLAG_PERSISTENT);
    222       if ((flags & kUmaStabilityHistogramFlag) == kUmaStabilityHistogramFlag)
    223         report_histogram_->Add(HISTOGRAM_REPORT_FLAG_UMA_STABILITY);
    224       else if (flags & kUmaTargetedHistogramFlag)
    225         report_histogram_->Add(HISTOGRAM_REPORT_FLAG_UMA_TARGETED);
    226       break;
    227 
    228     case HISTOGRAM_LOOKUP:
    229       report_histogram_->Add(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP);
    230       break;
    231   }
    232 }
    233 
    234 }  // namespace base
    235