Buffering & Flushing
Smart strategies for buffering and flushing logs in Triton for optimal performance and reliability across Apex and LWC.
Understanding Buffering vs Flushing
Apex:
addLog(builder)buffers.log(builder)flushes immediately (use at key boundaries or errors).Triton sets stack trace & operation automatically when missing, and appends governor limit info via the builder.
LWC:
triton.log(builder)buffers in memory.triton.logNow(builder)flushes that one immediately.Triton's LWC TransactionManager auto-flushes after idle periods; still flush on navigation/unload when practical.
Real-World Example: Financial Transaction Processing
public class PaymentProcessor {
public static void processPayment(Id accountId, Decimal amount) {
Long startTime = System.now().getTime();
// Set up template for all payment processing logs
Triton.instance.setTemplate(
Triton.makeBuilder()
.category(TritonTypes.Category.Integration)
.type(TritonTypes.Type.Backend)
.area(TritonTypes.Area.PaymentProcessing)
.relatedObject(accountId)
);
// Buffer routine operations using template
Triton.instance.addLog(
Triton.instance.fromTemplate()
.level(TritonTypes.Level.DEBUG)
.summary('Payment processing started')
.details('accountId=' + accountId + ', amount=' + amount)
);
try {
// First, make the callout to payment gateway
HttpRequest req = new HttpRequest();
req.setEndpoint('https://api.paymentgateway.com/process');
req.setMethod('POST');
req.setHeader('Content-Type', 'application/json');
req.setBody(JSON.serialize(new Map<String, Object>{
'accountId' => accountId,
'amount' => amount,
'currency' => 'USD'
}));
HttpResponse response = new Http().send(req);
if (response.getStatusCode() == 200) {
// Parse successful response
Map<String, Object> responseData = (Map<String, Object>)JSON.deserializeUntyped(response.getBody());
// Now perform DML after successful callout
Payment__c payment = new Payment__c(
Account__c = accountId,
Amount__c = amount,
Status__c = 'Completed'
);
insert payment;
// Buffer success milestone using template
Triton.instance.addLog(
Triton.instance.fromTemplate()
.level(TritonTypes.Level.INFO)
.summary('Payment processed successfully')
.details('paymentId=' + payment.Id)
.relatedObject(payment.Id)
.integrationPayload(req, response)
.duration(System.now().getTime() - startTime)
);
} else {
// Immediately flush critical error using template
Triton.instance.log(
Triton.instance.fromTemplate()
.exception(new PaymentException('Gateway error: ' + response.getStatusCode()))
.summary('Payment gateway failed')
.integrationPayload(req, response)
);
}
} catch (Exception e) {
// Immediately flush critical errors using template
Triton.instance.log(
Triton.instance.fromTemplate()
.exception(e)
.summary('Payment processing failed')
);
throw e;
} finally {
// Flush all buffered logs at transaction boundary
Triton.instance.flush();
}
}
}LWC Buffering Example
When to Buffer vs Flush
Buffer When:
Routine operations: Normal processing steps, debug information
High-volume scenarios: Processing multiple records in loops
Performance-critical paths: Where logging overhead must be minimized
Non-critical information: Debug logs, informational milestones
Flush Immediately When:
Critical errors: Exceptions that might prevent further processing
Transaction boundaries: End of methods, batch chunks, queueable completion
User-facing failures: Errors that affect user experience
Integration failures: Callout errors, external service issues
Component teardown: LWC component destruction
Performance Considerations
Apex Performance
Buffering reduces DML: Multiple logs are sent together, reducing platform event overhead
Flush strategically: Use
flush()at natural boundaries to avoid memory buildupError scenarios: Always flush on errors to ensure critical information is captured
Governor limits: Monitor platform event limits in high-volume scenarios
LWC Performance
Memory management: Buffered logs consume memory until flushed
Auto-flush: Triton automatically flushes after idle periods
Navigation events: Flush on page navigation or component destruction
Error handling: Use
logNow()for critical errors to ensure immediate capture
Best Practices
Buffer Management
Set clear boundaries: Define when to flush based on logical transaction boundaries
Monitor memory usage: Be aware of buffered log volume in long-running processes
Error handling: Always flush on exceptions to preserve critical context
Performance testing: Measure the impact of buffering vs immediate flushing
Flush Strategies
Method boundaries: Flush at the end of public methods
Batch operations: Flush after each batch chunk
Queueable completion: Flush at the end of queueable execution
Component lifecycle: Flush in LWC
disconnectedCallback()Error scenarios: Immediate flush for all exceptions
Monitoring and Debugging
Log volume: Monitor the number of buffered vs flushed logs
Memory usage: Track memory consumption in long-running processes
Error correlation: Ensure errors are properly flushed for debugging
Performance impact: Measure the overhead of different buffering strategies
Advanced Patterns
Conditional Flushing
Smart Buffering with Limits
By mastering buffering and flushing strategies, you'll optimize performance while ensuring critical logs are never lost and debugging information is always available when needed.
Last updated