log
This commit is contained in:
parent
b316ce61d8
commit
3f9c1a759c
@ -12,6 +12,14 @@
|
||||
#import "server/MySimpleServer.h"
|
||||
#import "server/FloatingWindow.h"
|
||||
|
||||
#import "server/XSLog.h"
|
||||
|
||||
// 重定向 NSLog 到文件
|
||||
__attribute__((constructor)) static void SetupXSLog() {
|
||||
XSLogSetupLogWithFilePath(@"/var/mobile/Documents/AppRunMain.log", 5 * 1024 * 1024);
|
||||
XSLogRedirectNSLog();
|
||||
}
|
||||
|
||||
@interface UIWindow (FloatingWindow)
|
||||
@end
|
||||
|
||||
|
||||
22
AppRunMan/server/XSLog.h
Normal file
22
AppRunMan/server/XSLog.h
Normal file
@ -0,0 +1,22 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
/// @param logFileName 日志文件名
|
||||
/// @param maxFileSize 日志文件最大大小(字节),超过此大小将创建新文件
|
||||
void XSLogSetupLogWithFileName(NSString *logFileName, unsigned long long maxFileSize);
|
||||
|
||||
/// @param logFilePath 日志文件路径
|
||||
/// @param maxFileSize 日志文件最大大小(字节),超过此大小将创建新文件
|
||||
void XSLogSetupLogWithFilePath(NSString *logFilePath, unsigned long long maxFileSize);
|
||||
|
||||
|
||||
void XSLogMessage(NSString *format, ...) __attribute__((format(NSString, 1, 2)));
|
||||
|
||||
void XSLogRedirectNSLog(void);
|
||||
|
||||
// 定义一个宏,方便替换NSLog
|
||||
#define XSLog(format, ...) XSLogMessage((format), ##__VA_ARGS__)
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
162
AppRunMan/server/XSLog.m
Normal file
162
AppRunMan/server/XSLog.m
Normal file
@ -0,0 +1,162 @@
|
||||
#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]);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user