Skip to content

Instantly share code, notes, and snippets.

@joshuajhomann
Created September 27, 2021 15:54
Show Gist options
  • Save joshuajhomann/2fdbbb6a6bf94863704e6092ecc6f49b to your computer and use it in GitHub Desktop.
Save joshuajhomann/2fdbbb6a6bf94863704e6092ecc6f49b to your computer and use it in GitHub Desktop.
import UIKit
import OSLog
struct LogName {
let network = "Networking"
}
@dynamicMemberLookup
enum Log {
struct Info: CustomStringConvertible {
let description: String
let category: String
fileprivate init(description: String, category: String) {
self.description = description
self.category = category
}
}
private static var logs: [String: Logger] = [:]
private static let name = LogName()
static let enumeratedLogInfo: [Info] = {
let mirror = Mirror(reflecting: Log.name)
return mirror.children.compactMap { child in
guard let description = child.value as? String, let category = child.label else { return nil }
return Info(description: description, category: category)
}
}()
static subscript(dynamicMember keyPath: KeyPath<LogName, String>) -> Logger {
let category = name[keyPath: keyPath]
let log = Self.logs[category, default: Logger(subsystem: Bundle.main.bundleIdentifier ?? "", category: category)]
logs[category] = log
return log
}
static func fetchLogEntries<SomeSequence: Sequence>(
for logInfo: SomeSequence,
since elapsed: TimeInterval,
isReversed: Bool = true
) throws -> [OSLogEntryLog] where SomeSequence.Element == Info {
let logStore = try OSLogStore(scope: .currentProcessIdentifier)
let position = logStore.position(date: .now.addingTimeInterval(-elapsed))
let predicate = NSCompoundPredicate(
type: .or,
subpredicates: logInfo.map(\.category).map { NSPredicate(format: "category == %@", argumentArray: [$0]) }
)
let entries = try logStore.getEntries(with: isReversed ? [.reverse] : [], at: position, matching: predicate)
return entries.compactMap { $0 as? OSLogEntryLog }.filter { $0.subsystem == Bundle.main.bundleIdentifier ?? "" }
}
}
enum TabSeparatedValue {
static func escape(_ value: String) -> String {
"\"" + value.replacingOccurrences(of: "\"", with: "'") + "\""
}
static func makeRow(from strings: [String]) -> String {
strings.map(Self.escape(_:)).joined(separator: "\t") + "\r\n"
}
static func make(header: [String], rows: [[String]]) -> String {
makeRow(from: header) + rows.map(makeRow(from:)).joined()
}
}
extension FileManager {
static func writeTemporary(_ value: String, filename: String) throws -> URL {
let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0].appendingPathComponent(filename)
try value.write(to: url, atomically: true, encoding: .utf8)
return url
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment