| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // Author: jmarantz@google.com (Joshua Marantz) |
| |
| #ifndef PAGESPEED_KERNEL_BASE_STATISTICS_TEMPLATE_H_ |
| #define PAGESPEED_KERNEL_BASE_STATISTICS_TEMPLATE_H_ |
| |
| #include <algorithm> |
| #include <cstddef> |
| #include <map> |
| #include <vector> |
| |
| #include "pagespeed/kernel/base/basictypes.h" |
| #include "pagespeed/kernel/base/statistics.h" |
| #include "pagespeed/kernel/base/stl_util.h" |
| #include "pagespeed/kernel/base/string.h" |
| #include "pagespeed/kernel/base/string_util.h" |
| #include "pagespeed/kernel/base/writer.h" |
| |
| namespace net_instaweb { |
| class MessageHandler; |
| |
| // This class makes it easier to define new Statistics implementations |
| // by providing a templatized implementation of variable registration and |
| // management. |
| template<class Var, class Hist, class TimedVar> class StatisticsTemplate |
| : public Statistics { |
| public: |
| StatisticsTemplate() {} |
| virtual ~StatisticsTemplate() { |
| STLDeleteContainerPointers(variables_.begin(), variables_.end()); |
| STLDeleteContainerPointers(histograms_.begin(), histograms_.end()); |
| STLDeleteContainerPointers(timed_vars_.begin(), timed_vars_.end()); |
| } |
| |
| // Implementations of Statistics API --- see base class docs for |
| // description. |
| virtual Var* AddVariable(const StringPiece& name) { |
| Var* var = FindVariable(name); |
| if (var == NULL) { |
| var = NewVariable(name, variables_.size()); |
| variables_.push_back(var); |
| variable_names_.push_back(name.as_string()); |
| variable_map_[name.as_string()] = var; |
| } |
| return var; |
| } |
| |
| virtual Var* AddGlobalVariable(const StringPiece& name) { |
| Var* var = FindVariable(name); |
| if (var == NULL) { |
| var = NewGlobalVariable(name, variables_.size()); |
| variables_.push_back(var); |
| variable_names_.push_back(name.as_string()); |
| variable_map_[name.as_string()] = var; |
| } |
| return var; |
| } |
| |
| virtual Var* FindVariable(const StringPiece& name) const { |
| typename VarMap::const_iterator p = variable_map_.find(name.as_string()); |
| Var* var = NULL; |
| if (p != variable_map_.end()) { |
| var = p->second; |
| } |
| return var; |
| } |
| |
| virtual Hist* AddHistogram(const StringPiece& name) { |
| Hist* hist = FindHistogram(name); |
| if (hist == NULL) { |
| hist = NewHistogram(name); |
| histograms_.push_back(hist); |
| histogram_names_.push_back(name.as_string()); |
| histogram_map_[name.as_string()] = hist; |
| } |
| return hist; |
| } |
| |
| virtual Hist* FindHistogram(const StringPiece& name) const { |
| typename HistMap::const_iterator p = histogram_map_.find(name.as_string()); |
| Hist* hist = NULL; |
| if (p != histogram_map_.end()) { |
| hist = p->second; |
| } |
| return hist; |
| } |
| |
| virtual TimedVar* AddTimedVariable(const StringPiece& name, |
| const StringPiece& group) { |
| TimedVar* timedvar = FindTimedVariable(name); |
| if (timedvar == NULL) { |
| timedvar = NewTimedVariable(name, timed_vars_.size()); |
| timed_vars_.push_back(timedvar); |
| timed_var_map_[name.as_string()] = timedvar; |
| timed_var_group_map_[group.as_string()].push_back(name.as_string()); |
| } |
| return timedvar; |
| } |
| |
| virtual TimedVar* FindTimedVariable(const StringPiece& name) const { |
| typename TimedVarMap::const_iterator p = |
| timed_var_map_.find(name.as_string()); |
| TimedVar* timedvar = NULL; |
| if (p != timed_var_map_.end()) { |
| timedvar = p->second; |
| } |
| return timedvar; |
| } |
| |
| virtual const StringVector& HistogramNames() { |
| return histogram_names_; |
| } |
| |
| virtual const std::map<GoogleString, StringVector>& TimedVariableMap() { |
| return timed_var_group_map_; |
| } |
| |
| virtual void Dump(Writer* writer, MessageHandler* message_handler) { |
| int longest_string = 0; |
| for (int i = 0, n = variables_.size(); i < n; ++i) { |
| const GoogleString& var_name = variable_names_[i]; |
| int length_number = Integer64ToString(variables_[i]->Get()).size(); |
| int length_name = var_name.size(); |
| longest_string = std::max(longest_string, length_name + length_number); |
| } |
| |
| GoogleString spaces_buffer = GoogleString(longest_string, ' '); |
| StringPiece spaces(spaces_buffer); |
| for (int i = 0, n = variables_.size(); i < n; ++i) { |
| const GoogleString& var_name = variable_names_[i]; |
| GoogleString var_as_str = Integer64ToString(variables_[i]->Get()); |
| writer->Write(var_name, message_handler); |
| writer->Write(": ", message_handler); |
| int num_spaces = longest_string - var_name.size() - var_as_str.size(); |
| writer->Write(spaces.substr(0, num_spaces), message_handler); |
| writer->Write(var_as_str, message_handler); |
| writer->Write("\n", message_handler); |
| } |
| } |
| |
| virtual void Clear() { |
| for (int i = 0, n = variables_.size(); i < n; ++i) { |
| Variable* var = variables_[i]; |
| var->Clear(); |
| } |
| for (int i = 0, n = histograms_.size(); i < n; ++i) { |
| Histogram* hist = histograms_[i]; |
| hist->Clear(); |
| } |
| for (int i = 0, n = timed_vars_.size(); i < n; ++i) { |
| TimedVariable* timedvar = timed_vars_[i]; |
| timedvar->Clear(); |
| } |
| } |
| |
| protected: |
| // Interface to subclass. |
| virtual Var* NewVariable(const StringPiece& name, int index) = 0; |
| |
| // Default implementation just calls NewVariable |
| virtual Var* NewGlobalVariable(const StringPiece& name, int index) { |
| return NewVariable(name, index); |
| } |
| |
| virtual Hist* NewHistogram(const StringPiece& name) = 0; |
| virtual TimedVar* NewTimedVariable(const StringPiece& name, int index) = 0; |
| |
| size_t variables_size() const { return variables_.size(); } |
| Var* variables(size_t pos) { return variables_.at(pos); } |
| |
| size_t histograms_size() const { return histograms_.size(); } |
| Hist* histograms(size_t pos) { return histograms_.at(pos); } |
| |
| const GoogleString& histogram_names(size_t pos) const { |
| return histogram_names_.at(pos); |
| } |
| |
| private: |
| typedef std::vector<Var*> VarVector; |
| typedef std::map<GoogleString, Var*> VarMap; |
| typedef std::vector<Hist*> HistVector; |
| typedef std::map<GoogleString, Hist*> HistMap; |
| |
| typedef std::vector<TimedVar*> TimedVarVector; |
| typedef std::map<GoogleString, TimedVar*> TimedVarMap; |
| VarVector variables_; |
| VarMap variable_map_; |
| HistVector histograms_; |
| HistMap histogram_map_; |
| TimedVarVector timed_vars_; |
| TimedVarMap timed_var_map_; |
| // map between group and names of stats. |
| std::map<GoogleString, StringVector> timed_var_group_map_; |
| StringVector variable_names_; |
| StringVector histogram_names_; |
| |
| DISALLOW_COPY_AND_ASSIGN(StatisticsTemplate); |
| }; |
| |
| // A specialization of StatisticsTemplate for implementations that can only |
| // do scalar statistics variables. |
| template<class Var> |
| class ScalarStatisticsTemplate |
| : public StatisticsTemplate<Var, CountHistogram, FakeTimedVariable> { |
| public: |
| ScalarStatisticsTemplate() {} |
| virtual ~ScalarStatisticsTemplate() {} |
| |
| protected: |
| virtual CountHistogram* NewHistogram(const StringPiece& name) { |
| return new CountHistogram; |
| } |
| |
| virtual FakeTimedVariable* NewTimedVariable(const StringPiece& name, |
| int index) { |
| return this->NewFakeTimedVariable(name, index); |
| } |
| }; |
| |
| } // namespace net_instaweb |
| |
| #endif // PAGESPEED_KERNEL_BASE_STATISTICS_TEMPLATE_H_ |