blob: fa840717ad72b7f43a86c79699e9cc87cedf2de5 [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.ignite.internal.plugin;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.cluster.ClusterMetrics;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.cluster.ClusterState;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.DataRegionConfiguration;
import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.GridLoggerProxy;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.persistence.DataRegion;
import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager;
import org.apache.ignite.internal.processors.port.GridPortRecord;
import org.apache.ignite.internal.util.StripedExecutor;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.SB;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_CONFIG_URL;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_LOG_CLASSPATH_CONTENT_ON_STARTUP;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_NO_ASCII;
import static org.apache.ignite.internal.IgniteKernal.DFLT_LOG_CLASSPATH_CONTENT_ON_STARTUP;
import static org.apache.ignite.internal.IgniteKernal.NL;
import static org.apache.ignite.internal.IgniteKernal.SITE;
import static org.apache.ignite.internal.IgniteVersionUtils.ACK_VER_STR;
import static org.apache.ignite.internal.IgniteVersionUtils.BUILD_TSTAMP_STR;
import static org.apache.ignite.internal.IgniteVersionUtils.COPYRIGHT;
import static org.apache.ignite.internal.IgniteVersionUtils.REV_HASH_STR;
import static org.apache.ignite.internal.IgniteVersionUtils.VER_STR;
import static org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDatabaseSharedManager.INTERNAL_DATA_REGION_NAMES;
import static org.apache.ignite.internal.util.IgniteUtils.MB;
/**
* Default implementation of Ignite information.
*/
public class IgniteLogInfoProviderImpl implements IgniteLogInfoProvider {
/** Format of output metrics. */
private final DecimalFormat decimalFormat = new DecimalFormat("#.##", DecimalFormatSymbols.getInstance(Locale.US));
/** {@inheritDoc} */
@Override public void ackKernalInited(IgniteLogger log, IgniteConfiguration cfg) {
assert log != null;
RuntimeMXBean rtBean = ManagementFactory.getRuntimeMXBean();
ackAsciiLogo(log, cfg, rtBean);
ackConfigUrl(log);
ackConfiguration(log, cfg);
ackOsInfo(log);
ackLanguageRuntime(log, cfg);
ackRemoteManagement(log, cfg);
ackLogger(log);
ackVmArguments(log, cfg, rtBean);
ackClassPaths(log, rtBean);
ackSystemProperties(log);
ackEnvironmentVariables(log);
ackMemoryConfiguration(log, cfg);
ackCacheConfiguration(log, cfg);
if (cfg.isPeerClassLoadingEnabled())
ackP2pConfiguration(log);
ackRebalanceConfiguration(log, cfg);
ackIPv4StackFlagIsSet(log);
ackWaitForBackupsOnShutdownPropertyIsUsed(log);
ack3rdPartyLicenses(log, cfg);
logNodeUserAttributes(log, cfg);
ackSpis(log, cfg);
}
/** {@inheritDoc} */
@Override public void ackNodeBasicMetrics(IgniteLogger log, Ignite ignite) {
ackNodeBasicMetrics(log, (IgniteEx)ignite, decimalFormat);
}
/** {@inheritDoc} */
@Override public void ackNodeDataStorageMetrics(IgniteLogger log, Ignite ignite) {
GridKernalContext ctx = ((IgniteEx)ignite).context();
dataStorageReport(log, ctx.cache().context().database(), decimalFormat);
}
/** {@inheritDoc} */
@Override public void ackNodeMemoryStatisticsMetrics(IgniteLogger log, Ignite ignite) {
GridKernalContext ctx = ((IgniteEx)ignite).context();
memoryStatisticsReport(log, ctx.cache().context().database(), decimalFormat);
}
/** {@inheritDoc} */
@Override public void ackKernalStarted(IgniteLogger log, Ignite ignite) {
IgniteEx igEx = (IgniteEx)ignite;
ackSecurity(log, ignite);
ackPerformanceSuggestions(log, igEx);
ackClassPathContent(log);
ackNodeInfo(log, igEx);
}
/** {@inheritDoc} */
@Override public void ackKernalStopped(IgniteLogger log, Ignite ignite, boolean err) {
ackNodeStopped(log, (IgniteEx)ignite, err);
}
/**
* Acks ASCII-logo. Thanks to http://patorjk.com/software/taag
*/
void ackAsciiLogo(IgniteLogger log, IgniteConfiguration cfg, RuntimeMXBean rtBean) {
if (System.getProperty(IGNITE_NO_ASCII) != null)
return;
String ver = "ver. " + ACK_VER_STR;
// Big thanks to: http://patorjk.com/software/taag
// Font name "Small Slant"
if (log.isInfoEnabled()) {
log.info(NL + NL +
">>> __________ ________________ " + NL +
">>> / _/ ___/ |/ / _/_ __/ __/ " + NL +
">>> _/ // (7 7 // / / / / _/ " + NL +
">>> /___/\\___/_/|_/___/ /_/ /___/ " + NL +
">>> " + NL +
">>> " + ver + NL +
">>> " + COPYRIGHT + NL +
">>> " + NL +
">>> Ignite documentation: " + "https://" + SITE + NL
);
}
if (log.isQuiet()) {
U.quiet(false,
" __________ ________________ ",
" / _/ ___/ |/ / _/_ __/ __/ ",
" _/ // (7 7 // / / / / _/ ",
"/___/\\___/_/|_/___/ /_/ /x___/ ",
"",
ver,
COPYRIGHT,
"",
"Ignite documentation: " + "https://" + SITE,
"",
"Quiet mode.");
String fileName = log.fileName();
if (fileName != null)
U.quiet(false, " ^-- Logging to file '" + fileName + '\'');
U.quiet(false, " ^-- Logging by '" + ((GridLoggerProxy)log).getLoggerInfo() + '\'');
U.quiet(false,
" ^-- To see **FULL** console log here add -DIGNITE_QUIET=false or \"-v\" to ignite.{sh|bat}",
"");
}
}
/**
* Acks configuration URL.
*/
void ackConfigUrl(IgniteLogger log) {
if (log.isInfoEnabled())
log.info("Config URL: " + System.getProperty(IGNITE_CONFIG_URL, "n/a"));
}
/**
* @param cfg Ignite configuration to ack.
*/
void ackConfiguration(IgniteLogger log, IgniteConfiguration cfg) {
if (log.isInfoEnabled())
log.info(cfg.toString());
}
/**
* Logs out OS information.
*/
void ackOsInfo(IgniteLogger log) {
if (log.isQuiet())
U.quiet(false, "OS: " + U.osString());
if (log.isInfoEnabled()) {
log.info("OS: " + U.osString());
log.info("OS user: " + System.getProperty("user.name"));
int jvmPid = U.jvmPid();
log.info("PID: " + (jvmPid == -1 ? "N/A" : jvmPid));
}
}
/**
* Logs out language runtime.
*/
void ackLanguageRuntime(IgniteLogger log, IgniteConfiguration cfg) {
if (log.isQuiet())
U.quiet(false, "VM information: " + U.jdkString());
if (log.isInfoEnabled()) {
log.info("Language runtime: " + U.language(U.resolveClassLoader(cfg)));
log.info("VM information: " + U.jdkString());
log.info("VM total memory: " + U.heapSize(2) + "GB");
}
}
/**
* Acks remote management.
*/
void ackRemoteManagement(IgniteLogger log, IgniteConfiguration cfg) {
if (!log.isInfoEnabled())
return;
SB sb = new SB();
sb.a("Remote Management [");
boolean on = U.isJmxRemoteEnabled();
sb.a("restart: ").a(onOff(U.isRestartEnabled())).a(", ");
sb.a("REST: ").a(onOff(U.isRestEnabled(cfg))).a(", ");
sb.a("JMX (");
sb.a("remote: ").a(onOff(on));
if (on) {
sb.a(", ");
sb.a("port: ").a(System.getProperty("com.sun.management.jmxremote.port", "<n/a>")).a(", ");
sb.a("auth: ").a(onOff(Boolean.getBoolean("com.sun.management.jmxremote.authenticate"))).a(", ");
// By default, SSL is enabled, that's why additional check for null is needed.
// See http://docs.oracle.com/javase/6/docs/technotes/guides/management/agent.html
sb.a("ssl: ").a(onOff(Boolean.getBoolean("com.sun.management.jmxremote.ssl") ||
System.getProperty("com.sun.management.jmxremote.ssl") == null));
}
sb.a(")");
sb.a(']');
log.info(sb.toString());
}
/**
* Acks Logger configuration.
*/
void ackLogger(IgniteLogger log) {
if (log.isInfoEnabled())
log.info("Logger: " + ((GridLoggerProxy)log).getLoggerInfo());
}
/**
* Prints out VM arguments and IGNITE_HOME in info mode.
*
* @param rtBean Java runtime bean.
*/
void ackVmArguments(IgniteLogger log, IgniteConfiguration cfg, RuntimeMXBean rtBean) {
// Ack IGNITE_HOME and VM arguments.
if (log.isInfoEnabled() && S.includeSensitive()) {
log.info("IGNITE_HOME=" + cfg.getIgniteHome());
log.info("VM arguments: " + rtBean.getInputArguments());
}
}
/**
* Prints out class paths in debug mode.
*
* @param rtBean Java runtime bean.
*/
void ackClassPaths(IgniteLogger log, RuntimeMXBean rtBean) {
// Ack all class paths.
if (log.isDebugEnabled()) {
try {
log.debug("Boot class path: " + rtBean.getBootClassPath());
log.debug("Class path: " + rtBean.getClassPath());
log.debug("Library path: " + rtBean.getLibraryPath());
}
catch (Exception ignore) {
// No-op: ignore for Java 9+ and non-standard JVMs.
}
}
}
/**
* Prints all system properties in debug mode.
*/
void ackSystemProperties(IgniteLogger log) {
if (log.isDebugEnabled() && S.includeSensitive())
for (Map.Entry<Object, Object> entry : IgniteSystemProperties.snapshot().entrySet())
log.debug("System property [" + entry.getKey() + '=' + entry.getValue() + ']');
}
/**
* Prints all environment variables in debug mode.
*/
void ackEnvironmentVariables(IgniteLogger log) {
if (log.isDebugEnabled())
for (Map.Entry<?, ?> envVar : System.getenv().entrySet())
log.debug("Environment variable [" + envVar.getKey() + '=' + envVar.getValue() + ']');
}
/**
* Acknowledge the Ignite configuration related to the data storage.
*/
void ackMemoryConfiguration(IgniteLogger log, IgniteConfiguration cfg) {
DataStorageConfiguration memCfg = cfg.getDataStorageConfiguration();
if (memCfg == null)
return;
U.log(log, "System cache's DataRegion size is configured to " +
(memCfg.getSystemDataRegionConfiguration().getInitialSize() / (1024 * 1024)) + " MB. " +
"Use DataStorageConfiguration.systemRegionInitialSize property to change the setting.");
}
/**
* Acknowledge all caches configurations presented in the IgniteConfiguration.
*/
void ackCacheConfiguration(IgniteLogger log, IgniteConfiguration cfg) {
CacheConfiguration[] cacheCfgs = cfg.getCacheConfiguration();
if (cacheCfgs == null || cacheCfgs.length == 0)
U.warn(log, "Cache is not configured - in-memory data grid is off.");
else {
SB sb = new SB();
HashMap<String, ArrayList<String>> memPlcNamesMapping = new HashMap<>();
for (CacheConfiguration c : cacheCfgs) {
String cacheName = U.maskName(c.getName());
String memPlcName = c.getDataRegionName();
if (CU.isSystemCache(cacheName))
memPlcName = "sysMemPlc";
else if (memPlcName == null && cfg.getDataStorageConfiguration() != null)
memPlcName = cfg.getDataStorageConfiguration().getDefaultDataRegionConfiguration().getName();
if (!memPlcNamesMapping.containsKey(memPlcName))
memPlcNamesMapping.put(memPlcName, new ArrayList<String>());
ArrayList<String> cacheNames = memPlcNamesMapping.get(memPlcName);
cacheNames.add(cacheName);
}
for (Map.Entry<String, ArrayList<String>> e : memPlcNamesMapping.entrySet()) {
sb.a("in '").a(e.getKey()).a("' dataRegion: [");
for (String s : e.getValue())
sb.a("'").a(s).a("', ");
sb.d(sb.length() - 2, sb.length()).a("], ");
}
U.log(log, "Configured caches [" + sb.d(sb.length() - 2, sb.length()).toString() + ']');
}
}
/**
* Acknowledge configuration related to the peer class loading.
*/
void ackP2pConfiguration(IgniteLogger log) {
U.warn(log,
"Peer class loading is enabled (disable it in production for performance and " +
"deployment consistency reasons)");
}
/**
* Acknowledge that the rebalance configuration properties are setted correctly.
*/
void ackRebalanceConfiguration(IgniteLogger log, IgniteConfiguration cfg) {
if (cfg.isClientMode()) {
if (cfg.getRebalanceThreadPoolSize() != IgniteConfiguration.DFLT_REBALANCE_THREAD_POOL_SIZE)
U.warn(log, "Setting the rebalance pool size has no effect on the client mode");
}
else {
if (cfg.getRebalanceThreadPoolSize() < 1)
throw new IgniteException("Rebalance thread pool size minimal allowed value is 1. " +
"Change IgniteConfiguration.rebalanceThreadPoolSize property before next start.");
if (cfg.getRebalanceBatchesPrefetchCount() < 1)
throw new IgniteException("Rebalance batches prefetch count minimal allowed value is 1. " +
"Change IgniteConfiguration.rebalanceBatchesPrefetchCount property before next start.");
if (cfg.getRebalanceBatchSize() <= 0)
throw new IgniteException("Rebalance batch size must be greater than zero. " +
"Change IgniteConfiguration.rebalanceBatchSize property before next start.");
if (cfg.getRebalanceThrottle() < 0)
throw new IgniteException("Rebalance throttle can't have negative value. " +
"Change IgniteConfiguration.rebalanceThrottle property before next start.");
if (cfg.getRebalanceTimeout() < 0)
throw new IgniteException("Rebalance message timeout can't have negative value. " +
"Change IgniteConfiguration.rebalanceTimeout property before next start.");
for (CacheConfiguration ccfg : cfg.getCacheConfiguration()) {
if (ccfg.getRebalanceBatchesPrefetchCount() < 1)
throw new IgniteException("Rebalance batches prefetch count minimal allowed value is 1. " +
"Change CacheConfiguration.rebalanceBatchesPrefetchCount property before next start. " +
"[cache=" + ccfg.getName() + "]");
}
}
}
/**
* Prints warning if 'java.net.preferIPv4Stack=true' is not set.
*/
void ackIPv4StackFlagIsSet(IgniteLogger log) {
boolean preferIPv4 = Boolean.parseBoolean(System.getProperty("java.net.preferIPv4Stack"));
if (!preferIPv4) {
U.quietAndWarn(log, "Please set system property '-Djava.net.preferIPv4Stack=true' " +
"to avoid possible problems in mixed environments.");
}
}
/**
* Prints warning if IGNITE_WAIT_FOR_BACKUPS_ON_SHUTDOWN is used.
*/
void ackWaitForBackupsOnShutdownPropertyIsUsed(IgniteLogger log) {
if (IgniteSystemProperties.getString(IgniteSystemProperties.IGNITE_WAIT_FOR_BACKUPS_ON_SHUTDOWN) == null)
return;
log.warning("IGNITE_WAIT_FOR_BACKUPS_ON_SHUTDOWN system property is deprecated and will be removed " +
"in a future version. Use ShutdownPolicy instead.");
}
/**
* Print 3-rd party licenses location.
*/
void ack3rdPartyLicenses(IgniteLogger log, IgniteConfiguration cfg) {
// Ack 3-rd party licenses location.
if (log.isInfoEnabled() && cfg.getIgniteHome() != null)
log.info("3-rd party licenses can be found at: " + cfg.getIgniteHome() + File.separatorChar + "libs" +
File.separatorChar + "licenses");
}
/**
* Prints all user attributes in info mode.
*/
void logNodeUserAttributes(IgniteLogger log, IgniteConfiguration cfg) {
if (log.isInfoEnabled())
for (Map.Entry<?, ?> attr : cfg.getUserAttributes().entrySet())
log.info("Local node user attribute [" + attr.getKey() + '=' + attr.getValue() + ']');
}
/**
* Prints all configuration properties in info mode and SPIs in debug mode.
*/
void ackSpis(IgniteLogger log, IgniteConfiguration cfg) {
if (log.isDebugEnabled()) {
log.debug("+-------------+");
log.debug("START SPI LIST:");
log.debug("+-------------+");
log.debug("Grid checkpoint SPI : " + Arrays.toString(cfg.getCheckpointSpi()));
log.debug("Grid collision SPI : " + cfg.getCollisionSpi());
log.debug("Grid communication SPI : " + cfg.getCommunicationSpi());
log.debug("Grid deployment SPI : " + cfg.getDeploymentSpi());
log.debug("Grid discovery SPI : " + cfg.getDiscoverySpi());
log.debug("Grid event storage SPI : " + cfg.getEventStorageSpi());
log.debug("Grid failover SPI : " + Arrays.toString(cfg.getFailoverSpi()));
log.debug("Grid load balancing SPI : " + Arrays.toString(cfg.getLoadBalancingSpi()));
log.debug("Grid Metrics Exporter SPI : " + Arrays.toString(cfg.getMetricExporterSpi()));
}
}
/**
* Print performance suggestions.
*/
void ackPerformanceSuggestions(IgniteLogger log, IgniteEx ignite) {
GridKernalContext ctx = ignite.context();
ctx.performance().add("Disable assertions (remove '-ea' from JVM options)", !U.assertionsEnabled());
ctx.performance().logSuggestions(log, ignite.name());
}
/**
* Prints the list of {@code *.jar} and {@code *.class} files containing in the classpath.
*/
void ackClassPathContent(IgniteLogger log) {
if (IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_QUIET, true))
return;
boolean enabled = IgniteSystemProperties.getBoolean(IGNITE_LOG_CLASSPATH_CONTENT_ON_STARTUP,
DFLT_LOG_CLASSPATH_CONTENT_ON_STARTUP);
if (enabled) {
String clsPath = System.getProperty("java.class.path", ".");
String[] clsPathElements = clsPath.split(File.pathSeparator);
U.log(log, "Classpath value: " + clsPath);
SB clsPathContent = new SB("List of files containing in classpath: ");
for (String clsPathEntry : clsPathElements) {
try {
if (clsPathEntry.contains("*"))
ackClassPathWildCard(clsPathEntry, clsPathContent);
else
ackClassPathEntry(clsPathEntry, clsPathContent);
}
catch (Exception e) {
U.warn(log, String.format("Could not log class path entry '%s': %s", clsPathEntry, e.getMessage()));
}
}
U.log(log, clsPathContent.toString());
}
}
/**
* @param clsPathEntry Classpath string to process.
* @param clsPathContent StringBuilder to attach path to.
*/
void ackClassPathWildCard(String clsPathEntry, SB clsPathContent) {
final int lastSeparatorIdx = clsPathEntry.lastIndexOf(File.separator);
final int asteriskIdx = clsPathEntry.indexOf('*');
// Just to log possibly incorrect entries to err.
if (asteriskIdx >= 0 && asteriskIdx < lastSeparatorIdx)
throw new RuntimeException("Could not parse classpath entry");
final int fileMaskFirstIdx = lastSeparatorIdx + 1;
final String fileMask =
(fileMaskFirstIdx >= clsPathEntry.length()) ? "*.jar" : clsPathEntry.substring(fileMaskFirstIdx);
Path path = Paths.get(lastSeparatorIdx > 0 ? clsPathEntry.substring(0, lastSeparatorIdx) : ".")
.toAbsolutePath()
.normalize();
if (lastSeparatorIdx == 0)
path = path.getRoot();
try {
DirectoryStream<Path> files =
Files.newDirectoryStream(path, fileMask);
for (Path f : files) {
String s = f.toString();
if (s.toLowerCase().endsWith(".jar"))
clsPathContent.a(f.toString()).a(";");
}
}
catch (IOException e) {
throw new UncheckedIOException(e);
}
}
/**
* @param clsPathEntry Classpath string to process.
* @param clsPathContent StringBuilder to attach path to.
*/
void ackClassPathEntry(String clsPathEntry, SB clsPathContent) {
File clsPathElementFile = new File(clsPathEntry);
if (clsPathElementFile.isDirectory())
clsPathContent.a(clsPathEntry).a(";");
else {
String extension = clsPathEntry.length() >= 4
? clsPathEntry.substring(clsPathEntry.length() - 4).toLowerCase()
: null;
if (".jar".equals(extension) || ".zip".equals(extension))
clsPathContent.a(clsPathEntry).a(";");
}
}
/**
* Print local node information after kernal startup.
*/
void ackNodeInfo(IgniteLogger log, IgniteEx ignite) {
ClusterNode locNode = ignite.localNode();
GridKernalContext ctx = ignite.context();
if (log.isQuiet()) {
U.quiet(false, "");
U.quiet(false, "Ignite node started OK (id=" + U.id8(locNode.id()) +
(F.isEmpty(ignite.name()) ? "" : ", instance name=" + ignite.name()) + ')');
}
if (log.isInfoEnabled()) {
String ack = "Ignite ver. " + VER_STR + '#' + BUILD_TSTAMP_STR + "-sha1:" + REV_HASH_STR;
String dash = U.dash(ack.length());
SB sb = new SB();
for (GridPortRecord rec : ctx.ports().records())
sb.a(rec.protocol()).a(":").a(rec.port()).a(" ");
String str =
NL + NL +
">>> " + dash + NL +
">>> " + ack + NL +
">>> " + dash + NL +
">>> OS name: " + U.osString() + NL +
">>> CPU(s): " + locNode.metrics().getTotalCpus() + NL +
">>> Heap: " + U.heapSize(locNode, 2) + "GB" + NL +
">>> VM name: " + ((IgniteKernal)ignite).vmName() + NL +
(ignite.name() == null ? "" : ">>> Ignite instance name: " + ignite.name() + NL) +
">>> Local node [" +
"ID=" + locNode.id().toString().toUpperCase() +
", order=" + locNode.order() + ", clientMode=" + ctx.clientNode() +
"]" + NL +
">>> Local node addresses: " + U.addressesAsString(locNode) + NL +
">>> Local ports: " + sb + NL +
">>> " + dash + NL;
log.info(str);
}
if (ctx.state().clusterState().state() == ClusterState.INACTIVE) {
U.quietAndInfo(log, ">>> Ignite cluster is in INACTIVE state (limited functionality available). " +
"Use control.(sh|bat) script or IgniteCluster.state(ClusterState.ACTIVE) to change the state.");
}
}
/**
* Logs out node metrics.
*/
void ackNodeBasicMetrics(IgniteLogger log, IgniteEx ignite, DecimalFormat dblFmt) {
if (!log.isInfoEnabled())
return;
GridKernalContext ctx = ignite.context();
IgniteConfiguration cfg = ignite.configuration();
ExecutorService execSvc = ctx.pools().getExecutorService();
ExecutorService sysExecSvc = ctx.pools().getSystemExecutorService();
ExecutorService stripedExecSvc = ctx.pools().getStripedExecutorService();
Map<String, ? extends ExecutorService> customExecSvcs = ctx.pools().customExecutors();
ClusterMetrics m = ignite.cluster().localNode().metrics();
int locCpus = m.getTotalCpus();
double cpuLoadPct = m.getCurrentCpuLoad() * 100;
double avgCpuLoadPct = m.getAverageCpuLoad() * 100;
double gcPct = m.getCurrentGcCpuLoad() * 100;
// Heap params.
long heapUsed = m.getHeapMemoryUsed();
long heapMax = m.getHeapMemoryMaximum();
long heapUsedInMBytes = heapUsed / MB;
long heapCommInMBytes = m.getHeapMemoryCommitted() / MB;
double freeHeapPct = heapMax > 0 ? ((double)((heapMax - heapUsed) * 100)) / heapMax : -1;
int hosts = 0;
int servers = 0;
int clients = 0;
int cpus = 0;
try {
ClusterMetrics metrics = ignite.cluster().metrics();
Collection<ClusterNode> nodes0 = ignite.cluster().nodes();
hosts = U.neighborhood(nodes0).size();
servers = ignite.cluster().forServers().nodes().size();
clients = ignite.cluster().forClients().nodes().size();
cpus = metrics.getTotalCpus();
}
catch (IgniteException ignore) {
// No-op.
}
String id = U.id8(ignite.localNode().id());
AffinityTopologyVersion topVer = ctx.discovery().topologyVersionEx();
ClusterNode locNode = ctx.discovery().localNode();
String netDetails = "";
if (!F.isEmpty(cfg.getLocalHost()))
netDetails += ", localHost=" + cfg.getLocalHost();
if (locNode instanceof TcpDiscoveryNode)
netDetails += ", discoPort=" + ((TcpDiscoveryNode)locNode).discoveryPort();
if (cfg.getCommunicationSpi() instanceof TcpCommunicationSpi)
netDetails += ", commPort=" + ((TcpCommunicationSpi)cfg.getCommunicationSpi()).boundPort();
SB msg = new SB();
msg.nl()
.a("Metrics for local node (to disable set 'metricsLogFrequency' to 0)").nl()
.a(" ^-- Node [id=").a(id).a(ignite.name() != null ? ", name=" + ignite.name() : "").a(", uptime=")
.a(((IgniteKernal)ignite).upTimeFormatted()).a("]").nl()
.a(" ^-- Cluster [hosts=").a(hosts).a(", CPUs=").a(cpus).a(", servers=").a(servers)
.a(", clients=").a(clients).a(", topVer=").a(topVer.topologyVersion())
.a(", minorTopVer=").a(topVer.minorTopologyVersion()).a("]").nl()
.a(" ^-- Network [addrs=").a(locNode.addresses()).a(netDetails).a("]").nl()
.a(" ^-- CPU [CPUs=").a(locCpus).a(", curLoad=").a(dblFmt.format(cpuLoadPct))
.a("%, avgLoad=").a(dblFmt.format(avgCpuLoadPct)).a("%, GC=").a(dblFmt.format(gcPct)).a("%]").nl()
.a(" ^-- Heap [used=").a(dblFmt.format(heapUsedInMBytes))
.a("MB, free=").a(dblFmt.format(freeHeapPct))
.a("%, comm=").a(dblFmt.format(heapCommInMBytes)).a("MB]").nl()
.a(" ^-- Outbound messages queue [size=").a(m.getOutboundMessagesQueueSize()).a("]").nl()
.a(" ^-- ").a(createExecutorDescription("Public thread pool", execSvc)).nl()
.a(" ^-- ").a(createExecutorDescription("System thread pool", sysExecSvc)).nl()
.a(" ^-- ").a(createExecutorDescription("Striped thread pool", stripedExecSvc));
if (customExecSvcs != null) {
for (Map.Entry<String, ? extends ExecutorService> entry : customExecSvcs.entrySet())
msg.nl().a(" ^-- ").a(createExecutorDescription(entry.getKey(), entry.getValue()));
}
log.info(msg.toString());
ctx.cache().context().database().dumpStatistics(log);
}
/**
* Create description of an executor service for logging.
*
* @param execSvcName Name of the service.
* @param execSvc Service to create a description for.
*/
String createExecutorDescription(String execSvcName, ExecutorService execSvc) {
int poolSize = 0;
int poolActiveThreads = 0;
int poolQSize = 0;
if (execSvc instanceof ThreadPoolExecutor) {
ThreadPoolExecutor exec = (ThreadPoolExecutor)execSvc;
poolSize = exec.getPoolSize();
poolActiveThreads = Math.min(poolSize, exec.getActiveCount());
poolQSize = exec.getQueue().size();
}
else if (execSvc instanceof StripedExecutor) {
StripedExecutor exec = (StripedExecutor)execSvc;
poolSize = exec.stripesCount();
poolActiveThreads = exec.activeStripesCount();
poolQSize = exec.queueSize();
}
int poolIdleThreads = poolSize - poolActiveThreads;
return execSvcName + " [active=" + poolActiveThreads + ", idle=" + poolIdleThreads + ", qSize=" + poolQSize + "]";
}
/**
* Print data storage statistics.
*/
void dataStorageReport(IgniteLogger log, IgniteCacheDatabaseSharedManager db, DecimalFormat dblFmt) {
if (F.isEmpty(db.dataRegions()))
return;
SB dataRegionsInfo = new SB();
dataRegionsInfo.nl();
for (DataRegion region : db.dataRegions()) {
DataRegionConfiguration regCfg = region.config();
long pagesCnt = region.pageMemory().loadedPages();
long offHeapUsed = region.pageMemory().systemPageSize() * pagesCnt;
long offHeapInit = regCfg.getInitialSize();
long offHeapMax = regCfg.getMaxSize();
long offHeapComm = region.metrics().getOffHeapSize();
long offHeapUsedInMBytes = offHeapUsed / MB;
long offHeapMaxInMBytes = offHeapMax / MB;
long offHeapCommInMBytes = offHeapComm / MB;
long offHeapInitInMBytes = offHeapInit / MB;
double freeOffHeapPct = offHeapMax > 0 ?
((double)((offHeapMax - offHeapUsed) * 100)) / offHeapMax : -1;
String type = "user";
try {
if (region == db.dataRegion(null))
type = "default";
else if (INTERNAL_DATA_REGION_NAMES.contains(regCfg.getName()))
type = "internal";
}
catch (IgniteCheckedException ice) {
// Should never happen
ice.printStackTrace();
}
dataRegionsInfo.a(" ^-- ")
.a(regCfg.getName()).a(" region [type=").a(type)
.a(", persistence=").a(regCfg.isPersistenceEnabled())
.a(", lazyAlloc=").a(regCfg.isLazyMemoryAllocation()).a(',').nl()
.a(" ... ")
.a("initCfg=").a(dblFmt.format(offHeapInitInMBytes))
.a("MB, maxCfg=").a(dblFmt.format(offHeapMaxInMBytes))
.a("MB, usedRam=").a(dblFmt.format(offHeapUsedInMBytes))
.a("MB, freeRam=").a(dblFmt.format(freeOffHeapPct))
.a("%, allocRam=").a(dblFmt.format(offHeapCommInMBytes)).a("MB");
if (regCfg.isPersistenceEnabled()) {
dataRegionsInfo.a(", allocTotal=")
.a(dblFmt.format(region.metrics().getTotalAllocatedSize() / MB)).a("MB");
}
dataRegionsInfo.a(']').nl();
}
if (log.isQuiet())
U.quietMultipleLines(false, dataRegionsInfo.toString());
else if (log.isInfoEnabled())
log.info(dataRegionsInfo.toString());
}
/**
* @param log Ignite Logger.
* @param db Database Shared Manager.
* @param dblFmt Double format.
*/
void memoryStatisticsReport(IgniteLogger log, IgniteCacheDatabaseSharedManager db, DecimalFormat dblFmt) {
if (F.isEmpty(db.dataRegions()))
return;
SB sb = new SB();
sb.nl();
long loadedPages = 0;
long offHeapUsedSummary = 0;
long offHeapMaxSummary = 0;
long offHeapCommSummary = 0;
long pdsUsedSummary = 0;
boolean persistenceEnabled = false;
for (DataRegion region : db.dataRegions()) {
DataRegionConfiguration regCfg = region.config();
long pagesCnt = region.pageMemory().loadedPages();
long offHeapUsed = region.pageMemory().systemPageSize() * pagesCnt;
long offHeapMax = regCfg.getMaxSize();
long offHeapComm = region.metrics().getOffHeapSize();
offHeapUsedSummary += offHeapUsed;
offHeapMaxSummary += offHeapMax;
offHeapCommSummary += offHeapComm;
loadedPages += pagesCnt;
if (regCfg.isPersistenceEnabled()) {
pdsUsedSummary += region.metrics().getTotalAllocatedSize();
persistenceEnabled = true;
}
}
double freeOffHeapPct = offHeapMaxSummary > 0 ?
((double)((offHeapMaxSummary - offHeapUsedSummary) * 100)) / offHeapMaxSummary : -1;
sb.nl()
.a("Data storage metrics for local node (to disable set 'metricsLogFrequency' to 0)").nl()
.a(" ^-- Off-heap memory [used=").a(dblFmt.format(offHeapUsedSummary / MB))
.a("MB, free=").a(dblFmt.format(freeOffHeapPct))
.a("%, allocated=").a(dblFmt.format(offHeapCommSummary / MB)).a("MB]").nl()
.a(" ^-- Page memory [pages=").a(loadedPages).a("]").nl();
if (persistenceEnabled)
sb.a(" ^-- Ignite persistence [used=").a(dblFmt.format(pdsUsedSummary / MB)).a("MB]").nl();
if (log.isQuiet())
U.quietMultipleLines(false, sb.toString());
else if (log.isInfoEnabled())
log.info(sb.toString());
}
/** */
void ackNodeStopped(IgniteLogger log, IgniteEx ignite, boolean err) {
String igniteInstanceName = ignite.name();
// Ack stop.
if (log.isQuiet()) {
String nodeName = igniteInstanceName == null ? "" : "name=" + igniteInstanceName + ", ";
if (!err)
U.quiet(false, "Ignite node stopped OK [" + nodeName + "uptime=" +
((IgniteKernal)ignite).upTimeFormatted() + ']');
else
U.quiet(true, "Ignite node stopped wih ERRORS [" + nodeName + "uptime=" +
((IgniteKernal)ignite).upTimeFormatted() + ']');
}
if (!log.isInfoEnabled())
return;
if (!err) {
String ack = "Ignite ver. " + VER_STR + '#' + BUILD_TSTAMP_STR + "-sha1:" + REV_HASH_STR +
" stopped OK";
String dash = U.dash(ack.length());
log.info(NL + NL +
">>> " + dash + NL +
">>> " + ack + NL +
">>> " + dash + NL +
(igniteInstanceName == null ? "" : ">>> Ignite instance name: " + igniteInstanceName + NL) +
">>> Grid uptime: " + ((IgniteKernal)ignite).upTimeFormatted() +
NL +
NL);
}
else {
String ack = "Ignite ver. " + VER_STR + '#' + BUILD_TSTAMP_STR + "-sha1:" + REV_HASH_STR +
" stopped with ERRORS";
String dash = U.dash(ack.length());
log.info(NL + NL +
">>> " + ack + NL +
">>> " + dash + NL +
(igniteInstanceName == null ? "" : ">>> Ignite instance name: " + igniteInstanceName + NL) +
">>> Grid uptime: " + ((IgniteKernal)ignite).upTimeFormatted() +
NL +
">>> See log above for detailed error message." + NL +
">>> Note that some errors during stop can prevent grid from" + NL +
">>> maintaining correct topology since this node may have" + NL +
">>> not exited grid properly." + NL +
NL);
}
}
/**
* Prints security status.
*/
void ackSecurity(IgniteLogger log, Ignite ignite) {
assert log != null;
GridKernalContext ctx = ((IgniteEx)ignite).context();
U.quietAndInfo(log, "Security status [authentication=" + onOff(ctx.security().enabled())
+ ", sandbox=" + onOff(ctx.security().sandbox().enabled())
+ ", tls/ssl=" + onOff(ctx.config().getSslContextFactory() != null) + ']');
}
/**
* Gets "on" or "off" string for given boolean value.
*
* @param b Boolean value to convert.
* @return Result string.
*/
public static String onOff(boolean b) {
return b ? "on" : "off";
}
}