This source file includes following definitions.
- Initialize
- IsActive
- RegisterOrDeleteDuplicate
- RegisterOrDeleteDuplicateRanges
- WriteHTMLGraph
- WriteGraph
- ToJSON
- GetHistograms
- GetBucketRanges
- FindHistogram
- GetSnapshot
- DumpHistogramsToVlog
#include "base/metrics/statistics_recorder.h"
#include "base/at_exit.h"
#include "base/debug/leak_annotations.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/values.h"
using std::list;
using std::string;
namespace {
base::LazyInstance<base::StatisticsRecorder>::Leaky g_statistics_recorder_ =
    LAZY_INSTANCE_INITIALIZER;
}  
namespace base {
void StatisticsRecorder::Initialize() {
  
  g_statistics_recorder_.Get();
}
bool StatisticsRecorder::IsActive() {
  if (lock_ == NULL)
    return false;
  base::AutoLock auto_lock(*lock_);
  return NULL != histograms_;
}
HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate(
    HistogramBase* histogram) {
  
  
  
  
  
  if (lock_ == NULL) {
    ANNOTATE_LEAKING_OBJECT_PTR(histogram);  
    return histogram;
  }
  HistogramBase* histogram_to_delete = NULL;
  HistogramBase* histogram_to_return = NULL;
  {
    base::AutoLock auto_lock(*lock_);
    if (histograms_ == NULL) {
      histogram_to_return = histogram;
    } else {
      const string& name = histogram->histogram_name();
      HistogramMap::iterator it = histograms_->find(name);
      if (histograms_->end() == it) {
        (*histograms_)[name] = histogram;
        ANNOTATE_LEAKING_OBJECT_PTR(histogram);  
        histogram_to_return = histogram;
      } else if (histogram == it->second) {
        
        histogram_to_return = histogram;
      } else {
        
        histogram_to_return = it->second;
        histogram_to_delete = histogram;
      }
    }
  }
  delete histogram_to_delete;
  return histogram_to_return;
}
const BucketRanges* StatisticsRecorder::RegisterOrDeleteDuplicateRanges(
    const BucketRanges* ranges) {
  DCHECK(ranges->HasValidChecksum());
  scoped_ptr<const BucketRanges> ranges_deleter;
  if (lock_ == NULL) {
    ANNOTATE_LEAKING_OBJECT_PTR(ranges);
    return ranges;
  }
  base::AutoLock auto_lock(*lock_);
  if (ranges_ == NULL) {
    ANNOTATE_LEAKING_OBJECT_PTR(ranges);
    return ranges;
  }
  list<const BucketRanges*>* checksum_matching_list;
  RangesMap::iterator ranges_it = ranges_->find(ranges->checksum());
  if (ranges_->end() == ranges_it) {
    
    checksum_matching_list = new list<const BucketRanges*>();
    ANNOTATE_LEAKING_OBJECT_PTR(checksum_matching_list);
    (*ranges_)[ranges->checksum()] = checksum_matching_list;
  } else {
    checksum_matching_list = ranges_it->second;
  }
  list<const BucketRanges*>::iterator checksum_matching_list_it;
  for (checksum_matching_list_it = checksum_matching_list->begin();
       checksum_matching_list_it != checksum_matching_list->end();
       ++checksum_matching_list_it) {
    const BucketRanges* existing_ranges = *checksum_matching_list_it;
    if (existing_ranges->Equals(ranges)) {
      if (existing_ranges == ranges) {
        return ranges;
      } else {
        ranges_deleter.reset(ranges);
        return existing_ranges;
      }
    }
  }
  
  
  checksum_matching_list->push_front(ranges);
  return ranges;
}
void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
                                        std::string* output) {
  if (!IsActive())
    return;
  Histograms snapshot;
  GetSnapshot(query, &snapshot);
  for (Histograms::iterator it = snapshot.begin();
       it != snapshot.end();
       ++it) {
    (*it)->WriteHTMLGraph(output);
    output->append("<br><hr><br>");
  }
}
void StatisticsRecorder::WriteGraph(const std::string& query,
                                    std::string* output) {
  if (!IsActive())
    return;
  if (query.length())
    StringAppendF(output, "Collections of histograms for %s\n", query.c_str());
  else
    output->append("Collections of all histograms\n");
  Histograms snapshot;
  GetSnapshot(query, &snapshot);
  for (Histograms::iterator it = snapshot.begin();
       it != snapshot.end();
       ++it) {
    (*it)->WriteAscii(output);
    output->append("\n");
  }
}
std::string StatisticsRecorder::ToJSON(const std::string& query) {
  if (!IsActive())
    return std::string();
  std::string output("{");
  if (!query.empty()) {
    output += "\"query\":";
    EscapeJSONString(query, true, &output);
    output += ",";
  }
  Histograms snapshot;
  GetSnapshot(query, &snapshot);
  output += "\"histograms\":[";
  bool first_histogram = true;
  for (Histograms::const_iterator it = snapshot.begin(); it != snapshot.end();
       ++it) {
    if (first_histogram)
      first_histogram = false;
    else
      output += ",";
    std::string json;
    (*it)->WriteJSON(&json);
    output += json;
  }
  output += "]}";
  return output;
}
void StatisticsRecorder::GetHistograms(Histograms* output) {
  if (lock_ == NULL)
    return;
  base::AutoLock auto_lock(*lock_);
  if (histograms_ == NULL)
    return;
  for (HistogramMap::iterator it = histograms_->begin();
       histograms_->end() != it;
       ++it) {
    DCHECK_EQ(it->first, it->second->histogram_name());
    output->push_back(it->second);
  }
}
void StatisticsRecorder::GetBucketRanges(
    std::vector<const BucketRanges*>* output) {
  if (lock_ == NULL)
    return;
  base::AutoLock auto_lock(*lock_);
  if (ranges_ == NULL)
    return;
  for (RangesMap::iterator it = ranges_->begin();
       ranges_->end() != it;
       ++it) {
    list<const BucketRanges*>* ranges_list = it->second;
    list<const BucketRanges*>::iterator ranges_list_it;
    for (ranges_list_it = ranges_list->begin();
         ranges_list_it != ranges_list->end();
         ++ranges_list_it) {
      output->push_back(*ranges_list_it);
    }
  }
}
HistogramBase* StatisticsRecorder::FindHistogram(const std::string& name) {
  if (lock_ == NULL)
    return NULL;
  base::AutoLock auto_lock(*lock_);
  if (histograms_ == NULL)
    return NULL;
  HistogramMap::iterator it = histograms_->find(name);
  if (histograms_->end() == it)
    return NULL;
  return it->second;
}
void StatisticsRecorder::GetSnapshot(const std::string& query,
                                     Histograms* snapshot) {
  if (lock_ == NULL)
    return;
  base::AutoLock auto_lock(*lock_);
  if (histograms_ == NULL)
    return;
  for (HistogramMap::iterator it = histograms_->begin();
       histograms_->end() != it;
       ++it) {
    if (it->first.find(query) != std::string::npos)
      snapshot->push_back(it->second);
  }
}
StatisticsRecorder::StatisticsRecorder() {
  DCHECK(!histograms_);
  if (lock_ == NULL) {
    
    
    
    
    
    
    lock_ = new base::Lock;
  }
  base::AutoLock auto_lock(*lock_);
  histograms_ = new HistogramMap;
  ranges_ = new RangesMap;
  if (VLOG_IS_ON(1))
    AtExitManager::RegisterCallback(&DumpHistogramsToVlog, this);
}
void StatisticsRecorder::DumpHistogramsToVlog(void* instance) {
  DCHECK(VLOG_IS_ON(1));
  StatisticsRecorder* me = reinterpret_cast<StatisticsRecorder*>(instance);
  string output;
  me->WriteGraph(std::string(), &output);
  VLOG(1) << output;
}
StatisticsRecorder::~StatisticsRecorder() {
  DCHECK(histograms_ && ranges_ && lock_);
  
  scoped_ptr<HistogramMap> histograms_deleter;
  scoped_ptr<RangesMap> ranges_deleter;
  
  
  {
    base::AutoLock auto_lock(*lock_);
    histograms_deleter.reset(histograms_);
    ranges_deleter.reset(ranges_);
    histograms_ = NULL;
    ranges_ = NULL;
  }
  
}
StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
StatisticsRecorder::RangesMap* StatisticsRecorder::ranges_ = NULL;
base::Lock* StatisticsRecorder::lock_ = NULL;
}