github-actions[bot] commented on code in PR #35023: URL: https://github.com/apache/doris/pull/35023#discussion_r1604799241
########## be/src/util/doris_metrics.h: ########## @@ -17,11 +17,14 @@ #pragma once +#include <jni.h> Review Comment: warning: 'jni.h' file not found [clang-diagnostic-error] ```cpp #include <jni.h> ^ ``` ########## be/src/util/jvm_metrics.cpp: ########## @@ -0,0 +1,423 @@ +// 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 <functional> + +#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) : _jvm_stats(env) { + DCHECK(registry != nullptr); + _registry = registry; + + _server_entity = _registry->register_entity("server"); + DCHECK(_server_entity != nullptr); + if (_jvm_stats.init_complete()) { + _server_entity->register_hook(_s_hook_name, std::bind(&JvmMetrics::update, this)); + } + + 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() { + _jvm_stats.refresh(this); +} +#include <util/jni-util.h> + +jvmStats::jvmStats(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; +} + +#include "jni.h" + +void jvmStats::refresh(JvmMetrics* jvm_metrics) { Review Comment: warning: function 'refresh' exceeds recommended size/complexity thresholds [readability-function-size] ```cpp void jvmStats::refresh(JvmMetrics* jvm_metrics) { ^ ``` <details> <summary>Additional context</summary> **be/src/util/jvm_metrics.cpp:250:** 159 lines including whitespace and comments (threshold 80) ```cpp void jvmStats::refresh(JvmMetrics* jvm_metrics) { ^ ``` </details> ########## be/src/util/jvm_metrics.cpp: ########## @@ -0,0 +1,423 @@ +// 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 <functional> + +#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) : _jvm_stats(env) { + DCHECK(registry != nullptr); + _registry = registry; + + _server_entity = _registry->register_entity("server"); + DCHECK(_server_entity != nullptr); + if (_jvm_stats.init_complete()) { + _server_entity->register_hook(_s_hook_name, std::bind(&JvmMetrics::update, this)); + } + + 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() { + _jvm_stats.refresh(this); +} +#include <util/jni-util.h> + +jvmStats::jvmStats(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; +} + +#include "jni.h" + +void jvmStats::refresh(JvmMetrics* jvm_metrics) { + if (!_init_complete) { + return; + } + static_cast<void>(JniUtil::GetJNIEnv(&env)); + + 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, NULL); + if (nameStr != NULL) { Review Comment: warning: use nullptr [modernize-use-nullptr] ```suggestion if (nameStr != nullptr) { ``` ########## be/src/util/jvm_metrics.cpp: ########## @@ -0,0 +1,423 @@ +// 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 <functional> + +#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) : _jvm_stats(env) { + DCHECK(registry != nullptr); + _registry = registry; + + _server_entity = _registry->register_entity("server"); + DCHECK(_server_entity != nullptr); + if (_jvm_stats.init_complete()) { + _server_entity->register_hook(_s_hook_name, std::bind(&JvmMetrics::update, this)); + } + + 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() { + _jvm_stats.refresh(this); +} +#include <util/jni-util.h> + +jvmStats::jvmStats(JNIEnv* ENV) : env(ENV) { Review Comment: warning: function 'jvmStats' exceeds recommended size/complexity thresholds [readability-function-size] ```cpp jvmStats::jvmStats(JNIEnv* ENV) : env(ENV) { ^ ``` <details> <summary>Additional context</summary> **be/src/util/jvm_metrics.cpp:123:** 123 lines including whitespace and comments (threshold 80) ```cpp jvmStats::jvmStats(JNIEnv* ENV) : env(ENV) { ^ ``` </details> ########## be/src/util/jvm_metrics.h: ########## @@ -0,0 +1,149 @@ +// 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. + +#pragma once + +#include <jni.h> Review Comment: warning: 'jni.h' file not found [clang-diagnostic-error] ```cpp #include <jni.h> ^ ``` ########## be/src/util/jvm_metrics.h: ########## @@ -0,0 +1,149 @@ +// 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. + +#pragma once + +#include <jni.h> + +#include "jni.h" +#include "util/jni-util.h" +#include "util/metrics.h" + +namespace doris { + +class JvmMetrics; + +class jvmStats { +private: + JNIEnv* env = nullptr; + jclass _managementFactoryClass = nullptr; + jmethodID _getMemoryMXBeanMethod = nullptr; + jclass _memoryUsageClass = nullptr; + jclass _memoryMXBeanClass = nullptr; + jmethodID _getHeapMemoryUsageMethod = nullptr; + jmethodID _getNonHeapMemoryUsageMethod = nullptr; + jmethodID _getMemoryUsageUsedMethod = nullptr; + jmethodID _getMemoryUsageCommittedMethod = nullptr; + jmethodID _getMemoryUsageMaxMethod = nullptr; + + jmethodID _getMemoryPoolMXBeansMethod = nullptr; + + jclass _listClass = nullptr; + jmethodID _getListSizeMethod = nullptr; + jmethodID _getListUseIndexMethod = nullptr; + + jclass _memoryPoolMXBeanClass = nullptr; + jmethodID _getMemoryPoolMXBeanUsageMethod = nullptr; + + jmethodID _getMemoryPollMXBeanPeakMethod = nullptr; + jmethodID _getMemoryPollMXBeanNameMethod = nullptr; + + enum memoryPoolNameEnum { YOUNG, SURVIVOR, OLD }; + const std::map<std::string, memoryPoolNameEnum> _memoryPoolName = { + {"Eden Space", YOUNG}, + {"PS Eden Space", YOUNG}, + {"Par Eden Space", YOUNG}, + {"G1 Eden Space", YOUNG}, + + {"Survivor Space", SURVIVOR}, + {"PS Survivor Space", SURVIVOR}, + {"Par Survivor Space", SURVIVOR}, + {"G1 Survivor Space", SURVIVOR}, + + {"Tenured Gen", OLD}, + {"PS Old Gen", OLD}, + {"CMS Old Gen", OLD}, + {"G1 Old Gen", OLD}, + + }; + + jmethodID _getThreadMXBeanMethod = nullptr; + jclass _threadMXBeanClass = nullptr; + jmethodID _getAllThreadIdsMethod = nullptr; + jmethodID _getThreadInfoMethod = nullptr; + jclass _threadInfoClass = nullptr; + + jmethodID _getPeakThreadCountMethod = nullptr; + + jmethodID _getThreadStateMethod = nullptr; + jclass _threadStateClass = nullptr; + + jobject _newThreadStateObj = nullptr; + jobject _runnableThreadStateObj = nullptr; + jobject _blockedThreadStateObj = nullptr; + jobject _waitingThreadStateObj = nullptr; + jobject _timedWaitingThreadStateObj = nullptr; + jobject _terminatedThreadStateObj = nullptr; + + jclass _garbageCollectorMXBeanClass = nullptr; + jmethodID _getGCNameMethod = nullptr; + jmethodID _getGarbageCollectorMXBeansMethod = nullptr; + jmethodID _getGCCollectionCountMethod = nullptr; + jmethodID _getGCCollectionTimeMethod = nullptr; + + bool _init_complete = false; + +public: + jvmStats(JNIEnv* ENV); + bool init_complete() { return _init_complete; } Review Comment: warning: method 'init_complete' can be made const [readability-make-member-function-const] ```suggestion bool init_complete() const { return _init_complete; } ``` ########## be/src/util/jvm_metrics.h: ########## @@ -0,0 +1,149 @@ +// 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. + +#pragma once + +#include <jni.h> + +#include "jni.h" +#include "util/jni-util.h" +#include "util/metrics.h" + +namespace doris { + +class JvmMetrics; + +class jvmStats { +private: + JNIEnv* env = nullptr; + jclass _managementFactoryClass = nullptr; + jmethodID _getMemoryMXBeanMethod = nullptr; + jclass _memoryUsageClass = nullptr; + jclass _memoryMXBeanClass = nullptr; + jmethodID _getHeapMemoryUsageMethod = nullptr; + jmethodID _getNonHeapMemoryUsageMethod = nullptr; + jmethodID _getMemoryUsageUsedMethod = nullptr; + jmethodID _getMemoryUsageCommittedMethod = nullptr; + jmethodID _getMemoryUsageMaxMethod = nullptr; + + jmethodID _getMemoryPoolMXBeansMethod = nullptr; + + jclass _listClass = nullptr; + jmethodID _getListSizeMethod = nullptr; + jmethodID _getListUseIndexMethod = nullptr; + + jclass _memoryPoolMXBeanClass = nullptr; + jmethodID _getMemoryPoolMXBeanUsageMethod = nullptr; + + jmethodID _getMemoryPollMXBeanPeakMethod = nullptr; + jmethodID _getMemoryPollMXBeanNameMethod = nullptr; + + enum memoryPoolNameEnum { YOUNG, SURVIVOR, OLD }; + const std::map<std::string, memoryPoolNameEnum> _memoryPoolName = { + {"Eden Space", YOUNG}, + {"PS Eden Space", YOUNG}, + {"Par Eden Space", YOUNG}, + {"G1 Eden Space", YOUNG}, + + {"Survivor Space", SURVIVOR}, + {"PS Survivor Space", SURVIVOR}, + {"Par Survivor Space", SURVIVOR}, + {"G1 Survivor Space", SURVIVOR}, + + {"Tenured Gen", OLD}, + {"PS Old Gen", OLD}, + {"CMS Old Gen", OLD}, + {"G1 Old Gen", OLD}, + + }; + + jmethodID _getThreadMXBeanMethod = nullptr; + jclass _threadMXBeanClass = nullptr; + jmethodID _getAllThreadIdsMethod = nullptr; + jmethodID _getThreadInfoMethod = nullptr; + jclass _threadInfoClass = nullptr; + + jmethodID _getPeakThreadCountMethod = nullptr; + + jmethodID _getThreadStateMethod = nullptr; + jclass _threadStateClass = nullptr; + + jobject _newThreadStateObj = nullptr; + jobject _runnableThreadStateObj = nullptr; + jobject _blockedThreadStateObj = nullptr; + jobject _waitingThreadStateObj = nullptr; + jobject _timedWaitingThreadStateObj = nullptr; + jobject _terminatedThreadStateObj = nullptr; + + jclass _garbageCollectorMXBeanClass = nullptr; + jmethodID _getGCNameMethod = nullptr; + jmethodID _getGarbageCollectorMXBeansMethod = nullptr; + jmethodID _getGCCollectionCountMethod = nullptr; + jmethodID _getGCCollectionTimeMethod = nullptr; + + bool _init_complete = false; + +public: + jvmStats(JNIEnv* ENV); + bool init_complete() { return _init_complete; } + void refresh(JvmMetrics* jvm_metrics); + ~jvmStats(); +}; + +class JvmMetrics { +public: + JvmMetrics(MetricRegistry* registry, JNIEnv* env); + ~JvmMetrics() {} Review Comment: warning: use '= default' to define a trivial destructor [modernize-use-equals-default] ```suggestion ~JvmMetrics() = default; ``` ########## be/src/util/jvm_metrics.cpp: ########## @@ -0,0 +1,423 @@ +// 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 <functional> + +#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) : _jvm_stats(env) { + DCHECK(registry != nullptr); + _registry = registry; + + _server_entity = _registry->register_entity("server"); + DCHECK(_server_entity != nullptr); + if (_jvm_stats.init_complete()) { + _server_entity->register_hook(_s_hook_name, std::bind(&JvmMetrics::update, this)); + } + + 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() { + _jvm_stats.refresh(this); +} +#include <util/jni-util.h> + +jvmStats::jvmStats(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; +} + +#include "jni.h" + +void jvmStats::refresh(JvmMetrics* jvm_metrics) { Review Comment: warning: function 'refresh' has cognitive complexity of 65 (threshold 50) [readability-function-cognitive-complexity] ```cpp void jvmStats::refresh(JvmMetrics* jvm_metrics) { ^ ``` <details> <summary>Additional context</summary> **be/src/util/jvm_metrics.cpp:251:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp if (!_init_complete) { ^ ``` **be/src/util/jvm_metrics.cpp:266:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_heap_size_bytes_used->set_value(heapMemoryUsed < 0 ? 0 : heapMemoryUsed); ^ ``` **be/src/util/jvm_metrics.cpp:268:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp heapMemoryCommitted < 0 ? 0 : heapMemoryCommitted); ^ ``` **be/src/util/jvm_metrics.cpp:269:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_heap_size_bytes_max->set_value(heapMemoryMax < 0 ? 0 : heapMemoryMax); ^ ``` **be/src/util/jvm_metrics.cpp:279:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp nonHeapMemoryCommitted < 0 ? 0 : nonHeapMemoryCommitted); ^ ``` **be/src/util/jvm_metrics.cpp:280:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_non_heap_size_bytes_used->set_value(nonHeapMemoryUsed < 0 ? 0 ^ ``` **be/src/util/jvm_metrics.cpp:288:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp for (int i = 0; i < size; ++i) { ^ ``` **be/src/util/jvm_metrics.cpp:305:** +2, including nesting penalty of 1, nesting level increased to 2 ```cpp if (nameStr != NULL) { ^ ``` **be/src/util/jvm_metrics.cpp:307:** +3, including nesting penalty of 2, nesting level increased to 3 ```cpp if (it == _memoryPoolName.end()) { ^ ``` **be/src/util/jvm_metrics.cpp:310:** +3, including nesting penalty of 2, nesting level increased to 3 ```cpp if (it->second == memoryPoolNameEnum::YOUNG) { ^ ``` **be/src/util/jvm_metrics.cpp:311:** +4, including nesting penalty of 3, nesting level increased to 4 ```cpp jvm_metrics->jvm_young_size_bytes_used->set_value(used < 0 ? 0 : used); ^ ``` **be/src/util/jvm_metrics.cpp:312:** +4, including nesting penalty of 3, nesting level increased to 4 ```cpp jvm_metrics->jvm_young_size_bytes_peak_used->set_value(peakUsed < 0 ? 0 : peakUsed); ^ ``` **be/src/util/jvm_metrics.cpp:313:** +4, including nesting penalty of 3, nesting level increased to 4 ```cpp jvm_metrics->jvm_young_size_bytes_max->set_value(max < 0 ? 0 : max); ^ ``` **be/src/util/jvm_metrics.cpp:315:** +1, nesting level increased to 3 ```cpp } else if (it->second == memoryPoolNameEnum::OLD) { ^ ``` **be/src/util/jvm_metrics.cpp:316:** +4, including nesting penalty of 3, nesting level increased to 4 ```cpp jvm_metrics->jvm_old_size_bytes_used->set_value(used < 0 ? 0 : used); ^ ``` **be/src/util/jvm_metrics.cpp:317:** +4, including nesting penalty of 3, nesting level increased to 4 ```cpp jvm_metrics->jvm_old_size_bytes_peak_used->set_value(peakUsed < 0 ? 0 : peakUsed); ^ ``` **be/src/util/jvm_metrics.cpp:318:** +4, including nesting penalty of 3, nesting level increased to 4 ```cpp jvm_metrics->jvm_old_size_bytes_max->set_value(max < 0 ? 0 : max); ^ ``` **be/src/util/jvm_metrics.cpp:341:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_thread_peak_count->set_value(peakThreadCount < 0 ? 0 : peakThreadCount); ^ ``` **be/src/util/jvm_metrics.cpp:342:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_thread_count->set_value(threadCount < 0 ? 0 : threadCount); ^ ``` **be/src/util/jvm_metrics.cpp:344:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp for (int i = 0; i < threadCount; i++) { ^ ``` **be/src/util/jvm_metrics.cpp:346:** +2, including nesting penalty of 1, nesting level increased to 2 ```cpp if (threadInfo == nullptr) { ^ ``` **be/src/util/jvm_metrics.cpp:351:** +2, including nesting penalty of 1, nesting level increased to 2 ```cpp if (env->IsSameObject(threadState, _newThreadStateObj)) { ^ ``` **be/src/util/jvm_metrics.cpp:353:** +1, nesting level increased to 2 ```cpp } else if (env->IsSameObject(threadState, _runnableThreadStateObj)) { ^ ``` **be/src/util/jvm_metrics.cpp:355:** +1, nesting level increased to 2 ```cpp } else if (env->IsSameObject(threadState, _blockedThreadStateObj)) { ^ ``` **be/src/util/jvm_metrics.cpp:357:** +1, nesting level increased to 2 ```cpp } else if (env->IsSameObject(threadState, _waitingThreadStateObj)) { ^ ``` **be/src/util/jvm_metrics.cpp:359:** +1, nesting level increased to 2 ```cpp } else if (env->IsSameObject(threadState, _timedWaitingThreadStateObj)) { ^ ``` **be/src/util/jvm_metrics.cpp:361:** +1, nesting level increased to 2 ```cpp } else if (env->IsSameObject(threadState, _terminatedThreadStateObj)) { ^ ``` **be/src/util/jvm_metrics.cpp:368:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_thread_new_count->set_value(threadsNew < 0 ? 0 : threadsNew); ^ ``` **be/src/util/jvm_metrics.cpp:369:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_thread_runnable_count->set_value(threadsRunnable < 0 ? 0 : threadsRunnable); ^ ``` **be/src/util/jvm_metrics.cpp:370:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_thread_blocked_count->set_value(threadsBlocked < 0 ? 0 : threadsBlocked); ^ ``` **be/src/util/jvm_metrics.cpp:371:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_thread_waiting_count->set_value(threadsWaiting < 0 ? 0 : threadsWaiting); ^ ``` **be/src/util/jvm_metrics.cpp:373:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp threadsTimedWaiting < 0 ? 0 : threadsTimedWaiting); ^ ``` **be/src/util/jvm_metrics.cpp:374:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp jvm_metrics->jvm_thread_terminated_count->set_value(threadsTerminated < 0 ? 0 ^ ``` **be/src/util/jvm_metrics.cpp:382:** +1, including nesting penalty of 0, nesting level increased to 1 ```cpp for (int i = 0; i < numCollectors; i++) { ^ ``` **be/src/util/jvm_metrics.cpp:389:** +2, including nesting penalty of 1, nesting level increased to 2 ```cpp if (gcNameStr != nullptr) { ^ ``` **be/src/util/jvm_metrics.cpp:390:** +3, including nesting penalty of 2, nesting level increased to 3 ```cpp if (strcmp(gcNameStr, "G1 Young Generation") == 0) { ^ ``` **be/src/util/jvm_metrics.cpp:394:** +1, nesting level increased to 3 ```cpp } else { ^ ``` </details> ########## be/src/util/jvm_metrics.cpp: ########## @@ -0,0 +1,423 @@ +// 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 <functional> + +#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) : _jvm_stats(env) { + DCHECK(registry != nullptr); + _registry = registry; + + _server_entity = _registry->register_entity("server"); + DCHECK(_server_entity != nullptr); + if (_jvm_stats.init_complete()) { + _server_entity->register_hook(_s_hook_name, std::bind(&JvmMetrics::update, this)); + } + + 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() { + _jvm_stats.refresh(this); +} +#include <util/jni-util.h> + +jvmStats::jvmStats(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; +} + +#include "jni.h" + +void jvmStats::refresh(JvmMetrics* jvm_metrics) { Review Comment: warning: method 'refresh' can be made const [readability-make-member-function-const] be/src/util/jvm_metrics.h:102: ```diff - void refresh(JvmMetrics* jvm_metrics); + void refresh(JvmMetrics* jvm_metrics) const; ``` ```suggestion void jvmStats::refresh(JvmMetrics* jvm_metrics) const { ``` ########## be/src/util/jvm_metrics.h: ########## @@ -0,0 +1,149 @@ +// 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. + +#pragma once + +#include <jni.h> + +#include "jni.h" Review Comment: warning: duplicate include [readability-duplicate-include] be/src/util/jvm_metrics.h:20: ```diff - - #include "jni.h" ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org