我在一个 iPhone 项目中使用CocoaLumberjack来记录一些信息。
我遵循了入门指南,一切正常,但有一件事让我很头疼:似乎没有一种优雅的方式来定义整个应用程序的日志级别。为了使它工作,我需要在每个源文件中定义一个常量,如下所示:
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
那么,有没有办法为应用程序定义一个全局日志级别?
我在这个主题上找到了这篇文章,但我仍然需要在每个文件中添加一个#import ......
我在一个 iPhone 项目中使用CocoaLumberjack来记录一些信息。
我遵循了入门指南,一切正常,但有一件事让我很头疼:似乎没有一种优雅的方式来定义整个应用程序的日志级别。为了使它工作,我需要在每个源文件中定义一个常量,如下所示:
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
那么,有没有办法为应用程序定义一个全局日志级别?
我在这个主题上找到了这篇文章,但我仍然需要在每个文件中添加一个#import ......
您可以在 *.pch 文件中使用#include
语句,以便它自动包含在您的所有项目文件中。
我没有找到比我在问题中提到的文章中解释的更好的方法。
常量.h
extern int const ddLogLevel;
常数.m
#import "Constants.h"
#import "DDLog.h"
int const ddLogLevel = LOG_LEVEL_VERBOSE;
记录器配置
#import "DDLog.h"
#import "DDASLLogger.h"
#import "DDTTYLogger.h"
#import "DDFileLogger.h"
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
DDFileLogger *fileLogger = [[DDFileLogger alloc] init];
[DDLog addLogger:fileLogger];
[fileLogger release];
...
导入您的课程
#import "DDLog.h"
#import "Constants.h"
...
- (void)someMethod {
DDLogVerbose(@"Log this message");
}
您不需要现在已弃用的.pch
文件,只需在需要的地方包含一个头文件。
#ifndef Project_Logger_h
#define Project_Logger_h
#if defined(__OBJC__)
#import <CocoaLumberjack/DDLog.h>
extern int ddLogLevel;
#endif
#endif
#import "Logger.h"
int ddLogLevel = LOG_LEVEL_VERBOSE;
#import <CocoaLumberjack/CocoaLumberjack.h>
int ddLogLevel = DDLogLevelVerbose;
如果 2.0 退出测试版时语法发生变化,请评论或编辑。
#import "AppDelegate.h"
#import "Logger.h"
#import <CocoaLumberjack/DDFileLogger.h>
#import <CocoaLumberjack/DDASLLogger.h>
#import <CocoaLumberjack/DDTTYLogger.h>
@interface AppDelegate ()
@property (strong, nonatomic) DDFileLogger *fileLogger;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
DDFileLogger *fileLogger = [[DDFileLogger alloc] init];
fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling
fileLogger.logFileManager.maximumNumberOfLogFiles = 7;
[DDLog addLogger:fileLogger];
self.fileLogger = fileLogger;
DDLogDebug(@"%s", __PRETTY_FUNCTION__);
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
DDLogDebug(@"%s", __PRETTY_FUNCTION__);
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
DDLogDebug(@"%s", __PRETTY_FUNCTION__);
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
DDLogDebug(@"%s", __PRETTY_FUNCTION__);
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
DDLogDebug(@"%s", __PRETTY_FUNCTION__);
}
- (void)applicationWillTerminate:(UIApplication *)application
{
DDLogDebug(@"%s", __PRETTY_FUNCTION__);
}
您可以在 *.pch 文件中使用它来根据您当前的构建配置自动获取不同的全局日志级别。[对于 xcode 4+]
#ifdef DEBUG
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#else
static const int ddLogLevel = LOG_LEVEL_WARN;
#endif
或者如果您需要为每个记录器设置不同的日志级别,您可以使用 DDLog +addLogger:withLogLevel: 方法轻松实现。
[DDLog addLogger:[DDASLLogger sharedInstance] withLogLevel:LOG_LEVEL_INFO];
[DDLog addLogger:[DDTTYLogger sharedInstance] withLogLevel:LOG_LEVEL_DEBUG];
在您提到的每个源文件中定义日志级别是有好处的。您可以仅对当前正在处理的部分使用详细日志记录级别。对于其余部分,您可以使用其他级别,如信息、警告、错误。
为了动态注入日志级别(例如,从配置文件):
1) 使用以下代码创建一个名为 DDLogLevel 的新类:
#import "DDLogLevel.h"
#import "DDLog.h"
@implementation DDLogLevel
static int _ddLogLevel = LOG_LEVEL_VERBOSE;
+ (int)ddLogLevel
{
return _ddLogLevel;
}
+ (void)ddSetLogLevel:(int)logLevel
{
_ddLogLevel = logLevel;
}
@end
2) 在 DDLogLevel.h 中,找到包含以下语句的行:
#ifndef LOG_LEVEL_DEF
#define LOG_LEVEL_DEF ddLogLevel
#endif
并将其替换为:
#ifndef LOG_LEVEL_DEF
#define LOG_LEVEL_DEF [DDLogLevel ddLogLevel]
#endif
3) 最后,从您的初始化过程(可能来自 appDelegate)调用具有所需级别的 ddSetLogLevel。
分享我对 CocoaLumberjack 2.0.0 的配置,global log level
并可选择local log level
保留DynamicLogLevels 功能。
我的解决方案包括简单的头文件DSLogging.h
(它是对应的),它导入CocoaLumberjack.h
和定义方便的宏来设置使用 CocoaLumberjack 日志宏的文件。以下是您应该如何使用它:
DSLogging.h
标头(两种方式):
.pch
文件一次。在走这条路之前考虑一下。DSLogLevelSetup...
宏来设置文件的日志级别。注意:每个源文件中都应该有使用日志记录的宏。有关详细信息,请参阅内部文档。下载要点。
DSLogging.h
标题://
// Created by DanSkeel on 23.04.15.
#import "CocoaLumberjack.h"
#define DS_LogScopeGlobal extern
#define DS_LogScopeLocal static
#define DS_LogMutableYes
#define DS_LogMutableNo const
#define DS_LogValueGlobal ;
#define DS_LogValueLocal(lvl) = lvl
#define DS_Setup_Log(scope, mutablility, value) scope mutablility DDLogLevel ddLogLevel value
/** To setup loggin enviroment for particular file use one of these macros
*
* @note Use CocoaLumberjack as usual (https://github.com/CocoaLumberjack/CocoaLumberjack/blob/master/Documentation/GettingStarted.md):
*
* 1. just import DSLoggin.h in source file instead of CocoaLumberjack.h
*
* 2. Use one of these macros to setup loggin enviroment for the file.
* Note: there should one of these macros in EACH file that uses CocoaLumberjack macroses.
* @example To enable logging for file with globally defined level you can make convinient snippet:
* @code
* #import "DSLogging.h"
* DSLogLevelSetupGlobal
* @endcode
*
* Use @b SetupGlobal to setup files that will use global level from @p DSLogging.m file
*
* Use @b SetupMutableGlobal to be able to change global level at runtime (assign new level to ddLogLevel variable)
*
* Use @b Setup(DDLogLevel) to set local log level
*
* Use @b SetupMutable(DDLogLevel) to be able to modify local level at runtime ((assign new level to ddLogLevel variable))
*
* This approach preserves a lot of CocoaLumberjack advantages. See SO https://stackoverflow.com/a/29837945/991816
*
* @remarks details: these macros just help you define/reference ddLogLevel value. So if you
* see warning about <i> undeclared identifier </i> it should remind you to use one of these macros in this file.
*/
extern char optionClickMeToSeePrettyDoc;
#define DSLogLevelSetupMutableGlobal DS_Setup_Log(DS_LogScopeGlobal, DS_LogMutableYes, DS_LogValueGlobal)
#define DSLogLevelSetupGlobal DS_Setup_Log(DS_LogScopeGlobal, DS_LogMutableNo, DS_LogValueGlobal)
#define DSLogLevelSetupMutable(lvl) DS_Setup_Log(DS_LogScopeLocal, DS_LogMutableYes, DS_LogValueLocal(lvl))
#define DSLogLevelSetup(lvl) DS_Setup_Log(DS_LogScopeLocal, DS_LogMutableNo, DS_LogValueLocal(lvl))
DSLogging.m
来源://
// Created by DanSkeel on 23.04.15.
#import "DSLogging.h"
DDLogLevel ddLogLevel = DDLogLevelVerbose;
它比 CocoaLumberjack 好一点
它不会削减 CocoaLumberjack 功能
我是 CocoaLumberjack 的新手,我可能对我的方法过于乐观,如果我在某个时候撒谎,我会很高兴听到你的批评。
我这样做的方式受到了这个答案的启发.. 然而,这就是我以不同的方式做的方式,这样我就可以拥有一个全局级别的日志级别,并且如果我这样选择的话,我能够覆盖每个文件中的全局日志级别:
Constants.h
它GlobalDebugLevel.h
。这是因为在此文件中包含任何其他全局常量是没有意义的,除非您真的将始终使用全局调试级别并且不使用文件特定的日志级别。static const int ddLogLevel = LOG_LEVEL_VERBOSE;
每个人都很高兴:)
ps这是一个免费的解决方案..最初我尝试过,但是当我想在文件级别覆盖它时.pch
,编译器会抱怨已经定义ddLogLevel
有一种更简单的方法可以解决这个问题,您可以在 Logger 实例化时设置日志级别:
#ifdef DEBUG
[DDLog addLogger:[DDTTYLogger sharedInstance] withLevel:DDLogLevelDebug];
#else
[DDLog addLogger:[DDTTYLogger sharedInstance] withLevel:DDLogLevelError];
#endif
所以不需要额外的导入或 .pch 文件。
这是一个动态日志记录示例,它使用下面的 DanSkeels DSLogging 代码:
GFDPerson.h
#import <Foundation/Foundation.h>
@interface GFDPerson : NSObject{
@protected
NSArray *pLogLevelNames;
NSArray *pLogLevelKeys;
NSDictionary *pLogLevels;
}
-(void)logPerson;
-(void)setLogLevel:(NSUInteger)logLevel;
@end
GFDPerson.m
#import "GFDPerson.h"
#import "DSLogging.h"
DSLogLevelSetupMutable(DDLogLevelWarning);
@implementation GFDPerson
-(id)init{
if (self = [super init]) {
pLogLevelNames = [[NSArray alloc] initWithObjects:
@"no logging",
@"only errors",
@"errors and warnings",
@"errors, warnings and infos",
@"verbose",
nil];
pLogLevelKeys = [[NSArray alloc] initWithObjects:
[[NSNumber numberWithInteger:DDLogLevelOff]stringValue],
[[NSNumber numberWithInteger:DDLogLevelError]stringValue],
[[NSNumber numberWithInteger:DDLogLevelWarning]stringValue],
[[NSNumber numberWithInteger:DDLogLevelInfo]stringValue],
[[NSNumber numberWithInteger:DDLogLevelVerbose]stringValue],
nil];
pLogLevels = [[NSDictionary alloc]initWithObjects:pLogLevelNames
forKeys:pLogLevelKeys];
return self;
}
return nil;
}
-(void)setLogLevel:(NSUInteger)logLevel{
ddLogLevel = logLevel;
}
-(void)logPerson{
NSLog(@"Person is logging with Loglevel: %@",[pLogLevels valueForKey: [[NSNumber numberWithInteger:ddLogLevel]stringValue]]);
DDLogVerbose(@"Person log verbose");
DDLogInfo(@"Person log info");
DDLogWarn(@"Person log warning");
DDLogError(@"Person log error");
DDLogDebug(@"Person log debug");
}
@end
主文件
#import <Foundation/Foundation.h>
#import "DSLogging.h"
#import "GFDPerson.h"
DSLogLevelSetupMutable(DDLogLevelError);
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
ddLogLevel = DDLogLevelWarning;
NSLog(@"Warning:");
DDLogWarn(@"WARNING LOG!");
DDLogError(@"ERROR LOG!");
DDLogVerbose(@"VERBOSE LOG!");
ddLogLevel = DDLogLevelError;
NSLog(@"Error:");
DDLogWarn(@"WARNING LOG!");
DDLogError(@"ERROR LOG!");
DDLogVerbose(@"VERBOSE LOG!");
ddLogLevel = DDLogLevelOff;
NSLog(@"Off:");
DDLogWarn(@"WARNING LOG!");
DDLogError(@"ERROR LOG!");
DDLogVerbose(@"VERBOSE LOG!");
ddLogLevel = DDLogLevelVerbose;
NSLog(@"Verbose:");
DDLogWarn(@"WARNING LOG!");
DDLogError(@"ERROR LOG!");
DDLogVerbose(@"VERBOSE LOG!");
ddLogLevel = DDLogLevelOff;
GFDPerson *personA = [[GFDPerson alloc] init];
[personA logPerson];
[personA setLogLevel:DDLogLevelVerbose];
[personA logPerson];
[personA setLogLevel:DDLogLevelError];
[personA logPerson];
}
return 0;
}
此代码的输出:
Warning:
WARNING LOG!
ERROR LOG!
Error:
ERROR LOG!
Off:
Verbose:
WARNING LOG!
ERROR LOG!
VERBOSE LOG!
Person is logging with Loglevel: errors and warnings
Person log warning
Person log error
Person is logging with Loglevel: verbose
Person log verbose
Person log info
Person log warning
Person log error
Person log debug
Person is logging with Loglevel: only errors
Person log error
请评论,如果我误解或误用了某些东西......
CocoaLumberjack 包含一个示例应用程序,它展示了如何设置全局日志级别,您可以在此处找到https://github.com/robbiehanson/CocoaLumberjack/tree/master/Xcode/GlobalLogLevel
正如 FreeAsInBeer 所回答的那样,您可以在 .pch 文件中定义此常量。您可以在 .pch 文件中这样做。
// include Lumberjack header file
#import <Lumberjack/Lumberjack.h>
// define ddLogLevel constant
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
我是我的工具,我为自定义 Lumberjack 设置创建了一个新的头文件(例如 mylog.h)。这样,我#import
在我的 .pch 文件中使用语句来包含 mylog.h。这个自定义头文件可能是这样的。
// include Lumberjack header file
#import "Lumberjack.h"
#undef ZEKit_LOG_LEVEL
#if defined (DEBUG) && (DEBUG == 1)
#define ZEKit_LOG_LEVEL LOG_LEVEL_VERBOSE
#else
#define ZEKit_LOG_LEVEL LOG_LEVEL_WARN
#endif
static const int ddLogLevel = ZEKit_LOG_LEVEL;
// ... Other custom settings