Skip to content

Instantly share code, notes, and snippets.

@khorbushko
Created November 15, 2019 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save khorbushko/a51731d9f556de94ea40bcc1f35a687d to your computer and use it in GitHub Desktop.
Save khorbushko/a51731d9f556de94ea40bcc1f35a687d to your computer and use it in GitHub Desktop.
print listener
import Foundation
import CocoaLumberjack
typealias FilePath = String
final class AppLogger {
private static let listener = ConsoleEavesdropper()
// MARK: - Logger
class var logFilesPaths: [FilePath] {
get {
let logers = DDLog.sharedInstance.allLoggers
var logFiles: [FilePath] = []
for logger in logers {
if let currentLogger = logger as? DDFileLogger {
let files = currentLogger.logFileManager.unsortedLogFileInfos.compactMap({ $0.filePath })
logFiles.append(contentsOf: files)
}
}
return logFiles
}
}
class var content: String {
var returnString: String = String.empty
logFilesPaths.forEach({ (filePath) in
if let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
let contentString = String(data: data, encoding: .utf8) {
returnString += contentString
}
})
return returnString
}
// MARK: - Configuration
class func configure() {
#if !PRODUCTIONMODE
let fileLogger: DDFileLogger = DDFileLogger()
fileLogger.rollingFrequency = TimeInterval(60 * 60 * 24)
fileLogger.logFileManager.maximumNumberOfLogFiles = 1
fileLogger.logFormatter = LogFormatter()
DDLog.add(fileLogger, with: .all)
DDLogVerbose(String.empty)
DDLogVerbose(String.newLine)
DDLogVerbose("starting app")
let device = String(format: "Version: %@, Device: %@, %@, %@, UDID -> %@",
UIApplication.appVersion ?? "unknown",
UIDevice.current.modelName,
UIDevice.current.systemName,
UIDevice.current.systemVersion,
UIDevice.current.identifierForVendor?.uuidString ?? "nil")
DDLogVerbose(device)
listener.openConsolePipe()
listener.onWishperDetection = { whishper -> Bool in
DDLogVerbose(whishper)
return true
}
#endif
}
class func clear() {
logFilesPaths.forEach({ (filePath) in
try? FileManager.default.removeItem(atPath: filePath)
})
}
class func onAppTerminate() {
#if !PRODUCTIONMODE
DDLogVerbose("terminated app")
#endif
}
class func onBackground() {
#if !PRODUCTIONMODE
DDLogVerbose("background app")
#endif
}
class func onForeground() {
#if !PRODUCTIONMODE
DDLogVerbose("foreground app")
#endif
}
}
// MARK: - LogFormatter
fileprivate class LogFormatter: NSObject, DDLogFormatter { //swiftlint:disable:this private_over_fileprivate
private let dateFormatter: DateFormatter
override init() {
dateFormatter = DateFormatter()
dateFormatter.formatterBehavior = .behavior10_4
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss:SSS"
super.init()
}
func format(message logMessage: DDLogMessage) -> String? {
let dateAndTime = dateFormatter.string(from: logMessage.timestamp)
return "\(dateAndTime) [\(logMessage.fileName):\(logMessage.line)]: \(logMessage.message)"
}
}
import UIKit
final class ConsoleEavesdropper {
private var inputPipe: Pipe?
private var outputPipe: Pipe?
var onWishperDetection: ((String) -> Bool)?
func openConsolePipe() {
inputPipe = Pipe()
outputPipe = Pipe()
guard let inputPipe = inputPipe,
let outputPipe = outputPipe else {
return
}
#if !os(iOS)
return
#endif
let pipeReadHandle = inputPipe.fileHandleForReading
dup2(STDOUT_FILENO, outputPipe.fileHandleForWriting.fileDescriptor)
dup2(inputPipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO)
dup2(inputPipe.fileHandleForWriting.fileDescriptor, STDERR_FILENO)
NotificationCenter.default.addObserver(self, selector: #selector(self.handlePipeNotification), name: FileHandle.readCompletionNotification, object: pipeReadHandle)
pipeReadHandle.readInBackgroundAndNotify()
}
@objc func handlePipeNotification(notification: Notification) {
inputPipe?.fileHandleForReading.readInBackgroundAndNotify()
if let data = notification.userInfo?[NSFileHandleNotificationDataItem] as? Data,
let printWishper = String(data: data, encoding: String.Encoding.ascii) {
if onWishperDetection?(printWishper) == false {
return
}
outputPipe?.fileHandleForWriting.write(data)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment