Why This Is Useful
If you’ve worked in Salesforce for any length of time you’ll know that debug logs can get genuinely painful.
Salesforce dumps everything into one enormous log. Or worse, if you’ve got Aura and Lightning Web Components on the page, it splits things across a bajillion separate logs and you get to hunt through them. Add a few managed packages and your logs are mostly noise you don’t care about.
Oh, and they’re capped at 20MB, so a busy transaction just gets truncated, usually right where the interesting bit was.
Nebula Logger fixes all of this. It’s an exceptionally well made open source library by Jonathan Gillespie, with substantial contributions from James Simone, and it gives you real logging in Salesforce: structured, queryable, reportable and persistent.
Installing It
Grab the unlocked package from the GitHub repo. Jonathan keeps install links right in the README for both unlocked and managed versions.
An unlocked package means you can look at all the code, which given this is going to sit in the middle of your org is rather nice.
The Basics
public class MyService
{
public void doSomething(Id accountId)
{
Logger.info('Starting work on account', accountId);
try
{
Account acct = [SELECT Id, Name FROM Account WHERE Id = :accountId];
Logger.debug('Found the account: ' + acct.Name);
}
catch (Exception e)
{
Logger.error('Something went wrong', e);
}
//Nothing is written until you call this
Logger.saveLog();
}
}Two things to notice.
Log levels. Logger.error(), warn(), info(), debug(), fine(), finer(), finest(). Now you can filter for errors instead of scrolling past ten thousand lines of noise.Logger.saveLog() is required. Entries are buffered and only committed when you call it. Forget it and nothing is saved, which is the number one “why isn’t this working” with Nebula Logger. Call it once at the end of your transaction, not after every entry.
The Bit That Makes It Genuinely Worth It
You can attach a record straight to a log entry:
Logger.info('Processing this account', myAccount);
Logger.error('Failed to process', myAccount, someException);Now your log entry is related to that record. Which means you can drop a related list on your Account page layout showing every log entry for that Account.
When somebody says “this account isn’t syncing properly,” you open the record and there’s the error. No log hunting, no reproducing the issue, no asking them what time it happened.
That alone is worth the install.
Logs Are Just Records
Everything lands in custom objects (Log__c and LogEntry__c), which means all your normal Salesforce tools work on them:
List<LogEntry__c> recentErrors = [SELECT Id, Message__c, Timestamp__c
FROM LogEntry__c
WHERE LoggingLevel__c = 'ERROR'
AND Timestamp__c = LAST_N_DAYS:7
ORDER BY Timestamp__c DESC];Build reports on your errors. Build a dashboard. Set up a report subscription so you get emailed when error volume spikes. Fire a Flow when a critical error is logged.
You genuinely cannot do any of that with native debug logs.
It Works In LWC Too
import { LightningElement } from 'lwc';
import { createLogger } from 'c/logger';
export default class MyComponent extends LightningElement {
logger = createLogger();
handleError(error) {
this.logger.error('Something broke in the component').setError(error);
this.logger.saveLog();
}
}Your JavaScript errors land in the same place as your Apex errors, correlated by transaction. Which, if you’ve ever tried to trace a bug across the LWC/Apex boundary using browser console logs and separate debug logs, is a genuinely large improvement.
Async Logging
Remember from the async Apex guide that failures in async jobs disappear silently because there’s no user watching? Nebula Logger is the answer to that. Log inside your Queueable and Batch jobs and the failures actually show up somewhere.
It’s also configurable to save via Platform Events rather than DML, which means your logs survive even when the transaction rolls back. That is exactly what you want when you’re trying to work out why something failed, since a normal DML-based log would be rolled back along with everything else.
Two Things To Set Up Properly
1. Configure your logging levels per user. Nebula Logger uses custom settings so you can run at ERROR in production and FINEST for yourself while debugging. Don’t log everything for everyone, you’ll fill your storage.
2. Set up log retention. There’s a built in batch job for purging old logs. Configure it on day one. Logs are records, records consume storage, and unlike native debug logs these don’t clean themselves up.
Full documentation is in the wiki. If you’re running anything meaningful in production, this is one of the highest value things you can install.
Get Coding With The Force Merch!!
We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.
Get Shirts Here!
Get Cups, Artwork, Coffee Cups, Bags, Masks and more here!
Check Out More Coding With The Force Stuff!
If you liked this post make sure to follow us on all our social media outlets to stay as up to date as possible with everything!
Youtube
Patreon
Github
Facebook
Twitter
Instagram
Salesforce Development Books I Recommend
Advanced Apex Programming
Salesforce Lightning Platform Enterprise Architecture
Mastering Salesforce DevOps
Good Non-SF Specific Development Books:
Clean Code
Clean Architecture