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
.info
level will include logs with levels.info
,.warning
, and.error
.On the other hand, selecting the
.warning
level will only include logs with levels.warning
and.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
Logger
implementationsCustom loggers need to respect the set log level themselves.
All produced
LogEntry
objects will be delivered toLogger
implementations 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 .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 21 days ago