Logging

The Airship SDK allows configuring different log levels that can be helpful for debugging issues.

The Airship SDK provides configurable log levels to help you debug issues without overwhelming the console. By default, the log level is set to Info for development builds and Error for production builds to ensure clean logs in a live environment.

Log levels

The following log levels are available, ordered from most to least verbose.

Log LevelDescription
VerboseReports highly detailed SDK status, which is useful for deep debugging and troubleshooting.
DebugReports general SDK status with more detailed information than Info.
InfoReports general SDK status and lifecycle events.
WarningUsed for API deprecations, invalid setup, and other potentially problematic situations that are generally recoverable.
ErrorUsed for critical errors, exceptions, and other situations that the SDK cannot gracefully handle.
None / AssertDisables all logging. This level is named None on most platforms and Assert on Android.

Configuring log levels

You can set the log level in the Airship config options that are passed during takeOff. This setting acts as a minimum, and only logs at that level and higher will be logged.

Example enabling verbose logs

// Available log levels: VERBOSE, DEBUG, INFO, WARNING, ASSERT
AirshipConfigOptions.newBuilder()
    .setDevelopmentLogLevel(Log.VERBOSE)
    .setProductionLogLevel(Log.VERBOSE)
    ...
// Available log levels: VERBOSE, DEBUG, INFO, WARNING, ASSERT
AirshipConfigOptions.newBuilder()
    .setDevelopmentLogLevel(Log.VERBOSE)
    .setProductionLogLevel(Log.VERBOSE)
    ...
var config = AirshipConfig()
config.productionLogLevel = .verbose
config.developmentLogLevel = .verbose
// Available log levels: VERBOSE, DEBUG, INFO, WARNING, NONE
UAConfig *config = [UAConfig config];
config.productionLogLevel = UAAirshipLogLevelVerbose;
config.developmentLogLevel = UAAirshipLogLevelVerbose;
// Available log levels: verbose, debug, info, warning, none
await Airship.takeOff({
    default: {
        logLevel: "verbose"
    },
    ...
});

Due to how takeOff caches config, you may need to restart the app after the new takeOff before the log levels take effect.

  Airship.takeOff(
    AirshipConfig(
      defaultEnvironment: ConfigEnvironment(
        appSecret: "APP_SECRET",
        appKey: "APP_KEY",
        logLevel: LogLevel.verbose,
        ios: IOSEnvironment(
          logPrivacyLevel: AirshipLogPrivacyLevel.public
        ),
        android: AndroidEnvironment(
          logPrivacyLevel: AirshipLogPrivacyLevel.public
        )
      )
    )
  );
// Available log levels: verbose, debug, info, warning, none
Airship.takeOff({
  default: {
    logLevel: "verbose"
  },
  ...
});
// Available log levels: verbose, debug, info, warning, none
await Airship.takeOff({
    default: {
        logLevel: "verbose"
    },
    ...
});

Android airshipconfig.properties:

# Available log levels: VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT
productionLogLevel = VERBOSE
developmentLogLevel = VERBOSE

iOS AirshipConfig.plist:

<!--  Available log levels: TRACE, DEBUG, INFO, WARNING, NONE -->
<key>productionLogLevel</key>
<string>TRACE</string>
<key>developmentLogLevel</key>
<string>TRACE</string>

Android airshipconfig.properties:

# Available log levels: VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT
productionLogLevel = VERBOSE
developmentLogLevel = VERBOSE

iOS AirshipConfig.plist:

<!--  Available log levels: VERBOSE, DEBUG, INFO, WARNING, NONE -->
<key>productionLogLevel</key>
<string>VERBOSE</string>
<key>developmentLogLevel</key>
<string>VERBOSE</string>
// Available log levels: logLevelVerbose, logLevelDebug, logLevelInfo, logLevelWarning, logLevelNone
Airship.takeOff({
    default: {
        logLevel: Airship.logLevelVerbose
    },
    ...
});

Due to how takeOff caches config, you may need to restart the app after the new takeOff before the log levels take effect.

Log levels can be set within the Airship config menu.

Verifying log level

You can confirm the current log level by checking the Airship log output in your console. The format differs slightly between Android and iOS.

Android

On Android, Airship logs use the standard log priority tags (e.g., V, D, I). To find them, filter your logs for the tag UAirship and observe the priority letter.

Example (Verbose Log) The V in the output indicates a VERBOSE level log.

Sample - UALib com.urbanairship.sample V UAirship - !SDK-VERSION-STRING!:com.urbanairship.android:urbanairship-core:16.9.0

iOS

On iOS, Airship adds a prefix to each log message that includes the level. The format is [Airship] [L], where L is the first letter of the log level.

Example (Verbose Log) The [V] prefix indicates a VERBOSE level log.

[Airship] [V] AirshipCore/TaskManager.swift attemptRequest(_:nextBackOff:) [Line 275] Task ChannelAudienceManager.update started

Log privacy levels

For better security in production environments, you can control the visibility of log contents using privacy levels. This is especially useful when you need to debug a release build without exposing sensitive information.

private (default)

This is the default setting, designed to protect data in a production environment.

  • iOS: Uses os.Logger to log all messages at the private level. The content of most logs will be redacted and will not be visible in the Console app unless a special profile is installed on the device.
  • Android: Uses the standard android.util.Log. In production builds, verbose and debug messages are completely dropped and will not be logged.

public

This setting increases log visibility, making it easier to capture detailed information from release builds.

  • iOS: All logs are sent to os.Logger with a public privacy level, preventing their content from being redacted.
  • Android & iOS: To ensure visibility in production builds, verbose and debug messages are automatically elevated to the info log level.

Setting the privacy level

You can set the privacy level in the Airship config options that are passed during takeOff.

Example enabling public logging

AirshipConfigOptions.newBuilder()
    .setDevelopmentLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PUBLIC)
    .setProductionLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PUBLIC)
    ...
AirshipConfigOptions.newBuilder()
    .setDevelopmentLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PUBLIC)
    .setProductionLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PUBLIC)
    ...
var config = AirshipConfig()
config.developmentLogPrivacyLevel = .public
config.productionLogPrivacyLevel = .public
Not supported in code. Can be set through AirshipConfig.plist.
await Airship.takeOff({
    default: {
        logLevel: "verbose",
        ios: {
          logPrivacyLevel: "public"
        },
        android: {
          logPrivacyLevel: "public"
        }
    },
    ...
});

Due to how takeOff caches config, you may need to restart the app after the new takeOff before the log levels take effect.

  Airship.takeOff(
    AirshipConfig(
      defaultEnvironment: ConfigEnvironment(
        appSecret: "APP_SECRET",
        appKey: "APP_KEY",
        logLevel: LogLevel.verbose
      )
    )
  );
Airship.takeOff({
    default: {
        logLevel: "verbose",
        ios: {
          logPrivacyLevel: "public"
        },
        android: {
          logPrivacyLevel: "public"
        }
    },
    ...
});
await Airship.takeOff({
    default: {
        logLevel: "verbose",
        ios: {
          logPrivacyLevel: "public"
        },
        android: {
          logPrivacyLevel: "public"
        }
    },
    ...
});
Not supported.
Not supported.
Not supported.

Due to how takeOff caches config, you may need to restart the app after the new takeOff before the log levels take effect.

Currently not supported.