diff --git a/lib/drawio.js b/lib/drawio.js
index 873c43f85189a2cc74172565a8d7574cdcba9a0b..996fdabae929b3f865264e6a3cd21c23c5c2a47f 100644
--- a/lib/drawio.js
+++ b/lib/drawio.js
@@ -1,5 +1,5 @@
-import { callbackify, promisify } from "util";
-import child_process from "child_process";
+import { callbackify } from "util";
+import exec from "./exec";
 import fs from "fs";
 import logger from "gulplog";
 import { mkTempFile } from "./tempdir";
@@ -9,8 +9,6 @@ import { withBinary } from "./optional";
 
 const PLUGIN_NAME = "drawio";
 
-const execFile = promisify(child_process.execFile);
-
 const drawio = withBinary(
   "DRAWIO_BINARY",
   "drawio",
@@ -33,23 +31,21 @@ const drawio = withBinary(
               input.path,
             ];
 
-            const { stdout, stderr } = await execFile(DRAWIO_BINARY, args);
-            if (stdout.length > 0) {
-              logger.info(PLUGIN_NAME, "stdout:", stdout);
-            }
-            if (stderr.length > 0) {
-              logger.info(PLUGIN_NAME, "command:", DRAWIO_BINARY, args);
-              logger.info(PLUGIN_NAME, "stderr:", stderr);
-            }
+            await exec(PLUGIN_NAME, DRAWIO_BINARY, args);
+
+            logger.info(
+              "%s: %s -> %s",
+              PLUGIN_NAME,
+              input.relative,
+              output.relative
+            );
 
             output.contents = fs.createReadStream(output.path, {
               encoding: "UTF-8",
             });
-            logger.info("%s: generated %s", PLUGIN_NAME, output.relative);
-
             this.push(output);
           } catch (error) {
-            throw new PluginError(PLUGIN_NAME, error);
+            throw new PluginError(PLUGIN_NAME, error, { showStack: true });
           }
         })
       );
diff --git a/lib/exec.js b/lib/exec.js
new file mode 100644
index 0000000000000000000000000000000000000000..9c1b0e18b5376c8257617fc437811a08e0c3d029
--- /dev/null
+++ b/lib/exec.js
@@ -0,0 +1,26 @@
+import { execFile } from "child_process";
+import logger from "gulplog";
+
+/**
+ *
+ * @param {string} plugin_name
+ * @param {string} cmd
+ * @param {string[]} args
+ * @param {import("child_process").ExecFileOptions} opts
+ * @return {Promise<{ stdout: string|Buffer, stderr: string|Buffer }>}
+ */
+export default function exec(plugin_name, cmd, args, opts = {}) {
+  return new Promise((resolve, reject) => {
+    execFile(cmd, args, opts, (error, stdout, stderr) => {
+      if (!error) {
+        logger.debug("%s: %s terminated successfully", plugin_name, cmd);
+        return resolve({ stdout, stderr });
+      }
+      logger.error("%s: %s failed: %s", plugin_name, cmd, error.message);
+      logger.error("%s: command: `%s %s`", plugin_name, cmd, args.join(" "));
+      logger.error("%s: stdout:\n%s", plugin_name, stdout.toString());
+      logger.error("%s: stderr:\n%s", plugin_name, stderr.toString());
+      reject(error);
+    });
+  });
+}
diff --git a/lib/wkhtmltopdf.js b/lib/wkhtmltopdf.js
index 33febcdae0873d9fcf7e3c70e3e57c9e5287e717..0595fcf828c8cb81b58dec3dd7683df322bc0363 100644
--- a/lib/wkhtmltopdf.js
+++ b/lib/wkhtmltopdf.js
@@ -1,6 +1,6 @@
-import { callbackify, promisify } from "util";
-import child_process from "child_process";
+import { callbackify } from "util";
 import { createReadStream } from "fs";
+import exec from "./exec";
 import logger from "gulplog";
 import { mkTempFile } from "./tempdir";
 import { obj } from "through2";
@@ -8,8 +8,6 @@ import path from "path";
 import PluginError from "plugin-error";
 import { withBinary } from "./optional";
 
-const execFile = promisify(child_process.execFile);
-
 const PLUGIN_NAME = "wkhtmltopdf";
 
 const DEFAULT_OPTIONS = {
@@ -59,17 +57,13 @@ export const wkhtmltopdf = withBinary(
               output.path,
             ];
 
-            const { stdout, stderr } = await execFile(
-              WKHTMLTOPDF_BINARY,
-              execArgs
+            await exec(PLUGIN_NAME, WKHTMLTOPDF_BINARY, execArgs);
+            logger.info(
+              "%s: %s -> %s",
+              PLUGIN_NAME,
+              input.relative,
+              output.relative
             );
-            logger.info("%s: generated %s", PLUGIN_NAME, output.relative);
-            if (stdout.length > 0) {
-              logger.debug(PLUGIN_NAME, "stdout:", stdout);
-            }
-            if (stderr.length > 0) {
-              logger.debug(PLUGIN_NAME, "stderr:", stderr);
-            }
 
             output.contents = createReadStream(output.path);
             this.push(output);