e9ccf87816
There can be quite many threads running for H2 and the sshd server. On my test server there were around 20 H2 related threads and around 6 sshd related threads. Add "H2" and "sshd-SshdServer" as group prefixes, so that these threads will be listed in the summary under specific groups rather than being grouped under "Other". Change-Id: I138a5cbaf787c7c524c445368e7fcf7068e44a85
280 lines
8.0 KiB
Java
280 lines
8.0 KiB
Java
// Copyright (C) 2014 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package com.google.gerrit.server.config;
|
|
|
|
import com.google.gerrit.common.data.GlobalCapability;
|
|
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
|
import com.google.gerrit.server.git.WorkQueue;
|
|
import com.google.gerrit.server.git.WorkQueue.Task;
|
|
import com.google.inject.Inject;
|
|
import java.io.IOException;
|
|
import java.lang.management.ManagementFactory;
|
|
import java.lang.management.OperatingSystemMXBean;
|
|
import java.lang.management.RuntimeMXBean;
|
|
import java.lang.management.ThreadInfo;
|
|
import java.lang.management.ThreadMXBean;
|
|
import java.net.InetAddress;
|
|
import java.net.UnknownHostException;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import org.eclipse.jgit.internal.storage.file.WindowCacheStatAccessor;
|
|
import org.kohsuke.args4j.Option;
|
|
|
|
@RequiresCapability(GlobalCapability.MAINTAIN_SERVER)
|
|
public class GetSummary implements RestReadView<ConfigResource> {
|
|
|
|
private final WorkQueue workQueue;
|
|
private final Path sitePath;
|
|
|
|
@Option(name = "--gc", usage = "perform Java GC before retrieving memory stats")
|
|
private boolean gc;
|
|
|
|
public GetSummary setGc(boolean gc) {
|
|
this.gc = gc;
|
|
return this;
|
|
}
|
|
|
|
@Option(name = "--jvm", usage = "include details about the JVM")
|
|
private boolean jvm;
|
|
|
|
public GetSummary setJvm(boolean jvm) {
|
|
this.jvm = jvm;
|
|
return this;
|
|
}
|
|
|
|
@Inject
|
|
public GetSummary(WorkQueue workQueue, @SitePath Path sitePath) {
|
|
this.workQueue = workQueue;
|
|
this.sitePath = sitePath;
|
|
}
|
|
|
|
@Override
|
|
public SummaryInfo apply(ConfigResource rsrc) {
|
|
if (gc) {
|
|
System.gc();
|
|
System.runFinalization();
|
|
System.gc();
|
|
}
|
|
|
|
SummaryInfo summary = new SummaryInfo();
|
|
summary.taskSummary = getTaskSummary();
|
|
summary.memSummary = getMemSummary();
|
|
summary.threadSummary = getThreadSummary();
|
|
if (jvm) {
|
|
summary.jvmSummary = getJvmSummary();
|
|
}
|
|
return summary;
|
|
}
|
|
|
|
private TaskSummaryInfo getTaskSummary() {
|
|
Collection<Task<?>> pending = workQueue.getTasks();
|
|
int tasksTotal = pending.size();
|
|
int tasksRunning = 0;
|
|
int tasksReady = 0;
|
|
int tasksSleeping = 0;
|
|
for (Task<?> task : pending) {
|
|
switch (task.getState()) {
|
|
case RUNNING:
|
|
tasksRunning++;
|
|
break;
|
|
case READY:
|
|
tasksReady++;
|
|
break;
|
|
case SLEEPING:
|
|
tasksSleeping++;
|
|
break;
|
|
case CANCELLED:
|
|
case DONE:
|
|
case OTHER:
|
|
break;
|
|
}
|
|
}
|
|
|
|
TaskSummaryInfo taskSummary = new TaskSummaryInfo();
|
|
taskSummary.total = toInteger(tasksTotal);
|
|
taskSummary.running = toInteger(tasksRunning);
|
|
taskSummary.ready = toInteger(tasksReady);
|
|
taskSummary.sleeping = toInteger(tasksSleeping);
|
|
return taskSummary;
|
|
}
|
|
|
|
private MemSummaryInfo getMemSummary() {
|
|
Runtime r = Runtime.getRuntime();
|
|
long mMax = r.maxMemory();
|
|
long mFree = r.freeMemory();
|
|
long mTotal = r.totalMemory();
|
|
long mInuse = mTotal - mFree;
|
|
|
|
int jgitOpen = WindowCacheStatAccessor.getOpenFiles();
|
|
long jgitBytes = WindowCacheStatAccessor.getOpenBytes();
|
|
|
|
MemSummaryInfo memSummaryInfo = new MemSummaryInfo();
|
|
memSummaryInfo.total = bytes(mTotal);
|
|
memSummaryInfo.used = bytes(mInuse - jgitBytes);
|
|
memSummaryInfo.free = bytes(mFree);
|
|
memSummaryInfo.buffers = bytes(jgitBytes);
|
|
memSummaryInfo.max = bytes(mMax);
|
|
memSummaryInfo.openFiles = toInteger(jgitOpen);
|
|
return memSummaryInfo;
|
|
}
|
|
|
|
private ThreadSummaryInfo getThreadSummary() {
|
|
Runtime r = Runtime.getRuntime();
|
|
ThreadSummaryInfo threadInfo = new ThreadSummaryInfo();
|
|
threadInfo.cpus = r.availableProcessors();
|
|
threadInfo.threads = toInteger(ManagementFactory.getThreadMXBean().getThreadCount());
|
|
|
|
List<String> prefixes =
|
|
Arrays.asList(
|
|
"H2",
|
|
"HTTP",
|
|
"IntraLineDiff",
|
|
"ReceiveCommits",
|
|
"SSH git-receive-pack",
|
|
"SSH git-upload-pack",
|
|
"SSH-Interactive-Worker",
|
|
"SSH-Stream-Worker",
|
|
"SshCommandStart",
|
|
"sshd-SshServer");
|
|
String other = "Other";
|
|
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
|
|
|
|
threadInfo.counts = new HashMap<>();
|
|
for (long id : threadMXBean.getAllThreadIds()) {
|
|
ThreadInfo info = threadMXBean.getThreadInfo(id);
|
|
if (info == null) {
|
|
continue;
|
|
}
|
|
String name = info.getThreadName();
|
|
Thread.State state = info.getThreadState();
|
|
String group = other;
|
|
for (String p : prefixes) {
|
|
if (name.startsWith(p)) {
|
|
group = p;
|
|
break;
|
|
}
|
|
}
|
|
Map<Thread.State, Integer> counts = threadInfo.counts.get(group);
|
|
if (counts == null) {
|
|
counts = new HashMap<>();
|
|
threadInfo.counts.put(group, counts);
|
|
}
|
|
Integer c = counts.get(state);
|
|
counts.put(state, c != null ? c + 1 : 1);
|
|
}
|
|
|
|
return threadInfo;
|
|
}
|
|
|
|
private JvmSummaryInfo getJvmSummary() {
|
|
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
|
|
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
|
|
|
|
JvmSummaryInfo jvmSummary = new JvmSummaryInfo();
|
|
jvmSummary.vmVendor = runtimeBean.getVmVendor();
|
|
jvmSummary.vmName = runtimeBean.getVmName();
|
|
jvmSummary.vmVersion = runtimeBean.getVmVersion();
|
|
jvmSummary.osName = osBean.getName();
|
|
jvmSummary.osVersion = osBean.getVersion();
|
|
jvmSummary.osArch = osBean.getArch();
|
|
jvmSummary.user = System.getProperty("user.name");
|
|
|
|
try {
|
|
jvmSummary.host = InetAddress.getLocalHost().getHostName();
|
|
} catch (UnknownHostException e) {
|
|
// Ignored
|
|
}
|
|
|
|
jvmSummary.currentWorkingDirectory = path(Paths.get(".").toAbsolutePath().getParent());
|
|
jvmSummary.site = path(sitePath);
|
|
return jvmSummary;
|
|
}
|
|
|
|
private static Integer toInteger(int i) {
|
|
return i != 0 ? i : null;
|
|
}
|
|
|
|
private static String bytes(double value) {
|
|
value /= 1024;
|
|
String suffix = "k";
|
|
|
|
if (value > 1024) {
|
|
value /= 1024;
|
|
suffix = "m";
|
|
}
|
|
if (value > 1024) {
|
|
value /= 1024;
|
|
suffix = "g";
|
|
}
|
|
return String.format("%1$6.2f%2$s", value, suffix).trim();
|
|
}
|
|
|
|
private static String path(Path path) {
|
|
try {
|
|
return path.toRealPath().normalize().toString();
|
|
} catch (IOException err) {
|
|
return path.toAbsolutePath().normalize().toString();
|
|
}
|
|
}
|
|
|
|
public static class SummaryInfo {
|
|
public TaskSummaryInfo taskSummary;
|
|
public MemSummaryInfo memSummary;
|
|
public ThreadSummaryInfo threadSummary;
|
|
public JvmSummaryInfo jvmSummary;
|
|
}
|
|
|
|
public static class TaskSummaryInfo {
|
|
public Integer total;
|
|
public Integer running;
|
|
public Integer ready;
|
|
public Integer sleeping;
|
|
}
|
|
|
|
public static class MemSummaryInfo {
|
|
public String total;
|
|
public String used;
|
|
public String free;
|
|
public String buffers;
|
|
public String max;
|
|
public Integer openFiles;
|
|
}
|
|
|
|
public static class ThreadSummaryInfo {
|
|
public Integer cpus;
|
|
public Integer threads;
|
|
public Map<String, Map<Thread.State, Integer>> counts;
|
|
}
|
|
|
|
public static class JvmSummaryInfo {
|
|
public String vmVendor;
|
|
public String vmName;
|
|
public String vmVersion;
|
|
public String osName;
|
|
public String osVersion;
|
|
public String osArch;
|
|
public String user;
|
|
public String host;
|
|
public String currentWorkingDirectory;
|
|
public String site;
|
|
}
|
|
}
|