This commit is contained in:
lhyqy5 2025-11-06 15:26:20 +08:00
parent b316ce61d8
commit 3f9c1a759c
3 changed files with 192 additions and 0 deletions

View File

@ -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
View 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
View 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]);
});
}