mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Rageshake Service (#70)
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
//
|
||||
// Copyright 2021 The Matrix.org Foundation C.I.C
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftyBeaver
|
||||
|
||||
/// Various MXLog configuration options. Used in conjunction with `MXLog.configure()`
|
||||
@objc public class MXLogConfiguration: NSObject {
|
||||
|
||||
/// the desired log level. `.verbose` by default.
|
||||
@objc public var logLevel: MXLogLevel = MXLogLevel.verbose
|
||||
|
||||
/// whether logs should be written directly to files. `false` by default.
|
||||
@objc public var redirectLogsToFiles: Bool = false
|
||||
|
||||
/// the maximum total space to use for log files in bytes. `100MB` by default.
|
||||
@objc public var logFilesSizeLimit: UInt = 100 * 1024 * 1024 // 100MB
|
||||
|
||||
/// the maximum number of log files to use before rolling. `50` by default.
|
||||
@objc public var maxLogFilesCount: UInt = 50
|
||||
|
||||
/// the subname for log files. Files will be named as 'console-[subLogName].log'. `nil` by default
|
||||
@objc public var subLogName: String?
|
||||
}
|
||||
|
||||
/// MXLog logging levels. Use .none to disable logging entirely.
|
||||
@objc public enum MXLogLevel: UInt {
|
||||
case none
|
||||
case verbose
|
||||
case debug
|
||||
case info
|
||||
case warning
|
||||
case error
|
||||
}
|
||||
|
||||
private var logger: SwiftyBeaver.Type = {
|
||||
let logger = SwiftyBeaver.self
|
||||
MXLog.configureLogger(logger, withConfiguration: MXLogConfiguration())
|
||||
return logger
|
||||
}()
|
||||
|
||||
/**
|
||||
Logging utility that provies multiple logging levels as well as file output and rolling.
|
||||
Its purpose is to provide a common entry for customizing logging and should be used throughout the code.
|
||||
Please see `MXLog.h` for Objective-C options.
|
||||
*/
|
||||
@objc public class MXLog: NSObject {
|
||||
|
||||
/// Method used to customize MXLog's behavior.
|
||||
/// Called automatically when first accessing the logger with the default values.
|
||||
/// Please see `MXLogConfiguration` for all available options.
|
||||
/// - Parameters:
|
||||
/// - configuration: the `MXLogConfiguration` instance to use
|
||||
@objc static public func configure(_ configuration: MXLogConfiguration) {
|
||||
configureLogger(logger, withConfiguration: configuration)
|
||||
}
|
||||
|
||||
public static func verbose(_ message: @autoclosure () -> Any,
|
||||
_ file: String = #file,
|
||||
_ function: String = #function,
|
||||
line: Int = #line,
|
||||
context: Any? = nil) {
|
||||
logger.verbose(message(), file, function, line: line, context: context)
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 5.4)
|
||||
@objc public static func logVerbose(_ message: String, file: String, function: String, line: Int) {
|
||||
logger.verbose(message, file, function, line: line)
|
||||
}
|
||||
|
||||
public static func debug(_ message: @autoclosure () -> Any,
|
||||
_ file: String = #file,
|
||||
_ function: String = #function,
|
||||
line: Int = #line,
|
||||
context: Any? = nil) {
|
||||
logger.debug(message(), file, function, line: line, context: context)
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 5.4)
|
||||
@objc public static func logDebug(_ message: String, file: String, function: String, line: Int) {
|
||||
logger.debug(message, file, function, line: line)
|
||||
}
|
||||
|
||||
public static func info(_ message: @autoclosure () -> Any,
|
||||
_ file: String = #file,
|
||||
_ function: String = #function,
|
||||
line: Int = #line,
|
||||
context: Any? = nil) {
|
||||
logger.info(message(), file, function, line: line, context: context)
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 5.4)
|
||||
@objc public static func logInfo(_ message: String, file: String, function: String, line: Int) {
|
||||
logger.info(message, file, function, line: line)
|
||||
}
|
||||
|
||||
public static func warning(_ message: @autoclosure () -> Any, _
|
||||
file: String = #file,
|
||||
_ function: String = #function,
|
||||
line: Int = #line,
|
||||
context: Any? = nil) {
|
||||
logger.warning(message(), file, function, line: line, context: context)
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 5.4)
|
||||
@objc public static func logWarning(_ message: String, file: String, function: String, line: Int) {
|
||||
logger.warning(message, file, function, line: line)
|
||||
}
|
||||
|
||||
public static func error(_ message: @autoclosure () -> Any,
|
||||
_ file: String = #file,
|
||||
_ function: String = #function,
|
||||
line: Int = #line,
|
||||
context: Any? = nil) {
|
||||
logger.error(message(), file, function, line: line, context: context)
|
||||
}
|
||||
|
||||
@available(swift, obsoleted: 5.4)
|
||||
@objc public static func logError(_ message: String, file: String, function: String, line: Int) {
|
||||
logger.error(message, file, function, line: line)
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
fileprivate static func configureLogger(_ logger: SwiftyBeaver.Type, withConfiguration configuration: MXLogConfiguration) {
|
||||
if let subLogName = configuration.subLogName {
|
||||
MXLogger.setSubLogName(subLogName)
|
||||
}
|
||||
|
||||
MXLogger.redirectNSLog(toFiles: configuration.redirectLogsToFiles,
|
||||
numberOfFiles: configuration.maxLogFilesCount,
|
||||
sizeLimit: configuration.logFilesSizeLimit)
|
||||
|
||||
guard configuration.logLevel != .none else {
|
||||
return
|
||||
}
|
||||
|
||||
let consoleDestination = ConsoleDestination()
|
||||
consoleDestination.useNSLog = true
|
||||
consoleDestination.asynchronously = false
|
||||
consoleDestination.format = "$M"
|
||||
consoleDestination.levelColor.verbose = ""
|
||||
consoleDestination.levelColor.debug = ""
|
||||
consoleDestination.levelColor.info = ""
|
||||
consoleDestination.levelColor.warning = "⚠️"
|
||||
consoleDestination.levelColor.error = "🚨"
|
||||
|
||||
switch configuration.logLevel {
|
||||
case .verbose:
|
||||
consoleDestination.minLevel = .verbose
|
||||
case .debug:
|
||||
consoleDestination.minLevel = .debug
|
||||
case .info:
|
||||
consoleDestination.minLevel = .info
|
||||
case .warning:
|
||||
consoleDestination.minLevel = .warning
|
||||
case .error:
|
||||
consoleDestination.minLevel = .error
|
||||
case .none:
|
||||
break
|
||||
}
|
||||
|
||||
logger.removeAllDestinations()
|
||||
logger.addDestination(consoleDestination)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
The `MXLogger` tool redirects NSLog output into a fixed pool of files.
|
||||
Another log file is used every time [MXLogger redirectNSLogToFiles:YES]
|
||||
is called. The pool contains 3 files.
|
||||
|
||||
`MXLogger` can track and log uncatched exceptions or crashes.
|
||||
*/
|
||||
@interface MXLogger : NSObject
|
||||
|
||||
/**
|
||||
Redirect NSLog output to MXLogger files.
|
||||
|
||||
It is advised to condition this redirection in '#if (!isatty(STDERR_FILENO))' block to enable
|
||||
it only when the device is not attached to the debugger.
|
||||
|
||||
@param redirectNSLogToFiles YES to enable the redirection.
|
||||
*/
|
||||
+ (void)redirectNSLogToFiles:(BOOL)redirectNSLogToFiles;
|
||||
|
||||
/**
|
||||
Redirect NSLog output to MXLogger files.
|
||||
|
||||
It is advised to condition this redirection in '#if (!isatty(STDERR_FILENO))' block to enable
|
||||
it only when the device is not attached to the debugger.
|
||||
|
||||
@param redirectNSLogToFiles YES to enable the redirection.
|
||||
@param numberOfFiles number of files to keep (default is 10).
|
||||
*/
|
||||
+ (void)redirectNSLogToFiles:(BOOL)redirectNSLogToFiles numberOfFiles:(NSUInteger)numberOfFiles;
|
||||
|
||||
/**
|
||||
Redirect NSLog output to MXLogger files.
|
||||
|
||||
@param redirectNSLogToFiles YES to enable the redirection.
|
||||
@param numberOfFiles number of files to keep (default is 10).
|
||||
@param sizeLimit size limit of log files in bytes. 0 means no limitation, the default value for other methods
|
||||
*/
|
||||
+ (void)redirectNSLogToFiles:(BOOL)redirectNSLogToFiles numberOfFiles:(NSUInteger)numberOfFiles sizeLimit:(NSUInteger)sizeLimit;
|
||||
|
||||
/**
|
||||
Delete all log files.
|
||||
*/
|
||||
+ (void)deleteLogFiles;
|
||||
|
||||
/**
|
||||
Get the list of all log files.
|
||||
|
||||
@return files of
|
||||
*/
|
||||
+ (NSArray<NSString*>*)logFiles;
|
||||
|
||||
/**
|
||||
Make `MXLogger` catch and log unmanaged exceptions or application crashes.
|
||||
|
||||
When such error happens, `MXLogger` stores the application stack trace into a file
|
||||
just before the application leaves. The path of this file is provided by [MXLogger crashLog].
|
||||
|
||||
@param logCrashes YES to enable the catch.
|
||||
*/
|
||||
+ (void)logCrashes:(BOOL)logCrashes;
|
||||
|
||||
/**
|
||||
Set the app build version.
|
||||
It will be reported in crash report.
|
||||
*/
|
||||
+ (void)setBuildVersion:(NSString*)buildVersion;
|
||||
|
||||
/**
|
||||
Set a sub name for namespacing log files.
|
||||
|
||||
A sub name must be set when running from an app extension because extensions can
|
||||
run in parallel to the app.
|
||||
It must be called before `redirectNSLogToFiles`.
|
||||
|
||||
@param subLogName the subname for log files. Files will be named as 'console-[subLogName].log'
|
||||
Default is nil.
|
||||
*/
|
||||
+ (void)setSubLogName:(NSString*)subLogName;
|
||||
|
||||
/**
|
||||
If any, get the file containing the last application crash log.
|
||||
|
||||
Only one crash log is stored at a time. The best moment for the app to handle it is the
|
||||
at its next startup.
|
||||
|
||||
@return the crash log file. nil if there is none.
|
||||
*/
|
||||
+ (NSString*)crashLog;
|
||||
|
||||
/**
|
||||
Delete the crash log file.
|
||||
*/
|
||||
+ (void)deleteCrashLog;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket Ltd
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "MXLogger.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
// stderr so it can be restored
|
||||
int stderrSave = 0;
|
||||
|
||||
static NSString *buildVersion;
|
||||
static NSString *subLogName;
|
||||
|
||||
#define MXLOGGER_CRASH_LOG @"crash.log"
|
||||
|
||||
@implementation MXLogger
|
||||
|
||||
#pragma mark - NSLog redirection
|
||||
+ (void)redirectNSLogToFiles:(BOOL)redirectNSLogToFiles
|
||||
{
|
||||
[self redirectNSLogToFiles:redirectNSLogToFiles numberOfFiles:10];
|
||||
}
|
||||
|
||||
+ (void)redirectNSLogToFiles:(BOOL)redirectNSLogToFiles numberOfFiles:(NSUInteger)numberOfFiles
|
||||
{
|
||||
[self redirectNSLogToFiles:redirectNSLogToFiles numberOfFiles:numberOfFiles sizeLimit:0];
|
||||
}
|
||||
|
||||
+ (void)redirectNSLogToFiles:(BOOL)redirectNSLogToFiles numberOfFiles:(NSUInteger)numberOfFiles sizeLimit:(NSUInteger)sizeLimit
|
||||
{
|
||||
if (redirectNSLogToFiles)
|
||||
{
|
||||
NSMutableString *log = [NSMutableString string];
|
||||
|
||||
// Default subname
|
||||
if (!subLogName)
|
||||
{
|
||||
subLogName = @"";
|
||||
}
|
||||
|
||||
// Set log location
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *logsFolderPath = [MXLogger logsFolderPath];
|
||||
|
||||
// Do a circular buffer based on X files
|
||||
for (NSInteger index = numberOfFiles - 2; index >= 0; index--)
|
||||
{
|
||||
NSString *nsLogPathOlder;
|
||||
NSString *nsLogPathCurrent;
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
nsLogPathOlder = [NSString stringWithFormat:@"console%@.1.log", subLogName];
|
||||
nsLogPathCurrent = [NSString stringWithFormat:@"console%@.log", subLogName];
|
||||
}
|
||||
else
|
||||
{
|
||||
nsLogPathOlder = [NSString stringWithFormat:@"console%@.%tu.log", subLogName, index + 1];
|
||||
nsLogPathCurrent = [NSString stringWithFormat:@"console%@.%tu.log", subLogName, index];
|
||||
}
|
||||
|
||||
nsLogPathOlder = [logsFolderPath stringByAppendingPathComponent:nsLogPathOlder];
|
||||
nsLogPathCurrent = [logsFolderPath stringByAppendingPathComponent:nsLogPathCurrent];
|
||||
|
||||
if ([fileManager fileExistsAtPath:nsLogPathCurrent])
|
||||
{
|
||||
if ([fileManager fileExistsAtPath:nsLogPathOlder])
|
||||
{
|
||||
// Temp log
|
||||
[log appendFormat:@"[MXLogger] redirectNSLogToFiles: removeItemAtPath: %@\n", nsLogPathOlder];
|
||||
|
||||
NSError *error;
|
||||
[fileManager removeItemAtPath:nsLogPathOlder error:&error];
|
||||
if (error)
|
||||
{
|
||||
[log appendFormat:@"[MXLogger] ERROR: removeItemAtPath: %@. Error: %@\n", nsLogPathOlder, error];
|
||||
}
|
||||
}
|
||||
|
||||
// Temp log
|
||||
[log appendFormat:@"[MXLogger] redirectNSLogToFiles: moveItemAtPath: %@ toPath: %@\n", nsLogPathCurrent, nsLogPathOlder];
|
||||
|
||||
NSError *error;
|
||||
[fileManager moveItemAtPath:nsLogPathCurrent toPath:nsLogPathOlder error:&error];
|
||||
if (error)
|
||||
{
|
||||
[log appendFormat:@"[MXLogger] ERROR: moveItemAtPath: %@ toPath: %@. Error: %@\n", nsLogPathCurrent, nsLogPathOlder, error];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save stderr so it can be restored.
|
||||
stderrSave = dup(STDERR_FILENO);
|
||||
|
||||
NSString *nsLogPath = [logsFolderPath stringByAppendingPathComponent:[NSString stringWithFormat:@"console%@.log", subLogName]];
|
||||
freopen([nsLogPath fileSystemRepresentation], "w+", stderr);
|
||||
|
||||
// MXLogDebug(@"[MXLogger] redirectNSLogToFiles: YES");
|
||||
if (log.length)
|
||||
{
|
||||
// We can now log into files
|
||||
// MXLogDebug(@"%@", log);
|
||||
}
|
||||
|
||||
[self removeExtraFilesFromCount:numberOfFiles];
|
||||
|
||||
if (sizeLimit > 0)
|
||||
{
|
||||
[self removeFilesAfterSizeLimit:sizeLimit];
|
||||
}
|
||||
}
|
||||
else if (stderrSave)
|
||||
{
|
||||
// Flush before restoring stderr
|
||||
fflush(stderr);
|
||||
|
||||
// Now restore stderr, so new output goes to console.
|
||||
dup2(stderrSave, STDERR_FILENO);
|
||||
close(stderrSave);
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)deleteLogFiles
|
||||
{
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
for (NSString *logFile in [self logFiles])
|
||||
{
|
||||
[fileManager removeItemAtPath:logFile error:nil];
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSArray<NSString*>*)logFiles
|
||||
{
|
||||
NSMutableArray *logFiles = [NSMutableArray array];
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *logsFolderPath = [MXLogger logsFolderPath];
|
||||
|
||||
NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtPath:logsFolderPath];
|
||||
|
||||
// Find all *.log files
|
||||
NSString *file = nil;
|
||||
while ((file = [dirEnum nextObject]))
|
||||
{
|
||||
if ([[file lastPathComponent] hasPrefix:@"console"])
|
||||
{
|
||||
NSString *logPath = [logsFolderPath stringByAppendingPathComponent:file];
|
||||
[logFiles addObject:logPath];
|
||||
}
|
||||
}
|
||||
|
||||
// MXLogDebug(@"[MXLogger] logFiles: %@", logFiles);
|
||||
|
||||
return logFiles;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Exceptions and crashes
|
||||
// Exceptions uncaught by try catch block are handled here
|
||||
static void handleUncaughtException(NSException *exception)
|
||||
{
|
||||
[MXLogger logCrashes:NO];
|
||||
|
||||
// Extract running app information
|
||||
NSDictionary* infoDict = [[NSBundle mainBundle] infoDictionary];
|
||||
NSString* appVersion;
|
||||
NSString* app, *appId;
|
||||
|
||||
app = infoDict[@"CFBundleExecutable"];
|
||||
appId = infoDict[@"CFBundleIdentifier"];
|
||||
|
||||
if ([infoDict objectForKey:@"CFBundleVersion"])
|
||||
{
|
||||
appVersion = [NSString stringWithFormat:@"%@ (r%@)", [infoDict objectForKey:@"CFBundleShortVersionString"], [infoDict objectForKey:@"CFBundleVersion"]];
|
||||
}
|
||||
else
|
||||
{
|
||||
appVersion = [infoDict objectForKey:@"CFBundleShortVersionString"];
|
||||
}
|
||||
|
||||
// Build the crash log
|
||||
#if TARGET_OS_IPHONE
|
||||
NSString *model = [[UIDevice currentDevice] model];
|
||||
NSString *version = [[UIDevice currentDevice] systemVersion];
|
||||
#elif TARGET_OS_OSX
|
||||
NSString *model = @"Mac";
|
||||
NSString *version = [[NSProcessInfo processInfo] operatingSystemVersionString];
|
||||
#endif
|
||||
NSArray *backtrace = [exception callStackSymbols];
|
||||
NSString *description = [NSString stringWithFormat:@"%.0f - %@\n%@\nApplication: %@ (%@)\nApplication version: %@\nMatrix SDK version: %@\nBuild: %@\n%@ %@\n\nMain thread: %@\n%@\n",
|
||||
[[NSDate date] timeIntervalSince1970],
|
||||
[NSDate date],
|
||||
exception.description,
|
||||
app, appId,
|
||||
appVersion,
|
||||
@"",
|
||||
buildVersion,
|
||||
model, version,
|
||||
[NSThread isMainThread] ? @"YES" : @"NO",
|
||||
backtrace];
|
||||
|
||||
// Write to the crash log file
|
||||
[MXLogger deleteCrashLog];
|
||||
NSString *crashLog = crashLogPath();
|
||||
[description writeToFile:crashLog
|
||||
atomically:NO
|
||||
encoding:NSStringEncodingConversionAllowLossy
|
||||
error:nil];
|
||||
|
||||
NSLog(@"[MXLogger] handleUncaughtException:\n%@", description);
|
||||
// MXLogError(@"[MXLogger] handleUncaughtException:\n%@", description);
|
||||
}
|
||||
|
||||
// Signals emitted by the app are handled here
|
||||
static void handleSignal(int signalValue)
|
||||
{
|
||||
// Throw a custom Objective-C exception
|
||||
// The Objective-C runtime will then be able to build a readable call stack in handleUncaughtException
|
||||
[NSException raise:@"Signal detected" format:@"Signal detected: %d", signalValue];
|
||||
}
|
||||
|
||||
+ (void)logCrashes:(BOOL)logCrashes
|
||||
{
|
||||
if (logCrashes)
|
||||
{
|
||||
// Handle not managed exceptions by ourselves
|
||||
NSSetUncaughtExceptionHandler(&handleUncaughtException);
|
||||
|
||||
// Register signal event (seg fault & cie)
|
||||
signal(SIGABRT, handleSignal);
|
||||
signal(SIGILL, handleSignal);
|
||||
signal(SIGSEGV, handleSignal);
|
||||
signal(SIGFPE, handleSignal);
|
||||
signal(SIGBUS, handleSignal);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable crash handling
|
||||
NSSetUncaughtExceptionHandler(NULL);
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
signal(SIGILL, SIG_DFL);
|
||||
signal(SIGSEGV, SIG_DFL);
|
||||
signal(SIGFPE, SIG_DFL);
|
||||
signal(SIGBUS, SIG_DFL);
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)setBuildVersion:(NSString *)theBuildVersion
|
||||
{
|
||||
buildVersion = theBuildVersion;
|
||||
}
|
||||
|
||||
+ (void)setSubLogName:(NSString *)theSubLogName
|
||||
{
|
||||
subLogName = [NSString stringWithFormat:@"-%@", theSubLogName];
|
||||
}
|
||||
|
||||
// Return the path of the crash log file
|
||||
static NSString* crashLogPath(void)
|
||||
{
|
||||
return [[MXLogger logsFolderPath] stringByAppendingPathComponent:MXLOGGER_CRASH_LOG];
|
||||
}
|
||||
|
||||
+ (NSString*)crashLog
|
||||
{
|
||||
NSString *exceptionLog;
|
||||
|
||||
NSString *crashLog = crashLogPath();
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if([fileManager fileExistsAtPath:crashLog])
|
||||
{
|
||||
exceptionLog = crashLog;
|
||||
}
|
||||
return exceptionLog;
|
||||
}
|
||||
|
||||
+ (void)deleteCrashLog
|
||||
{
|
||||
NSString *crashLog = crashLogPath();
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if([fileManager fileExistsAtPath:crashLog])
|
||||
{
|
||||
[fileManager removeItemAtPath:crashLog error:nil];
|
||||
}
|
||||
}
|
||||
|
||||
// The folder where logs are stored
|
||||
+ (NSString*)logsFolderPath
|
||||
{
|
||||
NSString *logsFolderPath = nil;
|
||||
|
||||
// NSURL *sharedContainerURL = [[NSFileManager defaultManager] applicationGroupContainerURL];
|
||||
// if (sharedContainerURL)
|
||||
// {
|
||||
// logsFolderPath = [sharedContainerURL path];
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
NSArray<NSURL *> *paths = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
|
||||
logsFolderPath = paths[0].path;
|
||||
// }
|
||||
|
||||
return logsFolderPath;
|
||||
}
|
||||
|
||||
|
||||
// If [self redirectNSLogToFiles: numberOfFiles:] is called with a lower numberOfFiles we need to do some cleanup
|
||||
+ (void)removeExtraFilesFromCount:(NSUInteger)count
|
||||
{
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *logsFolderPath = [MXLogger logsFolderPath];
|
||||
|
||||
NSUInteger index = count;
|
||||
do
|
||||
{
|
||||
NSString *fileName = [NSString stringWithFormat:@"console%@.%tu.log", subLogName, index];
|
||||
NSString *logFile = [logsFolderPath stringByAppendingPathComponent:fileName];
|
||||
|
||||
if ([fileManager fileExistsAtPath:logFile])
|
||||
{
|
||||
[fileManager removeItemAtPath:logFile error:nil];
|
||||
// MXLogDebug(@"[MXLogger] removeExtraFilesFromCount: %@. removeItemAtPath: %@\n", @(count), logFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (index++);
|
||||
}
|
||||
|
||||
+ (void)removeFilesAfterSizeLimit:(NSUInteger)sizeLimit
|
||||
{
|
||||
NSUInteger logSize = 0;
|
||||
BOOL removeFiles = NO;
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *logsFolderPath = [MXLogger logsFolderPath];
|
||||
|
||||
// Start from console.1.log. Do not consider console.log. It should be almost empty
|
||||
NSUInteger index = 0;
|
||||
while (++index)
|
||||
{
|
||||
NSString *fileName = [NSString stringWithFormat:@"console%@.%tu.log", subLogName, index];
|
||||
NSString *logFile = [logsFolderPath stringByAppendingPathComponent:fileName];
|
||||
|
||||
if ([fileManager fileExistsAtPath:logFile])
|
||||
{
|
||||
logSize += [fileManager attributesOfItemAtPath:logFile error:nil].fileSize;
|
||||
|
||||
if (logSize >= sizeLimit)
|
||||
{
|
||||
removeFiles = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeFiles)
|
||||
{
|
||||
// MXLogDebug(@"[MXLogger] removeFilesAfterSizeLimit: Remove files from index %@ because logs are too large (%@ for a limit of %@)\n",
|
||||
// @(index),
|
||||
// [NSByteCountFormatter stringFromByteCount:logSize countStyle:NSByteCountFormatterCountStyleBinary],
|
||||
// [NSByteCountFormatter stringFromByteCount:sizeLimit countStyle:NSByteCountFormatterCountStyleBinary]);
|
||||
[self removeExtraFilesFromCount:index];
|
||||
}
|
||||
else
|
||||
{
|
||||
// MXLogDebug(@"[MXLogger] removeFilesAfterSizeLimit: No need: %@ for a limit of %@\n",
|
||||
// [NSByteCountFormatter stringFromByteCount:logSize countStyle:NSByteCountFormatterCountStyleBinary],
|
||||
// [NSByteCountFormatter stringFromByteCount:sizeLimit countStyle:NSByteCountFormatterCountStyleBinary]);
|
||||
}
|
||||
|
||||
}
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user