001/*
002 * JPPF.
003 * Copyright (C) 2005-2018 JPPF Team.
004 * http://www.jppf.org
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.jppf.management.diagnostics.provider;
020
021import static org.jppf.management.diagnostics.provider.MonitoringConstants.*;
022
023import java.lang.management.*;
024
025import org.jppf.management.diagnostics.*;
026import org.jppf.utils.TypedProperties;
027import org.slf4j.*;
028
029/**
030 * This class is the built-in JPPF monitoring data provider.
031 * @author Laurent Cohen
032 */
033public class DefaultMonitoringDataProvider extends MonitoringDataProvider {
034  /**
035   * Logger for this class.
036   */
037  private static final Logger log = LoggerFactory.getLogger(DefaultMonitoringDataProvider.class);
038  /**
039   * Determines whether the debug level is enabled in the log configuration, without the cost of a method call.
040   */
041  private static final boolean debugEnabled = log.isDebugEnabled();
042  /**
043   * Base path for localzation bundles.
044   */
045  private static final String I18N_BASE = "org.jppf.management.diagnostics.provider.DefaultMonitoringDataProvider";
046  /**
047   * Reference to the platform's {@link ThreadMXBean} instance.
048   */
049  private static final ThreadMXBean threadsMXBean = ManagementFactory.getThreadMXBean();
050  static {
051    if (threadsMXBean.isThreadCpuTimeSupported()) {
052      if (!threadsMXBean.isThreadCpuTimeEnabled()) threadsMXBean.setThreadCpuTimeEnabled(true);
053    } else if (debugEnabled) log.debug("CPU time collection is not supported - CPU load will be unavailable");
054    if (threadsMXBean.isThreadContentionMonitoringSupported()) threadsMXBean.setThreadContentionMonitoringEnabled(true);
055  }
056  /**
057   * Object that holds all references to Oshi API objects.
058   * This allows using this built-in provider on the console side without needing OShi classes in the classpath.
059   */
060  private Oshi oshi;
061  /**
062   * Collects regular snapshots of the total CPU time for the current process.
063   */
064  private CPUTimeCollector cpuTimeCollector;
065
066  @Override
067  public void defineProperties() {
068    setDoubleProperty(HEAP_USAGE_RATIO, -1d);
069    setDoubleProperty(HEAP_USAGE_MB, -1d);
070    setDoubleProperty(NON_HEAP_USAGE_RATIO, -1d);
071    setDoubleProperty(NON_HEAP_USAGE_MB, -1d);
072    setBooleanProperty(DEADLOCKED, false);
073    setIntProperty(LIVE_THREADS_COUNT, -1);
074    setDoubleProperty(PROCESS_CPU_LOAD, -1d);
075    setDoubleProperty(SYSTEM_CPU_LOAD, -1d);
076    setDoubleProperty(PROCESS_RESIDENT_SET_SIZE, -1d);
077    setDoubleProperty(PROCESS_VIRTUAL_SIZE, -1d);
078    setDoubleProperty(RAM_USAGE_RATIO, -1d);
079    setDoubleProperty(RAM_USAGE_MB, -1d);
080    setDoubleProperty(SWAP_USAGE_RATIO, -1d);
081    setDoubleProperty(SWAP_USAGE_MB, -1d);
082    setDoubleProperty(CPU_TEMPERATURE, -1d);
083    setStringProperty(OS_NAME, "n/a");
084    setDoubleProperty(PROCESS_RESIDENT_SET_SIZE, -1d);
085    setDoubleProperty(PROCESS_VIRTUAL_SIZE, -1d);
086  }
087
088  @Override
089  public void init() {
090    oshi = new Oshi().init();
091    if (debugEnabled) log.debug("Starting CPU time collector thread");
092    cpuTimeCollector = CPUTimeCollector.getInstance();
093  }
094
095  @Override
096  public TypedProperties getValues() {
097    final TypedProperties props = oshi.getValues();
098    final MemoryInformation memInfo = memoryInformation();
099    MemoryUsageInformation mem = memInfo.getHeapMemoryUsage();
100    props.setDouble(HEAP_USAGE_RATIO, 100d * mem.getUsedRatio());
101    props.setDouble(HEAP_USAGE_MB, (double) mem.getUsed() / MB);
102    mem = memInfo.getNonHeapMemoryUsage();
103    props.setDouble(NON_HEAP_USAGE_RATIO, 100d * mem.getUsedRatio());
104    props.setDouble(NON_HEAP_USAGE_MB, (double) mem.getUsed() / MB);
105    final long[] ids = threadsMXBean.findDeadlockedThreads();
106    props.setBoolean(DEADLOCKED, (ids != null) && (ids.length > 0));
107    props.setInt(LIVE_THREADS_COUNT, threadsMXBean.getThreadCount());
108    double d = cpuTimeCollector.getLoad();
109    if ((d < 0d) || (d > 1d)) d = -1d;
110    props.setDouble(PROCESS_CPU_LOAD, 100d * d);
111    return props;
112  }
113
114  @Override
115  protected String getLocalizationBase() {
116    return I18N_BASE;
117  }
118
119  /**
120   * Get the memory info for the whole JVM.
121   * @return a {@link MemoryInformation} instance.
122   */
123  private static MemoryInformation memoryInformation() {
124    return new MemoryInformation();
125  }
126}