---
title: Logging
description: Customers can log additional data from the mobile SDK for performance monitoring, issue investigation, and analytics.
component: recognize
page_id: recognize:mobile-sdk:mobile-sdk-logging
canonical_url: https://docs.pingidentity.com/recognize/mobile-sdk/mobile-sdk-logging.html
llms_txt: https://docs.pingidentity.com/recognize/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: April 20, 2026
section_ids:
  how-it-works: How It Works
  android: Android
  ios: iOS
  android-4-6: Android 4.6
  ios-4-6: iOS 4.6
  flutter: Flutter
  react-native: React Native
  collect-custom-logs: Collect Custom Logs
  android-2: Android
  ios-2: iOS
  react-native-2: React Native
  logging-levels: Logging Levels
---

# Logging

|   |                                 |
| - | ------------------------------- |
|   | Logging is disabled by default. |

|   |                                                                        |
| - | ---------------------------------------------------------------------- |
|   | Logs **do not** include any Personally Identifiable Information (PII). |

## How It Works

There are two options for logging:

1. To enable logging to PingOne Recognize infrastructure, use `keylessLogsConfiguration`. This gives PingOne Recognize richer SDK logs for investigation and enriches the [PingOne Recognize dashboard](https://dash.keyless.io/).

2. To collect logs only for your analytics (without sending to PingOne Recognize infrastructure), use `customLogsConfiguration`.

### Android

```kotlin
val setup = SetupConfig(
    apiKey = "...",
    hosts = listOf(""),
    keylessLogsConfiguration = LogsConfiguration(
        enabled = true,
        logLevel = LogLevels.INFO
    ),
    customLogsConfiguration = LogsConfiguration(
        enabled = true
    )
)
```

### iOS

```swift
let configuration = SetupConfig(
    apiKey: "some api key",
    hosts: ["some.host"],
    keylessLogsConfiguration: KeylessLogsConfiguration(enabled: true),
    customLogsConfiguration: CustomLogsConfiguration(enabled: true, logLevel: .INFO, callback: { event in
        print(event)
    })
)

Keyless.configure(setupConfiguration: configuration) { error in
    // handle error
}
```

### Android 4.6

```kotlin
val setupConfiguration = SetupConfiguration.builder
    .withApiKey("")
    .withHosts(listOf("..."))
    .withLogging(
        keylessLogsConfiguration = LogsConfiguration(enabled = true),
        customLogsConfiguration = LogsConfiguration(enabled = true, logLevel = LogLevels.INFO)
    )
    .build()
```

### iOS 4.6

```swift
let configuration = Keyless.SetupConfiguration
  .builder
  .withApiKey("some api key")
  .withHosts(["some.host"])
  .withLogging(
    keylessLogsConfiguration: KeylessLogsConfiguration(enabled: true, logLevel: .INFO),
    customLogsConfiguration: CustomLogsConfiguration(enabled: true, callback: { event in
      print(event)
    })
  )
  .build()

Keyless.configure(setupConfiguration: configuration) { error in
  // handle error
}
```

### Flutter

```dart
final configuration = SetupConfiguration(
  apiKey: apiKey,
  hosts: [host],
  loggingEnabled: true,
  loggingLevel: LogLevel.info,
);

try {
  final result = await Keyless.instance.configure(configuration);
  print("Configure finished successfully.");
} catch (error) {
  print("Configure finished with error: $error");
}
```

### React Native

```javascript
const config = new SetupConfig({
  apiKey: 'apiKey',
  hosts: ['HOSTS'],
  keylessLogsConfiguration: new LogsConfiguration({
    enabled: true,
    logLevel: LogLevels.INFO,
  }),
  customLogsConfiguration: new LogsConfiguration({
    enabled: true,
    logLevel: LogLevels.TRACE,
  }),
});

const result = await Keyless.configure(config);

result.fold({
  onSuccess: _data => {
    // Handle success
  },
  onFailure: _error => {
    // Handle error
  },
});
```

## Collect Custom Logs

Collect logs after enabling `customLogsConfiguration`:

### Android

1. Start collecting `Keyless.customLogs` (this must happen before `Keyless.configure()` to get all log events):

   ```kotlin
   Keyless.customLogs.collect { logEvent ->
       // handle logEvent
   }
   ```

2. Configure SDK with `SetupConfig`:

   ```kotlin
   val setup = SetupConfig(
       apiKey = "...",
       hosts = listOf(""),
       customLogsConfiguration = LogsConfiguration(
           enabled = true,
           logLevel = LogLevels.INFO // optional, defaults to INFO
       )
   )
   ```

### iOS

```swift
var myEventCollection = [LogEvent]()
let configuration = Keyless.SetupConfiguration
  .builder
  .withApiKey("some api key")
  .withHosts(["some.host"])
  .withLogging(
    keylessLogsConfiguration: KeylessLogsConfiguration(enabled: true, logLevel: .INFO),
    customLogsConfiguration: CustomLogsConfiguration(enabled: true, callback: { event in
      myEventCollection.append(event)
    })
  )
  .build()

Keyless.configure(setupConfiguration: configuration) { error in
  // handle error
}
```

### React Native

1. Start collecting PingOne Recognize custom logs (this must happen before `Keyless.configure()` to get all log events):

   ```javascript
   const eventSubscription = Keyless.subscribeToCustomLogs(eventLog => {
       // Handle log
   });

   const config = new SetupConfig({
     apiKey: 'apiKey',
     hosts: ['HOSTS'],
     customLogsConfiguration: new LogsConfiguration({
       enabled: true,
       logLevel: LogLevels.TRACE,
     }),
   });

   const result = await Keyless.configure(config);

   result.fold({
     onSuccess: _data => {
       // Handle success
     },
     onFailure: _error => {
       // Handle error
     },
   });
   ```

2. When you want to unsubscribe from logs, call:

   ```javascript
   eventSubscription?.unsubscribe();
   ```

## Logging Levels

You can set different logging levels for more or less detail:

* `INFO` (default)

* `DEBUG`

* `TRACE`

`TRACE` provides additional data:

* `userId`

* `devicePublicSigningKey`

* `coreLogHistory` (used for detailed debugging)
