Search in sources :

Example 6 with UncaughtExceptionHandler

use of io.cdap.cdap.common.logging.common.UncaughtExceptionHandler in project cdap by caskdata.

the class DaemonMain method doMain.

/**
 * The main method. It simply call methods in the same sequence
 * as if the program is started by jsvc.
 */
protected void doMain(final String[] args) throws Exception {
    try {
        init(args);
    } catch (Throwable t) {
        LOG.error("Exception raised when calling init", t);
        try {
            destroy();
        } catch (Throwable t2) {
            LOG.error("Exception raised when calling destroy", t);
            t.addSuppressed(t2);
        }
        // Throw to terminate the main thread
        throw t;
    }
    CountDownLatch shutdownLatch = new CountDownLatch(1);
    AtomicBoolean terminated = new AtomicBoolean();
    Runnable terminateRunnable = () -> {
        if (!terminated.compareAndSet(false, true)) {
            return;
        }
        try {
            try {
                DaemonMain.this.stop();
            } finally {
                try {
                    DaemonMain.this.destroy();
                } finally {
                    shutdownLatch.countDown();
                }
            }
        } catch (Throwable t) {
            LOG.error("Exception when shutting down: " + t.getMessage(), t);
        }
    };
    Runtime.getRuntime().addShutdownHook(new Thread(terminateRunnable));
    try {
        start();
    } catch (Throwable t) {
        // Throw to terminate the main thread
        LOG.error("Exception raised when calling start", t);
        terminateRunnable.run();
        throw t;
    }
    // Set uncaught exception handler after startup, this is so that if startup throws exception then we
    // want it to be logged as error (the handler logs it as debug)
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());
    shutdownLatch.await();
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CountDownLatch(java.util.concurrent.CountDownLatch) UncaughtExceptionHandler(io.cdap.cdap.common.logging.common.UncaughtExceptionHandler)

Example 7 with UncaughtExceptionHandler

use of io.cdap.cdap.common.logging.common.UncaughtExceptionHandler in project cdap by caskdata.

the class SparkContainerLauncher method launch.

/**
 * Launches the given main class. The main class will be loaded through the {@link SparkContainerClassLoader}.
 *
 * @param mainClassName the main class to launch
 * @param args arguments for the main class
 * @param removeMainClass whether to remove the jar for the main class from the classloader
 * @param masterEnvName name of the MasterEnvironment used to submit the Spark job. This will be used to setup
 *   bindings for service discovery and other CDAP capabilities. If null, the default Hadoop implementations will
 *   be used.
 */
public static void launch(String mainClassName, String[] args, boolean removeMainClass, @Nullable String masterEnvName) throws Exception {
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());
    ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
    Set<URL> urls = ClassLoaders.getClassLoaderURLs(systemClassLoader, new LinkedHashSet<URL>());
    // method call from the container launch script.
    if (removeMainClass) {
        urls.remove(getURLByClass(systemClassLoader, mainClassName));
    }
    // Remove the first scala from the set of classpath. This ensure the one from Spark is used for spark
    removeNonSparkJar(systemClassLoader, "scala.language", urls);
    // Remove the first jar containing LZBlockInputStream from the set of classpath.
    // The one from Kafka is not compatible with Spark
    removeNonSparkJar(systemClassLoader, "net.jpountz.lz4.LZ4BlockInputStream", urls);
    // First create a FilterClassLoader that only loads JVM and kafka classes from the system classloader
    // This is to isolate the scala library from children
    ClassLoader parentClassLoader = new FilterClassLoader(systemClassLoader, KAFKA_FILTER);
    boolean rewriteCheckpointTempFileName = Boolean.parseBoolean(System.getProperty(SparkRuntimeUtils.STREAMING_CHECKPOINT_REWRITE_ENABLED, "false"));
    // Creates the SparkRunnerClassLoader for class rewriting and it will be used for the rest of the execution.
    // Use the extension classloader as the parent instead of the system classloader because
    // Spark classes are in the system classloader which we want to rewrite.
    ClassLoader classLoader = new SparkContainerClassLoader(urls.toArray(new URL[0]), parentClassLoader, rewriteCheckpointTempFileName);
    // Sets the context classloader and launch the actual Spark main class.
    Thread.currentThread().setContextClassLoader(classLoader);
    // Create SLF4J logger from the context classloader. It has to be created from that classloader in order
    // for logs in this class to be in the same context as the one used in Spark.
    Object logger = createLogger(classLoader);
    // Install the JUL to SLF4J Bridge
    try {
        classLoader.loadClass(SLF4JBridgeHandler.class.getName()).getDeclaredMethod("install").invoke(null);
    } catch (Exception e) {
        // Log the error and continue
        log(logger, "warn", "Failed to invoke SLF4JBridgeHandler.install() required for jul-to-slf4j bridge", e);
    }
    // Get the SparkRuntimeContext to initialize all necessary services and logging context
    // Need to do it using the SparkRunnerClassLoader through reflection.
    Class<?> sparkRuntimeContextProviderClass = classLoader.loadClass(SparkRuntimeContextProvider.class.getName());
    if (masterEnvName != null) {
        sparkRuntimeContextProviderClass.getMethod("setMasterEnvName", String.class).invoke(null, masterEnvName);
    }
    Object sparkRuntimeContext = sparkRuntimeContextProviderClass.getMethod("get").invoke(null);
    if (sparkRuntimeContext instanceof Closeable) {
        System.setSecurityManager(new SparkRuntimeSecurityManager((Closeable) sparkRuntimeContext));
    }
    try {
        // in the PythonRunner/PythonWorkerFactory via SparkClassRewriter.
        if (!isPySpark()) {
            // Invoke StandardOutErrorRedirector.redirectToLogger()
            classLoader.loadClass(StandardOutErrorRedirector.class.getName()).getDeclaredMethod("redirectToLogger", String.class).invoke(null, mainClassName);
        }
        // which causes executor logs attempt to write to driver log directory
        if (System.getProperty("spark.executorEnv.CDAP_LOG_DIR") != null) {
            System.setProperty("spark.executorEnv.CDAP_LOG_DIR", "<LOG_DIR>");
        }
        // Optionally starts Py4j Gateway server in the executor container
        Runnable stopGatewayServer = startGatewayServerIfNeeded(classLoader, logger);
        try {
            log(logger, "info", "Launch main class {}.main({})", mainClassName, Arrays.toString(args));
            classLoader.loadClass(mainClassName).getMethod("main", String[].class).invoke(null, new Object[] { args });
            log(logger, "info", "Main method returned {}", mainClassName);
        } finally {
            stopGatewayServer.run();
        }
    } catch (Throwable t) {
        // LOG the exception since this exception will be propagated back to JVM
        // and kill the main thread (hence the JVM process).
        // If we don't log it here as ERROR, it will be logged by UncaughtExceptionHandler as DEBUG level
        log(logger, "error", "Exception raised when calling {}.main(String[]) method", mainClassName, t);
        throw t;
    } finally {
        if (sparkRuntimeContext instanceof Closeable) {
            Closeables.closeQuietly((Closeable) sparkRuntimeContext);
        }
    }
}
Also used : FilterClassLoader(io.cdap.cdap.common.lang.FilterClassLoader) Closeable(java.io.Closeable) URL(java.net.URL) URISyntaxException(java.net.URISyntaxException) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) SLF4JBridgeHandler(org.slf4j.bridge.SLF4JBridgeHandler) SparkRuntimeContextProvider(io.cdap.cdap.app.runtime.spark.SparkRuntimeContextProvider) SparkContainerClassLoader(io.cdap.cdap.app.runtime.spark.classloader.SparkContainerClassLoader) StandardOutErrorRedirector(io.cdap.cdap.common.logging.StandardOutErrorRedirector) SparkContainerClassLoader(io.cdap.cdap.app.runtime.spark.classloader.SparkContainerClassLoader) FilterClassLoader(io.cdap.cdap.common.lang.FilterClassLoader) UncaughtExceptionHandler(io.cdap.cdap.common.logging.common.UncaughtExceptionHandler)

Example 8 with UncaughtExceptionHandler

use of io.cdap.cdap.common.logging.common.UncaughtExceptionHandler in project cdap by caskdata.

the class DefaultRuntimeJob method run.

@Override
public void run(RuntimeJobEnvironment runtimeJobEnv) throws Exception {
    // Setup process wide settings
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());
    SLF4JBridgeHandler.removeHandlersForRootLogger();
    SLF4JBridgeHandler.install();
    // Get Program Options
    ProgramOptions programOpts = readJsonFile(new File(DistributedProgramRunner.PROGRAM_OPTIONS_FILE_NAME), ProgramOptions.class);
    ProgramRunId programRunId = programOpts.getProgramId().run(ProgramRunners.getRunId(programOpts));
    ProgramId programId = programRunId.getParent();
    Arguments systemArgs = programOpts.getArguments();
    // Setup logging context for the program
    LoggingContextAccessor.setLoggingContext(LoggingContextHelper.getLoggingContextWithRunId(programRunId, systemArgs.asMap()));
    // Get the cluster launch type
    Cluster cluster = GSON.fromJson(systemArgs.getOption(ProgramOptionConstants.CLUSTER), Cluster.class);
    // Get App spec
    ApplicationSpecification appSpec = readJsonFile(new File(DistributedProgramRunner.APP_SPEC_FILE_NAME), ApplicationSpecification.class);
    ProgramDescriptor programDescriptor = new ProgramDescriptor(programId, appSpec);
    // Create injector and get program runner
    Injector injector = Guice.createInjector(createModules(runtimeJobEnv, createCConf(runtimeJobEnv, programOpts), programRunId, programOpts));
    CConfiguration cConf = injector.getInstance(CConfiguration.class);
    // Initialize log appender
    LogAppenderInitializer logAppenderInitializer = injector.getInstance(LogAppenderInitializer.class);
    logAppenderInitializer.initialize();
    SystemArguments.setLogLevel(programOpts.getUserArguments(), logAppenderInitializer);
    ProxySelector oldProxySelector = ProxySelector.getDefault();
    RuntimeMonitors.setupMonitoring(injector, programOpts);
    Deque<Service> coreServices = createCoreServices(injector, systemArgs, cluster);
    startCoreServices(coreServices);
    // regenerate app spec
    ConfiguratorFactory configuratorFactory = injector.getInstance(ConfiguratorFactory.class);
    try {
        Map<String, String> systemArguments = new HashMap<>(programOpts.getArguments().asMap());
        File pluginDir = new File(programOpts.getArguments().getOption(ProgramOptionConstants.PLUGIN_DIR, DistributedProgramRunner.PLUGIN_DIR));
        // create a directory to store plugin artifacts for the regeneration of app spec to fetch plugin artifacts
        DirUtils.mkdirs(pluginDir);
        if (!programOpts.getArguments().hasOption(ProgramOptionConstants.PLUGIN_DIR)) {
            systemArguments.put(ProgramOptionConstants.PLUGIN_DIR, DistributedProgramRunner.PLUGIN_DIR);
        }
        // remember the file names in the artifact folder before app regeneration
        List<String> pluginFiles = DirUtils.listFiles(pluginDir, File::isFile).stream().map(File::getName).collect(Collectors.toList());
        ApplicationSpecification generatedAppSpec = regenerateAppSpec(systemArguments, programOpts.getUserArguments().asMap(), programId, appSpec, programDescriptor, configuratorFactory);
        appSpec = generatedAppSpec != null ? generatedAppSpec : appSpec;
        programDescriptor = new ProgramDescriptor(programDescriptor.getProgramId(), appSpec);
        List<String> pluginFilesAfter = DirUtils.listFiles(pluginDir, File::isFile).stream().map(File::getName).collect(Collectors.toList());
        if (pluginFilesAfter.isEmpty()) {
            systemArguments.remove(ProgramOptionConstants.PLUGIN_DIR);
        }
        // recreate it from the folders
        if (!pluginFiles.equals(pluginFilesAfter)) {
            systemArguments.remove(ProgramOptionConstants.PLUGIN_ARCHIVE);
        }
        // update program options
        programOpts = new SimpleProgramOptions(programOpts.getProgramId(), new BasicArguments(systemArguments), programOpts.getUserArguments(), programOpts.isDebug());
    } catch (Exception e) {
        LOG.warn("Failed to regenerate the app spec for program {}, using the existing app spec", programId, e);
    }
    ProgramStateWriter programStateWriter = injector.getInstance(ProgramStateWriter.class);
    RuntimeClientService runtimeClientService = injector.getInstance(RuntimeClientService.class);
    CompletableFuture<ProgramController.State> programCompletion = new CompletableFuture<>();
    try {
        ProgramRunner programRunner = injector.getInstance(ProgramRunnerFactory.class).create(programId.getType());
        // Create and run the program. The program files should be present in current working directory.
        try (Program program = createProgram(cConf, programRunner, programDescriptor, programOpts)) {
            ProgramController controller = programRunner.run(program, programOpts);
            controllerFuture.complete(controller);
            runtimeClientService.onProgramStopRequested(controller::stop);
            controller.addListener(new AbstractListener() {

                @Override
                public void completed() {
                    programCompletion.complete(ProgramController.State.COMPLETED);
                }

                @Override
                public void killed() {
                    // Write an extra state to make sure there is always a terminal state even
                    // if the program application run failed to write out the state.
                    programStateWriter.killed(programRunId);
                    programCompletion.complete(ProgramController.State.KILLED);
                }

                @Override
                public void error(Throwable cause) {
                    // Write an extra state to make sure there is always a terminal state even
                    // if the program application run failed to write out the state.
                    programStateWriter.error(programRunId, cause);
                    programCompletion.completeExceptionally(cause);
                }
            }, Threads.SAME_THREAD_EXECUTOR);
            if (stopRequested) {
                controller.stop();
            }
            // Block on the completion
            programCompletion.get();
        } finally {
            if (programRunner instanceof Closeable) {
                Closeables.closeQuietly((Closeable) programRunner);
            }
        }
    } catch (Throwable t) {
        controllerFuture.completeExceptionally(t);
        if (!programCompletion.isDone()) {
            // We log here so that the logs would still send back to the program logs collection.
            // Only log if the program completion is not done.
            // Otherwise the program runner itself should have logged the error.
            LOG.error("Failed to execute program {}", programRunId, t);
            // If the program completion is not done, then this exception
            // is due to systematic failure in which fail to run the program.
            // We write out an extra error state for the program to make sure the program state get transited.
            programStateWriter.error(programRunId, t);
        }
        throw t;
    } finally {
        stopCoreServices(coreServices, logAppenderInitializer);
        ProxySelector.setDefault(oldProxySelector);
        Authenticator.setDefault(null);
        runCompletedLatch.countDown();
    }
}
Also used : ApplicationSpecification(io.cdap.cdap.api.app.ApplicationSpecification) ConfiguratorFactory(io.cdap.cdap.internal.app.deploy.ConfiguratorFactory) HashMap(java.util.HashMap) Closeable(java.io.Closeable) ProgramRunnerFactory(io.cdap.cdap.app.runtime.ProgramRunnerFactory) DefaultProgramRunnerFactory(io.cdap.cdap.app.guice.DefaultProgramRunnerFactory) ProxySelector(java.net.ProxySelector) LogAppenderInitializer(io.cdap.cdap.logging.appender.LogAppenderInitializer) CompletableFuture(java.util.concurrent.CompletableFuture) ProgramStateWriter(io.cdap.cdap.app.runtime.ProgramStateWriter) MessagingProgramStateWriter(io.cdap.cdap.internal.app.program.MessagingProgramStateWriter) Injector(com.google.inject.Injector) AbstractListener(io.cdap.cdap.internal.app.runtime.AbstractListener) ProgramDescriptor(io.cdap.cdap.app.program.ProgramDescriptor) BasicArguments(io.cdap.cdap.internal.app.runtime.BasicArguments) UncaughtExceptionHandler(io.cdap.cdap.common.logging.common.UncaughtExceptionHandler) DistributedProgramRunner(io.cdap.cdap.internal.app.runtime.distributed.DistributedProgramRunner) DistributedMapReduceProgramRunner(io.cdap.cdap.internal.app.runtime.distributed.DistributedMapReduceProgramRunner) DistributedWorkerProgramRunner(io.cdap.cdap.internal.app.runtime.distributed.DistributedWorkerProgramRunner) ProgramRunner(io.cdap.cdap.app.runtime.ProgramRunner) DistributedWorkflowProgramRunner(io.cdap.cdap.internal.app.runtime.distributed.DistributedWorkflowProgramRunner) RuntimeClientService(io.cdap.cdap.internal.app.runtime.monitor.RuntimeClientService) ProgramController(io.cdap.cdap.app.runtime.ProgramController) Program(io.cdap.cdap.app.program.Program) Arguments(io.cdap.cdap.app.runtime.Arguments) SystemArguments(io.cdap.cdap.internal.app.runtime.SystemArguments) BasicArguments(io.cdap.cdap.internal.app.runtime.BasicArguments) Cluster(io.cdap.cdap.runtime.spi.provisioner.Cluster) RuntimeClientService(io.cdap.cdap.internal.app.runtime.monitor.RuntimeClientService) Service(com.google.common.util.concurrent.Service) ProfileMetricService(io.cdap.cdap.internal.profile.ProfileMetricService) LogAppenderLoaderService(io.cdap.cdap.logging.appender.loader.LogAppenderLoaderService) MessagingService(io.cdap.cdap.messaging.MessagingService) AbstractIdleService(com.google.common.util.concurrent.AbstractIdleService) MessagingHttpService(io.cdap.cdap.messaging.server.MessagingHttpService) MetricsCollectionService(io.cdap.cdap.api.metrics.MetricsCollectionService) ProgramId(io.cdap.cdap.proto.id.ProgramId) CConfiguration(io.cdap.cdap.common.conf.CConfiguration) SimpleProgramOptions(io.cdap.cdap.internal.app.runtime.SimpleProgramOptions) ProgramOptions(io.cdap.cdap.app.runtime.ProgramOptions) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) SimpleProgramOptions(io.cdap.cdap.internal.app.runtime.SimpleProgramOptions) File(java.io.File)

Example 9 with UncaughtExceptionHandler

use of io.cdap.cdap.common.logging.common.UncaughtExceptionHandler in project cdap by caskdata.

the class RemoteExecutionJobMain method main.

public static void main(String[] args) throws Exception {
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());
    new RemoteExecutionJobMain().doMain(args);
}
Also used : UncaughtExceptionHandler(io.cdap.cdap.common.logging.common.UncaughtExceptionHandler)

Aggregations

UncaughtExceptionHandler (io.cdap.cdap.common.logging.common.UncaughtExceptionHandler)9 CConfiguration (io.cdap.cdap.common.conf.CConfiguration)5 File (java.io.File)4 Configuration (org.apache.hadoop.conf.Configuration)4 Injector (com.google.inject.Injector)3 MetricsCollectionService (io.cdap.cdap.api.metrics.MetricsCollectionService)3 LogAppenderInitializer (io.cdap.cdap.logging.appender.LogAppenderInitializer)3 ApplicationSpecification (io.cdap.cdap.api.app.ApplicationSpecification)2 ProgramDescriptor (io.cdap.cdap.app.program.ProgramDescriptor)2 Arguments (io.cdap.cdap.app.runtime.Arguments)2 SConfiguration (io.cdap.cdap.common.conf.SConfiguration)2 BasicArguments (io.cdap.cdap.internal.app.runtime.BasicArguments)2 SystemArguments (io.cdap.cdap.internal.app.runtime.SystemArguments)2 MasterEnvironmentContext (io.cdap.cdap.master.spi.environment.MasterEnvironmentContext)2 Closeable (java.io.Closeable)2 IOException (java.io.IOException)2 AbstractIdleService (com.google.common.util.concurrent.AbstractIdleService)1 Service (com.google.common.util.concurrent.Service)1 AbstractModule (com.google.inject.AbstractModule)1 Module (com.google.inject.Module)1