org.neo4j.kernel.diagnostics.providers.SystemDiagnostics Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-kernel Show documentation
Show all versions of neo4j-kernel Show documentation
Neo4j kernel is a lightweight, embedded Java database designed to
store data structured as graphs rather than tables. For more
information, see http://neo4j.org.
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.kernel.diagnostics.providers;
import java.io.File;
import java.io.UncheckedIOException;
import java.lang.management.CompilationMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.ByteOrder;
import java.nio.file.Path;
import java.time.ZoneId;
import java.time.zone.ZoneRulesProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.neo4j.internal.diagnostics.DiagnosticsLogger;
import org.neo4j.internal.diagnostics.DiagnosticsProvider;
import org.neo4j.internal.nativeimpl.NativeAccess;
import org.neo4j.internal.nativeimpl.NativeAccessProvider;
import org.neo4j.io.fs.FileUtils;
import org.neo4j.io.os.OsBeanUtil;
import org.neo4j.util.VisibleForTesting;
import static java.lang.String.format;
import static java.net.NetworkInterface.getNetworkInterfaces;
import static org.neo4j.io.ByteUnit.bytesToString;
public enum SystemDiagnostics implements DiagnosticsProvider
{
SYSTEM_MEMORY( "System memory information" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
logBytes( logger, "Total Physical memory: ", OsBeanUtil.getTotalPhysicalMemory() );
logBytes( logger, "Free Physical memory: ", OsBeanUtil.getFreePhysicalMemory() );
logBytes( logger, "Committed virtual memory: ", OsBeanUtil.getCommittedVirtualMemory() );
logBytes( logger, "Total swap space: ", OsBeanUtil.getTotalSwapSpace() );
logBytes( logger, "Free swap space: ", OsBeanUtil.getFreeSwapSpace() );
}
},
JAVA_MEMORY( "JVM memory information" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
logger.log( "Free memory: " + bytesToString( Runtime.getRuntime().freeMemory() ) );
logger.log( "Total memory: " + bytesToString( Runtime.getRuntime().totalMemory() ) );
logger.log( "Max memory: " + bytesToString( Runtime.getRuntime().maxMemory() ) );
for ( GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans() )
{
logger.log( "Garbage Collector: " + gc.getName() + ": " + Arrays.toString( gc.getMemoryPoolNames() ) );
}
for ( MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans() )
{
MemoryUsage usage = pool.getUsage();
logger.log( format( "Memory Pool: %s (%s): committed=%s, used=%s, max=%s, threshold=%s",
pool.getName(), pool.getType(), usage == null ? "?" : bytesToString( usage.getCommitted() ),
usage == null ? "?" : bytesToString( usage.getUsed() ), usage == null ? "?" : bytesToString( usage.getMax() ),
pool.isUsageThresholdSupported() ? bytesToString( pool.getUsageThreshold() ) : "?" ) );
}
}
},
OPERATING_SYSTEM( "Operating system information" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
OperatingSystemMXBean os = ManagementFactory.getOperatingSystemMXBean();
logger.log( format( "Operating System: %s; version: %s; arch: %s; cpus: %s", os.getName(),
os.getVersion(), os.getArch(), os.getAvailableProcessors() ) );
logLong( logger, "Max number of file descriptors: ", OsBeanUtil.getMaxFileDescriptors() );
logLong( logger, "Number of open file descriptors: ", OsBeanUtil.getOpenFileDescriptors() );
logger.log( "Process id: " + ProcessHandle.current().pid() );
logger.log( "Byte order: " + ByteOrder.nativeOrder() );
logger.log( "Local timezone: " + getLocalTimeZone() );
}
private String getLocalTimeZone()
{
return ZoneId.systemDefault().getId();
}
},
JAVA_VIRTUAL_MACHINE( "JVM information" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
logger.log( "VM Name: " + runtime.getVmName() );
logger.log( "VM Vendor: " + runtime.getVmVendor() );
logger.log( "VM Version: " + runtime.getVmVersion() );
CompilationMXBean compiler = ManagementFactory.getCompilationMXBean();
logger.log( "JIT compiler: " + ( ( compiler == null ) ? "unknown" : compiler.getName() ) );
logger.log( "VM Arguments: " + runtime.getInputArguments() );
}
},
CLASSPATH( "Java classpath" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
Collection classpath;
if ( runtime.isBootClassPathSupported() )
{
classpath = buildClassPath( getClass().getClassLoader(),
Map.of( "bootstrap", runtime.getBootClassPath(), "classpath", runtime.getClassPath() ) );
}
else
{
classpath = buildClassPath( getClass().getClassLoader(), Map.of( "classpath", runtime.getClassPath() ) );
}
for ( String path : classpath )
{
logger.log( path );
}
}
private Collection buildClassPath( ClassLoader loader, Map classPaths )
{
Map paths = new HashMap<>();
Set> entries = classPaths.entrySet();
for ( Entry classPathEntry : entries )
{
String classPathType = classPathEntry.getKey();
String[] splittedClassPath = classPathEntry.getValue().split( File.pathSeparator );
for ( String entry : splittedClassPath )
{
String canonicalEntry = canonicalize( entry );
paths.merge( canonicalEntry, classPathType, ( k, v ) -> v + " + " + classPathType );
}
}
for ( int level = 0; loader != null; level++ )
{
if ( loader instanceof URLClassLoader )
{
URLClassLoader urls = (URLClassLoader) loader;
URL[] classLoaderUrls = urls.getURLs();
if ( classLoaderUrls != null )
{
for ( URL url : classLoaderUrls )
{
if ( "file".equalsIgnoreCase( url.getProtocol() ) )
{
String type = "loader." + level;
paths.merge( url.toString(), type, ( k, v ) -> k + " + " + type );
}
}
}
else
{
paths.put( loader.toString(), "" );
}
}
loader = loader.getParent();
}
List result = new ArrayList<>( paths.size() );
for ( Entry path : paths.entrySet() )
{
result.add( " [" + path.getValue() + "] " + path.getKey() );
}
return result;
}
},
LIBRARY_PATH( "Library path" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
for ( String path : runtime.getLibraryPath().split( File.pathSeparator ) )
{
logger.log( canonicalize( path ) );
}
}
},
SYSTEM_PROPERTIES( "System properties" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
for ( Object property : System.getProperties().keySet() )
{
if ( property instanceof String )
{
String key = (String) property;
if ( key.startsWith( "java." ) || key.startsWith( "os." ) || key.endsWith( ".boot.class.path" ) ||
key.equals( "line.separator" ) )
{
continue;
}
logger.log( key + " = " + System.getProperty( key ) );
}
}
}
},
TIMEZONE_DATABASE( "(IANA) TimeZone database version" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
Map versions = new HashMap<>();
for ( String tz : ZoneRulesProvider.getAvailableZoneIds() )
{
for ( String version : ZoneRulesProvider.getVersions( tz ).keySet() )
{
versions.compute( version, ( key, value ) -> value == null ? 1 : (value + 1) );
}
}
String[] sorted = versions.keySet().toArray( new String[0] );
Arrays.sort( sorted );
for ( String tz : sorted )
{
logger.log( format( " TimeZone version: %s (available for %d zone identifiers)", tz, versions.get( tz ) ) );
}
}
},
NETWORK( "Network information" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
try
{
Enumeration networkInterfaces = getNetworkInterfaces();
while ( networkInterfaces.hasMoreElements() )
{
NetworkInterface iface = networkInterfaces.nextElement();
logger.log( format( "Interface %s:", iface.getDisplayName() ) );
Enumeration addresses = iface.getInetAddresses();
while ( addresses.hasMoreElements() )
{
InetAddress address = addresses.nextElement();
String hostAddress = address.getHostAddress();
logger.log( format( " address: %s", hostAddress ) );
}
}
}
catch ( SocketException e )
{
logger.log( "ERROR: failed to inspect network interfaces and addresses: " + e.getMessage() );
}
}
},
NATIVE_ACCESSOR( "Native access information" )
{
@Override
public void dump( DiagnosticsLogger logger )
{
NativeAccess nativeAccess = NativeAccessProvider.getNativeAccess();
logger.log( "Native access details: " + nativeAccess.describe() );
}
};
private final String name;
SystemDiagnostics( String name )
{
this.name = name;
}
@Override
public String getDiagnosticsName()
{
return name;
}
@VisibleForTesting
static String canonicalize( String path )
{
try
{
boolean hasWildcard = path.endsWith( "*" );
if ( hasWildcard )
{
path = path.substring( 0, path.length() - 1 );
}
String result = FileUtils.getCanonicalFile( Path.of( path ) ).toAbsolutePath().toString();
if ( hasWildcard )
{
result += File.separator + "*";
}
return result;
}
catch ( UncheckedIOException e )
{
return Path.of( path ).toAbsolutePath().toString();
}
}
private static void logBytes( DiagnosticsLogger logger, String message, long value )
{
if ( value != OsBeanUtil.VALUE_UNAVAILABLE )
{
logger.log( message + bytesToString( value ) );
}
}
private static void logLong( DiagnosticsLogger logger, String message, long value )
{
if ( value != OsBeanUtil.VALUE_UNAVAILABLE )
{
logger.log( message + value );
}
}
}