Nebula Logger

repository·main·Indexed 21 days ago

https://github.com/jongpie/nebulalogger

A robust, 100% native observability solution for Salesforce providing a unified logging framework across Apex, Lightning, Flow, and OmniStudio. Version 4.18.4 includes an event-driven architecture and supports various plugins such as Async Failure Additions for enhanced error logging, Big Object Archiving for high-volume storage, Log Retention Rules for configurable data lifecycles, and Slack integration.

Tokens
57.5K
Snippets
163
Records
299
Agent score
74%

What's inside nebula-logger

  1. Overview of Nebula Logger features

    main

    Nebula Logger is a native Salesforce observability solution that uses an event-driven pub/sub architecture via the LogEntryEvent__e platform event.

    Key Capabilities:

    • Multi-Platform Logging: Supports Apex (classes, triggers, anonymous), Lightning Components (LWC & Aura), Flow & Process Builder (via invocable actions), and OmniStudio (Omniscripts & Integration Procedures).
    • Data Storage: Logs are stored in five custom objects: Log__c, LogEntry__c, LogEntryTag__c, LoggerTag__c, and LoggerScenario__c.
    • Security & Configuration: Includes automatic data masking via LogEntryDataMaskRule__mdt and customizable logging settings per user/profile using LoggerSettings__c.
    • UI Integration: View related logs on any Lightning record page using the relatedLogEntries LWC component.
    • Extensibility: Features a built-in plugin framework (available in Unlocked Package) to automate actions on log objects using Apex or Flow triggers.
  2. Access different cache levels via LoggerCache

    main

    Nebula Logger provides three singleton instances of Cacheable to handle different data lifecycles:

    1. Organization Cache: Uses Salesforce Platform Cache for organization-wide caching. If Platform Cache is unavailable, it falls back to the transaction cache.
    2. Session Cache: Uses Salesforce Platform Cache for session-specific caching. If Platform Cache is unavailable, it falls back to the transaction cache.
    3. Transaction Cache: Stores data in-memory for the duration of the current transaction only. This is used when Platform Cache is unavailable or when explicit transaction-level scoping is required.
    Cacheable orgCache = LoggerCache.getOrganizationCache();
    Cacheable sessionCache = LoggerCache.getSessionCache();
    Cacheable transCache = LoggerCache.getTransactionCache();
  3. Relate logs in Batchable and Queueable jobs

    main

    Since asynchronous jobs (Batchable, Queueable) run in separate transactions with unique transaction IDs, you can use Logger.setParentLogTransactionId(String) to link them to an original transaction. This populates the Log__c.ParentLog__c field, allowing you to trace the entire execution chain.

    Pattern for Batchable:

    1. In start(), capture the original ID using Logger.getTransactionId().
    2. In execute() and finish(), pass that ID to Logger.setParentLogTransactionId() before logging.
    public with sharing class BatchableLoggerExample implements Database.Batchable<SObject>, Database.Stateful {
      private String originalTransactionId;
    
      public Database.Queryable start(Database.BatchableContext batchableContext) {
        this.originalTransactionId = Logger.getTransactionId();
        Logger.info('Starting BatchableLoggerExample');
        Logger.saveLog();
        return Database.getQueryLocator([SELECT Id FROM Account]);
      }
    
      public void execute(Database.BatchableContext batchableContext, List<Account> scope) {
        Logger.setParentLogTransactionId(this.originalTransactionId);
        for (Account account : scope) {
          Logger.info('Processed an account record', account);
        }
        Logger.saveLog();
      }
    
      public void finish(Database.BatchableContext batchableContext) {
        Logger.setParentLogTransactionId(this.originalTransactionId);
        Logger.info('Finishing running BatchableLoggerExample');
        Logger.saveLog();
      }
    }
  4. Understand LoggerSettingsController.SettingsRecordResult

    main

    The SettingsRecordResult inner class is a wrapper used to return LoggerSettings__c records in a way that facilitates reliable sorting and display in the UI.

    It solves several issues encountered when querying setup owners directly in SOQL, such as inconsistent naming for Profiles (e.g., 'PT1' instead of the actual name) or unhelpful type identifiers (e.g., '00D' for Org or '00e' for Profiles).

    Properties:

    • record: The actual LoggerSettings__c record.
    • setupOwnerName: The human-readable name of the Profile or User.
    • setupOwnerType: The type of the owner.
    • createdByUsername: The username of the record creator.
    • lastModifiedByUsername: The username of the last modifier.
  5. Log from Salesforce Flows

    main

    Nebula Logger provides specialized classes to handle logging within Flow and Process Builder. Depending on your requirement, use one of the following:

    • FlowLogger: Handles common logic shared across flow logging components.
    • FlowRecordLogEntry: Use this to add a new log entry for a specific SObject record.
    • FlowCollectionLogEntry: Use this to add new log entries for a collection of SObject records.
    • FlowLogEntry: Use this for general log entries in Flow.
  6. Integrate Nebula Logger via CallableLogger

    main
    The CallableLogger class implements the System.Callable interface. This allows for a loosely-coupled integration with Nebula Logger, which is particularly useful for ISVs and package developers who want to provide optional logging support without direct dependencies. It also enables logging within OmniStudio's OmniScripts and Integration Procedures.
  7. Configure Nebula Logger via LoggerParameter custom metadata

    main

    Nebula Logger's behavior is centrally controlled through the LoggerParameter class, which loads settings from LoggerParameter_t custom metadata records. You can modify these settings to enable/disable features, change data storage strategies, or optimize performance.

    Common configuration categories include:

    • Data Storage: Control whether to use custom objects (e.g., LoggerTag__c) or standard fields (e.g., LogEntry__c.Tags__c) via NORMALIZE_TAG_DATA and NORMALIZE_SCENARIO_DATA.
    • Querying & Performance: Enable or disable querying of specific Salesforce schemas (e.g., QUERY_USER_DATA, QUERY_ORGANIZATION_DATA) and control whether these queries happen synchronously or asynchronously.
    • Stack Traces: Enable parsing via ENABLE_STACK_TRACE_PARSING and filter out specific utility classes using IGNORED_APEX_ORIGINS.
    • Limits & Metadata: Toggle storage of transaction limits (STORE_TRANSACTION_LIMITS), organization limits (STORE_ORGANIZATION_LIMITS), or HTTP/REST header values.
    • Platform Cache: Enable the use of Platform Cache via USE_PLATFORM_CACHE to optimize organization and session data retrieval.
  8. Optimize CPU usage with LogMessage

    main

    The LogMessage class allows for deferred string formatting. When using Logger.fine() or other low-level logging, passing a LogMessage object ensures that String.format() is only executed if the specified logging level is actually enabled for the user. This prevents unnecessary CPU consumption in production environments where verbose logging is disabled.

    // Efficient: String.format() is only called if FINE level is enabled
    LogMessage logMessage = new LogMessage('my example with input: {0}', 'myString');
    Logger.fine(logMessage);
    
    // Complex string building
    String unformattedMessage = 'my string with 3 inputs: {0} and then {1} and finally {2}';
    String formattedMessage = new LogMessage(unformattedMessage, 'something', 'something else', 'one more').getMessage();
  9. Compare Tagging Modes: Custom Objects vs. Salesforce Topics

    main

    Nebula Logger supports two modes for storing tags. Note that the Salesforce Topics mode is not available in the managed package.

    1. Logger's Custom Tagging Objects (Default)

    This mode uses custom objects to manage tags and is available in both unlocked and managed packages.

    • Data Model: Uses LoggerTag__c (the unique tag name) and LogEntryTag__c (a junction object between the tag and the log entry).
    • Visibility: Controlled via standard Salesforce sharing (OWD, sharing rules, etc.). By default, LoggerTag__c is 'public read-only' for internal users.
    • Capabilities: Supports all standard platform features like custom list views, reports, dashboards, Chatter feeds, and activities.

    2. Salesforce Topic and TopicAssignment Objects

    This mode leverages native Chatter functionality.

    • Data Model: Uses the standard Topic object and the TopicAssignment junction object.
    • Visibility: Topic records are visible to all Chatter users. TopicAssignment records are only visible to users with access to the related EntityId (the LogEntry__c).
    • Capabilities: Allows using Topics to filter list views. However, using Topics in reports and dashboards is only partially implemented by Salesforce.
  10. Understand the Prism.js static resource files

    main

    Nebula Logger uses Prism.js for syntax highlighting. The static resources are provided in two formats: unminified (for debugging and version control) and minified (for Salesforce deployment).

    FilePurpose
    prism.jsUnminified source - readable, used for debugging
    prism.cssUnminified source - readable, used for debugging
    prism.min.jsMinified - this is what Salesforce deploys
    prism.min.cssMinified - this is what Salesforce deploys
    prism.nebula-logger.cssUnminified - project-specific overrides for Nebula Logger

    Important Notes:

    • Do not edit .min files manually; they are automatically generated.
    • Edit prism.nebula-logger.css directly; it contains project-specific overrides for Nebula Logger and is always deployed to Salesforce. It is not generated by scripts.