package detective.core.distribute; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaRDD; import org.apache.spark.api.java.JavaSparkContext; import org.apache.spark.api.java.function.Function; import org.apache.spark.api.java.function.VoidFunction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import detective.core.distribute.collector.JobCollector; import detective.core.distribute.resultrender.ResultRender; import detective.core.distribute.resultrender.ResultRenderAnsiConsoleImpl; import detective.core.services.DetectiveFactory; public class SparkDriver { private final static Logger logger = LoggerFactory.getLogger(SparkDriver.class); private final static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); public static String getDefaultAppName(String packageOrClassName){ return "Detective-" + packageOrClassName + "-" + format.format(new Date()); } /** * ./bin/spark-submit --class detective.core.distribute.SparkDriver --master spark://127.0.0.1:7000 your.jar spark://127.0.0.1:7000 * * @param args classOrPackageName */ public static void main(String[] args) { if (args == null || args.length < 1){ System.err.println("Usage: detective.core.distribute.SparkDriver packageOrClassName applicationName(Optional)\n" + " if you'd like to setup master, please change your detective.conf file or -Dspark.master=yourMasterUrl\n" + " -Dspark.driver.host is the host name if you'd like to use"); System.exit(-1); } long errors = run(args); if (errors > 0) System.exit(-1); } /** * * @return how many jobs failed */ public static long run(String[] args) { String packageName = args[0]; String master = DetectiveFactory.INSTANCE.getConfig().getString("spark.master"); logger.info("Detective is running with master " + master); logger.info("Detective is running with package or class " + packageName); String appName = null; if (args.length >= 2){ appName = args[1]; }else appName = getDefaultAppName(packageName); Long startTime = System.nanoTime(); List<JobRunResult> jobsAfterRun = runJobs(packageName, appName); Long endTime = System.nanoTime(); Collections.sort(jobsAfterRun); long errors = 0; long skipped = 0; for (JobRunResult job : jobsAfterRun){ if (! job.getSuccessed()) errors = errors + 1; if (job.isIgnored()) skipped ++; logger.info(job.toString()); } Long timeElapsedSec = TimeUnit.SECONDS.convert(endTime - startTime, TimeUnit.NANOSECONDS); logger.info("Tests run: "+jobsAfterRun.size()+", Errors: "+errors+", Skipped: "+skipped+", Time elapsed: " + timeElapsedSec + " Seconds "); printResults(jobsAfterRun); return errors; } //This method here for testing only static List<JobRunResult> runJobs(String packageName, String appName) { String master = DetectiveFactory.INSTANCE.getConfig().getString("spark.master"); logger.info("Detective is running with master " + master); logger.info("Detective is running with package or class " + packageName); SparkConf sparkConf = new SparkConf() .setAppName(appName) .setMaster(master) //.setMaster("local[8]") //.setMaster("spark://127.0.0.1:7000") //.set("spark.driver.host", "localhost") //.set("spark.driver.port", "5555") ; int duplicatedtasks = DetectiveFactory.INSTANCE.getConfig().getInt("spark.pressureTest.duplicateTasks"); logger.info("Detective pressure test, jobs duplication: " + duplicatedtasks); List<JobToRun> jobs = JobCollector.collectAll(packageName, duplicatedtasks); if (jobs.size() <= 0){ logger.error("we can't found any story from your input " + packageName); System.exit(-1); } JavaSparkContext jsc = new JavaSparkContext(sparkConf); JavaRDD<JobToRun> dataset = jsc.parallelize(jobs, jobs.size()); JavaRDD<JobRunResult> datasetResult = dataset.map(new Function<JobToRun, JobRunResult>(){ @Override public JobRunResult call(JobToRun job) throws Exception { logger.info("Running Job:" + job.toString()); try { JobRunner runner = new JobRunnerFilterImpl(); runner.run(job); return job.getJobResult(); } catch (Throwable e) { //We never throw a exception into spark as we don't want it retry logger.error(e.getMessage(), e); JobRunResult result = new JobRunResult(); result.setStoryName(job.getStoryClassName()); result.setScenarioName("ScenarioIndex:" + job.getScenarioIndex()); result.setError(e); result.setSuccessed(false); return result; } }}); List<JobRunResult> jobsAfterRun = datasetResult.collect(); return jobsAfterRun; } private static void printResults(List<JobRunResult> results){ ResultRender render = new ResultRenderAnsiConsoleImpl(); render.render(results, 0); } }