Logging
Unify3Sdk exposes a small logging API that lets your app choose which entries to receive and then observe them as they are emitted. The main APIs are setLogLevels(minLevel:maxLevel:) for filtering and getLogs() for consuming Log values.
Choose the log levels you want
Section titled “Choose the log levels you want”Call setLogLevels(minLevel:maxLevel:) to define the inclusive range of log entries your app wants to receive.
var unify = Unify.Instance;
unify.SetLogLevels(LogLevel.Info, LogLevel.Error);val unify = Unify.getInstance(context)
unify.setLogLevels(LogLevel.INFO, LogLevel.ERROR)let unify = Unify.shared
try unify.setLogLevels(minLevel: .info, maxLevel: .error)That example requests:
LogLevel.infoLogLevel.warnLogLevel.error
It excludes lower-volume diagnostic entries such as LogLevel.trace and LogLevel.debug, and it also excludes LogLevel.fatal because it is above the chosen maximum.
The available levels are:
LogLevel.traceLogLevel.debugLogLevel.infoLogLevel.warnLogLevel.errorLogLevel.fatal
In practice:
- Use a wider range such as
.tracethrough.fatalwhen you need maximum diagnostic detail. - Use a narrower range such as
.infothrough.errorfor a quieter app-facing log view.
Read and print the logs
Section titled “Read and print the logs”getLogs() returns an AsyncThrowingStream of Log entries. Start a task that iterates over that stream and formats each entry however your app wants to display it.
var unify = Unify.Instance;
unify.SetLogLevels(LogLevel.Info, LogLevel.Error);
using var logCancellation = new CancellationTokenSource();
var logTask = Task.Run(async () =>{ try { await foreach (var log in unify.GetLogs(logCancellation.Token)) { Console.WriteLine($"[{log.Time:O}] [{log.Level}] [{log.Logger}] {log.Message}"); } } catch (OperationCanceledException) when (logCancellation.IsCancellationRequested) { }});val unify = Unify.getInstance(context)
unify.setLogLevels(LogLevel.INFO, LogLevel.ERROR)
val logJob = lifecycleScope.launch { unify.getLogs().collect { log -> println("[${log.time}] [${log.level}] [${log.logger}] ${log.message}") }}let unify = Unify.shared
try unify.setLogLevels(minLevel: .info, maxLevel: .error)
let logTask = Task { let formatter = ISO8601DateFormatter()
for try await log in unify.getLogs() { let timestamp = formatter.string(from: log.time) print("[\(timestamp)] [\(log.level)] [\(log.logger)] \(log.message)") }}Each Log contains:
time, the timestamp for that entrylevel, the log severity asLogLevellogger, the name of the logger that produced the entrymessage, the human-readable message text
Because the log API is a stream, it fits naturally alongside other long-running SDK flows. For example, an app can start log collection during setup and keep that task alive while it scans, connects, configures tests, and runs measurements.
Stop consuming the stream
Section titled “Stop consuming the stream”Log collection continues until the stream completes or your task is cancelled. When your app no longer needs logs, cancel the task that is iterating over getLogs():
logCancellation.Cancel();await logTask;logJob.cancel()logTask.cancel()If your app only needs temporary diagnostics around one workflow, this is usually the simplest lifecycle model: start the logging task, run the workflow, then cancel the task when you are done.