com.newrelic.agent.security.intcodeagent.logging.HealthCheckScheduleThread Maven / Gradle / Ivy
package com.newrelic.agent.security.intcodeagent.logging;
import com.newrelic.agent.security.AgentInfo;
import com.newrelic.agent.security.instrumentator.dispatcher.DispatcherPool;
import com.newrelic.agent.security.instrumentator.httpclient.RestRequestThreadPool;
import com.newrelic.agent.security.instrumentator.os.OSVariables;
import com.newrelic.agent.security.instrumentator.os.OsVariablesInstance;
import com.newrelic.agent.security.instrumentator.utils.AgentUtils;
import com.newrelic.agent.security.intcodeagent.apache.httpclient.IastHttpClient;
import com.newrelic.agent.security.intcodeagent.controlcommand.ControlCommandProcessorThreadPool;
import com.newrelic.agent.security.intcodeagent.filelogging.FileLoggerThreadPool;
import com.newrelic.agent.security.intcodeagent.models.javaagent.ThreadPoolActiveStat;
import com.newrelic.api.agent.security.instrumentation.helpers.GrpcClientRequestReplayHelper;
import com.newrelic.api.agent.security.utils.logging.LogLevel;
import com.newrelic.agent.security.intcodeagent.models.javaagent.JAHealthCheck;
import com.newrelic.agent.security.intcodeagent.models.javaagent.ThreadPoolStats;
import com.newrelic.agent.security.intcodeagent.schedulers.SchedulerHelper;
import com.newrelic.agent.security.intcodeagent.websocket.EventSendPool;
import com.newrelic.agent.security.intcodeagent.websocket.JsonConverter;
import com.newrelic.agent.security.intcodeagent.websocket.WSClient;
import com.newrelic.agent.security.intcodeagent.websocket.WSUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.text.StringSubstitutor;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import com.sun.management.OperatingSystemMXBean;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;
public class HealthCheckScheduleThread {
public static final String WEBSOCKET = "websocket";
private static HealthCheckScheduleThread instance;
private static final FileLoggerThreadPool logger = FileLoggerThreadPool.getInstance();
private ScheduledFuture future;
private static boolean isStatusLoggingActive = true;
private static OSVariables osVariables = OsVariablesInstance.getInstance().getOsVariables();
private Runnable runnable = new Runnable() {
public void run() {
JAHealthCheck sendJaHealthCheck = null;
try {
// since tcp connection keep alive check is more than 2 hours
// we send our custom object to check if connection is still alive or not
// this will be ignored by ic agent on the other side.
AgentInfo.getInstance().getJaHealthCheck().setStats(populateJVMStats());
AgentInfo.getInstance().getJaHealthCheck().setServiceStatus(getServiceStatus());
AgentInfo.getInstance().getJaHealthCheck().setThreadPoolStats(populateThreadPoolStats());
if (!AgentInfo.getInstance().isAgentActive()) {
return;
}
logger.log(LogLevel.INFO, String.format("Pending CCs to be processed : %s", RestRequestThreadPool.getInstance().getQueueSize()), this.getClass().getName());
AgentInfo.getInstance().getJaHealthCheck().getIastReplayRequest().incrementPendingControlCommandsBy(RestRequestThreadPool.getInstance().getQueueSize());
AgentInfo.getInstance().getJaHealthCheck().getIastReplayRequest().incrementPendingControlCommandsBy(GrpcClientRequestReplayHelper.getInstance().getRequestQueue().size());
AgentUtils.getInstance().addStatusLogMostRecentHCs(AgentInfo.getInstance().getJaHealthCheck().toString());
// channel.write(ByteBuffer.wrap(new JAHealthCheck(AgentNew.JA_HEALTH_CHECK).toString().getBytes()));
if (WSClient.getInstance().isOpen()) {
synchronized (AgentInfo.getInstance().getJaHealthCheck()){
sendJaHealthCheck = new JAHealthCheck(AgentInfo.getInstance().getJaHealthCheck());
AgentInfo.getInstance().getJaHealthCheck().reset();
}
WSClient.getInstance().send(JsonConverter.toJSON(sendJaHealthCheck));
}
} catch (NullPointerException ex) {
logger.log(LogLevel.WARNING, "No reference to Socket's OutputStream",
HealthCheckScheduleThread.class.getName());
} catch (Throwable e) {
logger.log(LogLevel.WARNING, "Error while trying to verify connection: ", e,
HealthCheckScheduleThread.class.getName());
}
}
};
private ThreadPoolStats populateThreadPoolStats() {
ThreadPoolStats threadPoolStats = new ThreadPoolStats();
threadPoolStats.setDispatcher(new ThreadPoolActiveStat(DispatcherPool.getInstance().getExecutor().getActiveCount(),
DispatcherPool.getInstance().getExecutor().getQueue().size()));
threadPoolStats.setEventSender(new ThreadPoolActiveStat(EventSendPool.getInstance().getExecutor().getActiveCount(),
EventSendPool.getInstance().getExecutor().getQueue().size()));
threadPoolStats.setControlCommandProcessor(new ThreadPoolActiveStat(ControlCommandProcessorThreadPool.getInstance().getExecutor().getActiveCount(),
ControlCommandProcessorThreadPool.getInstance().getExecutor().getQueue().size()));
threadPoolStats.setIastHttpRequestProcessor(new ThreadPoolActiveStat(RestRequestThreadPool.getInstance().getExecutor().getActiveCount(),
RestRequestThreadPool.getInstance().getExecutor().getQueue().size()));
threadPoolStats.setFileLogger(new ThreadPoolActiveStat(FileLoggerThreadPool.getInstance().getExecutor().getActiveCount(),
FileLoggerThreadPool.getInstance().getExecutor().getQueue().size()));
return threadPoolStats;
}
private HealthCheckScheduleThread() {}
public void scheduleNewTask() {
future = SchedulerHelper.getInstance().scheduleHealthCheck(runnable, 30, 300, TimeUnit.SECONDS);
}
public boolean cancelTask(boolean forceCancel) {
if (future == null) {
return true;
}
if (future != null && (forceCancel || future.isDone() || future.getDelay(TimeUnit.MINUTES) > 5)) {
logger.log(LogLevel.INFO, "Cancel current task of HealthCheck Schedule", HealthCheckScheduleThread.class.getName());
future.cancel(true);
return true;
}
return false;
}
private static Map getServiceStatus() {
Map serviceStatus = new HashMap<>();
/**
* 1. websocket
* 2. log writer
* 3. agent active
* 4. resource server
* 5. IAST rest client
* 6. Status log writer
* */
serviceStatus.put(WEBSOCKET, WSUtils.isConnected() ? "OK" : "Error");
serviceStatus.put("logWriter", FileLoggerThreadPool.getInstance().isLoggingActive() ? "OK" : "Error");
serviceStatus.put("initLogWriter", FileLoggerThreadPool.getInstance().isInitLoggingActive() ? "OK" : "Error");
serviceStatus.put("statusLogWriter", isStatusLoggingActive ? "OK" : "Error");
serviceStatus.put("agentActiveStat", AgentInfo.getInstance().isAgentActive() ? "OK" : "Error");
serviceStatus.put("iastRestClient", IastHttpClient.getInstance().isConnected() ? "OK" : "Error");
return serviceStatus;
}
private static Map populateJVMStats() {
Map stats = new HashMap<>();
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
stats.put("processHeapUsageMB", NumberUtils.toScaledBigDecimal(memoryMXBean.getHeapMemoryUsage().getUsed() / 1048576.0, 2, RoundingMode.HALF_DOWN).doubleValue());
stats.put("processMaxHeapMB", NumberUtils.toScaledBigDecimal(memoryMXBean.getHeapMemoryUsage().getMax() / 1048576.0, 2, RoundingMode.HALF_DOWN).doubleValue());
stats.put("processRssMB", NumberUtils.toScaledBigDecimal((memoryMXBean.getHeapMemoryUsage().getUsed() + memoryMXBean.getNonHeapMemoryUsage().getUsed()) / 1048576.0, 2, RoundingMode.HALF_DOWN).doubleValue());
stats.put("processFreeMemoryMB", NumberUtils.toScaledBigDecimal(Runtime.getRuntime().freeMemory() / 1048576.0, 2, RoundingMode.HALF_DOWN).doubleValue());
setOsStats(stats);
stats.put("nCores", Runtime.getRuntime().availableProcessors());
stats.put("rootDiskFreeSpaceMB", NumberUtils.toScaledBigDecimal(osVariables.getRootDir().getFreeSpace() / 1048576.0, 2, RoundingMode.HALF_DOWN).doubleValue());
stats.put("processDirDiskFreeSpaceMB", NumberUtils.toScaledBigDecimal(new File(".").getFreeSpace() / 1048576.0, 2, RoundingMode.HALF_DOWN).doubleValue());
return stats;
}
private static void setOsStats(Map stats) {
try {
OperatingSystemMXBean osBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
stats.put("systemCpuLoad", NumberUtils.toScaledBigDecimal(osBean.getSystemLoadAverage(), 2, RoundingMode.HALF_DOWN).doubleValue());
stats.put("processCpuUsage", NumberUtils.toScaledBigDecimal(osBean.getProcessCpuLoad()*100, 2, RoundingMode.HALF_DOWN).doubleValue());
stats.put("systemFreeMemoryMB", NumberUtils.toScaledBigDecimal(osBean.getFreePhysicalMemorySize() / 1048576.0, 2, RoundingMode.HALF_DOWN).doubleValue());
stats.put("systemTotalMemoryMB", NumberUtils.toScaledBigDecimal(osBean.getTotalPhysicalMemorySize() / 1048576.0, 2, RoundingMode.HALF_DOWN).doubleValue());
} catch (Throwable e) {
logger.log(LogLevel.FINER, "Error while populating OS related resource usage stats : ", e, HealthCheckScheduleThread.class.getName());
}
}
public static HealthCheckScheduleThread getInstance() {
try {
if (instance == null)
instance = new HealthCheckScheduleThread();
return instance;
} catch (Throwable e) {
logger.log(LogLevel.WARNING, "Error while starting: ", e, HealthCheckScheduleThread.class.getName());
}
throw null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy