blob: d45fdeda41d22d74dc870023b062c3a924413365 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
#include "util/memusage-path-handlers.h"
#include <gperftools/malloc_extension.h>
#include "runtime/mem-tracker.h"
#include "util/common-metrics.h"
#include "util/mem-info.h"
#include "util/pretty-printer.h"
#include "common/names.h"
using namespace impala;
using namespace rapidjson;
/// A MemTracker tracks memory consumption and limits which will be displayed. This method
/// adds the mem_limit and the current memory consumption to the rapidjson document. Also,
/// it dumps all the additional mem trackers to the rapidjson document.
void AddMemTracker(MemTracker* mem_tracker,
const Webserver::WebRequest& req, Document* document) {
DCHECK(mem_tracker != NULL);
Value mem_limit(PrettyPrinter::Print(mem_tracker->limit(), TUnit::BYTES).c_str(),
document->GetAllocator());
document->AddMember("mem_limit", mem_limit, document->GetAllocator());
Value consumption(
PrettyPrinter::Print(mem_tracker->consumption(), TUnit::BYTES).c_str(),
document->GetAllocator());
document->AddMember("consumption", consumption, document->GetAllocator());
// Dump all mem trackers.
Value detailed(mem_tracker->LogUsage(MemTracker::UNLIMITED_DEPTH).c_str(),
document->GetAllocator());
document->AddMember("detailed", detailed, document->GetAllocator());
}
/// Adds the following malloc data structures to the rapidjson document.
/// - Total inuse memory by application.
/// - Free memory(thread, central and page heap),
/// - Freelist of central cache, each class.
/// - Page heap freelist.
void AddTCmallocOverview(const Webserver::WebRequest& req, Document* document) {
stringstream ss;
#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
ss << "Memory tracking is not available with address or thread sanitizer builds.";
#else
char buf[2048];
MallocExtension::instance()->GetStats(buf, 2048);
ss << string(buf);
#endif
Value overview(ss.str().c_str(), document->GetAllocator());
document->AddMember("overview", overview, document->GetAllocator());
}
/// Adds the system memory configuration to the rapidjson document.
void AddSystemInfo(const Webserver::WebRequest& req, Document* document) {
Value systeminfo(MemInfo::DebugString().c_str(), document->GetAllocator());
document->AddMember("systeminfo", systeminfo, document->GetAllocator());
}
/// A MetricGroup is a container for a set of metric. This method extracts and adds the
/// initialized JVM, buffer-pool and aggregated memory metrics to the rapidjson document
/// from the given MetricGroup.
void AddMetricGroup(MetricGroup* metric_group,
const Webserver::WebRequest& req, Document* document) {
if (metric_group != nullptr) {
MetricGroup* aggregate_group = metric_group->FindChildGroup("memory");
if (aggregate_group != nullptr) {
Value json_metrics(kObjectType);
aggregate_group->ToJson(false, document, &json_metrics);
document->AddMember(
"aggregate_metrics", json_metrics["metrics"], document->GetAllocator());
}
MetricGroup* jvm_group = metric_group->FindChildGroup("jvm");
if (jvm_group != nullptr) {
Value jvm(kObjectType);
jvm_group->ToJson(false, document, &jvm);
Value heap(kArrayType);
Value non_heap(kArrayType);
Value total(kArrayType);
for (SizeType i = 0; i < jvm["metrics"].Size(); ++i) {
if (strstr(jvm["metrics"][i]["name"].GetString(), "total") != nullptr) {
total.PushBack(jvm["metrics"][i], document->GetAllocator());
} else if (strstr(jvm["metrics"][i]["name"].GetString(), "non-heap") != nullptr) {
non_heap.PushBack(jvm["metrics"][i], document->GetAllocator());
} else if (strstr(jvm["metrics"][i]["name"].GetString(), "heap") != nullptr) {
heap.PushBack(jvm["metrics"][i], document->GetAllocator());
}
}
document->AddMember("jvm_total", total, document->GetAllocator());
document->AddMember("jvm_heap", heap, document->GetAllocator());
document->AddMember("jvm_non_heap", non_heap, document->GetAllocator());
}
MetricGroup* buffer_pool_group = metric_group->FindChildGroup("buffer-pool");
if (buffer_pool_group != nullptr) {
Value json_metrics(kObjectType);
buffer_pool_group->ToJson(false, document, &json_metrics);
document->AddMember(
"buffer_pool", json_metrics["metrics"], document->GetAllocator());
}
}
}
void impala::AddMemUsageCallbacks(Webserver* webserver, MemTracker* mem_tracker,
MetricGroup* metric_group) {
if (mem_tracker != nullptr) {
auto callback = [mem_tracker, metric_group]
(const Webserver::WebRequest& req, Document* doc) {
AddMemTracker(mem_tracker, req, doc);
AddTCmallocOverview(req, doc);
AddSystemInfo(req, doc);
AddMetricGroup(metric_group, req, doc);
};
webserver->RegisterUrlCallback("/memz", "memz.tmpl", callback, true);
} else {
auto callback = [metric_group]
(const Webserver::WebRequest& req, Document* doc) {
AddTCmallocOverview(req, doc);
AddSystemInfo(req, doc);
AddMetricGroup(metric_group, req, doc);
};
webserver->RegisterUrlCallback("/memz", "memz.tmpl", callback, true);
}
}