Templates & the Builder Pattern
Leveraging templates and the builder pattern for consistent, maintainable Triton logging across Apex and LWC.
Why Templates Matter
Always prefer
TritonBuilder
+ template cloning over convenience helpers.Why: Templates standardize category, type, area, base details, and reduce copy/paste drift.
Apex β Set & Reuse a Template
// Early in the transaction (e.g., controller entry, batch start)
Triton.instance.setTemplate(
Triton.makeBuilder()
.category(TritonTypes.Category.Apex)
.level(TritonTypes.Level.DEBUG)
.type(TritonTypes.Type.Backend)
.area(TritonTypes.Area.OpportunityManagement) // agreed taxonomy
);
// Later: clone and specialize
Triton.instance.log(
Triton.instance.fromTemplate()
.level(TritonTypes.Level.INFO)
.summary('Opportunity sync started')
.details('seed=nightly, source=ERP')
);
LWC β Component-Scoped Template
import Triton, { LEVEL, TYPE, AREA } from 'c/triton';
const triton = new Triton().bindToComponent('c-opp-sync'); // scopes component details
triton.setTemplate(
triton.makeBuilder()
.type(TYPE.FRONTEND)
.area(AREA.OPPORTUNITY_MANAGEMENT)
);
// Usage later:
triton.log(
triton.fromTemplate()
.summary('Button clicked')
.details('action=sync-all')
);
Real-World Example: Customer Service Portal
// Customer service LWC component with comprehensive template
export default class CustomerServicePortal extends LightningElement {
triton;
connectedCallback() {
this.triton = new Triton().bindToComponent('c-customer-service-portal');
// Set comprehensive template for all customer service operations
this.triton.setTemplate(
this.triton.makeBuilder()
.type(TYPE.FRONTEND)
.area(AREA.COMMUNITY)
.level(LEVEL.INFO)
.relatedObjects([this.recordId])
);
}
async handleCaseCreation() {
try {
const result = await createCase({ caseData: this.caseForm });
// Uses template, adds specific details
this.triton.log(
this.triton.fromTemplate()
.summary('Case created successfully')
.details(JSON.stringify({
caseId: result.Id,
priority: this.caseForm.priority,
category: this.caseForm.category
}))
.relatedObjects([result.Id])
);
} catch (error) {
// Template properties preserved in error logs
this.triton.logNow(
this.triton.fromTemplate()
.exception(error)
.summary('Case creation failed')
);
}
}
}
Template Benefits
Consistency
All logs in a method/component share the same base properties
Reduces the risk of inconsistent categorization
Ensures proper context across all log entries
Maintainability
Changes to common properties only need to be made in one place
Reduces code duplication and drift
Makes updates and refactoring easier
Reduced Errors
No risk of forgetting to set important properties
Template ensures all required fields are populated
Consistent structure across all logging calls
Performance
Template cloning is efficient
Reduces object creation overhead
Maintains singleton pattern benefits
Template Override Pattern
Show how to override template properties when needed:
// Template sets common properties
Triton.instance.setTemplate(
Triton.makeBuilder()
.category(TritonTypes.Category.Apex)
.type(TritonTypes.Type.Backend)
.area(TritonTypes.Area.Accounts)
.relatedObject(accountId)
);
// Override specific properties as needed
Triton.instance.log(
Triton.instance.fromTemplate()
.level(TritonTypes.Level.INFO) // Override level
.summary('Account processed') // Add specific summary
.details('status=completed') // Add specific details
.duration(processingTime) // Add duration
.relatedObjects(new Set<Id>{contactId}) // Override related objects
);
Best Practices
Do's
β Clone from
fromTemplate()
to get a pre-filled builder and add specificsβ Set templates early in methods/components
β Use templates for all logging calls within a scope
β Override only what's specific to each log entry
Don'ts
β Call
addEvent/addDebug
directly in new codeβ Use
makeBuilder()
for every log entryβ Forget to set templates in new methods
β Override template properties unnecessarily
Template Scoping
Method-Level Templates
public void processAccount(Id accountId) {
// Set template for this method
Triton.instance.setTemplate(
Triton.makeBuilder()
.category(TritonTypes.Category.Apex)
.type(TritonTypes.Type.Backend)
.area(TritonTypes.Area.Accounts)
.relatedObject(accountId)
);
// All logs in this method use the template
Triton.instance.log(Triton.instance.fromTemplate().summary('Processing started'));
// ... processing logic ...
Triton.instance.log(Triton.instance.fromTemplate().summary('Processing completed'));
}
Component-Level Templates
export default class AccountManager extends LightningElement {
triton;
connectedCallback() {
this.triton = new Triton().bindToComponent('c-account-manager');
// Set template for entire component
this.triton.setTemplate(
this.triton.makeBuilder()
.type(TYPE.FRONTEND)
.area(AREA.ACCOUNTS)
.relatedObjects([this.recordId])
);
}
// All methods in this component can use the template
async handleSave() {
this.triton.log(this.triton.fromTemplate().summary('Save initiated'));
// ... save logic ...
}
async handleDelete() {
this.triton.log(this.triton.fromTemplate().summary('Delete initiated'));
// ... delete logic ...
}
}
Advanced Template Patterns
Conditional Template Properties
// Set base template
Triton.instance.setTemplate(
Triton.makeBuilder()
.category(TritonTypes.Category.Apex)
.type(TritonTypes.Type.Backend)
.area(TritonTypes.Area.Accounts)
);
// Add conditional properties
if (isHighPriority) {
Triton.instance.log(
Triton.instance.fromTemplate()
.level(TritonTypes.Level.WARNING)
.summary('High priority account processed')
);
} else {
Triton.instance.log(
Triton.instance.fromTemplate()
.level(TritonTypes.Level.INFO)
.summary('Standard account processed')
);
}
Template Inheritance
// Base template for all account operations
Triton.instance.setTemplate(
Triton.makeBuilder()
.category(TritonTypes.Category.Apex)
.type(TritonTypes.Type.Backend)
.area(TritonTypes.Area.Accounts)
);
// Specialize for specific operations
public void processHighValueAccount(Id accountId) {
// Override template for this specific operation
Triton.instance.setTemplate(
Triton.instance.fromTemplate()
.level(TritonTypes.Level.WARNING)
.relatedObject(accountId)
);
// All logs in this method inherit the specialized template
Triton.instance.log(Triton.instance.fromTemplate().summary('High value processing started'));
}
By mastering the template pattern, you'll create logging code that is consistent, maintainable, and efficient while providing rich context for all your log entries.
Last updated