You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
4.4 KiB
136 lines
4.4 KiB
import Foundation
|
|
import os.log
|
|
|
|
/// iOS端的文件日志助手类,提供与Android端FileLogger类似的功能
|
|
class FileLogger {
|
|
|
|
private static let logQueue = DispatchQueue(label: "com.yunqiinnovation.classic_bluetooth.logger", qos: .background)
|
|
private static let dateFormatter: DateFormatter = {
|
|
let formatter = DateFormatter()
|
|
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
|
|
return formatter
|
|
}()
|
|
|
|
/// 日志类型
|
|
enum LogLevel: String {
|
|
case debug = "DEBUG"
|
|
case info = "INFO"
|
|
case warning = "WARNING"
|
|
case error = "ERROR"
|
|
}
|
|
|
|
/// 输出调试日志
|
|
/// - Parameters:
|
|
/// - tag: 标签
|
|
/// - message: 日志消息
|
|
static func d(_ tag: String, _ message: String) {
|
|
log(level: .debug, tag: tag, message: message)
|
|
}
|
|
|
|
/// 输出信息日志
|
|
/// - Parameters:
|
|
/// - tag: 标签
|
|
/// - message: 日志消息
|
|
static func i(_ tag: String, _ message: String) {
|
|
log(level: .info, tag: tag, message: message)
|
|
}
|
|
|
|
/// 输出警告日志
|
|
/// - Parameters:
|
|
/// - tag: 标签
|
|
/// - message: 日志消息
|
|
static func w(_ tag: String, _ message: String) {
|
|
log(level: .warning, tag: tag, message: message)
|
|
}
|
|
|
|
/// 输出错误日志
|
|
/// - Parameters:
|
|
/// - tag: 标签
|
|
/// - message: 日志消息
|
|
/// - error: 可选的错误对象
|
|
static func e(_ tag: String, _ message: String, _ error: Error? = nil) {
|
|
var fullMessage = message
|
|
if let error = error {
|
|
fullMessage += " - Error: \(error.localizedDescription)"
|
|
}
|
|
log(level: .error, tag: tag, message: fullMessage)
|
|
}
|
|
|
|
/// 输出日志
|
|
/// - Parameters:
|
|
/// - level: 日志级别
|
|
/// - tag: 标签
|
|
/// - message: 日志消息
|
|
private static func log(level: LogLevel, tag: String, message: String) {
|
|
let timestamp = dateFormatter.string(from: Date())
|
|
let logMessage = "[\(timestamp)] [\(level.rawValue)] [\(tag)]: \(message)"
|
|
|
|
// 输出到控制台
|
|
print(logMessage)
|
|
|
|
// 异步写入日志文件
|
|
logQueue.async {
|
|
writeToLogFile(logMessage)
|
|
}
|
|
|
|
// 使用系统日志
|
|
if #available(iOS 10.0, *) {
|
|
let osLog = OSLog(subsystem: "com.yunqiinnovation.classic_bluetooth", category: tag)
|
|
let osLogType: OSLogType
|
|
|
|
switch level {
|
|
case .debug:
|
|
osLogType = .debug
|
|
case .info:
|
|
osLogType = .info
|
|
case .warning:
|
|
osLogType = .default
|
|
case .error:
|
|
osLogType = .error
|
|
}
|
|
|
|
os_log("%{public}@", log: osLog, type: osLogType, message)
|
|
}
|
|
}
|
|
|
|
/// 将日志写入文件
|
|
/// - Parameter message: 日志消息
|
|
private static func writeToLogFile(_ message: String) {
|
|
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
|
|
return
|
|
}
|
|
|
|
let logDirectoryURL = documentsDirectory.appendingPathComponent("Logs")
|
|
let dateString = DateFormatter().with { $0.dateFormat = "yyyy-MM-dd" }.string(from: Date())
|
|
let logFileURL = logDirectoryURL.appendingPathComponent("bluetooth_\(dateString).log")
|
|
|
|
do {
|
|
// 创建日志文件夹
|
|
try FileManager.default.createDirectory(at: logDirectoryURL, withIntermediateDirectories: true)
|
|
|
|
// 如果文件不存在,创建文件
|
|
if !FileManager.default.fileExists(atPath: logFileURL.path) {
|
|
FileManager.default.createFile(atPath: logFileURL.path, contents: nil)
|
|
}
|
|
|
|
// 追加日志内容
|
|
if let fileHandle = FileHandle(forWritingAtPath: logFileURL.path) {
|
|
fileHandle.seekToEndOfFile()
|
|
if let data = "\(message)\n".data(using: .utf8) {
|
|
fileHandle.write(data)
|
|
}
|
|
fileHandle.closeFile()
|
|
}
|
|
} catch {
|
|
print("写入日志文件失败: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - DateFormatter 扩展
|
|
extension DateFormatter {
|
|
func with(_ block: (DateFormatter) -> Void) -> DateFormatter {
|
|
block(self)
|
|
return self
|
|
}
|
|
}
|