Skip to content

v4.16.0 - Spring '25 Release

Compare
Choose a tag to compare
@jongpie jongpie released this 22 Apr 14:59
· 2 commits to main since this release
323fa77

πŸ§™β€β™‚οΈAn open source release is never late, nor is it early. It arrives precisely when it means to. And also when I have the time to work on it. πŸ§™β€β™‚οΈ

A huge thanks goes to everyone that's contributed to this release over the last several months! There has been a great mix of bug reporting, features requests, discussions + feedback, and code contributions. This has all been incredibly helpful in delivering some great enhancements this release. So thanks again to everyone that's helped!

Managed Package Release - v4.16.0

This release is for both the unlocked package (as always), as well as the managed package! You can see everything that's changed between v4.15.0 and v4.16.0 for the managed package by reviewing:

  • The v4.16.0 milestone to see all of the issues & pull requests that are included in the this release.
  • The diff between v4.15.0 and v4.16.0 to see all of the code & metadata changes that have been committed since the last managed package release.

Apex Logging Enhancements

  • βœ…Release v4.15.2 - Added Support for Logging Instances of Database.EmptyRecycleBinResult and List<Database.EmptyRecycleBinResult> by @TrangOul and @jongpie (PR #806) β†’ closed issue #804 reported by (also) @TrangOul

    • Add new instance method overloads in Nebula.LogEntryEventBuilder for setDatabaseResult() to support logging instances of Database.EmptyRecycleBinResult and List<Database.EmptyRecycleBinResult>

      global Nebula.LogEntryEventBuilder setDatabaseResult(Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global Nebula.LogEntryEventBuilder setDatabaseResult(List<Database.EmptyRecycleBinResult> emptyRecycleBinResults);
    • Added new static method overloads in Logger to make it easier to log instances of Database.EmptyRecycleBinResult and List<Database.EmptyRecycleBinResult>

      global static Nebula.LogEntryEventBuilder error(Nebula.LogMessage logMessage, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder error(String message, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder warn(Nebula.LogMessage logMessage, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder warn(String message, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder info(Nebula.LogMessage logMessage, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder info(String message, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder debug(Nebula.LogMessage logMessage, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder debug(String message, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder fine(Nebula.LogMessage logMessage, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder fine(Nebula.LogMessage logMessage, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder finer(String message, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder finer(String message, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder finest(String message, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder finest(String message, Database.EmptyRecycleBinResult emptyRecycleBinResult);
      global static Nebula.LogEntryEventBuilder logDatabaseErrors(System.LoggingLevel loggingLevel, Nebula.LogMessage logMessage, List<Database.EmptyRecycleBinResult> emptyRecycleBinResults);
      global static Nebula.LogEntryEventBuilder logDatabaseErrors(System.LoggingLevel loggingLevel, String message, List<Database.EmptyRecycleBinResult> emptyRecycleBinResults);
  • βœ…Release v4.15.10 - Approval Results Logging by @TrangOul, @jamessimone, and @jongpie (#850) β†’ closed issue #844 reported by @PawelWozniak

    • Added new setApprovalResult() methods in Nebula.LogEntryEventBuilder for logging instances of the standard Apex classes Approval.LockResult, Approval.ProcessResult, Approval.UnlockResult, as well as lists of each class

      global Nebula.LogEntryEventBuilder setApprovalResult(Approval.LockResult lockResult);
      global Nebula.LogEntryEventBuilder setApprovalResult(Approval.ProcessResult processResult);
      global Nebula.LogEntryEventBuilder setApprovalResult(Approval.UnlockResult unlockResult);
      global Nebula.LogEntryEventBuilder setApprovalResult(List<Approval.LockResult> lockResults);
      global Nebula.LogEntryEventBuilder setApprovalResult(List<Approval.ProcessResult> processResults);
      global Nebula.LogEntryEventBuilder setApprovalResult(List<Approval.UnlockResult> unlockResults);
    • Note: for now, the decision has been made to not provide overloads in Nebula.Logger for logging the approval classes - this is a little different from logging Database result classes, where Nebula.Logger does provide static method overloads. See this related comment for more details on why this decision was made for Approval result classes.

    • Example usage:

      SObject someRecord = [SELECT Id FROM Account LIMIT 1];
      Approval.LockResult lockResult = Approval.lock(someRecord);
      
      // The builder's new method overloads setApprovalResult() can be called to capture approval details
      Nebula.Logger.debug('Locked record for approval', someRecord)
          .setApprovalResult(lockResult);
      Nebula.Logger.saveLog();
    • The approval result data is stored in the existing set of DatabaseResult* fields on LogEntry__c like LogEntry__c.DatabaseResultType__c, shown below:

      image

CallableLogger / OmniStudio Logging Enhancements

Bugfixes

Optimizations

  • 🏎️Release v4.15.8 - Custom Index for Log__c.ParentLogTransactionId__c by @jamessimone (PR #849) β†’ fixed issue #847 reported by @jet89cook-google, @mkhokhlov, and @tsalb

    • Fixed #847 by adding Log__c.ParentLogTransactionId__c custom index to speed up code & queries that use this field
  • 🏎️Release v4.15.1 - System.OrgLimits Optimisations by @ngreardSF (PR #802) β†’ closed issue #801 reported by (also) @ngreardSF

    • Updated LogHandler class to cache the Apex call to System.OrgLimits.getMap() in loadOrganizationLimits() to reduce CPU usage
    • Added some comments + updated some existing variable names & class name to include 'serializable' to provide a little more context on why there is a custom class for org limits
  • 🏎️Release v4.15.3 - Improved Testability of Queries by @jongpie (PR #813) β†’ fixed issue #687 reported by @heapallocation, fixed issue #457 reported by @JeroenSfdc via discussion #454, and fixed issue #812 reported by @angelikagalang via discussion #799

    • Fixed #687: Improved how records are queried & converted to the inner classes in LoggerSObjectProxy, which are used for dynamically interacting with some standard SObject types that don't exist in all orgs (Network, OmniProcess, etc.)
    • These changes improve the testability of this part of the code base, resulting in more thorough tests & improved code coverage for the core package
    • Fixed #457 and fixed #812: Changed Nebula Logger's behavior during test execution so that the org's actual CMDT records are now loaded & used (e.g., records in LoggerParameter__mdt). This is controlled internally by Nebula Logger via a new Apex class LoggerConfigurationSelector
    • This provides admins & developers with the ability to fully test their usage of Nebula Logger, including any customizations that have been made to the included CMDT records
    • Internally, Nebula Logger's own tests still only use mock CMDT records - they do not leverage the org's actual CMDT records
    • Scope creep: added access for the existing Visualforce page LogMassDelete to the permission sets LoggerAdmin, LoggerLogViewer, and LoggerEndUser
    • This page has been around for ~3 years, but the permission sets didn't explicitly provide access to the page

Core Unlocked Package Release - v4.16.0

These changes are new for both the unlocked package and the managed package.

Spring '25 Release Upgrade

  • Bumped all metadata to API v63.0 (Spring '25 release)
    • Also updated the list of picklist values in several 'API version' picklist fields on Log__c and LogEntry__c
  • Greatly simplified the management of field permissions in all 4 permissions sets (listed below) by using the new object-level permission option <viewAllFields> (added in Spring '25)
    1. LoggerAdmin
    2. LoggerLogViewer
    3. LoggerEndUser
    4. LoggerLogCreator

CallableLogger / OmniStudio Logging Improvements

  • Fixed issue #837 reported by @gokhalesamruddhi by changing how some fields are set on new OmniStudio entries to avoid a NullPointerException when the entry's logging level doesn't meet the user's logging level
  • Scope creep: added the ability in CallableLogger to override shouldSave on new entries, similar to using Logger method overloads like Logger.newEntry(System.LoggingLevel loggingLevel, String message, Boolean shouldSave)
    • This provides the ability in OmniStudio to force a log entry to save, even if the entry's logging level doesn't meet the user's configured logging level.

Dev / Pipeline Changes

  • Upgraded several devDependencies items in package.json / regenerated package-lock.json
  • Started some foundational work to create a project-specific dev container. Eventually, this will be used both for 'local' dev (by me) & within the pipeline (build.yml). Three new files have been added to the repo:
    1. .devcontainer/devcontainer.json - provides a consistent dev setup + extensions in VS Code
    2. .devcontainer/Dockerfile - provides a consistent dev environment + dependencies in a Docker container
    3. .github/workflows/publish-docker-container.yml - auto-publishes a Docker image
      • Eventually, the new Docker image will be used both for 'local' dev (by me) & within the pipeline (build.yml)

Installation Info

Core Unlocked Package - no namespace

Full Changelog: v4.15.10...v4.16.0

Core Managed Package - Nebula namespace

Full Changelog: v4.15.0...v4.16.0