一、Mac 控制臺
Xcode工程其實是可以用命令行來build的,這樣就可以用命令行編譯出.app的文件,然后就可以打成ipa包。
整個流程做到自動化后,就可以方便的做每日的 daily build,便于產(chǎn)品和測試同事跟進進度!
系統(tǒng)日志App即:控制臺 Console.app
可以直接看蘋果文檔:歡迎使用控制臺 - Apple 支持

二、CocoaLumberjack 日志收集
CocoaLumberjack 是一個快速、簡單,但很強大的日志框架,用于 Mac OS X 和 iOS 系統(tǒng)。
在大多數(shù)用例中,Lumberjack比NSLog快了一個數(shù)量級。
Log分為以下幾種,分別代表不同的等級:
DDLogError
DDLogWarn
DDLogInfo
DDLogDebug
DDLogVerbose
嚴重度:
DDLogError>DDLogWarn>DDLogInfo>DDLogDebug>DDLogVerbose
語法
static const DDLogLevel ddLogLevel = DDLogLevelDebug;
`DDLog`語法跟`NSLog`語法一摸一樣
# NSLog
NSLog(@"Broken sprocket detected!");
NSLog(@"User selected file:%@ withSize:%u", filePath, fileSize);
# DDLog
DDLogError(@"Broken sprocket detected!");
DDLogVerbose(@"User selected file:%@ withSize:%u", filePath, fileSize);
github庫:CocoaLumberjack
導入pod庫:pod 'CocoaLumberjack'
使用配置:
#pragma mark 日志處理:CocoaLumberjack
- (void)configurationCocoaLumberjack {
// Uses os_log
//[DDLog addLogger:[DDASLLogger sharedInstance]]; //iOS10之前
[DDLog addLogger:[DDOSLogger sharedInstance]]; //iOS10之后
[DDLog addLogger:[DDTTYLogger sharedInstance]];
DDFileLogger *fileLogger = [[DDFileLogger alloc] init]; // File Logger
fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling
fileLogger.logFileManager.maximumNumberOfLogFiles = 7;
[DDLog addLogger:fileLogger];
}
使用CocoaLumberjack,出現(xiàn)問題:Use of undeclared identifier 'ddLogLevel'
解決方案:
在 pch文件添加以下配置
#ifdef __OBJC__
// 配置頭文件
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CocoaLumberjack/CocoaLumberjack.h>
// 老版本不可用
//#ifdef DEBUG
// static const int ddLogLevel = LOG_LEVEL_VERBOSE;
//#else
// static const int ddLogLevel = LOG_LEVEL_WARN;
//#endif
// 使用新版本
#ifdef DEBUG
static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
#else
static const DDLogLevel ddLogLevel = DDLogLevelWarning;
#endif
#endif
自己寫一個日志收集(Swfit版)
自己設(shè)計一個日志收集系統(tǒng)需要考慮多個方面,包括日志的格式、存儲、傳輸、性能優(yōu)化等。以下是一個簡單的日志收集系統(tǒng)的設(shè)計和實現(xiàn)代碼示例。
1. 設(shè)計思路
日志級別:支持不同級別的日志(如Verbose、Debug、Info、Warn、Error)。
日志格式:每條日志包含 時間戳、日志級別、日志內(nèi)容等信息。
日志存儲:將日志寫入文件,支持日志文件的滾動(如按天或按大?。?br>
日志傳輸:支持將日志文件上傳到服務器。
線程安全:確保在多線程環(huán)境下日志記錄是安全的。
2. 實現(xiàn)代碼
2.1 定義日志級別
enum LogLevel: String {
case verbose = "VERBOSE"
case debug = "DEBUG"
case info = "INFO"
case warn = "WARN"
case error = "ERROR"
}
2.2 日志管理器
以json文件的形式存儲在磁盤,再上傳到服務端。
import Foundation
class Logger {
static let shared = Logger()
private let logQueue = DispatchQueue(label: "com.yourapp.logger", attributes: .concurrent)
private var logFileHandle: FileHandle?
private let logFileURL: URL
private init() {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
logFileURL = documentsDirectory.appendingPathComponent("app.log")
createLogFileIfNeeded()
}
private func createLogFileIfNeeded() {
if !FileManager.default.fileExists(atPath: logFileURL.path) {
FileManager.default.createFile(atPath: logFileURL.path, contents: nil, attributes: nil)
}
logFileHandle = try? FileHandle(forWritingTo: logFileURL)
}
func log(_ level: LogLevel, message: String) {
let timestamp = Date().iso8601
let logMessage = "\(timestamp) [\(level.rawValue)] \(message)\n"
logQueue.async(flags: .barrier) {
if let data = logMessage.data(using: .utf8) {
self.logFileHandle?.seekToEndOfFile()
self.logFileHandle?.write(data)
}
}
}
func uploadLogFile(to url: URL, completion: @escaping (Bool) -> Void) {
logQueue.async {
self.logFileHandle?.synchronizeFile()
let logFileData = try? Data(contentsOf: self.logFileURL)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = logFileData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
self.log(.error, message: "Error uploading log file: \(error)")
completion(false)
return
}
self.log(.info, message: "Log file uploaded successfully")
completion(true)
}
task.resume()
}
}
deinit {
logFileHandle?.closeFile()
}
}
extension Date {
var iso8601: String {
let formatter = ISO8601DateFormatter()
return formatter.string(from: self)
}
}
3. 代碼說明
- 日志級別:定義了五種日志級別,方便區(qū)分日志的重要性。
- 日志格式:每條日志包含時間戳、日志級別和日志內(nèi)容,格式為[時間戳] [日志級別] 日志內(nèi)容。
- 日志存儲:日志被寫入到應用的Documents目錄下的app.log文件中。使用FileHandle來高效地追加日志內(nèi)容。
- 日志傳輸:提供了uploadLogFile方法,將日志文件上傳到指定的服務器URL。
- 線程安全:使用DispatchQueue確保日志記錄和文件上傳操作是線程安全的。
4. 擴展和優(yōu)化
- 日志滾動:可以擴展Logger類,支持按天或按文件大小滾動日志文件。
- 日志壓縮:在上傳日志文件之前,可以對日志文件進行壓縮,減少傳輸?shù)臄?shù)據(jù)量。
- 日志加密:如果日志包含敏感信息,可以在上傳之前對日志文件進行加密。
- 日志緩存:在網(wǎng)絡不可用時,可以將日志緩存到本地,待網(wǎng)絡恢復后再上傳。
5. 使用示例
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Logger.shared.log(.info, message: "Application started")
Logger.shared.log(.debug, message: "Debugging some issue")
Logger.shared.log(.error, message: "An error occurred")
}
}
6. 總結(jié)
通過 FileHandle 實現(xiàn)日志系統(tǒng),可以高效地管理日志文件的寫入和滾動。以上代碼提供了一個完整的實現(xiàn),支持日志級別、文件滾動、舊日志清理等功能,適合在 iOS 應用中使用。