Skip to content

Commit d452edd

Browse files
authored
Bugfix for broken LWC stack trace parsing (#614)
* Fixed ComponentLogger.cls so it handles recent-ish changes to the format of stack traces in LWCs * Suppressed a 'PropertyNamingConventions' PMD violation in ComponentLogger.cls due to a new lazy-loaded constant * Also fixed a System.debug() call in Logger.cls to just use 'Organization' instead of 'Schema.Organization' (caused by an overeager string replacement in a previous release)
1 parent 50449ff commit d452edd

7 files changed

Lines changed: 98 additions & 20 deletions

File tree

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55

66
The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects.
77

8-
## Unlocked Package - v4.12.6
8+
## Unlocked Package - v4.12.7
99

10-
[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001Mk5UQAS)
11-
[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001Mk5UQAS)
10+
[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001Mk6IQAS)
11+
[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001Mk6IQAS)
1212
[![View Documentation](./images/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/)
1313

14-
`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001Mk5UQAS`
14+
`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001Mk6IQAS`
1515

16-
`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001Mk5UQAS`
16+
`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001Mk6IQAS`
1717

1818
---
1919

nebula-logger/core/main/logger-engine/classes/ComponentLogger.cls

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,19 @@
99
* @see Logger
1010
* @see LogEntryEventBuilder
1111
*/
12-
@SuppressWarnings('PMD.ExcessivePublicCount, PMD.StdCyclomaticComplexity')
12+
@SuppressWarnings('PMD.ExcessivePublicCount, PMD.PropertyNamingConventions, PMD.StdCyclomaticComplexity')
1313
public inherited sharing class ComponentLogger {
14+
private static final String LOGGER_COMPONENT_NAME {
15+
get {
16+
if (LOGGER_COMPONENT_NAME == null) {
17+
String namespace = String.isNotBlank(Logger.getNamespacePrefix()) ? Logger.getNamespacePrefix() : 'c';
18+
LOGGER_COMPONENT_NAME = '/' + namespace + '/logger.js';
19+
}
20+
return LOGGER_COMPONENT_NAME;
21+
}
22+
set;
23+
}
24+
1425
static {
1526
Logger.ignoreOrigin(ComponentLogger.class);
1627
}
@@ -90,14 +101,13 @@ public inherited sharing class ComponentLogger {
90101
Boolean isAuraComponent = false;
91102

92103
if (String.isNotBlank(stackTraceString)) {
93-
String loggerComponentReferenceToIgnore = '/c/logger.js';
94104
String auraComponentContent = '/n/components/';
95-
String lwcModuleContent = '/n/modules/';
105+
String lwcModuleContent = 'modules/';
96106
Boolean parentComponentFound = false;
97107

98108
List<String> stackTraceLines = new List<String>();
99109
for (String currentStackTraceLine : stackTraceString.split('\n')) {
100-
if (currentStackTraceLine.contains(loggerComponentReferenceToIgnore)) {
110+
if (currentStackTraceLine.contains(LOGGER_COMPONENT_NAME)) {
101111
continue;
102112
} else if (parentComponentFound == false && currentStackTraceLine.contains(auraComponentContent)) {
103113
isAuraComponent = true;

nebula-logger/core/main/logger-engine/classes/Logger.cls

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
global with sharing class Logger {
1616
// There's no reliable way to get the version number dynamically in Apex
1717
@TestVisible
18-
private static final String CURRENT_VERSION_NUMBER = 'v4.12.6';
18+
private static final String CURRENT_VERSION_NUMBER = 'v4.12.7';
1919
private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG;
2020
private static final Set<String> IGNORED_APEX_CLASSES = initializeIgnoredApexClasses();
2121
private static final List<LogEntryEventBuilder> LOG_ENTRIES_BUFFER = new List<LogEntryEventBuilder>();
@@ -109,7 +109,7 @@ global with sharing class Logger {
109109
// The rest of the codebase should use a method in Logger.cls
110110
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Version Number: ' + getVersionNumber());
111111
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Transaction ID: ' + getTransactionId());
112-
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Schema.Organization API Version: ' + getOrganizationApiVersion());
112+
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Organization API Version: ' + getOrganizationApiVersion());
113113
setScenario(getUserSettings().DefaultScenario__c);
114114
}
115115

nebula-logger/core/main/logger-engine/lwc/logger/logger.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { LightningElement, api } from 'lwc';
77
import { createLoggerService } from './loggerService';
88

9-
const CURRENT_VERSION_NUMBER = 'v4.12.6';
9+
const CURRENT_VERSION_NUMBER = 'v4.12.7';
1010

1111
export default class Logger extends LightningElement {
1212
#loggerService = createLoggerService();

nebula-logger/core/tests/logger-engine/classes/ComponentLogger_Tests.cls

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,13 +241,49 @@ private class ComponentLogger_Tests {
241241
}
242242

243243
@IsTest
244-
static void it_should_parse_web_component_stack_trace() {
244+
static void it_should_parse_web_component_stack_trace_when_stack_trace_is_modern_format() {
245+
LoggerDataStore.setMock(LoggerMockDataStore.getEventBus());
246+
String expectedComponentType = 'LWC';
247+
String expectedComponentApiName = 'c/loggerLWCDemo';
248+
String expectedComponentFunctionName = 'logErrorExample';
249+
ComponentLogger.ComponentLogEntry componentLogEntry = createMockComponentLogEntry();
250+
componentLogEntry.stack = getMockModernWebComponentStackTrace();
251+
System.Assert.areEqual(0, Logger.saveLogCallCount);
252+
System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishCallCount());
253+
System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());
254+
255+
ComponentLogger.saveComponentLogEntries(new List<ComponentLogger.ComponentLogEntry>{ componentLogEntry }, null);
256+
257+
System.Assert.areEqual(1, Logger.saveLogCallCount);
258+
System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishCallCount());
259+
System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());
260+
LogEntryEvent__e publishedLogEntryEvent = (LogEntryEvent__e) LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0);
261+
System.Assert.areEqual('Component', publishedLogEntryEvent.OriginType__c);
262+
System.Assert.areEqual(componentLogEntry.browserFormFactor, publishedLogEntryEvent.BrowserFormFactor__c);
263+
System.Assert.areEqual(componentLogEntry.browserLanguage, publishedLogEntryEvent.BrowserLanguage__c);
264+
System.Assert.areEqual(componentLogEntry.browserScreenResolution, publishedLogEntryEvent.BrowserScreenResolution__c);
265+
System.Assert.areEqual(componentLogEntry.browserUrl, publishedLogEntryEvent.BrowserUrl__c);
266+
System.Assert.areEqual(componentLogEntry.browserUserAgent, publishedLogEntryEvent.BrowserUserAgent__c);
267+
System.Assert.areEqual(componentLogEntry.browserWindowResolution, publishedLogEntryEvent.BrowserWindowResolution__c);
268+
System.Assert.areEqual(componentLogEntry.loggingLevel, publishedLogEntryEvent.LoggingLevel__c);
269+
System.Assert.areEqual(componentLogEntry.message, publishedLogEntryEvent.Message__c);
270+
System.Assert.areEqual('Component', publishedLogEntryEvent.OriginType__c);
271+
System.Assert.areEqual(expectedComponentApiName + '.' + expectedComponentFunctionName, publishedLogEntryEvent.OriginLocation__c);
272+
// TODO Move these asserts to LogEntryHandler_Tests
273+
// System.Assert.areEqual(expectedComponentApiName, publishedLogEntryEvent.ComponentApiName__c);
274+
// System.Assert.areEqual(expectedComponentFunctionName, publishedLogEntryEvent.ComponentFunctionName__c);
275+
System.Assert.areEqual(expectedComponentType, publishedLogEntryEvent.ComponentType__c);
276+
System.Assert.areEqual(componentLogEntry.timestamp, publishedLogEntryEvent.Timestamp__c);
277+
}
278+
279+
@IsTest
280+
static void it_should_parse_web_component_stack_trace_when_stack_trace_is_legacy_format() {
245281
LoggerDataStore.setMock(LoggerMockDataStore.getEventBus());
246282
String expectedComponentType = 'LWC';
247283
String expectedComponentApiName = 'c/loggerLWCDemo';
248284
String expectedComponentFunctionName = 'saveLogWebExample';
249285
ComponentLogger.ComponentLogEntry componentLogEntry = createMockComponentLogEntry();
250-
componentLogEntry.stack = getMockWebComponentStackTrace();
286+
componentLogEntry.stack = getMockLegacyWebComponentStackTrace();
251287
System.Assert.areEqual(0, Logger.saveLogCallCount);
252288
System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishCallCount());
253289
System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());
@@ -422,8 +458,39 @@ private class ComponentLogger_Tests {
422458
'\nloggerAuraDemo.js:17:17';
423459
}
424460

425-
private static String getMockWebComponentStackTrace() {
426-
// This is a copy of an actual stack trace generated from c/loggerLWCDemo
461+
private static String getMockModernWebComponentStackTrace() {
462+
// This is a partial copy of an actual stack trace generated from c/loggerLWCDemo in January 2024
463+
List<String> lwcStackTraceLines = new List<String>{
464+
'@modules/c/logger.js:33:22',
465+
'LogEntryBuilder@modules/c/logger.js:59:87',
466+
'newLogEntry@modules/c/logger.js:189:14',
467+
'_newEntry@modules/c/logger.js:397:44',
468+
'error@modules/c/logger.js:264:21',
469+
'logErrorExample@modules/c/loggerLWCDemo.js:266:35',
470+
'createHooksCallback$LWS/<@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js line 35465 > eval:2583:24',
471+
'applyOrConstructTrapForTwoOrMoreArgs$LWS@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:32254:38',
472+
'callHook@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:10035:19',
473+
'invokeEventListener/<@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:9926:21',
474+
'runWithBoundaryProtection@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:10517:13',
475+
'invokeEventListener@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:9921:34',
476+
'b/<@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:9365:32',
477+
'handleEvent@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:1615:51',
478+
'invokeListenersByPlacement/<@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:1660:46',
479+
'invokeListenersByPlacement@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:1655:21',
480+
'domListener@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:1670:39',
481+
'EventListener.handleEvent*attachDOMListener@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:1687:30',
482+
'addCustomElementEventListener@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:1712:30',
483+
'patchedAddEventListener@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:3022:50',
484+
'value@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:5567:53',
485+
'addEventListener@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:11554:20',
486+
'applyEventListeners@https://static.lightning.force.com/cs220/auraFW/javascript/YWYyQV90T3g3VDhySzNWUm1kcF9WUVY4bi1LdGdMbklVbHlMdER1eVVlUGcyNDYuMTUuNS0zLjAuNA/aura_proddebug.js:8200:29',
487+
'...blah,blah,blah more javascript code goes here, etc.'
488+
};
489+
return String.join(lwcStackTraceLines, '\n');
490+
}
491+
492+
private static String getMockLegacyWebComponentStackTrace() {
493+
// This is a copy of an actual stack trace generated from c/loggerLWCDemo in August 2021
427494
return 'LogEntryBuilder@https://flow-ability-5496.lightning.force.com/lightning/n/modules/c/logger.js:28:24' +
428495
'\nnewLogEntry@https://flow-ability-5496.lightning.force.com/lightning/n/modules/c/logger.js:172:14' +
429496
'\n_newEntry@https://flow-ability-5496.lightning.force.com/lightning/n/modules/c/logger.js:349:44' +

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nebula-logger",
3-
"version": "4.12.6",
3+
"version": "4.12.7",
44
"description": "The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects.",
55
"author": "Jonathan Gillespie",
66
"license": "MIT",

sfdx-project.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
"package": "Nebula Logger - Core",
1414
"path": "./nebula-logger/core",
1515
"definitionFile": "./config/scratch-orgs/base-scratch-def.json",
16-
"versionNumber": "4.12.6.NEXT",
17-
"versionName": "Bugfix to Automatically Truncate LogEntryEvent__e Fields",
18-
"versionDescription": "Updated LoggerDataStore, Logger, and LogEntryEventBuilder to automatically truncate string field values that are too long for the corresponding LogEntryEvent__e fields",
16+
"versionNumber": "4.12.7.NEXT",
17+
"versionName": "Bugfix for LWC Stack Trace Parsing",
18+
"versionDescription": "Fixed ComponentLogger.cls so it handles recent-ish changes to the format of stack traces in LWCs. The field LogEntry__c.OriginLocation__c should now be correctly populated again for LWCs.",
1919
"releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases",
2020
"unpackagedMetadata": {
2121
"path": "./nebula-logger/extra-tests"
@@ -167,6 +167,7 @@
167167
"Nebula Logger - Core@4.12.4-bugfix-child-log__c-records-not-properly-linked-to-parent-log__c-records": "04t5Y000001Mk5KQAS",
168168
"Nebula Logger - Core@4.12.5-bugfix-for-name-shadowing-issues-with-schema-namespace": "04t5Y000001Mk5PQAS",
169169
"Nebula Logger - Core@4.12.6-bugfix-to-automatically-truncate-logentryevent__e-fields": "04t5Y000001Mk5UQAS",
170+
"Nebula Logger - Core@4.12.7-bugfix-for-lwc-stack-trace-parsing": "04t5Y000001Mk6IQAS",
170171
"Nebula Logger - Core Plugin - Async Failure Additions": "0Ho5Y000000blO4SAI",
171172
"Nebula Logger - Core Plugin - Async Failure Additions@1.0.0": "04t5Y0000015lhiQAA",
172173
"Nebula Logger - Core Plugin - Async Failure Additions@1.0.1": "04t5Y0000015lhsQAA",

0 commit comments

Comments
 (0)