Skip to content

Commit 2735d4e

Browse files
authored
Bugfix: child Log__c records are not always linked to their parent Log__c record (#605)
* Fixed #585 by updating LogHandler to requery & update any potential child logs without the parent log set
1 parent b0bec13 commit 2735d4e

10 files changed

Lines changed: 128 additions & 12 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.3
8+
## Unlocked Package - v4.12.4
99

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

14-
`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001Mk5AQAS`
14+
`sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001Mk5KQAS`
1515

16-
`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001Mk5AQAS`
16+
`sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001Mk5KQAS`
1717

1818
---
1919

docs/apex/Log-Management/LogManagementDataSelector.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,26 @@ List<Log\_\_c>
317317

318318
The list of matching `Log__c` records
319319

320+
#### `getLogsWithoutParentLogByParentTransactionId(List<String> parentTransactionIds)``List<Log__c>`
321+
322+
Returns a `List&lt;Log__c&gt;` of records with the specified parent transaction IDs and a `null` value in `ParentLog__c`
323+
324+
##### Parameters
325+
326+
| Param | Description |
327+
| ---------------------- | ---------------------------------------------------------------------------- |
328+
| `parentTransactionIds` | The list of `String` parent transaction IDs of the `Log__c` records to query |
329+
330+
##### Return
331+
332+
**Type**
333+
334+
List&lt;Log\_\_c&gt;
335+
336+
**Description**
337+
338+
The list of matching `Log__c` records
339+
320340
#### `getProfilesById(List<Id> profileIds)``List<Profile>`
321341

322342
Returns a `List&lt;Profile&gt;` of records with the specified profile IDs

nebula-logger/core/main/log-management/classes/LogHandler.cls

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public without sharing class LogHandler extends LoggerSObjectHandler {
5151
protected override void executeAfterInsert(Map<Id, SObject> triggerNewMap) {
5252
this.logs = (List<Log__c>) triggerNewMap.values();
5353

54+
this.updateUnlinkedChildLogs();
5455
this.shareLogsWithLoggingUsers();
5556
}
5657

@@ -196,6 +197,22 @@ public without sharing class LogHandler extends LoggerSObjectHandler {
196197
}
197198
}
198199

200+
private void updateUnlinkedChildLogs() {
201+
Map<String, Log__c> transactionIdToPossibleParentLog = new Map<String, Log__c>();
202+
for (Log__c log : this.logs) {
203+
if (log.TransactionId__c != log.ParentLogTransactionId__c) {
204+
transactionIdToPossibleParentLog.put(log.TransactionId__c, log);
205+
}
206+
}
207+
List<String> possibleParentLogTransactionIds = new List<String>(transactionIdToPossibleParentLog.keySet());
208+
209+
List<Log__c> unlinkedChildLogs = LogManagementDataSelector.getInstance().getLogsWithoutParentLogByParentTransactionId(possibleParentLogTransactionIds);
210+
for (Log__c unlinkedChildLog : unlinkedChildLogs) {
211+
unlinkedChildLog.ParentLog__c = transactionIdToPossibleParentLog.get(unlinkedChildLog.ParentLogTransactionId__c)?.Id;
212+
}
213+
LoggerDataStore.getDatabase().updateRecords(unlinkedChildLogs);
214+
}
215+
199216
private void shareLogsWithLoggingUsers() {
200217
// For each log record, share the record with the user that created the log (Log__c.LoggedBy__c)
201218
List<Log__Share> logShares = new List<Log__Share>();

nebula-logger/core/main/log-management/classes/LogManagementDataSelector.cls

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,19 @@ public without sharing virtual class LogManagementDataSelector {
223223
return [SELECT Id, Name, LoggedBy__c, LoggedBy__r.Name, StartTime__c, TotalLogEntries__c, TransactionId__c FROM Log__c WHERE Id IN :logIds];
224224
}
225225

226+
/**
227+
* @description Returns a `List<Log__c>` of records with the specified parent transaction IDs and a `null` value in `ParentLog__c`
228+
* @param parentTransactionIds The list of `String` parent transaction IDs of the `Log__c` records to query
229+
* @return The list of matching `Log__c` records
230+
*/
231+
public virtual List<Log__c> getLogsWithoutParentLogByParentTransactionId(List<String> parentTransactionIds) {
232+
return [
233+
SELECT Id, ParentLogTransactionId__c, ParentLog__c, ParentLog__r.TransactionId__c, TransactionId__c
234+
FROM Log__c
235+
WHERE ParentLogTransactionId__c IN :parentTransactionIds AND ParentLog__c = NULL
236+
];
237+
}
238+
226239
/**
227240
* @description Returns a `List<Log__c>` of records with the specified transaction IDs
228241
* @param transactionIds The list of `String` transaction IDs of the `Log__c` records to query

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

Lines changed: 1 addition & 1 deletion
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.3';
18+
private static final String CURRENT_VERSION_NUMBER = 'v4.12.4';
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>();

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.3';
9+
const CURRENT_VERSION_NUMBER = 'v4.12.4';
1010

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

nebula-logger/core/tests/log-management/classes/LogHandler_Tests.cls

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ private class LogHandler_Tests {
287287
}
288288

289289
@IsTest
290-
static void it_should_set_parent_log_when_it_exists() {
290+
static void it_should_set_parent_log_when_it_exists_in_the_database() {
291291
String parentLogTransactionId = 'ABC-1234';
292292
Log__c parentLog = new Log__c(TransactionId__c = parentLogTransactionId);
293293
insert parentLog;
@@ -300,6 +300,33 @@ private class LogHandler_Tests {
300300
System.Assert.areEqual(parentLog.Id, log.ParentLog__c, JSON.serializePretty(log));
301301
}
302302

303+
@IsTest
304+
static void it_should_set_parent_log_when_it_is_created_after_child_log() {
305+
String parentLogTransactionId = 'ABC-1234';
306+
Log__c log = new Log__c(ParentLogTransactionId__c = parentLogTransactionId, TransactionId__c = 'XYZ-5678');
307+
insert log;
308+
Log__c parentLog = new Log__c(TransactionId__c = parentLogTransactionId);
309+
310+
insert parentLog;
311+
312+
log = [SELECT Id, ParentLogTransactionId__c, ParentLog__c FROM Log__c WHERE Id = :log.Id];
313+
System.Assert.areEqual(parentLogTransactionId, log.ParentLogTransactionId__c, JSON.serializePretty(log));
314+
System.Assert.areEqual(parentLog.Id, log.ParentLog__c, JSON.serializePretty(log));
315+
}
316+
317+
@IsTest
318+
static void it_should_set_parent_log_when_it_exists_in_the_same_trigger_context() {
319+
String parentLogTransactionId = 'ABC-1234';
320+
Log__c parentLog = new Log__c(TransactionId__c = parentLogTransactionId);
321+
Log__c log = new Log__c(ParentLogTransactionId__c = parentLogTransactionId, TransactionId__c = 'XYZ-5678');
322+
323+
insert new List<Log__c>{ log, parentLog };
324+
325+
log = [SELECT Id, ParentLogTransactionId__c, ParentLog__c FROM Log__c WHERE Id = :log.Id];
326+
System.Assert.areEqual(parentLogTransactionId, log.ParentLogTransactionId__c, JSON.serializePretty(log));
327+
System.Assert.areEqual(parentLog.Id, log.ParentLog__c, JSON.serializePretty(log));
328+
}
329+
303330
@IsTest
304331
static void it_should_keep_existing_retention_details_when_populated() {
305332
setupConfigurations();

nebula-logger/core/tests/log-management/classes/LogManagementDataSelector_Tests.cls

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,44 @@ private class LogManagementDataSelector_Tests {
228228
System.Assert.areEqual(logs.size(), returnedResults.size());
229229
}
230230

231+
@IsTest
232+
static void it_returns_logs_for_specified_parent_log_transaction_ids_and_no_parent_log() {
233+
LoggerSObjectHandler.shouldExecute(false);
234+
Log__c parentLog = (Log__c) LoggerMockDataCreator.createDataBuilder(Schema.Log__c.SObjectType).populateRequiredFields().getRecord();
235+
parentLog.TransactionId__c = 'some unique value for this log';
236+
insert parentLog;
237+
List<Log__c> logsToCreate = new List<Log__c>();
238+
List<Log__c> expectedLogs = new List<Log__c>();
239+
List<String> parentLogTransactionIds = new List<String>();
240+
for (Integer i = 0; i < 5; i++) {
241+
Log__c log = (Log__c) LoggerMockDataCreator.createDataBuilder(Schema.Log__c.SObjectType).populateRequiredFields().getRecord();
242+
log.TransactionId__c = 'some_fake_transaction_id_' + i;
243+
// Make 1 log with an actual an actual parent log
244+
if (i == 0) {
245+
log.ParentLog__c = parentLog.Id;
246+
log.ParentLogTransactionId__c = parentLog.TransactionId__c;
247+
}
248+
// Make a few logs with a parent transaction ID but no parent log
249+
if (i == 1 || i == 2 || i == 3) {
250+
log.ParentLog__c = null;
251+
log.ParentLogTransactionId__c = 'some other value';
252+
expectedLogs.add(log);
253+
}
254+
if (String.isNotBlank(log.ParentLogTransactionId__c)) {
255+
parentLogTransactionIds.add(log.ParentLogTransactionId__c);
256+
}
257+
logsToCreate.add(log);
258+
}
259+
System.Assert.areEqual(parentLogTransactionIds.size(), expectedLogs.size() + 1, 'Test has started under the wrong conditions');
260+
insert logsToCreate;
261+
262+
List<Log__c> returnedResults = LogManagementDataSelector.getInstance().getLogsWithoutParentLogByParentTransactionId(parentLogTransactionIds);
263+
264+
System.Assert.isFalse(returnedResults.isEmpty());
265+
System.Assert.areEqual(expectedLogs.size(), returnedResults.size());
266+
System.Assert.areEqual(new Map<Id, Log__c>(expectedLogs).keySet(), new Map<Id, Log__c>(returnedResults).keySet());
267+
}
268+
231269
@IsTest
232270
static void it_returns_logs_for_specified_log_transaction_ids() {
233271
LoggerSObjectHandler.shouldExecute(false);

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.3",
3+
"version": "4.12.4",
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.3.NEXT",
17-
"versionName": "Bugfix for UserInfo.getSessionId() Exception",
18-
"versionDescription": "Added a try-catch block to usage of UserInfo.getSessionId() to handle a platform-thrown exception that occurs in some transactions (such as connected apps with JWT).",
16+
"versionNumber": "4.12.4.NEXT",
17+
"versionName": "Bugfix Child Log__c Records Not Properly Linked to Parent Log__c Records",
18+
"versionDescription": "Fixed some scenarios where a Log__c record would have a value in ParentLogTransactionId__c but a null value in ParentLog__c",
1919
"releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases",
2020
"unpackagedMetadata": {
2121
"path": "./nebula-logger/extra-tests"
@@ -164,6 +164,7 @@
164164
"Nebula Logger - Core@4.12.1-improved-error-emails": "04t5Y000001Mk4bQAC",
165165
"Nebula Logger - Core@4.12.2-automatically-select-default-field-set-in-relatedlogentries-lwc": "04t5Y000001Mk55QAC",
166166
"Nebula Logger - Core@4.12.3-bugfix-for-userinfo.getsessionid()-exception": "04t5Y000001Mk5AQAS",
167+
"Nebula Logger - Core@4.12.4-bugfix-child-log__c-records-not-properly-linked-to-parent-log__c-records": "04t5Y000001Mk5KQAS",
167168
"Nebula Logger - Core Plugin - Async Failure Additions": "0Ho5Y000000blO4SAI",
168169
"Nebula Logger - Core Plugin - Async Failure Additions@1.0.0": "04t5Y0000015lhiQAA",
169170
"Nebula Logger - Core Plugin - Async Failure Additions@1.0.1": "04t5Y0000015lhsQAA",

0 commit comments

Comments
 (0)