227 lines
7.7 KiB
C
227 lines
7.7 KiB
C
|
|
// Software License Agreement (BSD License)
|
||
|
|
//
|
||
|
|
// Copyright (c) 2010-2023, Deusty, LLC
|
||
|
|
// All rights reserved.
|
||
|
|
//
|
||
|
|
// Redistribution and use of this software in source and binary forms,
|
||
|
|
// with or without modification, are permitted provided that the following conditions are met:
|
||
|
|
//
|
||
|
|
// * Redistributions of source code must retain the above copyright notice,
|
||
|
|
// this list of conditions and the following disclaimer.
|
||
|
|
//
|
||
|
|
// * Neither the name of Deusty nor the names of its contributors may be used
|
||
|
|
// to endorse or promote products derived from this software without specific
|
||
|
|
// prior written permission of Deusty, LLC.
|
||
|
|
|
||
|
|
// Disable legacy macros
|
||
|
|
#ifndef DD_LEGACY_MACROS
|
||
|
|
#define DD_LEGACY_MACROS 0
|
||
|
|
#endif
|
||
|
|
#ifndef DD_NSLOG_LEVEL
|
||
|
|
#define DD_NSLOG_LEVEL 2
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
#import "DDLog.h"
|
||
|
|
#import "DDFileLogger.h"
|
||
|
|
#import "DDLogFileInfo.h"
|
||
|
|
#import "DDLogFileManager.h"
|
||
|
|
#import "DDLogFileManagerDefault.h"
|
||
|
|
#import "DDLogFileFormatterDefault.h"
|
||
|
|
|
||
|
|
#define NSLogError(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 1) NSLog((frmt), ##__VA_ARGS__); } while(0)
|
||
|
|
#define NSLogWarn(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 2) NSLog((frmt), ##__VA_ARGS__); } while(0)
|
||
|
|
#define NSLogInfo(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 3) NSLog((frmt), ##__VA_ARGS__); } while(0)
|
||
|
|
#define NSLogDebug(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 4) NSLog((frmt), ##__VA_ARGS__); } while(0)
|
||
|
|
#define NSLogVerbose(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 5) NSLog((frmt), ##__VA_ARGS__); } while(0)
|
||
|
|
|
||
|
|
|
||
|
|
NS_ASSUME_NONNULL_BEGIN
|
||
|
|
|
||
|
|
/**
|
||
|
|
* This class provides a logger to write log statements to a file.
|
||
|
|
**/
|
||
|
|
|
||
|
|
|
||
|
|
// Default configuration and safety/sanity values.
|
||
|
|
//
|
||
|
|
// maximumFileSize -> kDDDefaultLogMaxFileSize
|
||
|
|
// rollingFrequency -> kDDDefaultLogRollingFrequency
|
||
|
|
// maximumNumberOfLogFiles -> kDDDefaultLogMaxNumLogFiles
|
||
|
|
// logFilesDiskQuota -> kDDDefaultLogFilesDiskQuota
|
||
|
|
//
|
||
|
|
// You should carefully consider the proper configuration values for your application.
|
||
|
|
|
||
|
|
extern unsigned long long const kDDDefaultLogMaxFileSize;
|
||
|
|
extern NSTimeInterval const kDDDefaultLogRollingFrequency;
|
||
|
|
extern NSUInteger const kDDDefaultLogMaxNumLogFiles;
|
||
|
|
extern unsigned long long const kDDDefaultLogFilesDiskQuota;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The standard implementation for a file logger
|
||
|
|
*/
|
||
|
|
@interface DDFileLogger : DDAbstractLogger <DDLogger>
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Designated initializer, requires a `DDLogFileManager` instance.
|
||
|
|
* A global queue w/ default priority is used to run callbacks.
|
||
|
|
* If needed, specify queue using `initWithLogFileManager:completionQueue:`.
|
||
|
|
*/
|
||
|
|
- (instancetype)initWithLogFileManager:(id <DDLogFileManager>)logFileManager logfileFormatter:(nullable DDLogFileFormatterDefault *)logfileFormatter;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Designated initializer, requires a `DDLogFileManager` instance.
|
||
|
|
* The completionQueue is used to execute `didArchiveLogFile:wasRolled:`,
|
||
|
|
* and the callback in `rollLogFileWithCompletionBlock:`.
|
||
|
|
* If nil, a global queue w/ default priority is used.
|
||
|
|
*/
|
||
|
|
- (instancetype)initWithLogFileManager:(id <DDLogFileManager>)logFileManager logfileFormatter:(nullable DDLogFileFormatterDefault *)logfileFormatter completionQueue:(nullable dispatch_queue_t)dispatchQueue NS_DESIGNATED_INITIALIZER;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Deprecated. Use `willLogMessage:`
|
||
|
|
*/
|
||
|
|
- (void)willLogMessage __attribute__((deprecated("Use -willLogMessage:"))) NS_REQUIRES_SUPER;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Deprecated. Use `didLogMessage:`
|
||
|
|
*/
|
||
|
|
- (void)didLogMessage __attribute__((deprecated("Use -didLogMessage:"))) NS_REQUIRES_SUPER;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Called when the logger is about to write message. Call super before your implementation.
|
||
|
|
*/
|
||
|
|
- (void)willLogMessage:(DDLogFileInfo *)logFileInfo NS_REQUIRES_SUPER;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Called when the logger wrote message. Call super after your implementation.
|
||
|
|
*/
|
||
|
|
- (void)didLogMessage:(DDLogFileInfo *)logFileInfo NS_REQUIRES_SUPER;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Writes all in-memory log data to the permanent storage. Call super before your implementation.
|
||
|
|
* Don't call this method directly, instead use the `[DDLog flushLog]` to ensure all log messages are included in flush.
|
||
|
|
*/
|
||
|
|
- (void)flush NS_REQUIRES_SUPER;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Called when the logger checks archive or not current log file.
|
||
|
|
* Override this method to extend standard behavior. By default returns NO.
|
||
|
|
* This is executed directly on the logger's internal queue, so keep processing light!
|
||
|
|
*/
|
||
|
|
- (BOOL)shouldArchiveRecentLogFileInfo:(DDLogFileInfo *)recentLogFileInfo;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Log File Rolling:
|
||
|
|
*
|
||
|
|
* `maximumFileSize`:
|
||
|
|
* The approximate maximum size (in bytes) to allow log files to grow.
|
||
|
|
* If a log file is larger than this value after a log statement is appended,
|
||
|
|
* then the log file is rolled.
|
||
|
|
*
|
||
|
|
* `rollingFrequency`
|
||
|
|
* How often to roll the log file.
|
||
|
|
* The frequency is given as an `NSTimeInterval`, which is a double that specifies the interval in seconds.
|
||
|
|
* Once the log file gets to be this old, it is rolled.
|
||
|
|
*
|
||
|
|
* `doNotReuseLogFiles`
|
||
|
|
* When set, will always create a new log file at application launch.
|
||
|
|
*
|
||
|
|
* Both the `maximumFileSize` and the `rollingFrequency` are used to manage rolling.
|
||
|
|
* Whichever occurs first will cause the log file to be rolled.
|
||
|
|
*
|
||
|
|
* For example:
|
||
|
|
* The `rollingFrequency` is 24 hours,
|
||
|
|
* but the log file surpasses the `maximumFileSize` after only 20 hours.
|
||
|
|
* The log file will be rolled at that 20 hour mark.
|
||
|
|
* A new log file will be created, and the 24 hour timer will be restarted.
|
||
|
|
*
|
||
|
|
* You may optionally disable rolling due to filesize by setting `maximumFileSize` to zero.
|
||
|
|
* If you do so, rolling is based solely on `rollingFrequency`.
|
||
|
|
*
|
||
|
|
* You may optionally disable rolling due to time by setting `rollingFrequency` to zero (or any non-positive number).
|
||
|
|
* If you do so, rolling is based solely on `maximumFileSize`.
|
||
|
|
*
|
||
|
|
* If you disable both `maximumFileSize` and `rollingFrequency`, then the log file won't ever be rolled.
|
||
|
|
* This is strongly discouraged.
|
||
|
|
**/
|
||
|
|
@property (readwrite, assign) unsigned long long maximumFileSize;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* See description for `maximumFileSize`
|
||
|
|
*/
|
||
|
|
@property (readwrite, assign) NSTimeInterval rollingFrequency;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* See description for `maximumFileSize`
|
||
|
|
*/
|
||
|
|
@property (readwrite, assign, atomic) BOOL doNotReuseLogFiles;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The DDLogFileManager instance can be used to retrieve the list of log files,
|
||
|
|
* and configure the maximum number of archived log files to keep.
|
||
|
|
*
|
||
|
|
* @see DDLogFileManager.maximumNumberOfLogFiles
|
||
|
|
**/
|
||
|
|
@property (strong, nonatomic, readonly) id <DDLogFileManager> logFileManager;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* When using a custom formatter you can set the `logMessage` method not to append
|
||
|
|
* `\n` character after each output. This allows for some greater flexibility with
|
||
|
|
* custom formatters. Default value is YES.
|
||
|
|
**/
|
||
|
|
@property (nonatomic, readwrite, assign) BOOL automaticallyAppendNewlineForCustomFormatters;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* You can optionally force the current log file to be rolled with this method.
|
||
|
|
* CompletionBlock will be called on main queue.
|
||
|
|
*/
|
||
|
|
- (void)rollLogFileWithCompletionBlock:(nullable void (^)(void))completionBlock
|
||
|
|
NS_SWIFT_NAME(rollLogFile(withCompletion:));
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Method is deprecated.
|
||
|
|
* @deprecated Use `rollLogFileWithCompletionBlock:` method instead.
|
||
|
|
*/
|
||
|
|
- (void)rollLogFile __attribute__((deprecated("Use -rollLogFileWithCompletionBlock:")));
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
- (void)logData:(NSData *)data;
|
||
|
|
|
||
|
|
// Will assert if used outside logger's queue.
|
||
|
|
- (void)lt_logData:(NSData *)data;
|
||
|
|
|
||
|
|
- (nullable NSData *)lt_dataForMessage:(DDLogMessage *)message;
|
||
|
|
|
||
|
|
|
||
|
|
// Inherited from DDAbstractLogger
|
||
|
|
|
||
|
|
// - (id <DDLogFormatter>)logFormatter;
|
||
|
|
// - (void)setLogFormatter:(id <DDLogFormatter>)formatter;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Returns the log file that should be used.
|
||
|
|
* If there is an existing log file that is suitable,
|
||
|
|
* within the constraints of `maximumFileSize` and `rollingFrequency`, then it is returned.
|
||
|
|
*
|
||
|
|
* Otherwise a new file is created and returned. If this failes, `NULL` is returned.
|
||
|
|
**/
|
||
|
|
@property (nonatomic, nullable, readonly, strong) DDLogFileInfo *currentLogFileInfo;
|
||
|
|
|
||
|
|
@end
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
NS_ASSUME_NONNULL_END
|