package com.paypal.mesos.executor.monitoring; import com.paypal.mesos.executor.CommandBuilder; import com.paypal.mesos.executor.config.Config; import com.paypal.mesos.executor.utils.ProcessUtils; import org.apache.log4j.Logger; import rx.Observable; import rx.Observer; import rx.Subscription; import rx.functions.Action1; import rx.subjects.BehaviorSubject; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.StringTokenizer; import java.util.concurrent.TimeUnit; //TODO remode public class ComposeMonitor { private static final Logger log = Logger.getLogger(ComposeMonitor.class); public final BehaviorSubject<Integer> monitor; public ComposeMonitor() { monitor = BehaviorSubject.create(); } public Subscription subscribeToChanges(Action1<Integer> action) { return monitor.subscribe(action); } public void startMonitoring(final List<String> fileNames) { log.info("start montioring is called:" + fileNames); Observable.interval(Config.POD_MONITOR_INTERVAL, TimeUnit.MILLISECONDS).subscribe(new Observer<Long>() { @Override public void onCompleted() { log.info("monitor thread on completed :completed monitoring compose for file:" + fileNames); } @Override public void onError(Throwable e) { log.error("monitor thread on error: encountred an error monitoring:" + fileNames, e); monitor.onNext(1); } @Override public void onNext(Long t) { List<String> containerIds = getContainerIds(fileNames); if (log.isDebugEnabled()) log.debug(Arrays.toString(containerIds.toArray())); if (containerIds != null) { for (String containerId : containerIds) { ContainerDetails details = getContainerDetails(containerId); int exitCode = details.getExitCode(); int restartCount = details.getRestartCount(); if (details.isRunning() == false && exitCode != 0 && restartCount == details.getMaxAllowedRestartCount()) { RestartPolicyException exception = new RestartPolicyException(containerId, exitCode, restartCount); onError(exception); } } } } }); } public List<String> getContainerIds(List<String> fileNames) { List<String> containerIds = new ArrayList<String>(); String listConatinerIdsCommand = CommandBuilder.getContainerIds(fileNames); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); int exitCode = ProcessUtils.executeCommand(listConatinerIdsCommand, null, outputStream, null, null); if (exitCode == 0) { String commandOutput = outputStream.toString(); containerIds = parseListCommandOutput(commandOutput); } return containerIds; } private List<String> parseListCommandOutput(String output) { List<String> containersIds = new ArrayList<String>(); if (output != null) { StringTokenizer tokenizer = new StringTokenizer(output, "\n"); while (tokenizer.hasMoreTokens()) { containersIds.add(tokenizer.nextToken().trim()); } } return containersIds; } public ContainerDetails getContainerDetails(String containerId) { String detailsCommand = CommandBuilder.getContainerDetails(containerId); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); int exitCode = ProcessUtils.executeCommand(detailsCommand, null, outputStream, null, null); if (exitCode == 0) { String details = outputStream.toString(); ContainerDetails containerDetails = parseDetails(containerId, details); return containerDetails; } else { throw new ContainerDetailRetrievalException(containerId); } } public ContainerDetails parseDetails(String containerId, String details) { StringTokenizer tokenizer = new StringTokenizer(details, ","); if (tokenizer.countTokens() == 5) { try { int pid = Integer.parseInt(tokenizer.nextToken()); int exitCode = Integer.parseInt(tokenizer.nextToken()); boolean isRunning = Boolean.parseBoolean(tokenizer.nextToken()); int restartCount = Integer.parseInt(tokenizer.nextToken()); int maxRestartCount = Integer.parseInt(tokenizer.nextToken().trim()); return new ContainerDetails(containerId, isRunning, restartCount, maxRestartCount, exitCode, pid); } catch (Exception exception) { log.error("problem while parsing container details for containerId:" + containerId + ":details string is:" + details, exception); throw new ContainerDetailRetrievalException(containerId); } } else { throw new ContainerDetailRetrievalException(containerId); } } }