Подтвердить что ты не робот

Глобальный уровень журнала для CocoaLumberjack

Я использую CocoaLumberjack в проекте iPhone, чтобы зарегистрировать некоторую информацию.

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

static const int ddLogLevel = LOG_LEVEL_VERBOSE;

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 3

Нет заголовков префикса.

Вам не нужен теперь устаревший .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__);
}

Ответ 4

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

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

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

Ответ 6

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

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

  • Импортировать заголовок DSLogging.h (два пути):
  • Используйте макросы DSLogLevelSetup... для установки уровня журнала для файла. Примечание: в исходном файле EACH должны быть макросы, в которых используется ведение журнала.

Подробнее см. документацию внутри. Загрузить gist.

DSLogging.h header:

//
//  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.

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

Ответ 7

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

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

static const int ddLogLevel = LOG_LEVEL_VERBOSE;

и все счастливы:)

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

Ответ 8

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

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

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

Ответ 9

Вот пример динамического ведения журнала, который использует код 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

Прошу прокомментировать, Если я неправильно понял или неправильно понял...

Ответ 11

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

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

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

Im мой инструмент, я создаю новый файл заголовка (например, 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