Уровень глобального журнала для CocoaLumberjack - PullRequest
35 голосов
/ 25 февраля 2011

Я использую CocoaLumberjack в проекте iPhone для регистрации некоторой информации.

Я следовал Руководство по началу работы , и все работает нормально,но есть одна вещь, которая меня беспокоит: похоже, не существует элегантного способа определения уровня журнала для всего приложения.Чтобы это работало, мне нужно определить константу в каждом исходном файле, например:

static const int ddLogLevel = LOG_LEVEL_VERBOSE;

Итак, есть ли способ определить глобальный уровень журнала для приложения?

Iнашел эту статью на эту тему, но мне все еще нужно добавить #import в каждый файл ...

Ответы [ 11 ]

21 голосов
/ 01 марта 2011

Вы можете использовать оператор #include в файле * .pch, чтобы он автоматически включался во все файлы вашего проекта.

18 голосов
/ 07 марта 2011

Я не нашел лучшего способа сделать это, чем тот, который описан в статье , о которой я упоминал в вопросе.

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");
}
16 голосов
/ 13 ноября 2014

Не нужно больше префиксных заголовков, пожалуйста.

Вам не нужен устаревший .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__);
}
5 голосов
/ 09 декабря 2013

Вы можете использовать это в своем файле * .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];

Определение уровня ведения журнала в каждом упомянутом вами исходном файле имеет преимущество. Вы можете использовать подробный уровень ведения журнала только для той части, над которой вы сейчас работаете. Для остальной части вы можете использовать другой уровень, как информация, предупреждение, ошибка.

4 голосов
/ 30 апреля 2014

Чтобы динамически внедрить уровень журнала (например, из файла конфигурации):

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 с нужным уровнем.

2 голосов
/ 24 апреля 2015

Поделитесь моей конфигурацией для CocoaLumberjack 2.0.0 с global log level и необязательно local log level с сохраненной функцией DynamicLogLevels .

Мое решение включает простой заголовочный файл DSLogging.h (и его аналог), который импортирует CocoaLumberjack.h и определяет удобные макросы для настройки файлов, использующих макросы журнала CocoaLumberjack. Вот как вы должны его использовать:

  1. Import 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 и могу быть слишком оптимистичен в отношении моего подхода, был бы рад услышать ваших критиков, если я лгу в какой-то момент.

0 голосов
/ 06 июня 2015

Ниже приведен пример динамического ведения журнала, в котором используется код DSLogging DanSkeels:

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

Прокомментируйте, пожалуйста, если я что-то неправильно понял или неправильно использовал ...

0 голосов
/ 22 мая 2015

Существует гораздо более простой способ решить эту проблему, вы можете установить уровень журнала в экземпляре Logger:

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

Так что нет необходимости в дополнительном импорте или .pch-файле.

0 голосов
/ 12 января 2015

То, как я это сделал, было вдохновлено этим ответом. Однако я сделал это по-другому, так что я мог иметь как глобальный уровень журнала , так и , чтобы иметь возможностьпереопределите уровень глобального журнала в каждом файле, если я выбрал:

  • Вместо вызова файла Constants.h я назвал его GlobalDebugLevel.h.Это связано с тем, что не имеет смысла включать какие-либо другие глобальные константы в этот файл, если только вы действительно не будете всегда использовать глобальный уровень отладки и не будете использовать для определенных уровней файлов журнала.* В файлах, которые я хочу иметь свой собственный уровень журнала .. Я просто закомментирую `#import" GlobalLogLevel.h "и затем добавлю что-то вроде этого:

static const int ddLogLevel = LOG_LEVEL_VERBOSE;

и все довольны:)

ps это бесплатное решение .pch. Сначала я попробовал это, но потом компилятор пожаловался бы, что ddLogLevel уже определено всякий раз, когда я хочу переопределить его вуровень файла

0 голосов
/ 04 июня 2014

Как ответил FreeAsInBeer, вы можете определить эту константу в файле .pch. Вы можете сделать это в файле .pch.

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

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

Я - мой инструмент, я создаю новый заголовочный файл (например, mylog.h) для пользовательских настроек Lumberjack. таким образом я использую оператор #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
...