CocoaLumberjack的全局日志级别

时间:2011-02-25 13:56:48

标签: ios objective-c logging lumberjack

我在iPhone项目中使用CocoaLumberjack来记录一些信息。

我已经关注the Getting started guide,一切正常,但有一件事让我感到困惑:似乎没有一种优雅的方式来定义整个应用程序的日志级别。为了使它工作,我需要在每个源文件中定义一个常量,如下所示:

static const int ddLogLevel = LOG_LEVEL_VERBOSE;

那么,有没有办法为应用程序定义全局日志级别?

我在主题上找到了this article,但我仍然需要在每个文件中添加#import ...

12 个答案:

答案 0 :(得分:21)

您可以在* .pch文件中使用#include语句,以便它自动包含在您项目的所有文件中。

答案 1 :(得分:18)

我没有找到比我在问题中提到的the article中解释的更好的方法。

Constant.h

extern int const ddLogLevel;

Constant.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");
}

答案 2 :(得分:16)

请不要再使用前缀标题。

您不需要现已弃用的.pch文件,只需在需要时包含头文件。

Logger.h - CocoaLumberjack 1.9.x

#ifndef Project_Logger_h
#define Project_Logger_h

#if defined(__OBJC__)

#import <CocoaLumberjack/DDLog.h>
extern int ddLogLevel;

#endif

#endif

Logger.m

#import "Logger.h"

int ddLogLevel = LOG_LEVEL_VERBOSE;

CocoaLumberjack 2.x的更改

#import <CocoaLumberjack/CocoaLumberjack.h>

int ddLogLevel = DDLogLevelVerbose;

如果2.0超出测试版时语法发生变化,请发表评论或编辑。

AppDelegate中的示例用法

#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__);
}

答案 3 :(得分:5)

您可以在* .pch文件中使用此功能,根据您当前的构建配置自动获取不同的全局日志级别。[for 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];

在您提到的每个源文件中定义日志级别都有好处。您可以仅为当前正在处理的部分使用详细日志记录级别。对于休息部分,您可以使用其他级别,如信息,警告,错误。

答案 4 :(得分:4)

为了动态注入日志级别(例如,从配置文件中):

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并调用所需的级别。

答案 5 :(得分:3)

对于使用CocoaLumberjackSwift的用户,您只需在代码中的任何位置设置以下全局变量即可:

dynamicLogLevel = .verbose

Discussion here

答案 6 :(得分:2)

将CocoaLumberjack 2.0.0的配置与global log level和可选的local log level共享,并保留DynamicLogLevels feature

我的解决方案包括导入DSLogging.h的简单头文件CocoaLumberjack.h(并且它是对应的),并定义了用于设置使用CocoaLumberjack日志宏的文件的便捷宏。以下是您应该如何使用它:

  1. 导入DSLogging.h标题(两种方式):
  2. 使用DSLogLevelSetup...宏设置文件的日志级别。注意:EACH源文件中应该有使用日志记录的宏。
  3. 有关详细信息,请参阅内部文档。 Download gist

    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;
    

    为什么我认为这是一个好方法:

    1. 这比CocoaLumberjack好一点

      • 全球水平(可以变异)
      • 允许您按地方级别“覆盖”全局级别(可以是可变的)
    2. 它没有削减CocoaLumberjack函数

      • 使用变量来设置级别,因此它可以与CocoaLumberjack的高级功能一起使用。
    3. 我是CocoaLumberjack的新手,我对自己的方法过于乐观,如果我在某个方面撒谎,我会很高兴听到你们的批评。

答案 7 :(得分:0)

我这样做的方式受到this回答的启发..然而,这就是我的不同之处,以便我可以同时覆盖全局级别的日志级别如果我选择的话,每个文件中的全局日志级别:

  • 我没有调用文件Constants.h,而是调用了GlobalDebugLevel.h。这是因为在此文件中包含任何其他全局常量没有意义,除非您确实始终使用全局调试级别并且不使用特定于文件的日志级别。
  • 在我希望拥有它自己的日志级别的文件中..我只是注释掉`#import“GlobalLogLevel.h”然后包含这样的内容:

static const int ddLogLevel = LOG_LEVEL_VERBOSE;

每个人都很高兴:)

P.S。这是一个.pch免费的解决方案..从头开始我试过了但是编译器会抱怨ddLogLevel已经定义,只要我想在文件级覆盖它

答案 8 :(得分:0)

有一种更简单的方法可以解决这个问题,你可以在Logger实例化中设置日志级别:

#ifdef DEBUG
  [DDLog addLogger:[DDTTYLogger sharedInstance] withLevel:DDLogLevelDebug];
#else
  [DDLog addLogger:[DDTTYLogger sharedInstance] withLevel:DDLogLevelError];
#endif

因此不需要额外的导入或.pch文件。

答案 9 :(得分:0)

这是一个动态日志记录示例,它使用下面的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

的main.m

#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

请评论,如果我误解或误用了某些东西......

答案 10 :(得分:-1)

CocoaLumberjack附带了一个示例应用程序,它显示了如何设置可在此处找到的全局日志级别https://github.com/robbiehanson/CocoaLumberjack/tree/master/Xcode/GlobalLogLevel

答案 11 :(得分:-1)

正如FreeAsInBeer所回答的那样,您可以在.pch文件中定义此常量。您可以在.pch文件中执行此操作。

// include Lumberjack header file 
#import <Lumberjack/Lumberjack.h>

// define ddLogLevel constant
static const int ddLogLevel = LOG_LEVEL_VERBOSE;

我是我的工具,我为自定义Lumberjack设置创建了一个新的头文件(例如mylog.h)。这样,我在.pch文件中使用#import语句来包含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