Logging
Configure log levels, privacy settings, and custom log handlers to control how the Airship SDK logs messages.
The Airship SDK provides configurable log levels to help you debug issues without overwhelming the console. If you don’t configure logging, the SDK uses Info for development builds and Error for production builds with private privacy level.
Log levels
The log level acts as a minimum threshold—only logs at that level and higher will be logged. Available log levels, ordered from most to least verbose:
| Log Level | Prefix | Description |
|---|---|---|
| Verbose | V | Highly detailed SDK status for deep debugging and troubleshooting |
| Debug | D | General SDK status with more detailed information than Info |
| Info | I | General SDK status and lifecycle events |
| Warning | W | API deprecations, invalid setup, and other recoverable issues |
| Error | E | Critical errors and exceptions that the SDK cannot gracefully handle |
| Assert | — | Disables all logging |
Log privacy levels
Control the visibility of log contents using privacy levels. This is especially useful when debugging release builds without exposing sensitive information.
- private (default): Uses the standard
android.util.Log. In production builds,verboseanddebugmessages are completely dropped and will not be logged. Use this for production builds to protect sensitive data. - public: Sends all logs with a
publicprivacy level, making it easier to capture detailed information from release builds. To ensure visibility in production builds,verboseanddebugmessages are automatically elevated to theinfolog level.
When using public privacy level, verbose and debug log messages are automatically elevated to info level to ensure all detailed logs are visible when debugging production builds.
Configuration
You can set separate log levels and privacy levels for development and production builds in your Airship config during takeOff.
Common configuration
Typical setup: more verbose logging for development, minimal logging for production:
Common logging configuration
airshipConfigOptions {
// Development: verbose logging for debugging
setDevelopmentLogLevel(AirshipConfigOptions.LogLevel.VERBOSE)
setDevelopmentLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PUBLIC)
// Production: minimal logging to reduce noise
setProductionLogLevel(AirshipConfigOptions.LogLevel.ERROR)
setProductionLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PRIVATE)
// ...
}AirshipConfigOptions.newBuilder()
// Development: verbose logging for debugging
.setDevelopmentLogLevel(AirshipConfigOptions.LogLevel.VERBOSE)
.setDevelopmentLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PUBLIC)
// Production: minimal logging to reduce noise
.setProductionLogLevel(AirshipConfigOptions.LogLevel.ERROR)
.setProductionLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PRIVATE)
...Debugging production issues
When debugging issues in production builds, temporarily enable verbose logging to capture detailed SDK behavior:
Debugging production
airshipConfigOptions {
// Production debugging: enable verbose logs
setProductionLogLevel(AirshipConfigOptions.LogLevel.VERBOSE)
setProductionLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PUBLIC)
// ...
}AirshipConfigOptions.newBuilder()
// Production debugging: enable verbose logs
.setProductionLogLevel(AirshipConfigOptions.LogLevel.VERBOSE)
.setProductionLogPrivacyLevel(AirshipConfigOptions.PrivacyLevel.PUBLIC)
...Verifying log level
You can confirm the current log level by checking the Airship log output in your console. 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.0Custom log handler
You can provide a custom log handler to intercept and handle all Airship log messages. This is useful when you need to integrate Airship logs with your own logging system or customize how logs are formatted or stored.
When a custom log handler is set, the default Airship log handler is completely replaced. Log level filtering is performed before your handler is called, so your handler will only receive logs that meet the configured log level threshold.
Implement the AirshipLogHandler interface and set it on UALog.logHandler before calling Airship.takeOff():
Custom log handler
// Example log handler to forward logs to Android logcat and upload to a remote logging service
val customLogHandler = AirshipLogHandler { tag, logLevel, throwable, message ->
val msg = message()
// Forward to Android logcat
when (logLevel) {
Log.VERBOSE -> Log.v(tag, msg, throwable)
Log.DEBUG -> Log.d(tag, msg, throwable)
Log.INFO -> Log.i(tag, msg, throwable)
Log.WARN -> Log.w(tag, msg, throwable)
Log.ERROR -> Log.e(tag, msg, throwable)
else -> Unit // Do nothing
}
// Optionally: send to remote logging service
MyLoggingService.log(tag, logLevel, msg, throwable)
}
// Set the custom handler globally, before Airship.takeOff()
UALog.logHandler = customLogHandlerAirshipLogHandler logHandler = new AirshipLogHandler() {
@Override
public void log(@NotNull String tag, int logLevel, @Nullable Throwable throwable, @NotNull Function0<@NotNull String> message) {
String msg = message.invoke();
// Forward to Android logcat
switch (logLevel) {
case Log.VERBOSE:
Log.v(tag, msg, throwable);
break;
case Log.DEBUG:
Log.d(tag, msg, throwable);
break;
case Log.INFO:
Log.i(tag, msg, throwable);
break;
case Log.WARN:
Log.w(tag, msg, throwable);
break;
case Log.ERROR:
Log.e(tag, msg, throwable);
break;
default:
break; // Do nothing
}
// Optionally: send to remote logging service
MyLoggingService.log(tag, logLevel, msg, throwable);
}
};
// Set the custom handler globally, before Airship.takeOff()
UALog.setLogHandler(logHandler);Categories