496 lines
22 KiB
C++
496 lines
22 KiB
C++
// 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 "jvm_metrics.h"
|
|
|
|
#include <util/jni-util.h>
|
|
|
|
#include <functional>
|
|
|
|
#include "common/config.h"
|
|
#include "util/metrics.h"
|
|
namespace doris {
|
|
|
|
#define DEFINE_JVM_SIZE_BYTES_METRIC(name, type) \
|
|
DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(name##_##type, MetricUnit::BYTES, "", name, \
|
|
Labels({{"type", #type}}));
|
|
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_heap_size_bytes, max);
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_heap_size_bytes, committed);
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_heap_size_bytes, used);
|
|
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_non_heap_size_bytes, used);
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_non_heap_size_bytes, committed);
|
|
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_young_size_bytes, used);
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_young_size_bytes, peak_used);
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_young_size_bytes, max);
|
|
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_old_size_bytes, used);
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_old_size_bytes, peak_used);
|
|
DEFINE_JVM_SIZE_BYTES_METRIC(jvm_old_size_bytes, max);
|
|
|
|
#define DEFINE_JVM_THREAD_METRIC(type) \
|
|
DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_thread_##type, MetricUnit::NOUNIT, "", jvm_thread, \
|
|
Labels({{"type", #type}}));
|
|
|
|
DEFINE_JVM_THREAD_METRIC(count);
|
|
DEFINE_JVM_THREAD_METRIC(peak_count);
|
|
DEFINE_JVM_THREAD_METRIC(new_count);
|
|
DEFINE_JVM_THREAD_METRIC(runnable_count);
|
|
DEFINE_JVM_THREAD_METRIC(blocked_count);
|
|
DEFINE_JVM_THREAD_METRIC(waiting_count);
|
|
DEFINE_JVM_THREAD_METRIC(timed_waiting_count);
|
|
DEFINE_JVM_THREAD_METRIC(terminated_count);
|
|
|
|
DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_gc_g1_young_generation_count, MetricUnit::NOUNIT, "",
|
|
jvm_gc,
|
|
Labels({{"name", "G1 Young generation Count"},
|
|
{"type", "count"}}));
|
|
|
|
DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_gc_g1_young_generation_time_ms, MetricUnit::MILLISECONDS,
|
|
"", jvm_gc,
|
|
Labels({{"name", "G1 Young generation Time"},
|
|
{"type", "time"}}));
|
|
|
|
DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_gc_g1_old_generation_count, MetricUnit::NOUNIT, "", jvm_gc,
|
|
Labels({{"name", "G1 Old generation Count"},
|
|
{"type", "count"}}));
|
|
|
|
DEFINE_COUNTER_METRIC_PROTOTYPE_5ARG(jvm_gc_g1_old_generation_time_ms, MetricUnit::MILLISECONDS, "",
|
|
jvm_gc,
|
|
Labels({{"name", "G1 Old generation Time"},
|
|
{"type", "time"}}));
|
|
|
|
const char* JvmMetrics::_s_hook_name = "jvm_metrics";
|
|
|
|
JvmMetrics::JvmMetrics(MetricRegistry* registry, JNIEnv* env) {
|
|
DCHECK(registry != nullptr);
|
|
_registry = registry;
|
|
|
|
_server_entity = _registry->register_entity("server");
|
|
DCHECK(_server_entity != nullptr);
|
|
|
|
do {
|
|
if (!doris::config::enable_jvm_monitor) {
|
|
break;
|
|
}
|
|
try {
|
|
_jvm_stats.init(env);
|
|
} catch (...) {
|
|
LOG(WARNING) << "JVM STATS INIT FAIL";
|
|
break;
|
|
}
|
|
if (!_jvm_stats.init_complete()) {
|
|
break;
|
|
}
|
|
_server_entity->register_hook(_s_hook_name, std::bind(&JvmMetrics::update, this));
|
|
} while (false);
|
|
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_heap_size_bytes_max);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_heap_size_bytes_committed);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_heap_size_bytes_used);
|
|
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_non_heap_size_bytes_used);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_non_heap_size_bytes_committed);
|
|
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_young_size_bytes_used);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_young_size_bytes_peak_used);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_young_size_bytes_max);
|
|
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_old_size_bytes_used);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_old_size_bytes_peak_used);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_old_size_bytes_max);
|
|
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_count);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_peak_count);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_new_count);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_runnable_count);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_blocked_count);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_waiting_count);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_timed_waiting_count);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_thread_terminated_count);
|
|
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_gc_g1_young_generation_count);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_gc_g1_young_generation_time_ms);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_gc_g1_old_generation_count);
|
|
INT_GAUGE_METRIC_REGISTER(_server_entity, jvm_gc_g1_old_generation_time_ms);
|
|
}
|
|
|
|
void JvmMetrics::update() {
|
|
static long fail_count = 0;
|
|
bool have_exception = false;
|
|
try {
|
|
_jvm_stats.refresh(this);
|
|
} catch (...) {
|
|
have_exception = true;
|
|
LOG(WARNING) << "JVM MONITOR UPDATE FAIL!";
|
|
fail_count++;
|
|
}
|
|
|
|
//When 30 consecutive exceptions occur, turn off jvm information collection.
|
|
if (!have_exception) {
|
|
fail_count = 0;
|
|
}
|
|
if (fail_count >= 30) {
|
|
LOG(WARNING) << "JVM MONITOR CLOSE!";
|
|
_jvm_stats.set_complete(false);
|
|
_server_entity->deregister_hook(_s_hook_name);
|
|
|
|
jvm_heap_size_bytes_max->set_value(0);
|
|
jvm_heap_size_bytes_committed->set_value(0);
|
|
jvm_heap_size_bytes_used->set_value(0);
|
|
|
|
jvm_non_heap_size_bytes_used->set_value(0);
|
|
jvm_non_heap_size_bytes_committed->set_value(0);
|
|
|
|
jvm_young_size_bytes_used->set_value(0);
|
|
jvm_young_size_bytes_peak_used->set_value(0);
|
|
jvm_young_size_bytes_max->set_value(0);
|
|
|
|
jvm_old_size_bytes_used->set_value(0);
|
|
jvm_old_size_bytes_peak_used->set_value(0);
|
|
jvm_old_size_bytes_max->set_value(0);
|
|
|
|
jvm_thread_count->set_value(0);
|
|
jvm_thread_peak_count->set_value(0);
|
|
jvm_thread_new_count->set_value(0);
|
|
jvm_thread_runnable_count->set_value(0);
|
|
jvm_thread_blocked_count->set_value(0);
|
|
jvm_thread_waiting_count->set_value(0);
|
|
jvm_thread_timed_waiting_count->set_value(0);
|
|
jvm_thread_terminated_count->set_value(0);
|
|
|
|
jvm_gc_g1_young_generation_count->set_value(0);
|
|
jvm_gc_g1_young_generation_time_ms->set_value(0);
|
|
jvm_gc_g1_old_generation_count->set_value(0);
|
|
jvm_gc_g1_old_generation_time_ms->set_value(0);
|
|
}
|
|
}
|
|
|
|
void JvmStats::init(JNIEnv* ENV) {
|
|
env = ENV;
|
|
_managementFactoryClass = env->FindClass("java/lang/management/ManagementFactory");
|
|
if (_managementFactoryClass == nullptr) {
|
|
LOG(WARNING)
|
|
<< "Class java/lang/management/ManagementFactory Not Find.JVM monitoring fails.";
|
|
return;
|
|
}
|
|
|
|
_getMemoryMXBeanMethod = env->GetStaticMethodID(_managementFactoryClass, "getMemoryMXBean",
|
|
"()Ljava/lang/management/MemoryMXBean;");
|
|
|
|
_memoryUsageClass = env->FindClass("java/lang/management/MemoryUsage");
|
|
if (_memoryUsageClass == nullptr) {
|
|
LOG(WARNING) << "Class java/lang/management/MemoryUsage Not Find.JVM monitoring fails.";
|
|
return;
|
|
}
|
|
_getMemoryUsageUsedMethod = env->GetMethodID(_memoryUsageClass, "getUsed", "()J");
|
|
_getMemoryUsageCommittedMethod = env->GetMethodID(_memoryUsageClass, "getCommitted", "()J");
|
|
_getMemoryUsageMaxMethod = env->GetMethodID(_memoryUsageClass, "getMax", "()J");
|
|
|
|
_memoryMXBeanClass = env->FindClass("java/lang/management/MemoryMXBean");
|
|
if (_memoryMXBeanClass == nullptr) {
|
|
LOG(WARNING) << "Class java/lang/management/MemoryMXBean Not Find.JVM monitoring fails.";
|
|
return;
|
|
}
|
|
_getHeapMemoryUsageMethod = env->GetMethodID(_memoryMXBeanClass, "getHeapMemoryUsage",
|
|
"()Ljava/lang/management/MemoryUsage;");
|
|
_getNonHeapMemoryUsageMethod = env->GetMethodID(_memoryMXBeanClass, "getNonHeapMemoryUsage",
|
|
"()Ljava/lang/management/MemoryUsage;");
|
|
|
|
_getMemoryPoolMXBeansMethod = env->GetStaticMethodID(
|
|
_managementFactoryClass, "getMemoryPoolMXBeans", "()Ljava/util/List;");
|
|
|
|
_listClass = env->FindClass("java/util/List");
|
|
if (_listClass == nullptr) {
|
|
LOG(WARNING) << "Class java/util/List Not Find.JVM monitoring fails.";
|
|
return;
|
|
}
|
|
_getListSizeMethod = env->GetMethodID(_listClass, "size", "()I");
|
|
_getListUseIndexMethod = env->GetMethodID(_listClass, "get", "(I)Ljava/lang/Object;");
|
|
|
|
_memoryPoolMXBeanClass = env->FindClass("java/lang/management/MemoryPoolMXBean");
|
|
if (_memoryPoolMXBeanClass == nullptr) {
|
|
LOG(WARNING)
|
|
<< "Class java/lang/management/MemoryPoolMXBean Not Find.JVM monitoring fails.";
|
|
return;
|
|
}
|
|
_getMemoryPoolMXBeanUsageMethod = env->GetMethodID(_memoryPoolMXBeanClass, "getUsage",
|
|
"()Ljava/lang/management/MemoryUsage;");
|
|
_getMemoryPollMXBeanPeakMethod = env->GetMethodID(_memoryPoolMXBeanClass, "getPeakUsage",
|
|
"()Ljava/lang/management/MemoryUsage;");
|
|
_getMemoryPollMXBeanNameMethod =
|
|
env->GetMethodID(_memoryPoolMXBeanClass, "getName", "()Ljava/lang/String;");
|
|
|
|
_getThreadMXBeanMethod = env->GetStaticMethodID(_managementFactoryClass, "getThreadMXBean",
|
|
"()Ljava/lang/management/ThreadMXBean;");
|
|
|
|
_getGarbageCollectorMXBeansMethod = env->GetStaticMethodID(
|
|
_managementFactoryClass, "getGarbageCollectorMXBeans", "()Ljava/util/List;");
|
|
|
|
_garbageCollectorMXBeanClass = env->FindClass("java/lang/management/GarbageCollectorMXBean");
|
|
if (_garbageCollectorMXBeanClass == nullptr) {
|
|
LOG(WARNING) << "Class java/lang/management/GarbageCollectorMXBean Not Find.JVM monitoring "
|
|
"fails.";
|
|
return;
|
|
}
|
|
_getGCNameMethod =
|
|
env->GetMethodID(_garbageCollectorMXBeanClass, "getName", "()Ljava/lang/String;");
|
|
_getGCCollectionCountMethod =
|
|
env->GetMethodID(_garbageCollectorMXBeanClass, "getCollectionCount", "()J");
|
|
_getGCCollectionTimeMethod =
|
|
env->GetMethodID(_garbageCollectorMXBeanClass, "getCollectionTime", "()J");
|
|
|
|
_threadMXBeanClass = env->FindClass("java/lang/management/ThreadMXBean");
|
|
if (_threadMXBeanClass == nullptr) {
|
|
LOG(WARNING) << "Class java/lang/management/ThreadMXBean Not Find.JVM monitoring fails.";
|
|
return;
|
|
}
|
|
_getAllThreadIdsMethod = env->GetMethodID(_threadMXBeanClass, "getAllThreadIds", "()[J");
|
|
_getThreadInfoMethod = env->GetMethodID(_threadMXBeanClass, "getThreadInfo",
|
|
"([JI)[Ljava/lang/management/ThreadInfo;");
|
|
_getPeakThreadCountMethod = env->GetMethodID(_threadMXBeanClass, "getPeakThreadCount", "()I");
|
|
|
|
_threadInfoClass = env->FindClass("java/lang/management/ThreadInfo");
|
|
if (_threadInfoClass == nullptr) {
|
|
LOG(WARNING) << "Class java/lang/management/ThreadInfo Not Find.JVM monitoring fails.";
|
|
return;
|
|
}
|
|
|
|
_getThreadStateMethod =
|
|
env->GetMethodID(_threadInfoClass, "getThreadState", "()Ljava/lang/Thread$State;");
|
|
|
|
_threadStateClass = env->FindClass("java/lang/Thread$State");
|
|
if (_threadStateClass == nullptr) {
|
|
LOG(WARNING) << "Class java/lang/Thread$State Not Find.JVM monitoring fails.";
|
|
return;
|
|
}
|
|
|
|
jfieldID newThreadFieldID =
|
|
env->GetStaticFieldID(_threadStateClass, "NEW", "Ljava/lang/Thread$State;");
|
|
jfieldID runnableThreadFieldID =
|
|
env->GetStaticFieldID(_threadStateClass, "RUNNABLE", "Ljava/lang/Thread$State;");
|
|
jfieldID blockedThreadFieldID =
|
|
env->GetStaticFieldID(_threadStateClass, "BLOCKED", "Ljava/lang/Thread$State;");
|
|
jfieldID waitingThreadFieldID =
|
|
env->GetStaticFieldID(_threadStateClass, "WAITING", "Ljava/lang/Thread$State;");
|
|
jfieldID timedWaitingThreadFieldID =
|
|
env->GetStaticFieldID(_threadStateClass, "TIMED_WAITING", "Ljava/lang/Thread$State;");
|
|
jfieldID terminatedThreadFieldID =
|
|
env->GetStaticFieldID(_threadStateClass, "TERMINATED", "Ljava/lang/Thread$State;");
|
|
|
|
_newThreadStateObj = env->GetStaticObjectField(_threadStateClass, newThreadFieldID);
|
|
_runnableThreadStateObj = env->GetStaticObjectField(_threadStateClass, runnableThreadFieldID);
|
|
_blockedThreadStateObj = env->GetStaticObjectField(_threadStateClass, blockedThreadFieldID);
|
|
_waitingThreadStateObj = env->GetStaticObjectField(_threadStateClass, waitingThreadFieldID);
|
|
_timedWaitingThreadStateObj =
|
|
env->GetStaticObjectField(_threadStateClass, timedWaitingThreadFieldID);
|
|
_terminatedThreadStateObj =
|
|
env->GetStaticObjectField(_threadStateClass, terminatedThreadFieldID);
|
|
|
|
LOG(INFO) << "Start JVM monitoring.";
|
|
|
|
_init_complete = true;
|
|
return;
|
|
}
|
|
|
|
void JvmStats::refresh(JvmMetrics* jvm_metrics) {
|
|
if (!_init_complete) {
|
|
return;
|
|
}
|
|
|
|
Status st = JniUtil::GetJNIEnv(&env);
|
|
if (!st.ok()) {
|
|
LOG(WARNING) << "JVM STATS GET JNI ENV FAIL";
|
|
return;
|
|
}
|
|
|
|
jobject memoryMXBeanObj =
|
|
env->CallStaticObjectMethod(_managementFactoryClass, _getMemoryMXBeanMethod);
|
|
|
|
jobject heapMemoryUsageObj = env->CallObjectMethod(memoryMXBeanObj, _getHeapMemoryUsageMethod);
|
|
|
|
jlong heapMemoryUsed = env->CallLongMethod(heapMemoryUsageObj, _getMemoryUsageUsedMethod);
|
|
jlong heapMemoryCommitted =
|
|
env->CallLongMethod(heapMemoryUsageObj, _getMemoryUsageCommittedMethod);
|
|
jlong heapMemoryMax = env->CallLongMethod(heapMemoryUsageObj, _getMemoryUsageMaxMethod);
|
|
|
|
jvm_metrics->jvm_heap_size_bytes_used->set_value(heapMemoryUsed < 0 ? 0 : heapMemoryUsed);
|
|
jvm_metrics->jvm_heap_size_bytes_committed->set_value(
|
|
heapMemoryCommitted < 0 ? 0 : heapMemoryCommitted);
|
|
jvm_metrics->jvm_heap_size_bytes_max->set_value(heapMemoryMax < 0 ? 0 : heapMemoryMax);
|
|
|
|
jobject nonHeapMemoryUsageObj =
|
|
env->CallObjectMethod(memoryMXBeanObj, _getNonHeapMemoryUsageMethod);
|
|
|
|
jlong nonHeapMemoryCommitted =
|
|
env->CallLongMethod(nonHeapMemoryUsageObj, _getMemoryUsageCommittedMethod);
|
|
jlong nonHeapMemoryUsed = env->CallLongMethod(nonHeapMemoryUsageObj, _getMemoryUsageUsedMethod);
|
|
|
|
jvm_metrics->jvm_non_heap_size_bytes_committed->set_value(
|
|
nonHeapMemoryCommitted < 0 ? 0 : nonHeapMemoryCommitted);
|
|
jvm_metrics->jvm_non_heap_size_bytes_used->set_value(nonHeapMemoryUsed < 0 ? 0
|
|
: nonHeapMemoryUsed);
|
|
|
|
jobject memoryPoolMXBeansList =
|
|
env->CallStaticObjectMethod(_managementFactoryClass, _getMemoryPoolMXBeansMethod);
|
|
|
|
jint size = env->CallIntMethod(memoryPoolMXBeansList, _getListSizeMethod);
|
|
|
|
for (int i = 0; i < size; ++i) {
|
|
jobject memoryPoolMXBean =
|
|
env->CallObjectMethod(memoryPoolMXBeansList, _getListUseIndexMethod, i);
|
|
jobject usageObject =
|
|
env->CallObjectMethod(memoryPoolMXBean, _getMemoryPoolMXBeanUsageMethod);
|
|
|
|
jlong used = env->CallLongMethod(usageObject, _getMemoryUsageUsedMethod);
|
|
jlong max = env->CallLongMethod(usageObject, _getMemoryUsageMaxMethod);
|
|
|
|
jobject peakUsageObject =
|
|
env->CallObjectMethod(memoryPoolMXBean, _getMemoryPollMXBeanPeakMethod);
|
|
|
|
jlong peakUsed = env->CallLongMethod(peakUsageObject, _getMemoryUsageUsedMethod);
|
|
|
|
jstring name =
|
|
(jstring)env->CallObjectMethod(memoryPoolMXBean, _getMemoryPollMXBeanNameMethod);
|
|
const char* nameStr = env->GetStringUTFChars(name, nullptr);
|
|
if (nameStr != nullptr) {
|
|
auto it = _memoryPoolName.find(nameStr);
|
|
if (it == _memoryPoolName.end()) {
|
|
continue;
|
|
}
|
|
if (it->second == memoryPoolNameEnum::YOUNG) {
|
|
jvm_metrics->jvm_young_size_bytes_used->set_value(used < 0 ? 0 : used);
|
|
jvm_metrics->jvm_young_size_bytes_peak_used->set_value(peakUsed < 0 ? 0 : peakUsed);
|
|
jvm_metrics->jvm_young_size_bytes_max->set_value(max < 0 ? 0 : max);
|
|
|
|
} else if (it->second == memoryPoolNameEnum::OLD) {
|
|
jvm_metrics->jvm_old_size_bytes_used->set_value(used < 0 ? 0 : used);
|
|
jvm_metrics->jvm_old_size_bytes_peak_used->set_value(peakUsed < 0 ? 0 : peakUsed);
|
|
jvm_metrics->jvm_old_size_bytes_max->set_value(max < 0 ? 0 : max);
|
|
}
|
|
|
|
env->ReleaseStringUTFChars(name, nameStr);
|
|
}
|
|
env->DeleteLocalRef(memoryPoolMXBean);
|
|
env->DeleteLocalRef(usageObject);
|
|
env->DeleteLocalRef(peakUsageObject);
|
|
}
|
|
|
|
jobject threadMXBean =
|
|
env->CallStaticObjectMethod(_managementFactoryClass, _getThreadMXBeanMethod);
|
|
|
|
jlongArray threadIds = (jlongArray)env->CallObjectMethod(threadMXBean, _getAllThreadIdsMethod);
|
|
jint threadCount = env->GetArrayLength(threadIds);
|
|
|
|
jobjectArray threadInfos =
|
|
(jobjectArray)env->CallObjectMethod(threadMXBean, _getThreadInfoMethod, threadIds, 0);
|
|
|
|
int threadsNew = 0, threadsRunnable = 0, threadsBlocked = 0, threadsWaiting = 0,
|
|
threadsTimedWaiting = 0, threadsTerminated = 0;
|
|
jint peakThreadCount = env->CallIntMethod(threadMXBean, _getPeakThreadCountMethod);
|
|
|
|
jvm_metrics->jvm_thread_peak_count->set_value(peakThreadCount < 0 ? 0 : peakThreadCount);
|
|
jvm_metrics->jvm_thread_count->set_value(threadCount < 0 ? 0 : threadCount);
|
|
|
|
for (int i = 0; i < threadCount; i++) {
|
|
jobject threadInfo = env->GetObjectArrayElement(threadInfos, i);
|
|
if (threadInfo == nullptr) {
|
|
continue;
|
|
}
|
|
jobject threadState = env->CallObjectMethod(threadInfo, _getThreadStateMethod);
|
|
|
|
if (env->IsSameObject(threadState, _newThreadStateObj)) {
|
|
threadsNew++;
|
|
} else if (env->IsSameObject(threadState, _runnableThreadStateObj)) {
|
|
threadsRunnable++;
|
|
} else if (env->IsSameObject(threadState, _blockedThreadStateObj)) {
|
|
threadsBlocked++;
|
|
} else if (env->IsSameObject(threadState, _waitingThreadStateObj)) {
|
|
threadsWaiting++;
|
|
} else if (env->IsSameObject(threadState, _timedWaitingThreadStateObj)) {
|
|
threadsTimedWaiting++;
|
|
} else if (env->IsSameObject(threadState, _terminatedThreadStateObj)) {
|
|
threadsTerminated++;
|
|
}
|
|
env->DeleteLocalRef(threadInfo);
|
|
env->DeleteLocalRef(threadState);
|
|
}
|
|
|
|
jvm_metrics->jvm_thread_new_count->set_value(threadsNew < 0 ? 0 : threadsNew);
|
|
jvm_metrics->jvm_thread_runnable_count->set_value(threadsRunnable < 0 ? 0 : threadsRunnable);
|
|
jvm_metrics->jvm_thread_blocked_count->set_value(threadsBlocked < 0 ? 0 : threadsBlocked);
|
|
jvm_metrics->jvm_thread_waiting_count->set_value(threadsWaiting < 0 ? 0 : threadsWaiting);
|
|
jvm_metrics->jvm_thread_timed_waiting_count->set_value(
|
|
threadsTimedWaiting < 0 ? 0 : threadsTimedWaiting);
|
|
jvm_metrics->jvm_thread_terminated_count->set_value(threadsTerminated < 0 ? 0
|
|
: threadsTerminated);
|
|
|
|
jobject gcMXBeansList =
|
|
env->CallStaticObjectMethod(_managementFactoryClass, _getGarbageCollectorMXBeansMethod);
|
|
|
|
jint numCollectors = env->CallIntMethod(gcMXBeansList, _getListSizeMethod);
|
|
|
|
for (int i = 0; i < numCollectors; i++) {
|
|
jobject gcMXBean = env->CallObjectMethod(gcMXBeansList, _getListUseIndexMethod, i);
|
|
|
|
jstring gcName = (jstring)env->CallObjectMethod(gcMXBean, _getGCNameMethod);
|
|
jlong gcCollectionCount = env->CallLongMethod(gcMXBean, _getGCCollectionCountMethod);
|
|
jlong gcCollectionTime = env->CallLongMethod(gcMXBean, _getGCCollectionTimeMethod);
|
|
const char* gcNameStr = env->GetStringUTFChars(gcName, NULL);
|
|
if (gcNameStr != nullptr) {
|
|
if (strcmp(gcNameStr, "G1 Young Generation") == 0) {
|
|
jvm_metrics->jvm_gc_g1_young_generation_count->set_value(gcCollectionCount);
|
|
jvm_metrics->jvm_gc_g1_young_generation_time_ms->set_value(gcCollectionTime);
|
|
|
|
} else {
|
|
jvm_metrics->jvm_gc_g1_old_generation_count->set_value(gcCollectionCount);
|
|
jvm_metrics->jvm_gc_g1_old_generation_time_ms->set_value(gcCollectionTime);
|
|
}
|
|
|
|
env->ReleaseStringUTFChars(gcName, gcNameStr);
|
|
}
|
|
env->DeleteLocalRef(gcMXBean);
|
|
}
|
|
env->DeleteLocalRef(memoryMXBeanObj);
|
|
env->DeleteLocalRef(heapMemoryUsageObj);
|
|
env->DeleteLocalRef(nonHeapMemoryUsageObj);
|
|
env->DeleteLocalRef(memoryPoolMXBeansList);
|
|
env->DeleteLocalRef(threadMXBean);
|
|
env->DeleteLocalRef(gcMXBeansList);
|
|
}
|
|
JvmStats::~JvmStats() {
|
|
if (!_init_complete) {
|
|
return;
|
|
}
|
|
try {
|
|
env->DeleteLocalRef(_newThreadStateObj);
|
|
env->DeleteLocalRef(_runnableThreadStateObj);
|
|
env->DeleteLocalRef(_blockedThreadStateObj);
|
|
env->DeleteLocalRef(_waitingThreadStateObj);
|
|
env->DeleteLocalRef(_timedWaitingThreadStateObj);
|
|
env->DeleteLocalRef(_terminatedThreadStateObj);
|
|
|
|
} catch (...) {
|
|
// When be is killed, DeleteLocalRef may fail.
|
|
// In order to exit more gracefully, we catch the exception here.
|
|
}
|
|
}
|
|
|
|
} // namespace doris
|