blob: 040edb09c59bf63446e30665dd51aca2a2790c9b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.karaf.shell.commands.impl;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryType;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import org.apache.karaf.shell.api.action.lifecycle.Reference;
import org.apache.karaf.shell.commands.info.InfoProvider;
import org.apache.karaf.shell.api.action.Action;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.apache.karaf.shell.support.ansi.SimpleAnsi;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
@Command(scope = "shell", name = "info", description = "Prints system information.")
@Service
public class InfoAction implements Action {
private NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH));
private NumberFormat fmtDec = new DecimalFormat("###,###.##", new DecimalFormatSymbols(Locale.ENGLISH));
private NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH));
private OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
@Option(name="--memory-pools", aliases= {"-mp"}, description="Includes detailed information about memory pools")
protected boolean showMemoryPools;
@Reference
List<InfoProvider> infoProviders;
public InfoAction() {
fmtDec.setMinimumFractionDigits(2);
}
@Override
public Object execute() throws Exception {
int maxNameLen;
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
ThreadMXBean threads = ManagementFactory.getThreadMXBean();
MemoryMXBean mem = ManagementFactory.getMemoryMXBean();
ClassLoadingMXBean cl = ManagementFactory.getClassLoadingMXBean();
//
// print Karaf informations
//
maxNameLen = 25;
System.out.println("Karaf");
printValue("Karaf version", maxNameLen, System.getProperty("karaf.version"));
printValue("Karaf home", maxNameLen, System.getProperty("karaf.home"));
printValue("Karaf base", maxNameLen, System.getProperty("karaf.base"));
String osgi = getOsgiFramework();
if (osgi != null) {
printValue("OSGi Framework", maxNameLen, osgi);
}
System.out.println();
System.out.println("JVM");
printValue("Java Virtual Machine", maxNameLen, runtime.getVmName() + " version " + runtime.getVmVersion());
printValue("Version", maxNameLen, System.getProperty("java.version"));
printValue("Vendor", maxNameLen, runtime.getVmVendor());
printValue("Pid", maxNameLen, getPid());
printValue("Uptime", maxNameLen, printDuration(runtime.getUptime()));
try {
Class< ? > sunOS = Class.forName("com.sun.management.OperatingSystemMXBean");
printValue("Process CPU time", maxNameLen, printDuration(getValueAsLong(sunOS, "getProcessCpuTime") / 1000000));
printValue("Process CPU load", maxNameLen, fmtDec.format(getValueAsDouble(sunOS, "getProcessCpuLoad")));
printValue("System CPU load", maxNameLen, fmtDec.format(getValueAsDouble(sunOS, "getSystemCpuLoad")));
} catch (Throwable t) {
}
try {
Class<?> unixOS = Class.forName("com.sun.management.UnixOperatingSystemMXBean");
printValue("Open file descriptors", maxNameLen, printLong(getValueAsLong(unixOS, "getOpenFileDescriptorCount")));
printValue("Max file descriptors", maxNameLen, printLong(getValueAsLong(unixOS, "getMaxFileDescriptorCount")));
} catch (Throwable t) {
}
printValue("Total compile time", maxNameLen, printDuration(ManagementFactory.getCompilationMXBean().getTotalCompilationTime()));
System.out.println("Threads");
printValue("Live threads", maxNameLen, Integer.toString(threads.getThreadCount()));
printValue("Daemon threads", maxNameLen, Integer.toString(threads.getDaemonThreadCount()));
printValue("Peak", maxNameLen, Integer.toString(threads.getPeakThreadCount()));
printValue("Total started", maxNameLen, Long.toString(threads.getTotalStartedThreadCount()));
System.out.println("Memory");
printValue("Current heap size", maxNameLen, printSizeInKb(mem.getHeapMemoryUsage().getUsed()));
printValue("Maximum heap size", maxNameLen, printSizeInKb(mem.getHeapMemoryUsage().getMax()));
printValue("Committed heap size", maxNameLen, printSizeInKb(mem.getHeapMemoryUsage().getCommitted()));
printValue("Pending objects", maxNameLen, Integer.toString(mem.getObjectPendingFinalizationCount()));
for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) {
String val = "Name = '" + gc.getName() + "', Collections = " + gc.getCollectionCount() + ", Time = " + printDuration(gc.getCollectionTime());
printValue("Garbage collector", maxNameLen, val);
}
if (showMemoryPools) {
List<MemoryPoolMXBean> memoryPools = ManagementFactory.getMemoryPoolMXBeans();
System.out.println("Memory Pools");
printValue("Total Memory Pools", maxNameLen, printLong(memoryPools.size()));
String spaces4 = " ";
for (MemoryPoolMXBean pool : memoryPools)
{
String name = pool.getName();
MemoryType type = pool.getType();
printValue(spaces4 + "Pool (" + type + ")", maxNameLen, name);
// PeakUsage/CurrentUsage
MemoryUsage peakUsage = pool.getPeakUsage();
MemoryUsage usage = pool.getUsage();
if (usage != null && peakUsage != null) {
long init = peakUsage.getInit();
long used = peakUsage.getUsed();
long committed = peakUsage.getCommitted();
long max = peakUsage.getMax();
System.out.println(spaces4 + spaces4 + "Peak Usage");
printValue(spaces4 + spaces4 + spaces4 + "init", maxNameLen, printLong(init));
printValue(spaces4 + spaces4 + spaces4 + "used", maxNameLen, printLong(used));
printValue(spaces4 + spaces4 + spaces4 + "committed", maxNameLen, printLong(committed));
printValue(spaces4 + spaces4 + spaces4 + "max", maxNameLen, printLong(max));
init = usage.getInit();
used = usage.getUsed();
committed = usage.getCommitted();
max = usage.getMax();
System.out.println(spaces4 + spaces4 + "Current Usage");
printValue(spaces4 + spaces4 + spaces4 + "init", maxNameLen, printLong(init));
printValue(spaces4 + spaces4 + spaces4 + "used", maxNameLen, printLong(used));
printValue(spaces4 + spaces4 + spaces4 + "committed", maxNameLen, printLong(committed));
printValue(spaces4 + spaces4 + spaces4 + "max", maxNameLen, printLong(max));
}
}
}
System.out.println("Classes");
printValue("Current classes loaded", maxNameLen, printLong(cl.getLoadedClassCount()));
printValue("Total classes loaded", maxNameLen, printLong(cl.getTotalLoadedClassCount()));
printValue("Total classes unloaded", maxNameLen, printLong(cl.getUnloadedClassCount()));
System.out.println("Operating system");
printValue("Name", maxNameLen, os.getName() + " version " + os.getVersion());
printValue("Architecture", maxNameLen, os.getArch());
printValue("Processors", maxNameLen, Integer.toString(os.getAvailableProcessors()));
try {
printValue("Total physical memory", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getTotalPhysicalMemorySize")));
printValue("Free physical memory", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getFreePhysicalMemorySize")));
printValue("Committed virtual memory", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getCommittedVirtualMemorySize")));
printValue("Total swap space", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getTotalSwapSpaceSize")));
printValue("Free swap space", maxNameLen, printSizeInKb(getSunOsValueAsLong(os, "getFreeSwapSpaceSize")));
} catch (Throwable t) {
}
//Display Information from external information providers.
Map<String, Map<Object, Object>> properties = new HashMap<>();
if (infoProviders != null) {
// dump all properties to Map, KARAF-425
for (InfoProvider provider : infoProviders) {
if (!properties.containsKey(provider.getName())) {
properties.put(provider.getName(), new Properties());
}
properties.get(provider.getName()).putAll(provider.getProperties());
}
List<String> sections = new ArrayList<>(properties.keySet());
Collections.sort(sections);
for (String section : sections) {
List<Object> keys = new ArrayList<>(properties.get(section).keySet());
if (keys.size() > 0) {
System.out.println(section);
keys.sort(Comparator.comparing(String::valueOf));
for (Object key : keys) {
printValue(String.valueOf(key), maxNameLen, String.valueOf(properties.get(section).get(key)));
}
}
}
}
return null;
}
private String getPid() {
// In Java 9 the new process API can be used:
// long pid = ProcessHandle.current().getPid();
String name = ManagementFactory.getRuntimeMXBean().getName();
String[] parts = name.split("@");
return parts[0];
}
private long getSunOsValueAsLong(OperatingSystemMXBean os, String name) throws Exception {
Method mth = os.getClass().getMethod(name);
return (Long) mth.invoke(os);
}
private long getValueAsLong(Class<?> osImpl, String name) throws Exception {
if (osImpl.isInstance(os))
{
Method mth = osImpl.getMethod(name);
return (Long) mth.invoke(os);
}
return -1;
}
private double getValueAsDouble(Class<?> osImpl, String name) throws Exception {
if (osImpl.isInstance(os)) {
Method mth = osImpl.getMethod(name);
return (Double) mth.invoke(os);
}
return -1;
}
private String printLong(long i) {
return fmtI.format(i);
}
private String printSizeInKb(double size) {
return fmtI.format((long) (size / 1024)) + " kbytes";
}
protected String printDuration(double uptime) {
uptime /= 1000;
if (uptime < 60) {
return fmtD.format(uptime) + " seconds";
}
uptime /= 60;
if (uptime < 60) {
long minutes = (long) uptime;
String s = fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
return s;
}
uptime /= 60;
if (uptime < 24) {
long hours = (long) uptime;
long minutes = (long) ((uptime - hours) * 60);
String s = fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
if (minutes != 0) {
s += " " + fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
}
return s;
}
uptime /= 24;
long days = (long) uptime;
long hours = (long) ((uptime - days) * 24);
String s = fmtI.format(days) + (days > 1 ? " days" : " day");
if (hours != 0) {
s += " " + fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
}
return s;
}
void printSysValue(String prop, int pad) {
printValue(prop, pad, System.getProperty(prop));
}
void printValue(String name, int pad, String value) {
System.out.println(
" " + SimpleAnsi.INTENSITY_BOLD + name + SimpleAnsi.INTENSITY_NORMAL
+ spaces(pad - name.length()) + " " + value);
}
String spaces(int nb) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < nb; i++) {
sb.append(' ');
}
return sb.toString();
}
String getOsgiFramework() {
try {
Callable<String> call = new Callable<String>() {
@Override
public String call() throws Exception {
BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext();
Bundle sysBundle = context.getBundle(0);
return sysBundle.getSymbolicName() + "-" + sysBundle.getVersion();
}
};
return call.call();
} catch (Throwable t) {
// We're not in OSGi, just safely return null
return null;
}
}
}