From 644094e88f352ddb13b78278e01dfe4dc00c6b4e Mon Sep 17 00:00:00 2001 From: Jillian Crossley Date: Thu, 21 Dec 2023 23:06:56 +0000 Subject: [PATCH] util/util-app: Include the exception in the error message printed when the application encounters an error on startup Problem When the application exits prematurely due to an exception encountered on startup, this exception is not printed to stderr, only the message "Exception thrown in main on startup". The exception stack trace is printed to stdout, but this is unintuitive for the user. Solution Include the exception and stack trace in the exception printed to stderr. Differential Revision: https://phabricator.twitter.biz/D1116753 --- CHANGELOG.rst | 7 +++++++ PROJECT.yml | 1 - util-app/src/main/scala/com/twitter/app/App.scala | 10 +++++++++- util-app/src/test/scala/com/twitter/app/AppTest.scala | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 43fa096fe4..51b4ff60d0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,13 @@ Note that ``PHAB_ID=#`` and ``RB_ID=#`` correspond to associated messages in com Unreleased ---------- +Runtime Behavior Changes +~~~~~~~~~~~~~~~~~~~~~~~~ + +* util-app: When the application exits due to an error on startup, the error and + and stack trace are printed to stderr in addition to the existing stdout. ``PHAB_ID=D1116753`` + + 23.11.0 ------- diff --git a/PROJECT.yml b/PROJECT.yml index c9d152767c..675c29685a 100644 --- a/PROJECT.yml +++ b/PROJECT.yml @@ -4,4 +4,3 @@ owners: - csl-team:ldap - jillianc - mbezoyan - - nvong diff --git a/util-app/src/main/scala/com/twitter/app/App.scala b/util-app/src/main/scala/com/twitter/app/App.scala index cb4c916550..167fa1b6ec 100644 --- a/util-app/src/main/scala/com/twitter/app/App.scala +++ b/util-app/src/main/scala/com/twitter/app/App.scala @@ -3,6 +3,8 @@ package com.twitter.app import com.twitter.app.lifecycle.Event._ import com.twitter.conversions.DurationOps._ import com.twitter.util._ +import java.io.PrintWriter +import java.io.StringWriter import java.lang.reflect.InvocationTargetException import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.atomic.AtomicReference @@ -82,7 +84,13 @@ trait App extends ClosableOnce with CloseOnceAwaitably with Lifecycle { System.err.println(throwable.getMessage) System.exit(1) case _ => - exitOnError("Exception thrown in main on startup") + util.Using(new StringWriter) { stringWriter => + util.Using(new PrintWriter(stringWriter)) { printWriter => + throwable.printStackTrace(printWriter) + printWriter.flush() + exitOnError(s"Exception thrown in main on startup: ${stringWriter.toString}") + } + } } } diff --git a/util-app/src/test/scala/com/twitter/app/AppTest.scala b/util-app/src/test/scala/com/twitter/app/AppTest.scala index 5c70b2f126..a6c9eedcdb 100644 --- a/util-app/src/test/scala/com/twitter/app/AppTest.scala +++ b/util-app/src/test/scala/com/twitter/app/AppTest.scala @@ -67,7 +67,7 @@ class AppTest extends AnyFunSuite { test1.main(Array()) - assert(test1.reason.contains("Exception thrown in main on startup")) + assert(test1.reason.exists(_.contains("Exception thrown in main on startup"))) } test("App: propagate underlying exception from fields in app") {