36

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

我遵循了入门指南,一切正常,但有一件事让我很头疼:似乎没有一种优雅的方式来定义整个应用程序的日志级别。为了使它工作,我需要在每个源文件中定义一个常量,如下所示:

static const int ddLogLevel = LOG_LEVEL_VERBOSE;

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

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

4

12 回答 12

21

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

于 2011-03-01T14:16:01.433 回答
18

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

常量.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");
}
于 2011-03-07T10:52:32.713 回答
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

记录器.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__);
}
于 2014-11-13T11:59:19.207 回答
5

您可以在 *.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];

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

于 2013-12-09T07:58:48.273 回答
5

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

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。

于 2014-04-30T09:31:43.047 回答
4

对于那些使用 CocoaLumberjackSwift 的人,您可以简单地在代码中的任何位置设置以下全局变量:

dynamicLogLevel = .verbose

在这里讨论

于 2020-07-26T16:53:11.617 回答
3

分享我对 CocoaLumberjack 2.0.0 的配置,global log level并可选择local log level保留DynamicLogLevels 功能

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

  1. 导入DSLogging.h标头(两种方式):
  2. 使用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;

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

  1. 它比 CocoaLumberjack 好一点

    • 全局级别(可以是可变的)
    • 允许您按本地级别“覆盖”全局级别(可以是可变的)
  2. 它不会削减 CocoaLumberjack 功能

    • 使用变量设置级别,因此可以与 CocoaLumberjack 的高级功能一起使用。

我是 CocoaLumberjack 的新手,我可能对我的方法过于乐观,如果我在某个时候撒谎,我会很高兴听到你的批评。

于 2015-04-24T02:55:31.877 回答
0

我这样做的方式受到了这个答案的启发.. 然而,这就是我以不同的方式做的方式,这样我就可以拥有一个全局级别的日志级别,并且如果我这样选择的话,我能够覆盖每个文件中的全局日志级别:

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

static const int ddLogLevel = LOG_LEVEL_VERBOSE;

每个人都很高兴:)

ps这是一个免费的解决方案..最初我尝试过,但是当我想在文件级别覆盖它时.pch,编译器会抱怨已经定义ddLogLevel

于 2015-01-12T13:16:15.397 回答
0

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

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

所以不需要额外的导入或 .pch 文件。

于 2015-05-22T06:55:49.700 回答
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

主文件

#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

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

于 2015-06-06T14:09:04.487 回答
-1

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

于 2012-02-01T23:25:46.903 回答
-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)。这样,我#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
于 2014-06-04T14:12:49.467 回答