Skip to content

Instantly share code, notes, and snippets.

@kristopherjohnson
Last active November 6, 2020 05:59
Show Gist options
  • Save kristopherjohnson/0ded6cd153f61c627226 to your computer and use it in GitHub Desktop.
Save kristopherjohnson/0ded6cd153f61c627226 to your computer and use it in GitHub Desktop.
Demo of using the Apple System Log (ASL) API from Swift
// Note: This must be used in an Xcode project that contains a bridging header
// that includes <asl.h>
import Foundation
/// Provides high-level methods to access the raw data in
/// an ASL message.
struct SystemLogEntry {
/// Key-value pairs read from ASL message
let data: [String : String]
init(_ data: [String : String]) {
self.data = data
}
var time: String { return data[ASL_KEY_TIME] ?? "" }
var timeNanoSec: String { return data[ASL_KEY_TIME_NSEC] ?? "" }
var host: String { return data[ASL_KEY_HOST] ?? "" }
var sender: String { return data[ASL_KEY_SENDER] ?? "" }
var facility: String { return data[ASL_KEY_FACILITY] ?? "" }
var PID: String { return data[ASL_KEY_PID] ?? "" }
var UID: String { return data[ASL_KEY_UID] ?? "" }
var GID: String { return data[ASL_KEY_GID] ?? "" }
var level: String { return data[ASL_KEY_LEVEL] ?? "" }
var message: String { return data[ASL_KEY_MSG] ?? "" }
var readUID: String { return data[ASL_KEY_READ_UID] ?? "" }
var readGID: String { return data[ASL_KEY_READ_GID] ?? "" }
var expireTime: String { return data[ASL_KEY_EXPIRE_TIME] ?? "" }
var messageID: String { return data[ASL_KEY_MSG_ID] ?? "" }
var session: String { return data[ASL_KEY_SESSION] ?? "" }
var refPID: String { return data[ASL_KEY_REF_PID] ?? "" }
var refProc: String { return data[ASL_KEY_REF_PROC] ?? "" }
var auxTitle: String { return data[ASL_KEY_AUX_TITLE] ?? "" }
var auxUTI: String { return data[ASL_KEY_AUX_UTI] ?? "" }
var auxURL: String { return data[ASL_KEY_AUX_URL] ?? "" }
var option: String { return data[ASL_KEY_OPTION] ?? "" }
var module: String { return data[ASL_KEY_MODULE] ?? "" }
var senderInstance: String { return data[ASL_KEY_SENDER_INSTANCE] ?? "" }
var senderMachUUID: String { return data[ASL_KEY_SENDER_MACH_UUID] ?? "" }
var finalNotification: String { return data[ASL_KEY_FINAL_NOTIFICATION] ?? "" }
var OSActivityID: String { return data[ASL_KEY_OS_ACTIVITY_ID] ?? "" }
/// Get the entry time as an NSDate
var date: NSDate {
var sec = time.toInt() ?? 0
var nanosec = timeNanoSec.toInt() ?? 0
var timeInterval = NSTimeInterval(sec) + NSTimeInterval(nanosec) * 1.0e-9
return NSDate(timeIntervalSince1970: timeInterval)
}
/// Get the level as a displayable string
var levelDescription: String {
if let levelAsInt = level.toInt() {
switch Int32(levelAsInt) {
case ASL_LEVEL_EMERG: return ASL_STRING_EMERG
case ASL_LEVEL_ALERT: return ASL_STRING_ALERT
case ASL_LEVEL_CRIT: return ASL_STRING_CRIT
case ASL_LEVEL_ERR: return ASL_STRING_ERR
case ASL_LEVEL_WARNING: return ASL_STRING_WARNING
case ASL_LEVEL_NOTICE: return ASL_STRING_NOTICE
case ASL_LEVEL_INFO: return ASL_STRING_INFO
case ASL_LEVEL_DEBUG: return ASL_STRING_DEBUG
default: return "Unknown"
}
}
else {
return "Unknown"
}
}
}
struct SystemLog {
/// Invoke a specified closure for every entry in the system log
///
/// The closure argument is a dictionary where each key
/// is a message attribute name, and the value is the
/// value of that attribute.
static func readAllLogEntries(processLogEntry: (SystemLogEntry) -> ()) {
let query = asl_new(UInt32(ASL_TYPE_QUERY))
let response = asl_search(nil, query)
for var msg = asl_next(response); msg != nil; msg = asl_next(response) {
var dict: [String : String] = [:]
var keyIndex = UInt32(0)
for var key = asl_key(msg, keyIndex); key != nil; key = asl_key(msg, ++keyIndex) {
if let keyString = String.fromCString(key) {
let value = asl_get(msg, key)
let valueString = (value == nil) ? "" : String.fromCString(value)
dict[keyString] = valueString ?? ""
}
}
let logEntry = SystemLogEntry(dict)
processLogEntry(logEntry)
}
asl_release(response)
}
}
@kristopherjohnson
Copy link
Author

Example use:

// Print all log entries
var dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
SystemLog.readAllLogEntries { entry in
    let timestamp = dateFormatter.stringFromDate(entry.date)
    println("\(timestamp) [\(entry.PID)] \(entry.levelDescription): \(entry.message)")
}

@neil-wu
Copy link

neil-wu commented Aug 25, 2015

Can not get log on ios8 device?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment