Apex Observability Enhancements
This release is a big one - and so is the description, to try to cover all of the changes.
Overview
This introduces some very powerful enhancements to improve the observability of Apex code, making it easier for Salesforce experts to answer questions like "what happened in my Apex code?" and "what did my Apex code look like?". It also takes some big steps towards streamlining the fields on LogEntry__c
to simplify reporting, and shifting towards using custom LWCs to provide an improved user experience for viewing logging data.
Source Snippets
Nebula Logger now automatically logs a snippet of your Apex code, providing a snapshot of the relevant codeblock. These snippets are displayed in a very fancy code-viewer on the LogEntry__c
page, using PrismJS
- Origin Source Snippets: Any time you add a log entry in Apex, you will now be able to see a snippet of your Apex code that generated the
LogEntry__c
record. - Exception Source Snippets: Any time you include an Apex exception in your log entry, you will now also be able to see a snippet of Apex code that threw the exception.
For example, if you deploy the example Apex class below:
Example Class with Logging
public with sharing class ExampleClassWithLogging {
public void doSomething() {
Logger.finest('Starting the doSomething() method!');
try {
insertContact('Some Contact Name');
} catch (Exception ex) {
Logger.error('An unexpected exception occurred', ex);
Logger.saveLog();
throw ex;
}
}
public Schema.Contact insertContact(String contactName) {
Schema.Contact contact = new Schema.Contact();
// TODO don't forget to populate the record's required fields
// before deploying this code to prod!
insert contact;
return contact;
}
}
...if you then run and run new ExampleClassWithLogging().doSomething();
, Nebula Logger will generate a new LogEntry__c
record with 2 code snippets - one snippet for the origin of the entry, and another snippet for the included exception.
In each snippet, you can see about 12 lines of source code that executed - the relevant line of code is automatically highlighted.
You can also click the 'View Full Source' button to see the entire Apex class or trigger that is currently deployed to the org. The modal even indicates if the source code has been modified since the LogEntry__c
was generated, making it easy to know if the snippet on the LogEntry__c
is still accurate.
Streamlined Reporting with New Origin & Exception Source Fields
Nebula Logger supports logging in 5 (5-ish) metadata types:
- Apex classes
- Apex triggers
- Flows (and implicitly, Process Builder)
- Lightning web components
- Aura components
This release tries to provide a more consistent set of fields to use for reporting, regardless of which metadata type is using Nebula Logger.
Current State: LogEntry__c
Fields Are Not Very Scalable
Originally when Nebula Logger was first created, Apex classes were the only focus - as new metadata types have been added over the years, new fields have also been added LogEntry__c
that are specific to each metadata type. For example:
- There are Apex class-specific fields like
ApexClassName__c
andApexMethodName__c
- There are Flow-specific fields like
FlowActiveVersionId__c
- There are Lightning component-specific fields like
ComponentApiName__c
andComponentFunctionName__c
These approach has led to 2 challenges:
- Field Limits. Each custom object in Salesforce has a limit on the number of custom fields, and this approach quickly eats up some of the limit for
LogEntry__c
. - Reporting. The current fields don't provide a consistent way to report on the data, you effectively have to use different sets of fields to report on each metadata type. This overcomplicates things for teams that want to monitor & report on support issues.
These challenges have created a cycle of new challenges & issues:
- Not Scalable for Both Origin & Exception Metadata Sources The existing metadata-specific fields (like
ApexClassName__c
,FlowActiveVersionId__c
,ComponentApiName__c
, etc) are only for the log entry's origin (i.e., the metadata the generated the log entry). Due to concerns with field limits, there are not equivalent fields for exception details - arguably, it's more important to capture granular details about exceptions (instead of the origin), but the origin fields came first, and exception fields have never been added, which is a big gap in actionable data. - Not Scalable for All Supported Metadata Types The existing metadata-specific fields don't even cover all supported metadata types. Currently, Apex triggers aren't treated the same as the other metadata types. There are no trigger-specific fields, and most of Nebula Logger's codebase assumes "Apex code" == "Apex class". And while I think that triggers shouldn't contain logic (and thus, shouldn't really be doing any logging directly), the reality is that a lot of Salesforce orgs don't follow this best practice, and Nebula Logger should handle Apex triggers as effectively as it does Apex classes.
Future State: Scalable Exception & Origin Fields
To streamline things, this release introduces 2 sets of fields.
- Origin Source fields - details about the source metadata that generated the log entry
- Exception Source fields - details about the source metadata that generated the exception
Each set of fields consists of ~16 fields (about 16 Origin fields, and about 16 Exception fields). These fields are intended to work for all supported metadata types, which helps to simplify reporting, list views, etc.
The older, metadata-specific fields (like ApexClassName__c
, FlowActiveVersionId__c
, ComponentApiName__c
, etc) will continue to be populated & supported for now, though it is likely that they will eventually be deprecated in the future.
LogEntry__c
UI Changes
Overhauled the LogEntry__c
flexipage LogEntryRecordPage
As the number of fields on LogEntry__c
has grown, the complexity of the LogEntryRecordPage
has also grown. This releases adds more tabs to the page's horizontal tab set.
Shifting To Custom LWCs for Nebula Logger's Record Pages
Nebula Logger heavily utilizies App Builder record pages (FlexiPage
metadata) for displaying data in Log__c
, LogEntry__c
, etc - including heavy use of dynamic forms, conditional visibility, and some of the other amazing declarative features. However, there are several new & existing features that would benefit from custom UIs, and this release is the first step in adding new components that will improve the usefulness of the LogEntry__c
page.
In particular, this release introduces a few new components, used to display Apex snippets with PrismJS. Other new components will be introduced over the coming months.
Core Unlocked Package Changes
New LogEntry__c
Lighting Web Components (LWC)
logEntryMetadataViewer
- Added a new component built specifically for theLogEntry__c
object's record page. This LWC
New Helper Lighting Web Components (LWCs)
loggerCodeViewer
- Added a new helper UI component that uses Prism JS to provide some very nice syntax highlighting & line numbers for displaying blocks of JSON and Apex codeloggerPageSection
- Added a new helper UI component that provides a reusable way of implementing the lightning design system's "expandable section" component bluprint to mimic the functionality that the platform uses for native page layout sections
Updated Lighting Web Components (LWCs)
loggerHomeHeader
- Updated to use the new helper LWCloggerPageSection
to provide collapsible page sections in theView Environment Details
modalloggerSettings
- Updated to use the new helper LWCloggerPageSection
to provide collapsible page sections in theNew
/Edit
settings modallogViewer
- Updated to use the new helper LWCloggerCodeViewer
to display theLog__c
record's JSON data
New LogEntryEvent__e
Platform Event Fields
ExceptionLocation__c
ExceptionSourceActionName__c
ExceptionSourceApiName__c
ExceptionSourceMetadataType__c
OriginSourceActionName__c
OriginSourceApiName__c
OriginSourceMetadataType__c
New LogEntry__c
Fields
The 3 permission sets LoggerLogViewer
, and LoggerEndUser
have been updated to have the relevant access to these new fields
- 16 New 'Exception Source' fields
ExceptionLocation__c
- this also includes a custom index, and is equivalent to the existing fieldOriginLocation__c
.ExceptionSourceActionName__c
ExceptionSourceApiName__c
ExceptionSourceApiVersion__c
ExceptionSourceCreatedById__c
ExceptionSourceCreatedByLink__c
ExceptionSourceCreatedByUsername__c
ExceptionSourceCreatedDate__c
ExceptionSourceId__c
ExceptionSourceLastModifiedById__c
ExceptionSourceLastModifiedByLink__c
ExceptionSourceLastModifiedByUsername__c
ExceptionSourceLastModifiedDate__c
ExceptionSourceMetadataType__c
ExceptionSourceSnippet__c
HasExceptionSourceSnippet__c
- 15 New 'Origin Source' fields
OriginSourceActionName__c
OriginSourceApiName__c
OriginSourceApiVersion__c
OriginSourceCreatedById__c
OriginSourceCreatedByLink__c
OriginSourceCreatedByUsername__c
OriginSourceCreatedDate__c
OriginSourceId__c
OriginSourceLastModifiedById__c
OriginSourceLastModifiedByLink__c
OriginSourceLastModifiedByUsername__c
OriginSourceLastModifiedDate__c
OriginSourceMetadataType__c
OriginSourceSnippet__c
HasOriginSourceSnippet__c
New Apex Classes
LoggerStackTrace
- this new class centralizes stack trace parsing for Apex & JavaScript stack traces, and makes it easy to reuse this logic for both the backend & frontendLogEntryMetadataViewerController
- this is a new controller class for the new LWClogEntryMetadataViewer
, used to see code snippets for Apex classes & triggers
Updated Apex Classes
LogEntryEventBuilder
now usesLoggerStackTrace
for Apex stack trace parsingComponentLogger
now usesLoggerStackTrace
for JavaScript stack trace parsingLogManagementDataSelector
- Updated methodgetApexClasses()
to include theBody
field when queryingApexClass
- Added new methodgetApexTriggers()
to queryApexTrigger
dataLogEntryHandler
- Now also uses
LoggerStackTrace
to reconstitute a stack trace string into an instance ofLoggerStackTrace
to help with generating Apex code snippets - Now uses a new
private
inner classSourceMetadataSnippet
to query a snippet of theApexClass
orApexTrigger
source that generated theLogEntry__c
, as well as a snippet of the source that generated theLogEntry__c
record's exception fields (ExceptionType__c
,ExceptionMessage__c
, andExceptionStackTrace__c
)
- Now also uses
New LoggerParameter__mdt
Record
- Also added new
LoggerParameter__mdt
recordQueryApexTriggerData
.- When set to
true
(default), theApexTrigger
object is queried to get additional details about your Apex triggers - When set to
false
, theApexTrigger
will not be queried - any relevant fields onLogEntry__c
will benull
- When set to
New Static Resource LoggerResources
- Added a new zip static resource,
LoggerResources
, that contains the JS & CSS files for PrismJS. If/when other files are needed in future releases, they'll be included in this same static resource.
Installation Info
Core Unlocked Package - no namespace
Full Changelog: v4.13.0...v4.13.1
- SF CLI:
sf package install --wait 20 --security-type AdminsOnly --package 04t5Y000001MkE3QAK
- SFDX CLI:
sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04t5Y000001MkE3QAK
- Sandbox: https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001MkE3QAK
- Production: https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y000001MkE3QAK