Fix noisy nodejs runtime errors (#6995)
This commit is contained in:
parent
815f42d8a5
commit
15418b6789
|
@ -15,5 +15,8 @@
|
||||||
- [auto/python] - Export missing `ProjectBackend` type
|
- [auto/python] - Export missing `ProjectBackend` type
|
||||||
[#6984](https://github.com/pulumi/pulumi/pull/6984)
|
[#6984](https://github.com/pulumi/pulumi/pull/6984)
|
||||||
|
|
||||||
|
- [sdk/nodejs] - Fix noisy errors.
|
||||||
|
[#6995](https://github.com/pulumi/pulumi/pull/6995)
|
||||||
|
|
||||||
- Config: Avoid emitting integers in objects using exponential notation.
|
- Config: Avoid emitting integers in objects using exponential notation.
|
||||||
[#7005](https://github.com/pulumi/pulumi/pull/7005)
|
[#7005](https://github.com/pulumi/pulumi/pull/7005)
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
import * as log from "../../log";
|
||||||
|
|
||||||
// The very first thing we do is set up unhandled exception and rejection hooks to ensure that these
|
// The very first thing we do is set up unhandled exception and rejection hooks to ensure that these
|
||||||
// events cause us to exit with a non-zero code. It is critically important that we do this early:
|
// events cause us to exit with a non-zero code. It is critically important that we do this early:
|
||||||
// if we do not, unhandled rejections in particular may cause us to exit with a 0 exit code, which
|
// if we do not, unhandled rejections in particular may cause us to exit with a 0 exit code, which
|
||||||
|
@ -32,8 +34,10 @@ const loggedErrors = new Set<Error>();
|
||||||
let programRunning = false;
|
let programRunning = false;
|
||||||
const uncaughtHandler = (err: Error) => {
|
const uncaughtHandler = (err: Error) => {
|
||||||
uncaughtErrors.add(err);
|
uncaughtErrors.add(err);
|
||||||
if (!programRunning) {
|
if (!programRunning && !loggedErrors.has(err)) {
|
||||||
console.error(err.stack || err.message || ("" + err));
|
log.error(err.stack || err.message || ("" + err));
|
||||||
|
// dedupe errors that we're reporting when the program is not running
|
||||||
|
loggedErrors.add(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,7 +158,8 @@ function main(args: string[]): void {
|
||||||
const promise: Promise<void> = require("./run").run(
|
const promise: Promise<void> = require("./run").run(
|
||||||
argv,
|
argv,
|
||||||
/*programStarted: */ () => programRunning = true,
|
/*programStarted: */ () => programRunning = true,
|
||||||
/*reportLoggedError:*/ (err: Error) => loggedErrors.add(err));
|
/*reportLoggedError:*/ (err: Error) => loggedErrors.add(err),
|
||||||
|
/*isErrorReported: */ (err: Error) => loggedErrors.has(err));
|
||||||
|
|
||||||
// when the user's program completes successfully, set programRunning back to false. That way, if the Pulumi
|
// when the user's program completes successfully, set programRunning back to false. That way, if the Pulumi
|
||||||
// scaffolding code ends up throwing an exception during teardown, it will get printed directly to the console.
|
// scaffolding code ends up throwing an exception during teardown, it will get printed directly to the console.
|
||||||
|
|
|
@ -133,7 +133,8 @@ function throwOrPrintModuleLoadError(program: string, error: Error): void {
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export function run(argv: minimist.ParsedArgs,
|
export function run(argv: minimist.ParsedArgs,
|
||||||
programStarted: () => void,
|
programStarted: () => void,
|
||||||
reportLoggedError: (err: Error) => void) {
|
reportLoggedError: (err: Error) => void,
|
||||||
|
isErrorReported: (err: Error) => boolean) {
|
||||||
// If there is a --pwd directive, switch directories.
|
// If there is a --pwd directive, switch directories.
|
||||||
const pwd: string | undefined = argv["pwd"];
|
const pwd: string | undefined = argv["pwd"];
|
||||||
if (pwd) {
|
if (pwd) {
|
||||||
|
@ -174,19 +175,15 @@ export function run(argv: minimist.ParsedArgs,
|
||||||
process.argv = [ process.argv[0], process.argv[1], ...programArgs ];
|
process.argv = [ process.argv[0], process.argv[1], ...programArgs ];
|
||||||
|
|
||||||
// Set up the process uncaught exception, unhandled rejection, and program exit handlers.
|
// Set up the process uncaught exception, unhandled rejection, and program exit handlers.
|
||||||
const errorSet = new Set<Error>();
|
|
||||||
|
|
||||||
const uncaughtHandler = (err: Error) => {
|
const uncaughtHandler = (err: Error) => {
|
||||||
// In node, if you throw an error in a chained promise, but the exception is not finally
|
// In node, if you throw an error in a chained promise, but the exception is not finally
|
||||||
// handled, then you can end up getting an unhandledRejection for each exception/promise
|
// handled, then you can end up getting an unhandledRejection for each exception/promise
|
||||||
// pair. Because the exception is the same through all of these, we keep track of it and
|
// pair. Because the exception is the same through all of these, we keep track of it and
|
||||||
// only report it once so the user doesn't get N messages for the same thing.
|
// only report it once so the user doesn't get N messages for the same thing.
|
||||||
if (errorSet.has(err)) {
|
if (isErrorReported(err)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
errorSet.add(err);
|
|
||||||
|
|
||||||
// Default message should be to include the full stack (which includes the message), or
|
// Default message should be to include the full stack (which includes the message), or
|
||||||
// fallback to just the message if we can't get the stack.
|
// fallback to just the message if we can't get the stack.
|
||||||
//
|
//
|
||||||
|
|
|
@ -120,7 +120,7 @@ export function getResource(res: Resource, props: Inputs, custom: boolean, urn:
|
||||||
// Now run the operation, serializing the invocation if necessary.
|
// Now run the operation, serializing the invocation if necessary.
|
||||||
const opLabel = `monitor.getResource(${label})`;
|
const opLabel = `monitor.getResource(${label})`;
|
||||||
runAsyncResourceOp(opLabel, async () => {
|
runAsyncResourceOp(opLabel, async () => {
|
||||||
let resp: any;
|
let resp: any = {};
|
||||||
let err: Error | undefined;
|
let err: Error | undefined;
|
||||||
try {
|
try {
|
||||||
if (monitor) {
|
if (monitor) {
|
||||||
|
@ -226,7 +226,7 @@ export function readResource(res: Resource, t: string, name: string, props: Inpu
|
||||||
// Now run the operation, serializing the invocation if necessary.
|
// Now run the operation, serializing the invocation if necessary.
|
||||||
const opLabel = `monitor.readResource(${label})`;
|
const opLabel = `monitor.readResource(${label})`;
|
||||||
runAsyncResourceOp(opLabel, async () => {
|
runAsyncResourceOp(opLabel, async () => {
|
||||||
let resp: any;
|
let resp: any = {};
|
||||||
let err: Error | undefined;
|
let err: Error | undefined;
|
||||||
try {
|
try {
|
||||||
if (monitor) {
|
if (monitor) {
|
||||||
|
@ -340,7 +340,7 @@ export function registerResource(res: Resource, t: string, name: string, custom:
|
||||||
// Now run the operation, serializing the invocation if necessary.
|
// Now run the operation, serializing the invocation if necessary.
|
||||||
const opLabel = `monitor.registerResource(${label})`;
|
const opLabel = `monitor.registerResource(${label})`;
|
||||||
runAsyncResourceOp(opLabel, async () => {
|
runAsyncResourceOp(opLabel, async () => {
|
||||||
let resp: any;
|
let resp: any = {};
|
||||||
let err: Error | undefined;
|
let err: Error | undefined;
|
||||||
try {
|
try {
|
||||||
if (monitor) {
|
if (monitor) {
|
||||||
|
|
Loading…
Reference in a new issue