|
|
import Foundation
|
|
|
import SwiftUI
|
|
|
import os.log
|
|
|
import Combine
|
|
|
|
|
|
/// 日志级别枚举
|
|
|
enum LogLevel: String, CaseIterable {
|
|
|
case debug = "🔍"
|
|
|
case info = "ℹ️"
|
|
|
case warning = "⚠️"
|
|
|
case error = "❌"
|
|
|
case success = "✅"
|
|
|
|
|
|
var localizedName: String {
|
|
|
switch self {
|
|
|
case .debug: return "debug".localized
|
|
|
case .info: return "info".localized
|
|
|
case .warning: return "warning".localized
|
|
|
case .error: return "error".localized
|
|
|
case .success: return "success".localized
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// 日志管理器
|
|
|
class Logger: ObservableObject {
|
|
|
static let shared = Logger()
|
|
|
|
|
|
@Published var isEnabled = true
|
|
|
@Published var minimumLevel: LogLevel = .debug
|
|
|
|
|
|
private let dateFormatter: DateFormatter = {
|
|
|
let formatter = DateFormatter()
|
|
|
formatter.dateFormat = "HH:mm:ss"
|
|
|
return formatter
|
|
|
}()
|
|
|
|
|
|
private init() {}
|
|
|
|
|
|
/// 记录日志
|
|
|
/// - Parameters:
|
|
|
/// - level: 日志级别
|
|
|
/// - message: 日志消息
|
|
|
/// - file: 文件名(自动获取)
|
|
|
/// - function: 函数名(自动获取)
|
|
|
/// - line: 行号(自动获取)
|
|
|
/// - className: 类名(可选)
|
|
|
func log(
|
|
|
_ level: LogLevel,
|
|
|
_ message: String,
|
|
|
file: String = #file,
|
|
|
function: String = #function,
|
|
|
line: Int = #line,
|
|
|
className: String? = nil
|
|
|
) {
|
|
|
guard isEnabled && shouldLog(level) else { return }
|
|
|
|
|
|
let timestamp = dateFormatter.string(from: Date())
|
|
|
let fileName = URL(fileURLWithPath: file).lastPathComponent
|
|
|
let functionName = function
|
|
|
let lineNumber = line
|
|
|
let classDisplayName = className ?? "Unknown"
|
|
|
|
|
|
let logMessage = "[\(timestamp)] \(level.rawValue) [\(classDisplayName)] [\(fileName):\(lineNumber)] \(functionName): \(message)"
|
|
|
|
|
|
// 输出到控制台
|
|
|
print(logMessage)
|
|
|
|
|
|
// 同时输出到系统日志(可选)
|
|
|
#if DEBUG
|
|
|
// os_log("%{public}@", log: .default, type: .debug, logMessage)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
/// 检查是否应该记录该级别的日志
|
|
|
private func shouldLog(_ level: LogLevel) -> Bool {
|
|
|
let levelOrder: [LogLevel] = [.debug, .info, .warning, .error, .success]
|
|
|
guard let currentIndex = levelOrder.firstIndex(of: minimumLevel),
|
|
|
let messageIndex = levelOrder.firstIndex(of: level) else {
|
|
|
return false
|
|
|
}
|
|
|
return messageIndex >= currentIndex
|
|
|
}
|
|
|
|
|
|
// MARK: - 便捷方法
|
|
|
|
|
|
func debug(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
log(.debug, message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
|
|
|
func info(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
log(.info, message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
|
|
|
func warning(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
log(.warning, message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
|
|
|
func error(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
log(.error, message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
|
|
|
func success(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
log(.success, message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// MARK: - 全局日志函数
|
|
|
|
|
|
/// 全局调试日志函数
|
|
|
func logDebug(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
Logger.shared.debug(message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
|
|
|
/// 全局信息日志函数
|
|
|
func logInfo(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
Logger.shared.info(message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
|
|
|
/// 全局警告日志函数
|
|
|
func logWarning(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
Logger.shared.warning(message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
|
|
|
/// 全局错误日志函数
|
|
|
func logError(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
Logger.shared.error(message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
|
|
|
/// 全局成功日志函数
|
|
|
func logSuccess(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) {
|
|
|
Logger.shared.success(message, file: file, function: function, line: line, className: className)
|
|
|
}
|
|
|
|
|
|
// MARK: - 扩展:获取类名
|
|
|
|
|
|
extension NSObject {
|
|
|
var className: String {
|
|
|
return String(describing: type(of: self))
|
|
|
}
|
|
|
|
|
|
static var className: String {
|
|
|
return String(describing: self)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
extension View {
|
|
|
var className: String {
|
|
|
return String(describing: type(of: self))
|
|
|
}
|
|
|
}
|