Impala
Impalaistheopensource,nativeanalyticdatabaseforApacheHadoop.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
metrics.cc
Go to the documentation of this file.
1 // Copyright 2012 Cloudera Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "util/metrics.h"
16 
17 #include <sstream>
18 #include <boost/algorithm/string/join.hpp>
19 #include <boost/bind.hpp>
20 #include <boost/mem_fn.hpp>
21 #include <boost/math/special_functions/fpclassify.hpp>
22 #include <gutil/strings/substitute.h>
23 #include <rapidjson/stringbuffer.h>
24 #include <rapidjson/prettywriter.h>
25 
26 #include "common/logging.h"
27 #include "util/impalad-metrics.h"
28 
29 #include "common/names.h"
30 
31 using namespace impala;
32 using namespace rapidjson;
33 using namespace strings;
34 
35 namespace impala {
36 
37 template <>
38 void ToJsonValue<string>(const string& value, const TUnit::type unit,
39  Document* document, Value* out_val) {
40  Value val(value.c_str(), document->GetAllocator());
41  *out_val = val;
42 }
43 
44 }
45 
46 void Metric::AddStandardFields(Document* document, Value* val) {
47  Value name(key_.c_str(), document->GetAllocator());
48  val->AddMember("name", name, document->GetAllocator());
49  Value desc(description_.c_str(), document->GetAllocator());
50  val->AddMember("description", desc, document->GetAllocator());
51  Value metric_value(ToHumanReadable().c_str(), document->GetAllocator());
52  val->AddMember("human_readable", metric_value, document->GetAllocator());
53 }
54 
55 MetricGroup::MetricGroup(const std::string& name)
56  : obj_pool_(new ObjectPool()), name_(name) { }
57 
59  if (webserver != NULL) {
60  Webserver::UrlCallback default_callback =
61  bind<void>(mem_fn(&MetricGroup::CMCompatibleCallback), this, _1, _2);
62  webserver->RegisterUrlCallback("/jsonmetrics", "legacy-metrics.tmpl",
63  default_callback, false);
64 
65  Webserver::UrlCallback json_callback =
66  bind<void>(mem_fn(&MetricGroup::TemplateCallback), this, _1, _2);
67  webserver->RegisterUrlCallback("/metrics", "metrics.tmpl", json_callback);
68  }
69 
70  return Status::OK;
71 }
72 
74  Document* document) {
75  // If the request has a 'metric' argument, search all top-level metrics for that metric
76  // only. Otherwise, return document with list of all metrics at the top level.
77  Webserver::ArgumentMap::const_iterator metric_name = args.find("metric");
78  lock_guard<mutex> l(lock_);
79  if (metric_name != args.end()) {
80  MetricMap::const_iterator metric = metric_map_.find(metric_name->second);
81  if (metric != metric_map_.end()) {
82  metric->second->ToLegacyJson(document);
83  }
84  return;
85  }
86 
87  stack<MetricGroup*> groups;
88  groups.push(this);
89  while (!groups.empty()) {
90  // Depth-first traversal of children to flatten all metrics, which is what was
91  // expected by CM before we introduced metric groups.
92  MetricGroup* group = groups.top();
93  groups.pop();
94  BOOST_FOREACH(const ChildGroupMap::value_type& child, group->children_) {
95  groups.push(child.second);
96  }
97  BOOST_FOREACH(const MetricMap::value_type& m, group->metric_map_) {
98  m.second->ToLegacyJson(document);
99  }
100  }
101 }
102 
104  Document* document) {
105  Webserver::ArgumentMap::const_iterator metric_group = args.find("metric_group");
106  lock_guard<mutex> l(lock_);
107  // If no particular metric group is requested, render this metric group (and all its
108  // children).
109  if (metric_group == args.end()) {
110  Value container;
111  ToJson(true, document, &container);
112  document->AddMember("metric_group", container, document->GetAllocator());
113  return;
114  }
115 
116  // Search all metric groups to find the one we're looking for. In the future, we'll
117  // change this to support path-based resolution of metric groups.
118  MetricGroup* found_group = NULL;
119  stack<MetricGroup*> groups;
120  groups.push(this);
121  while (!groups.empty() && found_group == NULL) {
122  // Depth-first traversal of children to flatten all metrics, which is what was
123  // expected by CM before we introduced metric groups.
124  MetricGroup* group = groups.top();
125  groups.pop();
126  BOOST_FOREACH(const ChildGroupMap::value_type& child, group->children_) {
127  if (child.first == metric_group->second) {
128  found_group = child.second;
129  break;
130  }
131  groups.push(child.second);
132  }
133  }
134  if (found_group != NULL) {
135  Value container;
136  found_group->ToJson(false, document, &container);
137  document->AddMember("metric_group", container, document->GetAllocator());
138  } else {
139  Value error(Substitute("Metric group $0 not found", metric_group->second).c_str(),
140  document->GetAllocator());
141  document->AddMember("error", error, document->GetAllocator());
142  }
143 }
144 
145 void MetricGroup::ToJson(bool include_children, Document* document, Value* out_val) {
146  Value metric_list(kArrayType);
147  BOOST_FOREACH(const MetricMap::value_type& m, metric_map_) {
148  Value metric_value;
149  m.second->ToJson(document, &metric_value);
150  metric_list.PushBack(metric_value, document->GetAllocator());
151  }
152 
153  Value container(kObjectType);
154  container.AddMember("metrics", metric_list, document->GetAllocator());
155  container.AddMember("name", name_.c_str(), document->GetAllocator());
156  if (include_children) {
157  Value child_groups(kArrayType);
158  BOOST_FOREACH(const ChildGroupMap::value_type& child, children_) {
159  Value child_value;
160  child.second->ToJson(true, document, &child_value);
161  child_groups.PushBack(child_value, document->GetAllocator());
162  }
163  container.AddMember("child_groups", child_groups, document->GetAllocator());
164  }
165 
166  *out_val = container;
167 }
168 
170  lock_guard<mutex> l(lock_);
171  ChildGroupMap::iterator it = children_.find(name);
172  if (it != children_.end()) return it->second;
173  MetricGroup* group = obj_pool_->Add(new MetricGroup(name));
174  children_[name] = group;
175  return group;
176 }
177 
179  Webserver::ArgumentMap empty_map;
180  Document document;
181  document.SetObject();
182  TemplateCallback(empty_map, &document);
183  StringBuffer strbuf;
184  PrettyWriter<StringBuffer> writer(strbuf);
185  document.Accept(writer);
186  return strbuf.GetString();
187 }
void ToJsonValue< string >(const string &value, const TUnit::type unit, Document *document, Value *out_val)
Definition: metrics.cc:38
boost::scoped_ptr< ObjectPool > obj_pool_
Pool containing all metric objects.
Definition: metrics.h:287
void AddStandardFields(rapidjson::Document *document, rapidjson::Value *val)
Definition: metrics.cc:46
boost::function< void(const ArgumentMap &args, rapidjson::Document *json)> UrlCallback
Definition: webserver.h:38
boost::scoped_ptr< ObjectPool > obj_pool_
Object pool owned by the coordinator. Any executor will have its own pool.
Definition: coordinator.h:296
MetricGroup(const std::string &name)
Definition: metrics.cc:55
MetricGroup * GetChildGroup(const std::string &name)
Creates or returns an already existing child metric group.
Definition: metrics.cc:169
MetricGroups may be organised hierarchically as a tree.
Definition: metrics.h:200
void RegisterUrlCallback(const std::string &path, const std::string &template_filename, const UrlCallback &callback, bool is_on_nav_bar=true)
Only one callback may be registered per URL.
Definition: webserver.cc:412
Status Init(Webserver *webserver)
Definition: metrics.cc:58
std::map< std::string, std::string > ArgumentMap
Definition: webserver.h:36
const std::string & name() const
Definition: metrics.h:283
std::string DebugString()
Useful for debuggers, returns the output of CMCompatibleCallback().
Definition: metrics.cc:178
void TemplateCallback(const Webserver::ArgumentMap &args, rapidjson::Document *document)
Definition: metrics.cc:103
std::string name_
Name of this metric group.
Definition: metrics.h:290
MetricMap metric_map_
Definition: metrics.h:297
void ToJson(bool include_children, rapidjson::Document *document, rapidjson::Value *out_val)
Converts this metric group (and optionally all of its children recursively) to JSON.
Definition: metrics.cc:145
ChildGroupMap children_
Definition: metrics.h:301
void CMCompatibleCallback(const Webserver::ArgumentMap &args, rapidjson::Document *document)
Definition: metrics.cc:73
static const Status OK
Definition: status.h:87
boost::mutex lock_
Guards metric_map_ and children_.
Definition: metrics.h:293
string name
Definition: cpu-info.cc:50