Skip to content

Logging Examples

See specifications for logging on the Logger Reference page and Log Reference page.

Basic Logging

public class SpaceshipController {
    private static ok.Logger logger = ok.Logger.getLogger(SpaceshipController.class);
    private Spaceship__c spaceship;

    public Boolean prepareForHyperspaceJump() {
        Id pilotId = UserInfo.getUserId();
        Boolean isAuthorized = isHyperspaceJumpAuthorized(pilotId);
        if (!isAuthorized) {
            // WARNING log.
            logger.warn().linkSObject(spaceship).linkSObject2(pilotId).log('Pilot is not authorized.');
            return false;
        }
        // INFO log.
        logger.info().addPayloadJson(spaceship.getEngineStatus()).log('Hyperspace jump is ready.');
        return true;
    }
}

Exception Handling

public void safeOperation() {
    try {
        unsafeOperation();
    } catch (Exception e) {
        logger.error().addException(e).log('Unexpected error happened.');
    }
}

Add Payload

// String payload example:
Datetime now = Datetime.now();
logger.info().addPayload(now).log('String payload.');

// Serialized payload example:
public class Person {
    public String firstName;
    public String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

Person anakin = new Person('Anakin',  'Skywalker');
logger.info().addPayloadJson(anakin).log('Apex object serialized.');

Logging from a Batch Apex

Batch job methods are top level Apex methods and should implement the try-catch-finally-publish pattern.

See Async Job Logging.

public class Order66 implements Database.Batchable<SObject> {
    private static ok.Logger logger = ok.Logger.getLogger(Order66.class);

    public void execute(Database.BatchableContext context, List<SObject> scope) {
        try {
            // Set the context of the batch.
            // All the logs within this method will have their batch fields populated.
            ok.Logger.setBatchableContext(context);
            // Next is your implementation of the batchable job.
            someOperation();
        } catch (Exception e) {
            loggr.error().addException(e).log('Batch failed.');
        } finally {
            ok.Logger.publish();
        }
    }
}

Logging from a Schedulable Apex

Schedulable job method is a top level Apex method and should implement the try-catch-finally-publish pattern.

See Async Job Logging.

public class Order66 implements SchedulableContext {
    private static ok.Logger logger = ok.Logger.getLogger(Order66.class);

    public void execute(SchedulableContext context) {
        try {
            // Set the context of the schedulable job.
            // All the logs within this method will have their batch fields populated.
            ok.Logger.setSchedulableContext(context);
            // Next is your implementation of the schedulable job.
            someOperation();
        } catch (Exception e) {
            loggr.error().addException(e).log('Scheduled job failed.');
        } finally {
            ok.Logger.publish();
        }
    }
}

HTTP Callout

HttpRequest req = new HttpRequest();
logger.fine().addHttpRequest(req).log('HTTP request.');

HttpResponse resp = new Http().send(req);
if (resp.getStatusCode() != 200) {
    logger.error().addHttpCallout(req, resp).log('HTTP request failed.');
}

Apex REST

@RestResource(UrlMapping='/spaceship/*')
global with sharing class SpaceshipRestResource {
    private static ok.Logger logger = ok.Logger.getLogger(SpaceshipRestResource.class);

    @HttpGet
    global static String doGet() {
        try {
            logger.info().addRestRequest(RestContext.request).log('GET received.');
            someOperation();
            return 'ok';
        } catch (Exception e) {
            logger.error().addRestRequest(RestContext.request).log('GET handler error.');
            return 'err';
        } finally {
            ok.Logger.publish();
        }
    }

    // Serializable='always' enables the logger to serialize the data and include it in the log.
    @JsonAccess(Serializable='always')
    global class SpaceshipDto {
        global String name;
    }

    @HttpPost
    global static void doPost(SpaceshipDto spaceship) {
        RestResponse resp = new RestResponse();
        RestContext.response = resp;
        try {
            someOperation(spaceship);
            resp.statusCode = 200;
            resp.responseBody = Blob.valueOf('ok');
            logger.info().addRestRequest(RestContext.request, spaceship).addRestResponse(resp, resp.responseBody).log('POST handled.');
        } catch (Exception e) {
            resp.statusCode = 500;
            resp.responseBody = Blob.valueOf('err');
            logger.error().addRestRequest(RestContext.request, spaceship).addRestResponse(resp, resp.responseBody).log('POST handler error.');
        } finally {
            ok.Logger.publish();
        }
    }
}

Outbound Emails

Messaging.Email email;
logger.info().addEmail(email).log('Outbound email.');

List<Messaging.Email> emails;
logger.info().addEmails(emails).log('Outbound emails.');

Inbound Emails

Messaging.InboundEmail email;
Messaging.InboundEnvelope envelope;
logger.info().addInboundEmail(email, envelope).log('Inbound emails.');

Tagging

logger.info().addTag('sales').log('Tagged log');

Masking Secrets

String secret = 'super-private-key';
logger.info().addPayload(secret).hideSecret(secret).log('Sensitive data.');
// ok__Payload__c = '****'