/******************************************************************************* * Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved * * Licensed 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.robobninjas.riemann.spring.server; import com.google.common.base.Optional; import com.google.common.base.Throwables; import com.google.common.collect.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Path; import java.util.Arrays; import java.util.Scanner; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * Executes an external celery worker. * The process is closed with {@link #close()} * * @author Itai Frenkel * @since 3.0.1 */ public class RiemannProcess implements AutoCloseable { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); private final RiemannProcessOutputLogger riemannOutputLogger; public RiemannProcess(final Path configPath) { String[] command = new String[] {"riemann", configPath.toString()}; logger.debug("Starting Riemann with command : " + Arrays.toString(command)); final ProcessBuilder pb = new ProcessBuilder(); pb.command(Lists.newArrayList(command)); pb.redirectErrorStream(true); try { final Process process = pb.start(); this.riemannOutputLogger = new RiemannProcessOutputLogger(process.getInputStream(), logger); if (!riemannOutputLogger.awaitOnline(1, TimeUnit.MINUTES)) { throw new IllegalStateException("Riemann failed to start TCP server"); } } catch (final IOException e) { throw Throwables.propagate(e); } catch (InterruptedException e) { throw Throwables.propagate(e); } } private static boolean isWindows() { return System.getProperty("os.name").startsWith("Windows"); } @Override public void close() throws Exception { logger.debug("Terminating riemann process."); String[] cmd; if (isWindows()) { cmd = new String[] {"cmd", "/c", "taskkill /F /PID " + getPid()}; } else { cmd = new String [] {"kill", "-TERM", "" + getPid()}; } final ProcessBuilder pb = new ProcessBuilder(); pb.command(Lists.newArrayList(cmd)); pb.redirectErrorStream(true); logger.debug("Terminating Riemann with command: " + Arrays.toString(cmd)); final Process process = pb.start(); final ProcessOutputLogger outputLogger = new ProcessOutputLogger(process.getInputStream(), logger); try { int exitCode = process.waitFor(); if (exitCode != 0) { throw new IllegalStateException("Failed to terminate riemann process"); } } finally { outputLogger.close(); } } public String getHost() { return riemannOutputLogger.getHost(); } public int getPid() { return riemannOutputLogger.getPid(); } public Optional<Integer> getWebSocketPort() { return riemannOutputLogger.getWebSocketPort(); } public Optional<Integer> getTcpPort() { return riemannOutputLogger.getTcpPort(); } }