Swift Runtime Logging: Revealing Hidden Bugs

Mukhammadjon Tokhirov
2 min readMay 25, 2023

--

As developers, we all know the challenges of debugging runtime issues in Swift applications. Those elusive bugs that surface intermittently or seem impossible to reproduce can bring our productivity to a halt. However, fear not! In this article, we’ll explore a Swift code snippet that introduces a runtime logging mechanism. By this approach, we can gain valuable insights into our application’s behavior and unravel those hidden bugs that have been causing headaches.

Generally it is a simple code

public struct Logging {
public static func l(_ message: @autoclosure () -> Any, _ write: Bool = true) {
#if DEBUG
print(message())
#endif

if AppConfig.environment != .production, write {
print(message())
}
}

// Write log to file
public static func lf(tag: @autoclosure () -> String = "Log", _ message: @autoclosure () -> Any) {
if let path = FileManager.default.urls(for: .documentDirectory, in: .allDomainsMask).first {
if !path.exists {
FileManager.default.createFile(atPath: path.absoluteString, contents: nil)
}

let logURL = path.appendingPathComponent("\(Date().toString(format: "dd:MM:yyyy"))_falconLog_\(AppConfig.sessionNumber ?? 0).txt")
do {
let timestamp = Date().toString(format: "HH:mm:ss")
let log = "\(timestamp) [\(tag())]: \(message())\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"
try log.append(to: logURL)
} catch {
print("Error writing to log file: \(error)")
}
}
}
}

You may have some missing class, objects or extensions. For my case they are in the following code snippet.

enum Environment {
case production
case development
}

// Application config struct that holds static properties
struct AppConfig {
static var environment: Environment = .development
static var sessionNumber: Int = 0
}

fileprivate extension String {
func append(to url: URL) throws {
let data = self.data(using: .utf8)
try data?.append(fileURL: url)
}
}

fileprivate extension Data {
func append(fileURL: URL) throws {
if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
defer {
fileHandle.closeFile()
}
fileHandle.seekToEndOfFile()
fileHandle.write(self)
} else {
try write(to: fileURL, options: .atomic)
}
}
}

Integrating this logging mechanism into your development workflow can save you countless hours of frustration, allowing you to identify and resolve bugs more effectively.

--

--

No responses yet