diff --git a/src/errors.ts b/src/errors.ts index 7f8192a4..41ca2cfc 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -7,6 +7,8 @@ export interface AzFuncError { * User errors cannot be tracked in our telemetry because they could have user information (users can still track it themselves in their app insights resource) */ isAzureFunctionsSystemError: boolean; + + loggedOverRpc?: boolean; } export interface ValidatedError extends Error, Partial { diff --git a/src/setupEventStream.ts b/src/setupEventStream.ts index 21694f19..3f5a7603 100644 --- a/src/setupEventStream.ts +++ b/src/setupEventStream.ts @@ -98,7 +98,7 @@ async function handleMessage(inMsg: rpc.StreamingMessage): Promise { outMsg[eventHandler.responseName] = response; } catch (err) { const error = ensureErrorType(err); - if (error.isAzureFunctionsSystemError) { + if (error.isAzureFunctionsSystemError && !error.loggedOverRpc) { worker.log({ message: error.message, level: LogLevel.Error, diff --git a/src/startApp.ts b/src/startApp.ts index c4e4edf2..134e3e71 100644 --- a/src/startApp.ts +++ b/src/startApp.ts @@ -113,13 +113,16 @@ async function loadEntryPointFile(functionAppDirectory: string): Promise { console.error(error.stack); } else { // In this case, the error will never block the app - // The most we can do without breaking backwards compatibility is log it as a system log - worker.log({ - message: newMessage, - level: LogLevel.Error, - logCategory: LogCategory.System, - }); + // The most we can do without breaking backwards compatibility is log it as an rpc system log below } + + // Always log as rpc system log, which goes to our internal telemetry + worker.log({ + message: newMessage, + level: LogLevel.Error, + logCategory: LogCategory.System, + }); + error.loggedOverRpc = true; } } } diff --git a/test/startApp.test.ts b/test/startApp.test.ts index fa5cc183..f8911cae 100644 --- a/test/startApp.test.ts +++ b/test/startApp.test.ts @@ -53,11 +53,12 @@ describe('startApp', () => { stream.addTestMessage(msg.init.request(testAppPath)); if (fileSubpath.includes('missing')) { - await stream.assertCalledWith(msg.init.receivedRequestLog, msg.init.response); + await stream.assertCalledWith(msg.init.receivedRequestLog, msg.errorLog(errorMessage), msg.init.response); } else { await stream.assertCalledWith( msg.init.receivedRequestLog, msg.loadingEntryPoint(fileSubpath), + msg.errorLog(errorMessage), msg.init.response ); } @@ -66,7 +67,6 @@ describe('startApp', () => { if (isModelV4) { await stream.assertCalledWith( msg.indexing.receivedRequestLog, - msg.errorLog(errorMessage), msg.indexing.failedResponse(errorMessage, false) ); } else { @@ -74,11 +74,7 @@ describe('startApp', () => { } stream.addTestMessage(msg.funcLoad.request('helloWorld.js')); - await stream.assertCalledWith( - msg.funcLoad.receivedRequestLog, - msg.errorLog(errorMessage), - msg.funcLoad.failedResponse(errorMessage) - ); + await stream.assertCalledWith(msg.funcLoad.receivedRequestLog, msg.funcLoad.failedResponse(errorMessage)); } describe('Node >=v20', () => {