# LWC and Apex

Logging across LWC and Apex can be very helpful in both troubleshooting and profiling. The most common scenario is to track your component's UI logs and link these together with Apex action calls on the back end. This approach will allow you to see all LWC and Apex logs under the same transaction.

We'll assume that the start of our user flow originates from a button click (an LWC action) and then continues on the back end in Apex. Our goal is to link together the two types of logs. Let's begin with the LWC side.

## LWC Component

Let's place a button in our component that will start the main execution and logging from a click event.

{% code title="logDemo.html" %}

```javascript
<template>
    ....
    
    <lightning-button 
        variant="brand" 
        label="DML Error" 
        title="DML Error" 
        onclick={handleClick} 
        class="slds-m-left_x-small">
    </lightning-button>
    
    ....
</template>

```

{% endcode %}

## LWC Controller

Now, let's take a look at our LWC controller and create our first log.

{% code title="logDemo.js" lineNumbers="true" %}

```javascript
// Our apex action that will perform some logging
import apexActionThatGeneratesDMLError from '@salesforce/apex/LogDemoController.apexActionThatGeneratesDMLError';
// Triton logger component
import Triton, { AREA, TYPE } from 'c/triton';

export default class LogDemo extends LightningElement {
    triton;
    startTime;
    
    connectedCallback() {
        this.triton = new Triton();
    }
    
    handleClick() {
        this.startTime = performance.now();
        this.executeScenario();
    }
    
    async executeScenario() {
        // Log the start of our execution
        await this.triton.logNow(
            this.triton.debug(TYPE.FRONTEND, AREA.ACCOUNTS)
                .summary('LWC action (from js) - DML Error')
                .details('LWC action (from js) - DML Error - Execution Start')
                .duration(performance.now() - this.startTime)
        );

        try {
            // Invoke our Apex action passing in the transaction Id 
            // for the apex controller to re-use
            await apexActionThatGeneratesDMLError({
                transactionId: this.triton.transactionId
            });
        } catch (error) {
            // Log this exception
            await this.triton.logNow(this.triton.exception(error));
        }
    }
}    
```

{% endcode %}

The `executeScenario()` method above will generate two LWC logs: one debug and one error log (if the Apex action fails). Note that we are passing our generated transaction Id back to the Apex controller to use for back-end logging.

## Apex Controller

Next, let's look at our Apex controller. The action that we're calling from LWC is also doing some debug and error logging with the provided transaction Id.

{% code title="LogDemoController.cls" lineNumbers="true" %}

```apex
public with sharing class LogDemoController {

//this method will use our logger to create a new transaction Id
@AuraEnabled
public static String getTransactionId() {
	return Triton.instance.startTransaction();
}

@AuraEnabled
public static void apexActionThatGeneratesDMLError(String transactionId) {
	//letting our logger know to re-use an existing transaction Id
	Triton.instance.resumeTransaction(transactionId);
	Triton.instance.debug(TritonTypes.Type.Backend, /* type */
			TritonTypes.Area.Community, /* functional area */
			'LWC controller (apex) - DML Error', /* summary */
			'LWC controller (apex) - DML Error - Apex Execution Start' /* details */
	);
	
	try {
		ContentVersion contentVersion = new ContentVersion();
		contentVersion.ContentLocation = 'Apex Error';
		contentVersion.Title = 'Apex Error';
		contentVersion.PathOnClient = 'ApexError.pdf';
		//this insert statement will generate a DMLException
		insert contentVersion;
	} catch (Exception e) {
		//let's log this exception
		Triton.instance.error(TritonTypes.Area.Community, e);
	}
}
....

}
```

{% endcode %}

Similar to our LWC controller, executing this action will result in a debug and an error log created.

## The Result

Altogether, both LWC and Apex executions will generate the following log structure in a single transaction:

* Parent LWC **Debug** Log from `executeScenario()`
  1. Child Apex **Debug** Log from our `apexActionThatGeneratesDMLError()` action
  2. Child Apex **Error** Log from our try/catch block inside the Apex action
  3. Child LWC **Error** Log from the LWC error handler (if an error occurs)

{% hint style="info" %}
All logs within the same transaction are automatically linked together using the transaction ID. The transaction management is handled automatically by the Triton framework, including caching and auto-flushing of logs.
{% endhint %}

While this example demonstrates passing the transaction ID directly through method parameters, there's another powerful approach using Salesforce Platform Cache. This alternative method is particularly useful for complex scenarios involving multiple components or when direct parameter passing isn't practical. We'll explore platform caching in detail in the next article.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://triton.pharos.ai/pharos-triton/beyond-apex/lwc-and-apex.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
