163 lines
5.6 KiB
Objective-C
163 lines
5.6 KiB
Objective-C
#import "XSLog.h"
|
|
|
|
static NSString *kLogFilePath = @"app.log";
|
|
static unsigned long long kMaxFileSize = 10 * 1024 * 1024; // 10 MB
|
|
static NSFileHandle *logFileHandle;
|
|
static dispatch_queue_t logQueue;
|
|
static int logCount = 0; // 用于控制滚动检查频率
|
|
static const int kLogCheckFrequency = 100; // 每100条日志检查一次文件大小
|
|
|
|
// 内部函数声明
|
|
static void setupLogFileHandle(NSString *logFilePath);
|
|
static void checkAndRollLogFile(NSString *logFilePath);
|
|
static NSString *getLogFilePath(NSString *logFileName);
|
|
|
|
|
|
|
|
void XSLogSetupLogWithFilePath(NSString *logFilePath,
|
|
unsigned long long maxFileSize) {
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
kLogFilePath = logFilePath;
|
|
kMaxFileSize = maxFileSize;
|
|
logQueue = dispatch_queue_create("com.yourcompany.app.logQueue",
|
|
DISPATCH_QUEUE_SERIAL);
|
|
|
|
// 初始化文件句柄
|
|
setupLogFileHandle(logFilePath);
|
|
});
|
|
}
|
|
|
|
void XSLogSetupLogWithFileName(NSString *logFileName,
|
|
unsigned long long maxFileSize) {
|
|
kLogFilePath = getLogFilePath(logFileName);
|
|
XSLogSetupLogWithFilePath(kLogFilePath,maxFileSize);
|
|
}
|
|
|
|
static NSString *getLogFilePath(NSString *logFileName) {
|
|
// 获取Documents目录路径
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
|
|
NSUserDomainMask, YES);
|
|
NSString *documentsDirectory = [paths firstObject];
|
|
NSString *logFilePath =
|
|
[documentsDirectory stringByAppendingPathComponent:logFileName];
|
|
return logFilePath;
|
|
}
|
|
|
|
static void setupLogFileHandle(NSString *logFilePath) {
|
|
// 检查文件大小,如果超过最大值则进行滚动
|
|
checkAndRollLogFile(logFilePath);
|
|
|
|
// 关闭旧的句柄(如果存在)
|
|
if (logFileHandle) {
|
|
[logFileHandle closeFile];
|
|
logFileHandle = nil;
|
|
}
|
|
|
|
// 打开文件句柄
|
|
logFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath];
|
|
if (!logFileHandle) {
|
|
// 如果文件不存在,则创建
|
|
[[NSFileManager defaultManager] createFileAtPath:logFilePath
|
|
contents:nil
|
|
attributes:nil];
|
|
logFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath];
|
|
}
|
|
|
|
if (logFileHandle) {
|
|
// 将文件句柄移动到文件末尾
|
|
[logFileHandle seekToEndOfFile];
|
|
} else {
|
|
fprintf(stderr, "Error: Could not open log file for writing.\n");
|
|
}
|
|
}
|
|
|
|
|
|
static void checkAndRollLogFile(NSString *logFilePath) {
|
|
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
if ([fileManager fileExistsAtPath:logFilePath]) {
|
|
NSError *error = nil;
|
|
NSDictionary *fileAttributes =
|
|
[fileManager attributesOfItemAtPath:logFilePath error:&error];
|
|
if (fileAttributes) {
|
|
unsigned long long fileSize = [fileAttributes fileSize];
|
|
if (fileSize > kMaxFileSize) {
|
|
// 文件过大,进行滚动
|
|
NSString *backupFilePath =
|
|
[logFilePath stringByAppendingString:@".bak"];
|
|
[fileManager removeItemAtPath:backupFilePath
|
|
error:nil]; // 移除旧的备份文件
|
|
[fileManager moveItemAtPath:logFilePath
|
|
toPath:backupFilePath
|
|
error:&error]; // 将当前文件备份
|
|
if (error) {
|
|
fprintf(stderr, "Error rolling log file: %s\n",
|
|
error.localizedDescription.UTF8String);
|
|
}
|
|
// 创建新的空日志文件
|
|
[fileManager createFileAtPath:logFilePath contents:nil attributes:nil];
|
|
// 重新设置文件句柄
|
|
setupLogFileHandle(kLogFilePath);
|
|
}
|
|
} else {
|
|
fprintf(stderr, "Error getting file attributes: %s\n",
|
|
error.localizedDescription.UTF8String);
|
|
}
|
|
}
|
|
}
|
|
|
|
void XSLogRedirectNSLog(void) {
|
|
if (logFileHandle) {
|
|
int fd = [logFileHandle fileDescriptor];
|
|
if (fd != -1) {
|
|
// 将标准错误输出重定向到日志文件
|
|
if (dup2(fd, STDERR_FILENO) == -1) {
|
|
fprintf(stderr, "Error redirecting stderr to log file.\n");
|
|
}
|
|
} else {
|
|
fprintf(stderr, "Error: logFileHandle has an invalid file descriptor.\n");
|
|
}
|
|
} else {
|
|
fprintf(stderr, "Error: logFileHandle is not initialized. Cannot redirect stderr.\n");
|
|
}
|
|
}
|
|
|
|
void XSLogMessage(NSString *format, ...) {
|
|
va_list args;
|
|
va_start(args, format);
|
|
NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
|
|
va_end(args);
|
|
|
|
dispatch_async(logQueue, ^{
|
|
// 获取当前时间
|
|
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
|
|
dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS";
|
|
NSString *timestamp = [dateFormatter stringFromDate:[NSDate date]];
|
|
|
|
// 格式化日志消息
|
|
NSString *logString =
|
|
[NSString stringWithFormat:@"%@ %@\n", timestamp, message];
|
|
|
|
// 将日志写入文件
|
|
NSData *data = [logString dataUsingEncoding:NSUTF8StringEncoding];
|
|
if (logFileHandle) {
|
|
@try {
|
|
[logFileHandle writeData:data];
|
|
// 每次写入后,递增计数器
|
|
logCount++;
|
|
// 每隔 kLogCheckFrequency 条日志检查一次文件大小
|
|
if (logCount >= kLogCheckFrequency) {
|
|
logCount = 0; // 重置计数器
|
|
checkAndRollLogFile(kLogFilePath);
|
|
}
|
|
} @catch (NSException *exception) {
|
|
fprintf(stderr, "Error writing to log file: %s\n",
|
|
exception.reason.UTF8String);
|
|
}
|
|
}
|
|
|
|
// 同时输出到控制台,以便调试
|
|
fprintf(stderr, "%s", [logString UTF8String]);
|
|
});
|
|
}
|