diff --git a/README.md b/README.md index cf44b1810..7e17876c4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build](https://github.com/jongpie/NebulaLogger/actions/workflows/build.yml/badge.svg)](https://github.com/jongpie/NebulaLogger/actions/workflows/build.yml) [![codecov](https://codecov.io/gh/jongpie/NebulaLogger/branch/main/graph/badge.svg?token=1DJPDRM3N4)](https://codecov.io/gh/jongpie/NebulaLogger) -The most robust observability solution for Salesforce experts. Built 100% natively on the platform, and designed to work seamlessly with Apex, Lightning Components, Flow, Process Builder & integrations. +The most robust observability solution for Salesforce experts. Built 100% natively on the platform, and designed to work seamlessly with Apex, Lightning Components, Flow, OmniStudio, and integrations. ## Unlocked Package - v4.14.13 diff --git a/docs/apex/Logger-Engine/ComponentLogger.md b/docs/apex/Logger-Engine/ComponentLogger.md index be7b38dbc..6958efa6b 100644 --- a/docs/apex/Logger-Engine/ComponentLogger.md +++ b/docs/apex/Logger-Engine/ComponentLogger.md @@ -55,7 +55,7 @@ return The transaction ID (based on `Logger.getTransactionId())` ### Inner Classes -#### ComponentLogger.ComponentBrowser class +#### ComponentLogger.ComponentBrowserContext class A DTO object used to log details about the user's browser @@ -123,7 +123,7 @@ A DTO object used to create log entries for lightning components ##### Properties -###### `browser` → `ComponentBrowser` +###### `browser` → `ComponentBrowserContext` Context about the user's browser, automatically captured by Nebula Logger diff --git a/docs/lightning-components/LogEntryBuilder.md b/docs/lightning-components/LogEntryBuilder.md index 1bee4c7a4..5c4fe4140 100644 --- a/docs/lightning-components/LogEntryBuilder.md +++ b/docs/lightning-components/LogEntryBuilder.md @@ -1,89 +1,101 @@ - - -## LogEntryBuilder - -**Kind**: global class - -- [LogEntryBuilder](#LogEntryBuilder) - - [new LogEntryBuilder(loggingLevel)](#new_LogEntryBuilder_new) - - [.setMessage(message)](#LogEntryBuilder+setMessage) [LogEntryBuilder](#LogEntryBuilder) - - [.setRecordId(recordId)](#LogEntryBuilder+setRecordId) [LogEntryBuilder](#LogEntryBuilder) - - [.setRecord(record)](#LogEntryBuilder+setRecord) [LogEntryBuilder](#LogEntryBuilder) - - [.setScenario(scenario)](#LogEntryBuilder+setScenario) [LogEntryBuilder](#LogEntryBuilder) - - [.setError(error)](#LogEntryBuilder+setError) [LogEntryBuilder](#LogEntryBuilder) - - [.setExceptionDetails(exception)](#LogEntryBuilder+setExceptionDetails) [LogEntryBuilder](#LogEntryBuilder) - - [.setField(fieldToValue)](#LogEntryBuilder+setField) [LogEntryBuilder](#LogEntryBuilder) - - [.parseStackTrace(originStackTraceError)](#LogEntryBuilder+parseStackTrace) [LogEntryBuilder](#LogEntryBuilder) - - [.addTag(tag)](#LogEntryBuilder+addTag) [LogEntryBuilder](#LogEntryBuilder) - - [.addTags(tags)](#LogEntryBuilder+addTags) [LogEntryBuilder](#LogEntryBuilder) - - [.getComponentLogEntry()](#LogEntryBuilder+getComponentLogEntry) ComponentLogEntry - - - -### new LogEntryBuilder(loggingLevel) - -Constructor used to generate each JavaScript-based log entry event -This class is the JavaScript-equivalent of the Apex class `LogEntryBuilder` - -| Param | Type | Description | -| ------------ | ------------------- | ------------------------------------------------------------------------------- | -| loggingLevel | String | The `LoggingLevel` enum to use for the builder's instance of `LogEntryEvent__e` | - - - -### logEntryBuilder.setMessage(message) [LogEntryBuilder](#LogEntryBuilder) +## Functions + +
+
setMessage(message) LogEntryBuilder
+

Sets the log entry event's message field

+
+
setRecordId(recordId) LogEntryBuilder
+

Sets the log entry event's record fields

+
+
setRecord(record) LogEntryBuilder
+

Sets the log entry event's record fields

+
+
setScenario(scenario) LogEntryBuilder
+

Sets the log entry event's scenario field

+
+
setError(error) LogEntryBuilder
+

Deprecated - use setExceptionDetails(exception) instead + The name of this method is very similar to the logger function logger.error(), + resulting in confusion when used together: + logger.error('Unexpected error').setError(someErrorObject); + The new setExceptionDetails(exception) function provides the exact same functionality, + but aligns with the Apex builder's method name, and helps reduce the confusion with logger.error()

+
+
setExceptionDetails(exception) LogEntryBuilder
+

Sets the log entry event's exception fields

+
+
setField(fieldToValue) LogEntryBuilder
+

Sets multiple field values on the builder's LogEntryEvent__e record

+
+
parseStackTrace(originStackTraceError) LogEntryBuilder
+

Parses the provided error's stack trace and sets the log entry's origin & stack trace fields

+
+
addTag(tag) LogEntryBuilder
+

Appends the tag to the existing list of tags

+
+
addTags(tags) LogEntryBuilder
+

Appends the tag to the existing list of tags

+
+
getComponentLogEntry() ComponentLogEntry
+

Returns the object used to save log entry data

+
+
+ + + +## setMessage(message) LogEntryBuilder Sets the log entry event's message field -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | ------- | ------------------- | -------------------------------------------------- | | message | String | The string to use to set the entry's message field | - + -### logEntryBuilder.setRecordId(recordId) [LogEntryBuilder](#LogEntryBuilder) +## setRecordId(recordId) LogEntryBuilder Sets the log entry event's record fields -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | -------- | ------------------- | ------------------------------------------------- | | recordId | String | The ID of the SObject record related to the entry | - + -### logEntryBuilder.setRecord(record) [LogEntryBuilder](#LogEntryBuilder) +## setRecord(record) LogEntryBuilder Sets the log entry event's record fields -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | ------ | ------------------- | ----------------------------------------------------------------------------------------------------- | | record | Object | The `SObject` record related to the entry. The JSON of the record is automatically added to the entry | - + -### logEntryBuilder.setScenario(scenario) [LogEntryBuilder](#LogEntryBuilder) +## setScenario(scenario) LogEntryBuilder Sets the log entry event's scenario field -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | -------- | ------------------- | --------------------------------------------------- | | scenario | String | The string to use to set the entry's scenario field | - + -### logEntryBuilder.setError(error) [LogEntryBuilder](#LogEntryBuilder) +## setError(error) LogEntryBuilder Deprecated - use `setExceptionDetails(exception)` instead The name of this method is very similar to the logger function logger.error(), @@ -92,83 +104,83 @@ resulting in confusion when used together: The new `setExceptionDetails(exception)` function provides the exact same functionality, but aligns with the Apex builder's method name, and helps reduce the confusion with `logger.error()` -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | ----- | ------------------ | -------------------------------------------------------------------------------- | | error | Error | The instance of a JavaScript `Error` object to use, or an Apex HTTP error to use | - + -### logEntryBuilder.setExceptionDetails(exception) [LogEntryBuilder](#LogEntryBuilder) +## setExceptionDetails(exception) LogEntryBuilder Sets the log entry event's exception fields -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | --------- | ------------------ | -------------------------------------------------------------------------------- | | exception | Error | The instance of a JavaScript `Error` object to use, or an Apex HTTP error to use | - + -### logEntryBuilder.setField(fieldToValue) [LogEntryBuilder](#LogEntryBuilder) +## setField(fieldToValue) LogEntryBuilder Sets multiple field values on the builder's `LogEntryEvent__e` record -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | ------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | fieldToValue | Object | An object containing the custom field name as a key, with the corresponding value to store. Example: `{"SomeField__c": "some value", "AnotherField__c": "another value"}` | - + -### logEntryBuilder.parseStackTrace(originStackTraceError) [LogEntryBuilder](#LogEntryBuilder) +## parseStackTrace(originStackTraceError) LogEntryBuilder Parses the provided error's stack trace and sets the log entry's origin & stack trace fields -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | --------------------- | ------------------ | ----------------------------------------------------------------------- | | originStackTraceError | Error | The instance of a JavaScript `Error` object with a stack trace to parse | - + -### logEntryBuilder.addTag(tag) [LogEntryBuilder](#LogEntryBuilder) +## addTag(tag) LogEntryBuilder Appends the tag to the existing list of tags -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | ----- | ------------------- | ---------------------------------------------------- | | tag | String | The string to add as a tag for the current log entry | - + -### logEntryBuilder.addTags(tags) [LogEntryBuilder](#LogEntryBuilder) +## addTags(tags) LogEntryBuilder Appends the tag to the existing list of tags -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) -**Returns**: [LogEntryBuilder](#LogEntryBuilder) - The same instance of `LogEntryBuilder`, useful for chaining methods +**Kind**: global function +**Returns**: LogEntryBuilder - The same instance of `LogEntryBuilder`, useful for chaining methods | Param | Type | Description | | ----- | --------------------------------- | -------------------------------------------------------- | | tags | Array.<String> | The list of strings to add as tags for the current entry | - + -### logEntryBuilder.getComponentLogEntry() ComponentLogEntry +## getComponentLogEntry() ComponentLogEntry Returns the object used to save log entry data -**Kind**: instance method of [LogEntryBuilder](#LogEntryBuilder) +**Kind**: global function **Returns**: ComponentLogEntry - An instance of `ComponentLogEntry` that matches the Apex class `ComponentLogger.ComponentLogEntry` diff --git a/docs/lightning-components/Logger.md b/docs/lightning-components/Logger.md index 563a2d25c..8bfc5866c 100644 --- a/docs/lightning-components/Logger.md +++ b/docs/lightning-components/Logger.md @@ -1,21 +1,3 @@ -## Constants - -
-
createLogger Promise.<LoggerService>
-

Deprecated - use getLogger() instead - Async function that returns a fully-loaded logger service. - Requires some code to be executed async, so the service is not immediately available. - Example: const logger = await createLogger();

-
-
getLogger LoggerService
-

Recommended approach - Synchronous function that returns a ready-to-use logger service. - Internally, some code is still executed async, but the service can immediately - be used, without awaiting a Promise - Example: const logger = getLogger();

-
-
- ## Functions
@@ -61,31 +43,21 @@

Saves any entries in Logger's buffer, using the specified save method for only this call All subsequent calls to saveLog() will use the transaction save method

+
createLogger() Promise.<LoggerService>
+

Deprecated - use getLogger() instead + Async function that returns a fully-loaded logger service. + Requires some code to be executed async, so the service is not immediately available. + Example: const logger = await createLogger();

+
+
getLogger() LoggerService
+

Recommended approach + Synchronous function that returns a ready-to-use logger service. + Internally, some code is still executed async, but the service can immediately + be used, without awaiting a Promise + Example: const logger = getLogger();

+
- - -## createLogger Promise.<LoggerService> - -Deprecated - use `getLogger()` instead -Async function that returns a fully-loaded logger service. -Requires some code to be executed async, so the service is not immediately available. -Example: `const logger = await createLogger();` - -**Kind**: global constant -**Returns**: Promise.<LoggerService> - A Promise that resolves an instance of `LoggerService` - - -## getLogger LoggerService - -Recommended approach -Synchronous function that returns a ready-to-use logger service. -Internally, some code is still executed async, but the service can immediately -be used, without awaiting a Promise -Example: `const logger = getLogger();` - -**Kind**: global constant -**Returns**: LoggerService - An instance of `LoggerService` ## getUserSettings() ComponentLogger.ComponentLoggerSettings @@ -240,3 +212,27 @@ All subsequent calls to saveLog() will use the transaction save method | Param | Type | Description | | ---------- | ------------------- | ------------------------------------------------------------------------ | | saveMethod | String | The enum value of Logger.SaveMethod to use for this specific save action | + + + +## createLogger() Promise.<LoggerService> + +Deprecated - use `getLogger()` instead +Async function that returns a fully-loaded logger service. +Requires some code to be executed async, so the service is not immediately available. +Example: `const logger = await createLogger();` + +**Kind**: global function +**Returns**: Promise.<LoggerService> - A Promise that resolves an instance of `LoggerService` + + +## getLogger() LoggerService + +Recommended approach +Synchronous function that returns a ready-to-use logger service. +Internally, some code is still executed async, but the service can immediately +be used, without awaiting a Promise +Example: `const logger = getLogger();` + +**Kind**: global function +**Returns**: LoggerService - An instance of `LoggerService` diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/chromeBrowserError.json b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/chromeBrowserError_debugMode.json similarity index 100% rename from nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/chromeBrowserError.json rename to nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/chromeBrowserError_debugMode.json diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/chromeBrowserError_withoutDebugMode.json b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/chromeBrowserError_withoutDebugMode.json new file mode 100644 index 000000000..3dc8cc4ad --- /dev/null +++ b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/chromeBrowserError_withoutDebugMode.json @@ -0,0 +1,3 @@ +{ + "stack": "Error\n at Proxy.info (modules/c/logger.js:3:10548)\n at eval (eval at (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:98298), :3:23715)\n at en. (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:67030)\n at mo (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:49:43179)\n at c. (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:49:21644)\n at a. [as info] (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:542:412)\n at https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:85471\n at en.eval [as applyTrapForOneOrMoreArgs] (eval at (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:98298), :3:4751)\n at en.eval (eval at (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:98298), :3:4255)\n at saveLogExample (https://dream-ability-7823.scratch.lightning.force.com/lightning/page/components/c/loggerAuraEmbedDemo.js:14:12)" +} diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/edgeBrowserError.json b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/edgeBrowserError_debugMode.json similarity index 100% rename from nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/edgeBrowserError.json rename to nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/edgeBrowserError_debugMode.json diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/edgeBrowserError_withoutDebugMode.json b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/edgeBrowserError_withoutDebugMode.json new file mode 100644 index 000000000..09d45d611 --- /dev/null +++ b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/edgeBrowserError_withoutDebugMode.json @@ -0,0 +1,3 @@ +{ + "stack": "Error\nat Proxy.info (modules/c/logger.js:3:11782)\nat eval (eval at (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:98298), :3:23715)\nat en. (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:67030)\nat mo (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:49:43179)\nat c. (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:49:21644)\nat a.info (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:542:412)\nat https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:85471\nat en.eval [as applyTrapForOneOrMoreArgs] (eval at (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:98298), :3:4751)\nat en.eval (eval at (https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:98298), :3:4255)\nat saveLogExample (https://dream-ability-7823.scratch.lightning.force.com/lightning/page/components/c/loggerAuraEmbedDemo.js:14:12)" +} diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/firefoxBrowserError.json b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/firefoxBrowserError_debugMode.json similarity index 100% rename from nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/firefoxBrowserError.json rename to nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/firefoxBrowserError_debugMode.json diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/firefoxBrowserError_withoutDebugMode.json b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/firefoxBrowserError_withoutDebugMode.json new file mode 100644 index 000000000..f4624442f --- /dev/null +++ b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/data/firefoxBrowserError_withoutDebugMode.json @@ -0,0 +1,3 @@ +{ + "stack": "info@modules/c/logger.js:3:11782\nzE/ eval:3:23715\nVt/<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:67030\nmo@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:49:43179\nSn/<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:49:21644\nR.prototype.hi/ eval:3:4751\nRt/<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js line 105 > eval:3:4255\nsaveLogExample@https://dream-ability-7823.scratch.lightning.force.com/lightning/page/components/c/loggerAuraEmbedDemo.js:14:12\nzE/ eval:3:23715\nHt/<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:68352\nGt/<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:105:66429\nK.prototype.Zc@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:628:177\nK.prototype.Xa@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:627:306\nhandleClick@https://static.lightning.force.com/cs226/aurafile/%7B%22mode%22%3A%22PROD%22%2C%22cac%22%3A1%2C%22app%22%3A%22one%3Aone%22%2C%22ls%22%3A1%2C%22lrmc%22%3A%22-386269907%22%7D/pIFDZ5nqs77gFqsVXe-2Jw/apppart1-4.js:980:6\nK.prototype.Zc@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:628:177\nuj/<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:514:349\nD.Xa@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:994:221\nuj@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:514:333\nXK.prototype.zr@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:1064:402\nZD.prototype.Xl@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:381:255\n$D/b<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:380:130\nBq@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:514:301\nb@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:990:72\nt@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:28:5715\nEventListener.handleEvent*ar@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:46:5450\nM.prototype.uk { jest.clearAllMocks(); }); - it('correctly parses Chrome stack trace', async () => { + it('correctly parses Chrome stack trace when debug mode is enabled', async () => { const loggerStackTrace = new LoggerStackTrace(); - const originStackTrace = loggerStackTrace.parse(CHROME_BROWSER_ERROR); + const originStackTrace = loggerStackTrace.parse(CHROME_BROWSER_ERROR_DEBUG_MODE); expect(originStackTrace.componentName).toEqual('c/loggerChromeLWCEmbedDemo'); expect(originStackTrace.functionName).toEqual('logInfoExample'); expect(originStackTrace.metadataType).toEqual('LightningComponentBundle'); }); - it('correctly parses Edge stack trace', async () => { + it('correctly parses Chrome stack trace when debug mode is disabled', async () => { const loggerStackTrace = new LoggerStackTrace(); - const originStackTrace = loggerStackTrace.parse(EDGE_BROWSER_ERROR); + const originStackTrace = loggerStackTrace.parse(CHROME_BROWSER_ERROR_WITHOUT_DEBUG_MODE); + + expect(originStackTrace.componentName).toEqual('c/loggerAuraEmbedDemo'); + expect(originStackTrace.functionName).toEqual('saveLogExample'); + expect(originStackTrace.metadataType).toEqual('AuraDefinitionBundle'); + }); + + it('correctly parses Edge stack trace when debug mode is enabled', async () => { + const loggerStackTrace = new LoggerStackTrace(); + + const originStackTrace = loggerStackTrace.parse(EDGE_BROWSER_ERROR_DEBUG_MODE); expect(originStackTrace.componentName).toEqual('c/loggerEdgeAuraEmbedDemo'); expect(originStackTrace.functionName).toEqual('saveLogExample'); expect(originStackTrace.metadataType).toEqual('AuraDefinitionBundle'); }); - it('correctly parses Firefox stack trace', async () => { + it('correctly parses Edge stack trace when debug mode is disabled', async () => { const loggerStackTrace = new LoggerStackTrace(); - const originStackTrace = loggerStackTrace.parse(FIREFOX_BROWSER_ERROR); + const originStackTrace = loggerStackTrace.parse(EDGE_BROWSER_ERROR_WITHOUT_DEBUG_MODE); + + expect(originStackTrace.componentName).toEqual('c/loggerAuraEmbedDemo'); + expect(originStackTrace.functionName).toEqual('saveLogExample'); + expect(originStackTrace.metadataType).toEqual('AuraDefinitionBundle'); + }); + + it('correctly parses Firefox stack trace when debug mode is enabled', async () => { + const loggerStackTrace = new LoggerStackTrace(); + + const originStackTrace = loggerStackTrace.parse(FIREFOX_BROWSER_ERROR_DEBUG_MODE); expect(originStackTrace.componentName).toEqual('c/loggerFirefoxLWCImportDemo'); expect(originStackTrace.functionName).toEqual('logInfoExample'); expect(originStackTrace.metadataType).toEqual('LightningComponentBundle'); }); + + it('correctly parses Firefox stack trace when debug mode is disabled', async () => { + const loggerStackTrace = new LoggerStackTrace(); + + const originStackTrace = loggerStackTrace.parse(FIREFOX_BROWSER_ERROR_WITHOUT_DEBUG_MODE); + + expect(originStackTrace.componentName).toEqual('c/loggerAuraEmbedDemo'); + expect(originStackTrace.functionName).toEqual('saveLogExample'); + expect(originStackTrace.metadataType).toEqual('AuraDefinitionBundle'); + }); }); diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js b/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js index 4be44675a..5ccfa3f66 100644 --- a/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js +++ b/nebula-logger/core/main/logger-engine/lwc/logger/loggerService.js @@ -202,27 +202,9 @@ export default class LoggerService { /* eslint-disable no-console */ _logToConsole(loggingLevel, message, componentLogEntry) { - let consoleLoggingFunction; - switch (loggingLevel) { - case 'ERROR': - consoleLoggingFunction = console.error; - break; - case 'WARN': - consoleLoggingFunction = console.warn; - break; - case 'INFO': - consoleLoggingFunction = console.info; - break; - default: - consoleLoggingFunction = console.debug; - break; - } - + const consoleLoggingFunction = console[loggingLevel.toLowerCase()] ?? console.debug; const loggingLevelEmoji = LOGGING_LEVEL_EMOJIS[loggingLevel]; const qualifiedMessage = `${loggingLevelEmoji} ${loggingLevel}: ${message}`; - // Some JS stack traces are huuuuge, so don't print it in the browser console. - // The stack trace will still be saved on the backend. - // '\n' + JSON.stringify(this.#componentLogEntry, replacer, 2) const formattedComponentLogEntryString = !componentLogEntry ? '' : '\n' + diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/loggerStackTrace.js b/nebula-logger/core/main/logger-engine/lwc/logger/loggerStackTrace.js index b0a994b6d..982a5ffa6 100644 --- a/nebula-logger/core/main/logger-engine/lwc/logger/loggerStackTrace.js +++ b/nebula-logger/core/main/logger-engine/lwc/logger/loggerStackTrace.js @@ -44,16 +44,13 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -const FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/; const CHROME_IE_STACK_REGEXP = /^\s*at .*(\S+:\d+|\(native\))/m; const SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code])?$/; class ErrorStackParser { parse(error) { let stackTraceParticles; - if (typeof error.stacktrace !== 'undefined' || typeof error['opera#sourceloc'] !== 'undefined') { - stackTraceParticles = this.parseOpera(error); - } else if (error.stack && error.stack.match(CHROME_IE_STACK_REGEXP)) { + if (error.stack && error.stack.match(CHROME_IE_STACK_REGEXP)) { stackTraceParticles = this.parseV8OrIE(error); } else if (error.stack) { stackTraceParticles = this.parseFFOrSafari(error); @@ -146,82 +143,6 @@ class ErrorStackParser { }; }, this); } - - parseOpera(e) { - if (!e.stacktrace || (e.message.indexOf('\n') > -1 && e.message.split('\n').length > e.stacktrace.split('\n').length)) { - return this.parseOpera9(e); - } else if (!e.stack) { - return this.parseOpera10(e); - } - return this.parseOpera11(e); - } - - parseOpera9(e) { - const lineRE = /Line (\d+).*script (?:in )?(\S+)/i; - const lines = e.message.split('\n'); - const result = []; - - for (let i = 2, len = lines.length; i < len; i += 2) { - const match = lineRE.exec(lines[i]); - if (match) { - result.push({ - fileName: match[2], - lineNumber: match[1], - source: lines[i] - }); - } - } - - return result; - } - - parseOpera10(e) { - const lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i; - const lines = e.stacktrace.split('\n'); - const result = []; - - for (let i = 0, len = lines.length; i < len; i += 2) { - const match = lineRE.exec(lines[i]); - if (match) { - result.push({ - functionName: match[3] || undefined, - fileName: match[2], - lineNumber: match[1], - source: lines[i] - }); - } - } - - return result; - } - - // Opera 10.65+ Error.stack very similar to FF/Safari - parseOpera11(error) { - const filtered = error.stack.split('\n').filter(function (line) { - return !!line.match(FIREFOX_SAFARI_STACK_REGEXP) && !line.match(/^Error created at/); - }, this); - - return filtered.map(function (line) { - const tokens = line.split('@'); - const locationParts = this.extractLocation(tokens.pop()); - const functionCall = tokens.shift() || ''; - const functionName = functionCall.replace(//, '$2').replace(/\([^)]*\)/g, '') || undefined; - let argsRaw; - if (functionCall.match(/\(([^)]*)\)/)) { - argsRaw = functionCall.replace(/^[^(]+\(([^)]*)\)$/, '$1'); - } - const args = argsRaw === undefined || argsRaw === '[arguments not available]' ? undefined : argsRaw.split(','); - - return { - functionName: functionName, - args: args, - fileName: locationParts[0], - lineNumber: locationParts[1], - columnNumber: locationParts[2], - source: line - }; - }, this); - } } /* End of code originally copied from stacktrace.js */ @@ -243,11 +164,8 @@ export default class LoggerStackTrace { return; } - if (!originStackTraceParticle && currentStackTraceParticle.fileName?.endsWith('aura_proddebug.js')) { - return; - } - - if (!originStackTraceParticle && currentStackTraceParticle.fileName?.endsWith('aura_proddebug')) { + const ignoredAuraFilenamesRegEx = /aura_prod(?:\.js|debug(?:\.js)?)$/; + if (!originStackTraceParticle && ignoredAuraFilenamesRegEx.test(currentStackTraceParticle.fileName)) { return; }