Skip to content

Commit

Permalink
Updated the behavior of Logger.setAsyncContext() to only set the cont…
Browse files Browse the repository at this point in the history
…ext the first time a non-null context value is provided
  • Loading branch information
jongpie committed Sep 24, 2024
1 parent 1629291 commit 81b5bce
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

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.

## Unlocked Package - v4.14.10
## Unlocked Package - v4.14.11

[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015oTdQAI)
[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015oTdQAI)
Expand Down
27 changes: 20 additions & 7 deletions nebula-logger/core/main/logger-engine/classes/Logger.cls
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
global with sharing class Logger {
// There's no reliable way to get the version number dynamically in Apex
@TestVisible
private static final String CURRENT_VERSION_NUMBER = 'v4.14.10';
private static final String CURRENT_VERSION_NUMBER = 'v4.14.11';
private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG;
private static final List<LogEntryEventBuilder> LOG_ENTRIES_BUFFER = new List<LogEntryEventBuilder>();
private static final String MISSING_SCENARIO_ERROR_MESSAGE = 'No logger scenario specified. A scenario is required for logging in this org.';
Expand Down Expand Up @@ -196,31 +196,39 @@ global with sharing class Logger {
* @param batchableContext - The instance of `Database.BatchableContext` to track
*/
global static void setAsyncContext(Database.BatchableContext batchableContext) {
setAsyncContext(new AsyncContext(batchableContext));
if (batchableContext != null) {
setAsyncContext(new AsyncContext(batchableContext));
}
}

/**
* @description Stores additional details about the current transacation's async context
* @param finalizerContext - The instance of `System.FinalizerContext` to track
*/
global static void setAsyncContext(System.FinalizerContext finalizerContext) {
setAsyncContext(new AsyncContext(finalizerContext));
if (finalizerContext != null) {
setAsyncContext(new AsyncContext(finalizerContext));
}
}

/**
* @description Stores additional details about the current transacation's async context
* @param queueableContext - The instance of `System.QueueableContext` to track
*/
global static void setAsyncContext(System.QueueableContext queueableContext) {
setAsyncContext(new AsyncContext(queueableContext));
if (queueableContext != null) {
setAsyncContext(new AsyncContext(queueableContext));
}
}

/**
* @description Stores additional details about the current transacation's async context
* @param schedulableContext - The instance of `System.SchedulableContext` to track
*/
global static void setAsyncContext(System.SchedulableContext schedulableContext) {
setAsyncContext(new AsyncContext(schedulableContext));
if (schedulableContext != null) {
setAsyncContext(new AsyncContext(schedulableContext));
}
}

/**
Expand Down Expand Up @@ -3415,8 +3423,13 @@ global with sharing class Logger {
}

private static void setAsyncContext(AsyncContext asyncContext) {
currentAsyncContext = asyncContext;
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Async Context: ' + System.JSON.serializePretty(asyncContext));
// Only set the async context the first time that a non-null value is provided
// Previous versions of Nebula Logger would always set it, but that wasn't the
// intended behavior
if (currentAsyncContext == null) {
currentAsyncContext = asyncContext;
System.debug(System.LoggingLevel.INFO, 'Nebula Logger - Async Context: ' + System.JSON.serializePretty(asyncContext));
}
}

private static SaveMethod getSaveMethod(String saveMethodName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import FORM_FACTOR from '@salesforce/client/formFactor';
import { log as lightningLog } from 'lightning/logger';
import { LoggerStackTrace } from './loggerStackTrace';

const CURRENT_VERSION_NUMBER = 'v4.14.10';
const CURRENT_VERSION_NUMBER = 'v4.14.11';

const LOGGING_LEVEL_EMOJIS = {
ERROR: '⛔',
Expand Down
128 changes: 128 additions & 0 deletions nebula-logger/core/tests/logger-engine/classes/Logger_Tests.cls
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,39 @@ private class Logger_Tests {
System.Assert.areEqual(Database.BatchableContext.class.getName(), logEntryEvent.AsyncContextType__c);
}

@IsTest
static void it_should_use_first_non_null_context_details_for_batchable_context_when_event_published() {
Database.BatchableContext nullMockContext = null;
Database.BatchableContext firstNonNullMockContext = new LoggerMockDataCreator.MockBatchableContext();
Database.BatchableContext secondNonNullMockContext = new LoggerMockDataCreator.MockBatchableContext();
System.Assert.areNotEqual(
firstNonNullMockContext,
secondNonNullMockContext,
'Test has started under the wrong conditions, expected 2 different mock contexts'
);
LoggerDataStore.setMock(LoggerMockDataStore.getEventBus());
LogEntryEvent__e logEntryEvent = Logger.info('hello, world').getLogEntryEvent();
System.Assert.isNull(logEntryEvent.AsyncContextChildJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextParentJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextTriggerId__c);
System.Assert.isNull(logEntryEvent.AsyncContextType__c);
System.Assert.areEqual(1, Logger.getBufferSize());
System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());

Logger.setAsyncContext(nullMockContext);
Logger.setAsyncContext(firstNonNullMockContext);
Logger.setAsyncContext(secondNonNullMockContext);
Logger.saveLog(Logger.SaveMethod.EVENT_BUS);

System.Assert.areEqual(0, Logger.getBufferSize());
System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());
System.Assert.areEqual(logEntryEvent, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0));
System.Assert.areEqual(firstNonNullMockContext.getChildJobId(), logEntryEvent.AsyncContextChildJobId__c);
System.Assert.areEqual(firstNonNullMockContext.getJobId(), logEntryEvent.AsyncContextParentJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextTriggerId__c);
System.Assert.areEqual(Database.BatchableContext.class.getName(), logEntryEvent.AsyncContextType__c);
}

@IsTest
static void it_should_set_async_context_details_for_finalizer_context_when_event_published() {
Id mockParentAsyncApexJobId = LoggerMockDataCreator.createId(Schema.AsyncApexJob.SObjectType);
Expand All @@ -818,6 +851,39 @@ private class Logger_Tests {
System.Assert.areEqual(System.FinalizerContext.class.getName(), logEntryEvent.AsyncContextType__c);
}

@IsTest
static void it_should_use_first_non_null_context_details_for_finalizer_context_when_event_published() {
System.FinalizerContext nullMockContext = null;
System.FinalizerContext firstNonNullMockContext = new LoggerMockDataCreator.MockFinalizerContext();
System.FinalizerContext secondNonNullMockContext = new LoggerMockDataCreator.MockFinalizerContext();
System.Assert.areNotEqual(
firstNonNullMockContext,
secondNonNullMockContext,
'Test has started under the wrong conditions, expected 2 different mock contexts'
);
LoggerDataStore.setMock(LoggerMockDataStore.getEventBus());
LogEntryEvent__e logEntryEvent = Logger.info('hello, world').getLogEntryEvent();
System.Assert.isNull(logEntryEvent.AsyncContextChildJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextParentJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextTriggerId__c);
System.Assert.isNull(logEntryEvent.AsyncContextType__c);
System.Assert.areEqual(1, Logger.getBufferSize());
System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());

Logger.setAsyncContext(nullMockContext);
Logger.setAsyncContext(firstNonNullMockContext);
Logger.setAsyncContext(secondNonNullMockContext);
Logger.saveLog(Logger.SaveMethod.EVENT_BUS);

System.Assert.areEqual(0, Logger.getBufferSize());
System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());
System.Assert.areEqual(logEntryEvent, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0));
System.Assert.isNull(logEntryEvent.AsyncContextChildJobId__c);
System.Assert.areEqual(firstNonNullMockContext.getAsyncApexJobId(), logEntryEvent.AsyncContextParentJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextTriggerId__c);
System.Assert.areEqual(System.FinalizerContext.class.getName(), logEntryEvent.AsyncContextType__c);
}

@IsTest
static void it_should_set_async_context_details_for_queueable_context_when_event_published() {
Id mockParentAsyncApexJobId = LoggerMockDataCreator.createId(Schema.AsyncApexJob.SObjectType);
Expand All @@ -844,6 +910,39 @@ private class Logger_Tests {
System.Assert.areEqual(System.QueueableContext.class.getName(), logEntryEvent.AsyncContextType__c);
}

@IsTest
static void it_should_use_first_non_null_context_details_for_queueable_context_when_event_published() {
System.QueueableContext nullMockContext = null;
System.QueueableContext firstNonNullMockContext = new LoggerMockDataCreator.MockQueueableContext();
System.QueueableContext secondNonNullMockContext = new LoggerMockDataCreator.MockQueueableContext();
System.Assert.areNotEqual(
firstNonNullMockContext,
secondNonNullMockContext,
'Test has started under the wrong conditions, expected 2 different mock contexts'
);
LoggerDataStore.setMock(LoggerMockDataStore.getEventBus());
LogEntryEvent__e logEntryEvent = Logger.info('hello, world').getLogEntryEvent();
System.Assert.isNull(logEntryEvent.AsyncContextChildJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextParentJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextTriggerId__c);
System.Assert.isNull(logEntryEvent.AsyncContextType__c);
System.Assert.areEqual(1, Logger.getBufferSize());
System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());

Logger.setAsyncContext(nullMockContext);
Logger.setAsyncContext(firstNonNullMockContext);
Logger.setAsyncContext(secondNonNullMockContext);
Logger.saveLog(Logger.SaveMethod.EVENT_BUS);

System.Assert.areEqual(0, Logger.getBufferSize());
System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());
System.Assert.areEqual(logEntryEvent, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0));
System.Assert.isNull(logEntryEvent.AsyncContextChildJobId__c);
System.Assert.areEqual(firstNonNullMockContext.getJobId(), logEntryEvent.AsyncContextParentJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextTriggerId__c);
System.Assert.areEqual(System.QueueableContext.class.getName(), logEntryEvent.AsyncContextType__c);
}

@IsTest
static void it_should_set_async_context_details_for_schedulable_context_when_event_published() {
Id mockCronTriggerId = LoggerMockDataCreator.createId(Schema.CronTrigger.SObjectType);
Expand All @@ -869,6 +968,35 @@ private class Logger_Tests {
System.Assert.areEqual(System.SchedulableContext.class.getName(), logEntryEvent.AsyncContextType__c);
}

@IsTest
static void it_should_use_first_non_null_context_details_for_schedulable_context_when_event_published() {
System.SchedulableContext nullMockContext = null;
System.SchedulableContext firstNonNullMockContext = new LoggerMockDataCreator.MockSchedulableContext();
System.SchedulableContext secondNonNullMockContext = new LoggerMockDataCreator.MockSchedulableContext();
System.Assert.areNotEqual(firstNonNullMockContext, secondNonNullMockContext, 'Test has started under the wrong conditions, expected 2 different mock contexts');
LoggerDataStore.setMock(LoggerMockDataStore.getEventBus());
LogEntryEvent__e logEntryEvent = Logger.info('hello, world').getLogEntryEvent();
System.Assert.isNull(logEntryEvent.AsyncContextChildJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextParentJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextTriggerId__c);
System.Assert.isNull(logEntryEvent.AsyncContextType__c);
System.Assert.areEqual(1, Logger.getBufferSize());
System.Assert.areEqual(0, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());

Logger.setAsyncContext(nullMockContext);
Logger.setAsyncContext(firstNonNullMockContext);
Logger.setAsyncContext(secondNonNullMockContext);
Logger.saveLog(Logger.SaveMethod.EVENT_BUS);

System.Assert.areEqual(0, Logger.getBufferSize());
System.Assert.areEqual(1, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().size());
System.Assert.areEqual(logEntryEvent, LoggerMockDataStore.getEventBus().getPublishedPlatformEvents().get(0));
System.Assert.isNull(logEntryEvent.AsyncContextChildJobId__c);
System.Assert.isNull(logEntryEvent.AsyncContextParentJobId__c);
System.Assert.areEqual(firstNonNullMockContext.getTriggerId(), logEntryEvent.AsyncContextTriggerId__c);
System.Assert.areEqual(System.SchedulableContext.class.getName(), logEntryEvent.AsyncContextType__c);
}

@IsTest
static void it_should_set_parent_transaction_id() {
String expectedParentTransactionId = 'imagineThisWereAGuid';
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nebula-logger",
"version": "4.14.10",
"version": "4.14.11",
"description": "The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects.",
"author": "Jonathan Gillespie",
"license": "MIT",
Expand Down
6 changes: 3 additions & 3 deletions sfdx-project.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
"path": "./nebula-logger/core",
"definitionFile": "./config/scratch-orgs/base-scratch-def.json",
"scopeProfiles": true,
"versionNumber": "4.14.10.NEXT",
"versionName": "New CallableLogger Apex class",
"versionDescription": "Added a new CallableLogger class that provides support for both OmniStudio logging, as well as the ability to dynamically call Nebula Logger in Apex when it's available",
"versionNumber": "4.14.11.NEXT",
"versionName": "Updated Behavior of Logger.setAsyncContext()",
"versionDescription": "Updated the behavior of Logger.setAsyncContext() to only set the context the first time a non-null context value is provided. Previously, subsequent calls would overwrite the context value, which wasn't really the intended behaviour.",
"releaseNotesUrl": "https://github.com/jongpie/NebulaLogger/releases",
"unpackagedMetadata": {
"path": "./nebula-logger/extra-tests"
Expand Down

0 comments on commit 81b5bce

Please sign in to comment.