Logging in Swift

Here’s the translation of the Go logging example to Swift, formatted in Markdown for Hugo:

import Foundation
import OSLog

func main() {
    // Simply invoking print functions uses the standard output,
    // which is already pre-configured for reasonable logging
    // output to the console.
    print("standard logger")

    // In Swift, we use the OSLog framework for more advanced logging.
    // We can create a custom logger with a specific subsystem and category.
    let logger = Logger(subsystem: "com.example.myapp", category: "main")
    
    // We can log messages with different log levels
    logger.log("Info message")
    logger.debug("Debug message")
    logger.error("Error message")

    // We can include additional information in our log messages
    logger.info("User logged in", metadata: ["userId": "12345"])

    // For more customized logging, we can use print with date and time
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss.SSSSSS"
    
    print("\(dateFormatter.string(from: Date())) with micro")

    // To include file and line information, we can use #file and #line
    print("\(dateFormatter.string(from: Date())) \(#file):\(#line) with file/line")

    // We can create a custom logging function
    func myLog(_ message: String) {
        print("my:\(dateFormatter.string(from: Date())) \(message)")
    }

    myLog("from mylog")

    // We can modify our custom logging function
    func ohMyLog(_ message: String) {
        print("ohmy:\(dateFormatter.string(from: Date())) \(message)")
    }

    ohMyLog("from mylog")

    // In Swift, we don't have a direct equivalent to Go's bytes.Buffer
    // But we can use a String to accumulate log messages
    var buffer = ""
    func bufLog(_ message: String) {
        buffer += "buf:\(dateFormatter.string(from: Date())) \(message)\n"
    }

    bufLog("hello")

    // This will show the buffered log on standard output
    print("from buflog:\(buffer)")

    // For structured logging, we can use Swift's Codable protocol
    // to create JSON output
    struct LogEntry: Codable {
        let time: Date
        let level: String
        let message: String
        let metadata: [String: AnyCodable]?
    }

    struct AnyCodable: Codable {
        let value: Any
        
        init(_ value: Any) {
            self.value = value
        }
        
        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            if let intVal = try? container.decode(Int.self) {
                self.value = intVal
            } else if let stringVal = try? container.decode(String.self) {
                self.value = stringVal
            } else {
                self.value = "unknown"
            }
        }
        
        func encode(to encoder: Encoder) throws {
            var container = encoder.singleValueContainer()
            if let intVal = value as? Int {
                try container.encode(intVal)
            } else if let stringVal = value as? String {
                try container.encode(stringVal)
            } else {
                try container.encode("unknown")
            }
        }
    }

    let jsonEncoder = JSONEncoder()
    jsonEncoder.dateEncodingStrategy = .iso8601
    
    let entry1 = LogEntry(time: Date(), level: "INFO", message: "hi there", metadata: nil)
    if let jsonData = try? jsonEncoder.encode(entry1),
       let jsonString = String(data: jsonData, encoding: .utf8) {
        print(jsonString)
    }

    let entry2 = LogEntry(time: Date(), level: "INFO", message: "hello again", metadata: ["key": AnyCodable("val"), "age": AnyCodable(25)])
    if let jsonData = try? jsonEncoder.encode(entry2),
       let jsonString = String(data: jsonData, encoding: .utf8) {
        print(jsonString)
    }
}

main()

This Swift code demonstrates various logging techniques, including:

  1. Basic printing to standard output
  2. Using the OSLog framework for more advanced logging
  3. Custom logging functions with timestamps
  4. Buffering log messages in a string
  5. Structured logging using JSON encoding

The code provides similar functionality to the Go example, adapted to Swift’s syntax and standard library. Note that Swift doesn’t have an exact equivalent to Go’s log package, so we’ve used a combination of print statements and the OSLog framework to achieve similar results.

To run this program, save it as logging.swift and use the Swift compiler:

$ swift logging.swift

The output will be similar to the Go example, with timestamps and formatted log messages.

Please note that the exact output may vary depending on the execution time and environment.