# Debug PWA Kit Apps

Bugs and performance bottlenecks are an unavoidable part of web app development. With PWA Kit, you can get to the bottom of these issues with a variety of tools and techniques for examining your app up close.

Replace any placeholders in this guide with actual values. Placeholders are formatted like this: `$PLACEHOLDER`.

## General Troubleshooting

Before you follow the more targeted advice in this guide, try these general troubleshooting steps first:

- Double-check that you’re running a supported version of Node (refer to the [Get Started](/docs/commerce/b2c-commerce/guide/getting-started.md) guide) before starting your local development server.
- Confirm that your development server is still running and the port hasn’t been taken over by another process.
- After a code change, confirm that the message `HTTP development server listening` appears in the terminal before reloading your browser.
- Look for errors in both the browser console and in the terminal.
- Look for network error responses using your browser’s developer tools. (In Chrome’s DevTools, go to the **Network** tab.)
- To help identify syntax errors and typos, run a code formatter and a linter. Configuration files are provided for both [Prettier](https://prettier.io/) (code formatter) and [ESLint](https://eslint.org/) (linter) in the Retail React App.
- Check your computer’s antivirus and firewall settings for anything that is preventing your code from running or blocking network requests.
- To identify and analyze performance issues, use the Profiler in Chrome’s DevTools. For more information, see this guide from Google: [Analyze Runtime Performance](https://developer.chrome.com/docs/devtools/evaluate-performance/). You can also install the React Developer Tools extension for Chrome to get another Profiler tab where you can see similar info but at the component level.

## Query Parameters for Debugging

There are two special query parameters that you can add to any URL served by your commerce app to help debug issues with server-side code.

### `__server_only`

The `__server_only` query parameter stops the [hydration](https://en.wikipedia.org/wiki/Hydration_\(web_development\)) process so that the page appears in your browser exactly as it does after server-side rendering. Seeing the server-side rendered version of the page helps troubleshoot issues not only with server-side rendering, but also with SEO since search engines crawl this version of the page.

### `__pretty_print`

The `__pretty_print` query parameter adds formatting to the `__PRELOADED_STATE__` object to make it more readable. This object provides a snapshot into your app’s state before hydration begins, so it can be helpful for debugging to see if it contains the values that you expect. To view the contents of the object, load your app, view the source of the page, and search for `__PRELOADED_STATE__`.

The `__PRELOADED_STATE__` object is included in a \<script> tag within the HTML source of the page that was initially requested when your app begins running on the server side. The `__PRELOADED_STATE__` object contains serialized values returned from the `getProps` function (including the versions of `getProps` that are attached to the `_app` component and the page component).

### `__server_timing`

This feature is generally available from PWA Kit version 3.7.

The `__server_timing` query parameter provides detailed performance metrics for various stages of the rendering process with the HTTP [Server-Timing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing) header. This feature allows you to gain insights into the performance characteristics of your applications, helping in optimization and troubleshooting. When the `__server_timing` query parameter is present, the Server-Timing HTTP response header will be available, providing performance metrics. Performance metrics logs are also available in [Log Center](#debug-using-log-center).

#### Track Performance Metrics in Real-Time

To track the current performance on your site:

1. Run `npm start`.
2. Go to `http://localhost:3000?__server_timing`. Or go to any local URL for a page on your site and add the `__server_timing`query parameter to the URL.
3. Check the network responses using your browser’s developer tools. (In Chrome’s DevTools, go to the Network tab.)
4. Check the `Server-Timing` HTTP response header.

#### Performance Metrics

These metrics are included in the Server-Timing header. Each metric helps you understand specific aspects of the server-side rendering (SSR) process:

- `ssr.route-matching`: Measures the time taken to match an incoming request to a specific route. It is crucial for evaluating if the route configuration file (route.js) is optimally structured. Typically, this metric should be less than a few milliseconds.

- `ssr.load-component`: Represents the time required to load components on demand at the page level. Generally, this metric should also be less than a few milliseconds.

- `ssr.fetch-strategies`: Indicates how long in total your fetch strategy takes to complete.

- `ssr.fetch-strategies.get-props.<page-name>`: Time taken by the getProps function for execution, where `<page-name>` is either the `App` component or the page. This is only applicable when the `useLegacyGetProps` higher-order component (HOC) is used.

- `ssr.fetch-strategies.react-query.pre-render`: Duration for pre-render stage to collect all queries before rendering. This is only applicable when the `useReactQuery` HOC is used.

- `ssr.fetch-strategies.react-query.use-query.<query.meta.displayName>`: Time taken by individual useQuery calls. The display name can be set using the `meta.displayName` property of the query. By default, all queries in the `commerce-sdk-react` library have `displayName` configured. If no display name is added, it will be an integer index. This is only applicable when the `useReactQuery` HOC is used.

- `ssr.render-to-string`: Time taken to render the application to a string, after all network requests have completed. This metric is crucial for assessing the complexity of the application. Typical values are less than 100ms for small apps and may be longer for large-scale applications.

- `ssr.total`: The total time taken for the server to render the HTML output, encapsulating all stages of the SSR process.

#### Track Performance Metrics Continuously

If you want to capture performance metrics continuously, set the local `SERVER_TIMING` environment variable to `true`. This allows you to look up historical events and debug issues involving performance at a later time thru logs.

:::note
It's not recommended to set this environment variable on production environments because of its increased log usage.
:::

For more performance-related recommendations, see [Pre-Build and Go-Live Best Practices Checklist](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/pwa-best-practices.md).

## Debug Locally

By default, the app server displays console messages in the terminal but doesn’t otherwise allow you to observe code execution. This limitation can make it hard to debug the code that renders pages on the server side (or on your local machine).

For enhanced debugging, you can start your local development server with an alternate command that runs an inspector process in Node that a debugger can attach to. (For more details, see the [Node documentation](https://nodejs.org/en/docs/inspector).)

You can attach the debugger included in many popular browsers and text editors to Node’s inspector process. Here are instructions for Google Chrome and Visual Studio Code.

### Google Chrome

1. Open a terminal.
2. Go to your project directory.
3. Start your local dev server using `npm run start:inspect`.
4. To confirm that the debugger is listening, look for a “Debugger listening” message in the terminal output.
5. Open Chrome and enter the URL chrome://inspect.
6. Click **Open dedicated DevTools for Node**.
7. DevTools opens in a new window.
8. To confirm that the debugger is attached, look for a “Debugger attached” message in the terminal output.
9. Set breakpoints, add `debugger` statements, and so on.
10. Load a page from your local development server in Chrome.
11. Use the dedicated window for debugging.

Now you can trace the execution of your server-side code!

To learn more about debugging with breakpoints in DevTools, see this guide from Google: [Debug JavaScript](https://developers.google.com/web/tools/chrome-devtools/javascript/).

### Visual Studio Code

1. Open your project files in Visual Studio Code.
2. From the menu bar, click **Terminal** > **New Terminal**.
3. Start your local dev server using `npm run start:inspect`.
4. Open the Command Palette. Shortcut for Windows: `Ctrl` + `Shift` + `P`. Shortcut for Mac `Command` + `Shift` + `P`.
5. Type the following command: “Debug: Attach to Node Process.”
6. A list of the Node processes appears. Choose the first one in the list.
7. To confirm that the debugger is attached, look for a “Debugger Attached” message in the terminal output.
8. Set breakpoints, add debugger statements, and so on.
9. Load a page from your local development server in your web browser.
10. Use the integrated debugger in Visual Studio Code for debugging.

Now you can trace the execution of your server-side code in Visual Studio Code!

:::tip
To avoid having to attach the Node process repeatedly, open the Command Palette and enter “Debug: Toggle Auto Attach.” Toggle the setting to **Always** and restart your local dev server in the Visual Studio Code terminal.
:::

## Debug on Managed Runtime

There are three ways to debug code deployed to Managed Runtime (MRT):

- Use [source maps](#debug-using-source-maps) to pinpoint where errors occurred.
- [Tail logs](#tail-logs-on-managed-runtime) to debug real-time issues or errors in a low-volume environment.
- For a production environment, use [Log Center](#debug-using-log-center), which offers powerful search and retention features.

### Debug Using Source Maps

Use source maps to identify any server-side errors. Source maps provide a simple error stack trace that pinpoints where an error occurred. For example, the stack trace identifies the file and line number where the error occurred to make troubleshooting easier.

:::warning
Enabling source maps has a performance impact, so we recommend using this feature in only non-production environments.
:::

#### Source Maps Prerequisites

To use source maps, you must build your site using PWA Kit version 3.4.x or later. If you have an earlier version, upgrade your project to use PWA Kit 3.4.x.

#### Enable Source Maps

Enable source maps with Runtime Admin, the B2C CLI, or the Managed Runtime API.

**Use Runtime Admin**

1. Log into [Runtime Admin](https://runtime.commercecloud.com).
2. Click your project.
3. Click an environment.
4. Click **Environment Settings**.
5. In the Advanced section, click **Edit**.
6. Enable **Source Maps**.
7. At the top of the Advanced section, click **Update**.
8. Wait for the bundle to finish redeploying.

**Use the Managed Runtime API**

Call the [projects_target_partial_update](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/references/mrt-admin?meta=projects_target_partial_update) API endpoint and set `enable_source_maps` to `true`. This configures the `NODE_OPTIONS` Managed Runtime environment variable in your environment with `--enable-source-maps`and redeploys the bundle.

Use the [B2C CLI](/docs/commerce/b2c-commerce/guide/b2c-developer-tooling.md):

```bash
export MRT_API_KEY="$API_KEY"

npx @salesforce/b2c-cli mrt env update \
  --project "$PROJECT_ID" --environment "$ENVIRONMENT_ID" --enable-source-maps
```

Alternatively, use the API:

```bash
curl "https://cloud.mobify.com/api/projects/$PROJECT_ID/target/$ENVIRONMENT_ID/" \
--request 'PATCH' \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data '{"enable_source_maps": true}'
```

#### Upload Source Maps

1. When you build your project, generate the `ssr.js.map` file by using this local environment variable: `PWA_KIT_SSR_SOURCE_MAP=true`.

```bash
PWA_KIT_SSR_SOURCE_MAP=true npm run build
export PWA_KIT_SSR_SOURCE_MAP=true
```

2. [Deploy your bundle](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/pushing-and-deploying-bundles.md) to Managed Runtime.

#### View Source Maps

After you [enable](#enable-source-maps) and [upload](#upload-source-maps) source maps, you can view them using [Tail Logs](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/debugging.md#tail-logs-on-managed-runtime) [on Managed Runtime](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/debugging.md#tail-logs-on-managed-runtime).

#### Considerations

Using source maps can cause performance issues. For example, there’s latency anytime `error.stack` is accessed. So when you include `console.error(e)` in your code, this can slow down your site.

#### Default Settings for Source Maps

- **New Non-Production Environments:** `enable_source_maps` is set to `true`.
- **New Production Environments:** `enable_source_maps` is set to `false`. This behavior helps to avoid potential performance impacts that may arise when the source maps feature is enabled.
- **All Pre-existing Environments:** `enable_source_maps` is set to `false`.

### Manage Log Levels

Control the verbosity of server-side logs in your environment by setting appropriate log levels. The log level you set affects both Log Center and Log Tailing output.

Available log levels, from most to least verbose, are:

- `TRACE`—Detailed information about application flow.
- `DEBUG`—Information useful for debugging.
- `INFO`—General information about application operation.
- `WARN`—Warning messages for potentially harmful situations.
- `ERROR`—Error events that might still allow the application to continue running.
- `FATAL`—Severe error events that could lead to application termination.

#### Recommended Log Levels

- **Existing projects:** Set to `TRACE` level for backward compatibility.
- **New production environments:** Set to `WARN` level to reduce noise in production logs.
- **New non-production environments:** Set to `DEBUG` level to help with development and testing.

#### Set Log Level by Using Runtime Admin

1. Log into [Runtime Admin](https://runtime.commercecloud.com).
2. Click your project.
3. Click an environment.
4. Click **Environment Settings**.
5. In the Advanced section, click **Edit**.
6. Select your desired **Log Filtering** level.
7. At the top of the Advanced section, click **Update**.

#### Set Log Level by Using the Managed Runtime API

Call the [projects_target_partial_update](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/references/mrt-admin?meta=projects_target_partial_update) API endpoint to set the log level.

This example curl command makes a `PATCH` request to the API to set the log level to `WARN`.

```bash
curl "https://cloud.mobify.com/api/projects/$PROJECT_ID/target/$ENVIRONMENT_ID/" \
--request 'PATCH' \
--header "Authorization: Bearer $API_KEY" \
--header 'Content-Type: application/json' \
--data '{"log_level": "WARN"}'
```

### Tail Logs on Managed Runtime

When your app is deployed to Managed Runtime, remote debugging is not supported. However, you can tail logs for any Managed Runtime environment in real time to help diagnose any server-side errors.

Use the B2C CLI from any directory, or the PWA Kit project commands below.

Use the [B2C CLI](/docs/commerce/b2c-commerce/guide/b2c-developer-tooling.md):

```bash
export MRT_API_KEY='your-runtime-admin-api-key'

npx @salesforce/b2c-cli mrt tail-logs --project my-storefront --environment staging
```

#### Within a PWA Kit Project

If you are working within a PWA Kit project generated from version 2.4.1 or higher, you can:

- View help for the logs command: `npm run tail-logs -- --help`
- Tail logs for a specific project and environment: `npm run tail-logs -- --environment $ENV_ID`

:::note
The extra `--` in the commands above is required.
:::

#### Outside of a PWA Kit Project

If you are working outside of a PWA Kit project, or have a project generated from below version 2.4.1, you can use `npx` to:

- View help for the logs command: `npx @salesforce/pwa-kit-dev tail-logs --help`
- Tail logs for a specific environment ID and project ID: `npx @salesforce/pwa-kit-dev tail-logs --environment $ENV_ID --project $PROJ_ID`

:::note
Instead of `--environment` and `--project` arguments, you can also use the shorter `-e` and `-p` arguments.
:::

#### Constraints and Considerations

When tailing logs, keep in mind the following constraints:

- Each log tailing session will terminate after 60 minutes.
- Each environment can support up to 100 active log-tailing sessions at a time, across all users.
- To tail logs, you need to be given developer or admin user permissions to the Managed Runtime project.

### Debug Using Log Center

Use [Log Center](https://help.salesforce.com/s/articleView?id=cc.b2c_log_center.htm\&type=5) to troubleshoot errors if you built a site using [PWA Kit](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide) or you have a B2C Commerce instance. Log Center:

- Provides a single location to access logs from Managed Runtime (MRT) and your B2C Commerce instance. Connect what's happening in your MRT environment with what's going on in your B2C Commerce instance.
- Provides a dashboard for viewing MRT metrics, which includes charts for request counts, cache hits, and error rates, among others. See [Managed Runtime Metrics](https://help.salesforce.com/s/articleView?id=cc.b2c_metrics_managed_runtime.htm\&type=5) in *Salesforce Help*.
- Lists Shopper Login and API Access (SLAS) errors. See [View SLAS Error Logs in Log Center](/docs/commerce/b2c-commerce/guide/slas.md#view-slas-error-logs-in-log-center).
- Displays CDN error logs (Status Code 5xx), which help you troubleshoot content delivery and performance issues.
- Allows you to [search](https://help.salesforce.com/s/articleView?id=cc.b2c_log_center_search.htm\&type=5) and filter many historical logs. You can get more information about what happened in production, to help investigate and resolve issues quicker.

:::note
- MRT logs in Log Center are available for any [environment](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/managed-runtime-administration.md#environments) with Log Center logs enabled and a B2C Commerce instance associated. Marking the environment as production isn't required. See the [Prerequisites](#log-center-prerequisites).
- There can be a delay of up to 15 minutes between the time that an event happens and the log appears in Log Center.
:::

This guide focuses on debugging for sites built using PWA Kit. For information about using Log Center with your B2C Commerce instance, see [Centralized Log Center](https://help.salesforce.com/s/articleView?id=cc.b2c_log_center.htm\&type=5).

#### Log Center Prerequisites

To access MRT logs for an environment in Log Center, you must first:

1. Have the **Log Center User** role in Account Manager. To verify, check your role in [Account Manager](https://account.demandware.com/). If you don't have the role, ask your Account Manager admin to give you access. See [Managing Account Manager for Salesforce B2C Commerce Users](https://help.salesforce.com/s/articleView?id=000391212\&type=1).
2. Set up the [environment](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/managed-runtime-administration.md#create-an-environment) as follows:

   - Select a B2C Commerce instance to connect to the environment.
   - Add one or more site IDs to associate with the environment.
   - Enable Log Center logs and Log Center metrics. See [Log Center Logs and Metrics](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/managed-runtime-administration.md#log-center-logs-and-metrics).

#### View Logs

After you complete the [Prerequisites](#log-center-prerequisites), to view MRT logs in Log Center:

1. [Start Log Center](https://help.salesforce.com/s/articleView?id=cc.b2c_start_log_center.htm\&type=5).

2. Select a **Region**.

3. Select a **[Realm](https://help.salesforce.com/s/articleView?id=cc.b2c_platform_overview.htm\&type=5)**. If you don’t know your realm ID, ask your Account Executive (AE) or Customer Success Manager (CSM).

4. Click **Show filtered results**.

5. Click **Search > Current Search**.

6. Under Service Type, select **mrt** for Managed Runtime logs

7. Under Request Type, select **SSR** for application logs or **CDN** for CDN logs.

8. Under Host, select the environment whose logs you want to see. The format of the host is `$PROJECT.$ENVIRONMENT`. If you have more than one MRT environment with Log Center logs enabled, you can see multiple MRT host names.

9. View the MRT logs.

   If you’re using PWA Kit version 3.6.0 or later, you can quickly find logs generated by your PWA Kit site by searching on namespaces added as prefixes to logs in Log Center. The namespace pinpoints the specific part of your codebase where an error occurred.

   By default, PWA Kit provides namespacing in the format `<package-name>.<Component>.<action> <LOGLEVEL>`, the namespace is `<package-name>.<Component>.<action>.` Here are definitions of the parts of the namespace and the log level.

   - `<package-name>`: The name of the package where the error occurred.
   - `<component>`: The component within the package that encountered the issue.
   - `<action>`: The action being performed when the error was triggered.
   - `<LOGLEVEL>`: The severity level of the error.: TRACE, DEBUG, INFO, WARN, ERROR, or FATAL.

     Here are common examples of namespaces provided by PWA Kit:

     - `pwa-kit-runtime.httprequest`
     - `retail-react-app.App.render`
     - `retail-react-app.useActiveData.sendViewProduct`

     Logs with custom or unknown severity levels are forwarded to Log Center as INFO logs.

10. **Optional:** You can create your own custom namespace based on your requirements. For example, if you’re using a third-party integration such as a content management system (CMS), you can add the integration as a namespace. That way you can easily find errors associated with that integration in Log Center.

    To create a custom namespace:

    - Go to the file in your project for which you want to log messages. For example, your homepage file:
      `app/pages/home/index.jsx`.

    - Add this to the file:

      `import logger from '@salesforce/retail-react-app/app/utils/logger-instance`

    - In the component for which you want to create a namespace, add an if statement. In this example, we use a component called `CmsProductDescription` and add a namespace called `Home.CmsProductDescription`.

```jsx
<CmsProductDescription>
           if (err.code === 'MISSING_DESCRIPTION') {
               logger.warn('Missing Description', {
                   namespace: 'Home.CmsProductDescription',
                   additionalProperties: {
                       errorMessage: err.message
                   }
               });
           }
</CmsProductDescription>
```

### Limitations

- **Managed Runtime:** Each MRT log message available when you tail logs or use Log Center is limited to 32 KB. Any characters over 32 KB are truncated in the message. To avoid seeing truncated messages, you can [tail logs](#tail-logs-on-managed-runtime) in a non-production environment and shorten any long messages.
- **Log Center:** For information about log levels and log volumes, see [Configuration for Administrators](https://help.salesforce.com/s/articleView?id=cc.b2c_configuration_for_administrators.htm\&type=5).

## See Also

- [Pre-Build and Go-Live Best Practices Checklist](/docs/commerce/b2c-commerce/guide/pwa-best-practices.md)
- [Monitor Your PWA Kit Site](/docs/commerce/b2c-commerce/guide/monitor-site.md)
