Skip to main content
Send logs from a React Native app to LogBrew. Start with one test log, then use the CLI to find it in the correct project. This guide uses Expo. A bare React Native app loads the key through its own configuration. Before you start, you need:
  • A React Native app that you can run locally.
  • A LogBrew project. See Projects.
  • A signed-in CLI. See CLI setup.

Install the SDK

Install both packages in the app directory. Keep the app’s React and React Native dependencies:

Create a project SDK key

Give the app a project-scoped, write-only SDK key. Expo puts every EXPO_PUBLIC_* value in the app bundle. Never put an account or server credential in that variable. CLI v0.1.32 or newer creates a key for an existing project. It does not create a new project. Find the project ID:
Create the key. Use a new file path in an owner-only directory:
Continue only after the command succeeds. If the result is unclear, run the same command again with the same arguments. Do not use --abandon-retry. Keep the key file out of source control. For local Expo development, put the key in an ignored .env.local file at the app root:
Reload the app fully after you change the value. See Expo environment variables for build-time configuration.

Create the client

Put this setup in one module that the app loads at startup. Do not create a client on each render. Put the service, environment, and release in context:
The fetch transport turns on automatic delivery with bounded retries and a queue. Do not add a second flush timer. The AppState listener requests a final flush when the app becomes inactive or goes to the background. Call stopAppStateListener() when the app tears down.

Send and find the test log

Call verifyLogBrewSetup() once from a development-only test action. Await the result and handle a rejected promise. Do not print the key or the event batch. A 2xx result with batches above 0 shows that LogBrew accepted the batch. An empty flush returns 204 with 0 attempts and 0 batches, because automatic delivery can send the event first. In both cases, read the saved log with the CLI:
Check the event time and service in the result. An empty result does not show the cause. Check the project, key, and time range. RecordingTransport.alwaysAccept() is for local tests only. It returns a synthetic 202 and sends no request.

Offline and restart delivery

Read client.deliveryHealth().storage in the running app:
  • persistent: the client uses the native queue. Pending events load again after an app restart.
  • memory: pending events are lost when the JavaScript runtime restarts.
The default persistentQueue: "auto" uses the native queue when the app binary contains the LogBrew native module. Expo Go and older binaries use memory. A JavaScript-only update cannot add the native module. If a production app needs restart delivery, set persistentQueue: "required". Client creation then fails with configuration_error when the native queue is missing. Rebuild the app with the native module. Use persistentQueue: "disabled" only when you want a memory queue. The native queue holds at most 1,000 events and 4 MiB of event data. Smaller client limits also apply. Delivery is at least once, so retries can send an event two times. A background flush is an attempt, not proof of delivery.

Choose the log content

Keep each message short and specific. Describe the app outcome, such as a failed request or a scheduled retry. Do not include names, email addresses, access tokens, form values, or request bodies. Use the severity that matches the event: info, warning, error, or critical. Keep the service, environment, and release consistent so you can find related records. npx react-native log-ios and npx react-native log-android show local device logs. They do not query LogBrew. See React Native native debugging.

Recover from a failed check

A failed flush() rejects with an SDK error code. Keep keys and event bodies out of error reports. See Troubleshooting for more checks.

Keep Expo Debug IDs in release bundles

Create the Expo Metro config through LogBrew. The runtime bundle then gets the same Debug ID as its source map:
If the app uses React Native Worklets bundle mode, apply that transform after the LogBrew helper:
The helper keeps existing Expo pre-serialization plugins. A bare React Native app wraps its finished Metro config with withLogBrewMetroConfig() instead. Do not use that wrapper with Expo. If you do, the production build stops with a message that points to getLogBrewExpoConfig().