LWC
In this article we'll take a look at logging in LWC components and familiarize ourselves with Triton's JS interface.
LWC is a powerful UI framework in use today by organizations of all sizes. LWC provides a wealth of capabilities that extend the platform's user interface and allow developers to create rich visual experiences. However, with great power comes complexity.
It's quite common for LWC-based interfaces to become large and complex. At that point, one needs a little something to help manage the expanding functionality without loosing sanity. As you may have guessed, this is yet another area to leverage Pharos Triton. Let's first examine the basics.
Component Binding
When initializing Triton in an LWC component, it's crucial to use the bindToComponent()
method. This method creates a component-specific context for logging that enables:
Component Identification: Each log entry is automatically tagged with the component that generated it
Template Management: Component-specific log templates are properly scoped and managed
Stack Trace Accuracy: Error traces and component details are correctly captured
Here's the proper way to bind Triton to your component:
The bindToComponent()
argument should be a unique identifier for your component, typically matching the component's name. This binding ensures that when debugging issues in production, you can easily trace logs back to their source component.
Always use bindToComponent()
when initializing Triton. Without it, you'll lose important component context in your logs and template functionality won't work correctly.
Creating an LWC Logger
The good news is that getting a hold of the Triton logger in LWC is quite easy. The logger component is called triton. To access its capabilities, simply include it in your controller class. The initialization timing depends on whether your component uses @wire methods:
Components Without @wire
For components without @wire decorators, initialize Triton in the connectedCallback() method. This is safe because connectedCallback is one of the first lifecycle hooks that fires when a component is added to the DOM, and without @wire decorators, there's no risk of missing early data or error events:
Components With @wire
When using @wire decorators, we need to be more careful about initialization timing. The Lightning Web Component lifecycle follows this sequence:
Constructor runs
@wire decorators are initialized and begin fetching data
connectedCallback executes
Component renders
This means that if we initialize Triton in connectedCallback, we might miss important wire-related events that occur between steps 2 and 3. Therefore, for components with @wire decorators, we initialize in the constructor.
Inside Triton.js
The LWC version of Triton implements a robust logging system with transaction management and automatic log flushing. The logger provides different logging levels (error, warning, info, debug) and uses a builder pattern for constructing logs with rich context.
Each log can include details such as:
Transaction ID for tracking related logs
User ID and timestamp
Component stack traces
Runtime information (browser, device, performance metrics)
Summary and detailed information
The logger automatically manages log buffering and flushing to the server, with an auto-flush mechanism that triggers after a period of inactivity.
TritonBuilder Pattern
Triton uses a builder pattern that allows for fluent, chainable logging statements. Each logging method (error, warning, info, debug) returns a builder instance that you can use to add additional context to your log:
The builder captures rich contextual information automatically, including:
Component details and stack traces
Runtime information (browser, device, etc.)
Transaction IDs
Timestamps
User context
Each builder method is chainable, allowing you to construct logs with as much or as little detail as needed:
Component-Specific Templates
Triton provides a powerful templating system that allows you to define logging templates specific to each component. When you use bindToComponent()
, Triton ensures that templates are properly scoped to your component through method proxying.
Setting Up Templates
You can define templates with common properties that you'll reuse across your component:
Using Templates
Once defined, you can use the template as a base for your logs, adding only the specific details that change:
This templating system is particularly valuable when:
Your component generates many similar logs
You want to ensure consistent logging patterns
You need to maintain common context across all component logs
You want to reduce repetitive logging code
Buffered vs Immediate Logging
Triton provides two methods for sending logs to the server:
log()
: Buffers the log entry for later sending. Multiple logs will be sent together during periodic flush operations or when explicitly flushed. This is more efficient for high-volume logging.logNow()
: Immediately sends the log entry to the server. This is useful for critical errors or when immediate logging feedback is required. Returns a Promise that resolves when the log is saved.
For example:
Real-World Logging Scenario
Consider a complex account management interface where users can perform multiple operations:
In this scenario:
Debug and success logs are buffered because they're routine and non-critical
Error logs are sent immediately because:
They need to be available right away for troubleshooting
The error might prevent subsequent operations from completing
Support teams can respond in real-time to mission-critical failures
The error context is preserved even if the component crashes
Time-sensitive operations can trigger immediate support intervention
This immediate logging pattern is particularly valuable in scenarios like financial transactions, healthcare operations, or other mission-critical processes where real-time monitoring and rapid response are essential.
Advanced Wire Patterns with Logging
When working with wired properties in LWC, there's a powerful pattern that combines programmatic refresh capabilities with logging. This involves wiring the same Apex method to two different properties:
This pattern serves two important purposes:
Programmatic Refresh: The
wiredOrderItems
property provides a reference that can be used to programmatically refresh the data usingrefreshApex(this.wiredOrderItems)
.Automatic Logging: The second wire decorator with the callback function handles data processing and automatically logs both successful retrievals and errors.
This approach is particularly useful when you need to:
Track all data loading attempts, both automatic and manual refreshes
Maintain a detailed audit trail of data operations
Debug intermittent loading issues
Monitor performance patterns in data retrieval
Now that we've covered some basics, let's have a look at a more interesting example and combine the LWC logger with its Apex counterpart.
Last updated