Skip to content

Commit f6b0afc

Browse files
authored
Optionally enforce scenario-based logging usage (#648)
* Added the ability to optionally enforce using scenario-based logging. This is controlled by a new LoggerParameter__mdt record, RequireScenarioUsage, and is disabled by default. * Upgraded LoggerScenarioRecordPage flexipage to use dynamic related lists, added missing field permission to LoggerAdmin * Scope creep: added a shell script to handle generating log files for 'sf apex tail log'
1 parent 11964ad commit f6b0afc

15 files changed

Lines changed: 256 additions & 29 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.13.2
8+
## Unlocked Package - v4.13.3
99

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

14-
`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001MkEmQAK`
14+
`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001MkEwQAK`
1515

16-
`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001MkEmQAK`
16+
`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001MkEwQAK`
1717

1818
---
1919

config/linters/lint-staged.config.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ module.exports = {
77
return [`eslint --config ./config/linters/.eslintrc.json ${filenames.join(' ')} --fix`];
88
// FIXME this command should only run tests for the changed LWCs (instead of running tests for all LWCs)
99
// return [`eslint --config ./config/linters/.eslintrc.json ${filenames.join(' ')} --fix`, `npm run test:lwc`];
10+
},
11+
'*.{cls,trigger}': filenames => {
12+
return filenames.map(
13+
filename => `sf scanner run --pmdconfig ./config/linters/pmd-ruleset.xml --engine pmd --severity-threshold 3 --target '${filename}'`
14+
);
15+
// return [`npm run scan:apex`, `npm run docs:fix && git add ./docs/ && git commit --amend --no-edit`];
1016
}
11-
// FIXME this command should only scan the changed Apex files (instead of scanning all Apex files)
12-
// '*.{cls,trigger}': () => {
13-
// return [`npm run scan:apex`];
14-
// // return [`npm run scan:apex`, `npm run docs:fix && git add ./docs/ && git commit --amend --no-edit`];
15-
// }
1617
};

docs/apex/Configuration/LoggerParameter.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ Controls if Nebula Logger queries `Schema.User` data. When set to `false`, any `
9494

9595
Indicates if Nebula Logger queries `Schema.User` data is queried synchronously & populated on `LogEntryEvent__e` records. When set to `false`, any `Schema.User` fields on `LogEntryEvent__e` that rely on querying will not be populated - the data will instead be queried asynchronously and populated on any resulting `Log__c` records. Controlled by the custom metadata record `LoggerParameter.QueryUserDataSynchronously`, or `true` as the default
9696

97+
#### `REQUIRE_SCENARIO_USAGE``Boolean`
98+
99+
Indicates if Nebula Logger will enforce scenario-based logging to be used. When set to `false`, specifying a scenario is completely optional. When set to `true`, a scenario is required to be set before any logging can occur. If a logging method is called & the current scenario is null/blank, then Nebula Logger will throw a runtime exception. Controlled by the custom metadata record `LoggerParameter.RequireScenarioUsage`, or `false` as the default
100+
97101
#### `SEND_ERROR_EMAIL_NOTIFICATIONS``Boolean`
98102

99103
Indicates if Nebula Logger will send an error email notification if any internal exceptions occur. Controlled by the custom metadata record `LoggerParameter.SendErrorEmailNotifications`, or `true` as the default

docs/apex/Logger-Engine/Logger.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5730,6 +5730,10 @@ The new entry's instance of `LogEntryEventBuilder`, useful for chaining met
57305730

57315731
### Inner Classes
57325732

5733+
#### Logger.LoggerException class
5734+
5735+
---
5736+
57335737
#### Logger.QueueableSaver class
57345738

57355739
Inner class for publishing log entries via the Queueable interface.

nebula-logger/core/main/configuration/classes/LoggerParameter.cls

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,26 @@ public class LoggerParameter {
335335
private set;
336336
}
337337

338+
/**
339+
* @description Indicates if Nebula Logger will enforce scenario-based logging to be used.
340+
* When set to `false`, specifying a scenario is completely optional.
341+
* When set to `true`, a scenario is required to be set before any logging can occur.
342+
* If a logging method is called & the current scenario is null/blank, then Nebula Logger will throw a runtime exception.
343+
* Controlled by the custom metadata record `LoggerParameter.RequireScenarioUsage`, or `false` as the default
344+
*/
345+
public static final Boolean REQUIRE_SCENARIO_USAGE {
346+
get {
347+
if (REQUIRE_SCENARIO_USAGE == null) {
348+
// Most features in Nebula Logger are enabled (true) by default,
349+
// but this one is intentionally set to false by default - not
350+
// all orgs want or need to use scenario-based logging
351+
REQUIRE_SCENARIO_USAGE = getBoolean('RequireScenarioUsage', false);
352+
}
353+
return REQUIRE_SCENARIO_USAGE;
354+
}
355+
private set;
356+
}
357+
338358
/**
339359
* @description Indicates if Nebula Logger will send an error email notification if any internal exceptions occur.
340360
* Controlled by the custom metadata record `LoggerParameter.SendErrorEmailNotifications`, or `true` as the default
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<CustomMetadata
3+
xmlns="http://soap.sforce.com/2006/04/metadata"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
6+
>
7+
<label>Require Scenario Usage</label>
8+
<protected>false</protected>
9+
<values>
10+
<field>Description__c</field>
11+
<value xsi:type="xsd:string">When set to &apos;false&apos; (default), specifying a scenario is completely optional.
12+
13+
When set to &apos;true&apos;, a scenario is required to be set before any logging can occur. If a logging method is called &amp; the current scenario is null/blank, then Nebula Logger will throw a runtime exception.</value>
14+
</values>
15+
<values>
16+
<field>Value__c</field>
17+
<value xsi:type="xsd:string">false</value>
18+
</values>
19+
</CustomMetadata>

nebula-logger/core/main/log-management/flexipages/LoggerScenarioRecordPage.flexipage-meta.xml

Lines changed: 123 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@
3333
<flexiPageRegions>
3434
<itemInstances>
3535
<componentInstance>
36+
<componentInstanceProperties>
37+
<name>actionNames</name>
38+
<valueList>
39+
<valueListItems>
40+
<value>Log__c.Manage</value>
41+
</valueListItems>
42+
</valueList>
43+
</componentInstanceProperties>
44+
<componentInstanceProperties>
45+
<name>adminFilters</name>
46+
</componentInstanceProperties>
47+
<componentInstanceProperties>
48+
<name>maxRecordsToDisplay</name>
49+
<value>30</value>
50+
</componentInstanceProperties>
3651
<componentInstanceProperties>
3752
<name>parentFieldApiName</name>
3853
<value>LoggerScenario__c.Id</value>
@@ -42,19 +57,62 @@
4257
<value>Logs__r</value>
4358
</componentInstanceProperties>
4459
<componentInstanceProperties>
45-
<name>relatedListComponentOverride</name>
60+
<name>relatedListDisplayType</name>
4661
<value>ADVGRID</value>
4762
</componentInstanceProperties>
4863
<componentInstanceProperties>
49-
<name>rowsToDisplay</name>
50-
<value>30</value>
64+
<name>relatedListFieldAliases</name>
65+
<valueList>
66+
<valueListItems>
67+
<value>NAME</value>
68+
</valueListItems>
69+
<valueListItems>
70+
<value>StartTime__c</value>
71+
</valueListItems>
72+
<valueListItems>
73+
<value>LoggedByUsernameLink__c</value>
74+
</valueListItems>
75+
<valueListItems>
76+
<value>TransactionId__c</value>
77+
</valueListItems>
78+
<valueListItems>
79+
<value>TotalLogEntries__c</value>
80+
</valueListItems>
81+
<valueListItems>
82+
<value>TotalERRORLogEntries__c</value>
83+
</valueListItems>
84+
<valueListItems>
85+
<value>TotalWARNLogEntries__c</value>
86+
</valueListItems>
87+
<valueListItems>
88+
<value>OWNER.ALIAS</value>
89+
</valueListItems>
90+
<valueListItems>
91+
<value>Priority__c</value>
92+
</valueListItems>
93+
<valueListItems>
94+
<value>Status__c</value>
95+
</valueListItems>
96+
</valueList>
97+
</componentInstanceProperties>
98+
<componentInstanceProperties>
99+
<name>relatedListLabel</name>
100+
<value>Logs</value>
51101
</componentInstanceProperties>
52102
<componentInstanceProperties>
53103
<name>showActionBar</name>
54104
<value>true</value>
55105
</componentInstanceProperties>
56-
<componentName>force:relatedListSingleContainer</componentName>
57-
<identifier>force_relatedListSingleContainer</identifier>
106+
<componentInstanceProperties>
107+
<name>sortFieldAlias</name>
108+
<value>StartTime__c</value>
109+
</componentInstanceProperties>
110+
<componentInstanceProperties>
111+
<name>sortFieldOrder</name>
112+
<value>Descending</value>
113+
</componentInstanceProperties>
114+
<componentName>lst:dynamicRelatedList</componentName>
115+
<identifier>lst_dynamicRelatedList</identifier>
58116
</componentInstance>
59117
</itemInstances>
60118
<name>relatedTabContent</name>
@@ -63,6 +121,18 @@
63121
<flexiPageRegions>
64122
<itemInstances>
65123
<componentInstance>
124+
<componentInstanceProperties>
125+
<name>actionNames</name>
126+
<valueList>
127+
<valueListItems>
128+
<value>MassChangeOwner</value>
129+
</valueListItems>
130+
</valueList>
131+
</componentInstanceProperties>
132+
<componentInstanceProperties>
133+
<name>maxRecordsToDisplay</name>
134+
<value>30</value>
135+
</componentInstanceProperties>
66136
<componentInstanceProperties>
67137
<name>parentFieldApiName</name>
68138
<value>LoggerScenario__c.Id</value>
@@ -72,19 +142,56 @@
72142
<value>LogEntries__r</value>
73143
</componentInstanceProperties>
74144
<componentInstanceProperties>
75-
<name>relatedListComponentOverride</name>
145+
<name>relatedListDisplayType</name>
76146
<value>ADVGRID</value>
77147
</componentInstanceProperties>
78148
<componentInstanceProperties>
79-
<name>rowsToDisplay</name>
80-
<value>30</value>
149+
<name>relatedListFieldAliases</name>
150+
<valueList>
151+
<valueListItems>
152+
<value>NAME</value>
153+
</valueListItems>
154+
<valueListItems>
155+
<value>Timestamp__c</value>
156+
</valueListItems>
157+
<valueListItems>
158+
<value>LoggedByUsernameLink__c</value>
159+
</valueListItems>
160+
<valueListItems>
161+
<value>Origin__c</value>
162+
</valueListItems>
163+
<valueListItems>
164+
<value>Message__c</value>
165+
</valueListItems>
166+
<valueListItems>
167+
<value>LoggingLevelWithImage__c</value>
168+
</valueListItems>
169+
<valueListItems>
170+
<value>Log__c</value>
171+
</valueListItems>
172+
<valueListItems>
173+
<value>RecordLink__c</value>
174+
</valueListItems>
175+
</valueList>
176+
</componentInstanceProperties>
177+
<componentInstanceProperties>
178+
<name>relatedListLabel</name>
179+
<value>Log Entries</value>
81180
</componentInstanceProperties>
82181
<componentInstanceProperties>
83182
<name>showActionBar</name>
84-
<value>true</value>
183+
<value>false</value>
85184
</componentInstanceProperties>
86-
<componentName>force:relatedListSingleContainer</componentName>
87-
<identifier>force_relatedListSingleContainer3</identifier>
185+
<componentInstanceProperties>
186+
<name>sortFieldAlias</name>
187+
<value>Timestamp__c</value>
188+
</componentInstanceProperties>
189+
<componentInstanceProperties>
190+
<name>sortFieldOrder</name>
191+
<value>Descending</value>
192+
</componentInstanceProperties>
193+
<componentName>lst:dynamicRelatedList</componentName>
194+
<identifier>lst_dynamicRelatedList2</identifier>
88195
</componentInstance>
89196
</itemInstances>
90197
<name>Facet-bf77ace2-6cee-4ca4-88b4-990633a74278</name>
@@ -125,7 +232,7 @@
125232
<componentInstance>
126233
<componentInstanceProperties>
127234
<name>active</name>
128-
<value>true</value>
235+
<value>false</value>
129236
</componentInstanceProperties>
130237
<componentInstanceProperties>
131238
<name>body</name>
@@ -141,6 +248,10 @@
141248
</itemInstances>
142249
<itemInstances>
143250
<componentInstance>
251+
<componentInstanceProperties>
252+
<name>active</name>
253+
<value>false</value>
254+
</componentInstanceProperties>
144255
<componentInstanceProperties>
145256
<name>body</name>
146257
<value>Facet-bf77ace2-6cee-4ca4-88b4-990633a74278</value>

nebula-logger/core/main/log-management/permissionsets/LoggerAdmin.permissionset-meta.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,11 @@
15581558
<field>Log__c.TransactionScenarioText__c</field>
15591559
<readable>true</readable>
15601560
</fieldPermissions>
1561+
<fieldPermissions>
1562+
<editable>false</editable>
1563+
<field>Log__c.TransactionScenario__c</field>
1564+
<readable>true</readable>
1565+
</fieldPermissions>
15611566
<fieldPermissions>
15621567
<editable>false</editable>
15631568
<field>Log__c.UserLicenseDefinitionKey__c</field>

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
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.13.2';
18+
private static final String CURRENT_VERSION_NUMBER = 'v4.13.3';
1919
private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG;
2020
private static final List<LogEntryEventBuilder> LOG_ENTRIES_BUFFER = new List<LogEntryEventBuilder>();
21+
private static final String MISSING_SCENARIO_ERROR_MESSAGE = 'No logger scenario specified. A scenario is required for logging in this org.';
2122
private static final String ORGANIZATION_DOMAIN_URL = System.URL.getOrgDomainUrl()?.toExternalForm();
2223
private static final String REQUEST_ID = System.Request.getCurrent().getRequestId();
2324
private static final Map<String, SaveMethod> SAVE_METHOD_NAME_TO_SAVE_METHOD = new Map<String, SaveMethod>();
@@ -3351,6 +3352,10 @@ global with sharing class Logger {
33513352
private static LogEntryEventBuilder newEntry(System.LoggingLevel loggingLevel, Boolean shouldSave) {
33523353
LogEntryEventBuilder logEntryEventBuilder = new LogEntryEventBuilder(getUserSettings(), loggingLevel, shouldSave);
33533354
if (logEntryEventBuilder.shouldSave()) {
3355+
if (LoggerParameter.REQUIRE_SCENARIO_USAGE && String.isBlank(currentEntryScenario)) {
3356+
throw new LoggerException(MISSING_SCENARIO_ERROR_MESSAGE);
3357+
}
3358+
33543359
LogEntryEvent__e logEntryEvent = logEntryEventBuilder.getLogEntryEvent();
33553360
logEntryEvent.ApiVersion__c = getOrganizationApiVersion();
33563361
logEntryEvent.EntryScenario__c = currentEntryScenario;
@@ -3493,6 +3498,11 @@ global with sharing class Logger {
34933498
}
34943499
}
34953500

3501+
// Inner class used for any exceptions specific to Nebula Logger functionality
3502+
@SuppressWarnings('PMD.ApexDoc')
3503+
public class LoggerException extends Exception {
3504+
}
3505+
34963506
// Inner class used for deserializing data from the status API
34973507
@SuppressWarnings('PMD.ApexDoc, PMD.VariableNamingConventions')
34983508
public class StatusApiResponse {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//------------------------------------------------------------------------------------------------//
55
import FORM_FACTOR from '@salesforce/client/formFactor';
66

7-
const CURRENT_VERSION_NUMBER = 'v4.13.2';
7+
const CURRENT_VERSION_NUMBER = 'v4.13.3';
88

99
// JavaScript equivalent to the Apex class ComponentLogger.ComponentLogEntry
1010
const ComponentLogEntry = class {

0 commit comments

Comments
 (0)