Logging in the iOS & tvOS Player SDK
Troubleshooting streams on mobile devices can be challenging, especially for issues that occur rarely and only in specific circumstances. A common approach in such a scenario is to add log statements to the code in order to observe configurations and states at the time of the failure.
Built-in logging
The Bitmovin Player for iOS/tvOS has built-in logging support to aid such use cases.
Enabling or Disabling logging
Logging is enabled by default with level .warning, printing entries to the console.
Logging can be disabled by setting the logger to nil:
DebugConfig.logging.logger = nil
Default logger can be restored by:
DebugConfig.logging.logger = ConsoleLogger()
Configuration
Log levels
Our SDK supports multiple log levels to allow gathering insights with fine-grained control:
| Level | Description |
|---|---|
.verbose | Provides detailed information, primarily for debugging purposes. |
.info | Indicates something has happened and is purely informative. |
.warning | Indicates something unexpected happened, however, the player can continue to function. |
.error | Indicates an issue that disrupts the proper functioning of the player. |
Log levels are hierarchical
This means that selecting a certain level also includes logs with higher levels.
For example, choosing the
.infolevel will include logs with levels.info,.warning, and.error.On the other hand, selecting the
.warninglevel will only include logs with levels.warningand.error.
The current logger's log level can be changed by simply assigning a new level:
DebugConfig.logging.logger?.level = .info
Exhaustive debug logs
To enable exhaustive debug logging across the whole Player SDK, use the following line of code:
DebugConfig.logging.logger?.level = .verbose
Advanced logger support
We support custom logger implementations via the Logger protocol.
Logger instances get LogEntry objects delivered by the Bitmovin Player.
Log level support within custom
LoggerimplementationsCustom loggers need to respect the set log level themselves.
All produced
LogEntryobjects will be delivered toLoggerimplementations and it is the task of the custom logger itself to filter undesired entries.
Custom logger example
The below example of a custom logger implementation uses the Logger from Apple's Logging framework:
import BitmovinPlayer
import OSLog
class AppleLogger: BitmovinPlayer.Logger {
typealias OSLogger = os.Logger
var level: LogLevel = .warning
private let logger = OSLogger(subsystem: "BitmovinPlayer", category: "video playback")
func log(_ logEntry: LogEntry) {
guard logEntry.level.rawValue >= level.rawValue else { return }
switch logEntry.level {
case .verbose:
logger.debug("[\(logEntry.sender)] \(logEntry.message)")
case .info:
logger.info("[\(logEntry.sender)] \(logEntry.message)")
case .warning:
logger.warning("[\(logEntry.sender)] \(logEntry.message) Reason: \(logEntry.data?.message ?? "N/A")")
case .error:
logger.error("[\(logEntry.sender)] \(logEntry.message) Reason: \(logEntry.data?.message ?? "N/A")")
@unknown default:
break
}
}
}
This logger would produce log messages such as:
2023-06-14 08:53:35.461189+0200 YOUR-APP-NAME [video playback] [Source] Downloading playlist finished with error. Reason: Invalid response received from manifest request. Status code: 404
Updated 5 months ago