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/<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js line 105 > 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/<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js line 105 > 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<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:341:184\nVp@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:514:75\nZl@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:515:44\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:508:263\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:497:63\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nG.prototype.Ke@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:459:327\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:225\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:508:341\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:502:251\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:508:341\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:508:341\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:497:63\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nG.prototype.Ke@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:459:327\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:225\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:497:63\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nG.prototype.Ke@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:459:327\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:225\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:502:251\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:508:341\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:497:63\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nG.prototype.Ke@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:459:327\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:225\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:508:341\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:508:341\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.$h@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:834:148\nrender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:497:63\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:135\nG.prototype.Ke@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:459:327\nG.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:475:225\nVI.prototype.ub@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:826:234\nVI.prototype.ci@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:838:8\nrerender@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:503:32\nG.prototype.Yd@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:476:137\nVI.prototype.Yd@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:828:345\nVI.prototype.Js@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:842:204\nvI@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:747:207\noI@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:746:171\nlI@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:737:374\nkI@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:736:367\nD.Vd@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:736:203\njI@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:736:136\nb@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:990:404\npromise callback*displayPage@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:1016:169\nhandleDisplayPage@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:1012:524\nK.prototype.Zc@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:628:177\nHF/<@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:487:40\nhandlePopulateGVP@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/syEesMFGx27PlOWgSlYTLQ/apppart4-4.js:1258:237\nb@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:990:72\nK.prototype.Vw@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:635:88\nK.prototype.Oc@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:633:60\nD.Op@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:1056:167\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\nQH@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:707:354\nD.Xz@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:763:223\nD.zk@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:761:50\nD.Tp@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:1057:302\nZD.prototype.Xl@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:381:255\nws@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:1052:392\nZD.prototype.Xl@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:381:255\nZD.prototype.start@https://static.lightning.force.com/cs226/auraFW/javascript/eGx3MHlRT1lEMUpQaWVxbGRUM1h0Z2hZX25NdHFVdGpDN3BnWlROY1ZGT3cyNTAuOC40LTYuNC41/aura_prod.js:380:313\naura_prod.js:105:85471"
+}
diff --git a/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/loggerStackTrace.test.js b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/loggerStackTrace.test.js
index 5fc630011..963c96238 100644
--- a/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/loggerStackTrace.test.js
+++ b/nebula-logger/core/main/logger-engine/lwc/logger/__tests__/loggerStackTrace.test.js
@@ -1,8 +1,11 @@
import LoggerStackTrace from '../loggerStackTrace';
-const CHROME_BROWSER_ERROR = require('./data/chromeBrowserError.json');
-const EDGE_BROWSER_ERROR = require('./data/edgeBrowserError.json');
-const FIREFOX_BROWSER_ERROR = require('./data/firefoxBrowserError.json');
+const CHROME_BROWSER_ERROR_DEBUG_MODE = require('./data/chromeBrowserError_debugMode.json');
+const CHROME_BROWSER_ERROR_WITHOUT_DEBUG_MODE = require('./data/chromeBrowserError_withoutDebugMode.json');
+const EDGE_BROWSER_ERROR_DEBUG_MODE = require('./data/edgeBrowserError_debugMode.json');
+const EDGE_BROWSER_ERROR_WITHOUT_DEBUG_MODE = require('./data/edgeBrowserError_withoutDebugMode.json');
+const FIREFOX_BROWSER_ERROR_DEBUG_MODE = require('./data/firefoxBrowserError_debugMode.json');
+const FIREFOX_BROWSER_ERROR_WITHOUT_DEBUG_MODE = require('./data/firefoxBrowserError_withoutDebugMode.json');
// These tests are very basic (at least for now), but provide validation
// that the stack trace parsing works as expected.
@@ -17,33 +20,63 @@ describe('logger stack trace parsing tests', () => {
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;
}