Czy to prawda, że nie należy używać nslog() w kodzie produkcyjnym?

Powiedziano mi o tym kilka razy na tej stronie, ale chciałem się upewnić, że tak naprawdę jest.

Spodziewałem się, że będę w stanie posypać wywołania funkcji nslog w całym moim kodzie, i że Xcode/gcc automatycznie usunie te wywołania podczas budowania moich wersji/dystrybucji.

Czy powinienem tego unikać? Jeśli tak, to jakie alternatywy występują najczęściej u doświadczonych programistów Objective-C?

Author: jpm, 2008-11-19

12 answers

Makra preprocesora są naprawdę świetne do debugowania. Nie ma nic złego w NSLog (), ale łatwo jest zdefiniować własną funkcję logowania z lepszą funkcjonalnością. Oto ten, którego używam, zawiera nazwę pliku i numer linii, aby ułatwić śledzenie instrukcji dziennika.

#define DEBUG_MODE

#ifdef DEBUG_MODE
    #define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
    #define DebugLog( s, ... ) 
#endif

Uznałem, że łatwiej jest umieścić to całe oświadczenie w nagłówku prefiksu, a nie w jego własnym pliku. Możesz, jeśli chcesz, zbudować bardziej skomplikowany system logowania, mając debuglog interakcji z normalne Obiekty Objective-C. Na przykład, możesz mieć klasę logging, która zapisuje do własnego pliku dziennika (lub bazy danych) i zawiera argument 'priority', który możesz ustawić w czasie wykonywania, Więc komunikaty debugowania nie są wyświetlane w wersji release, ale komunikaty o błędach są (jeśli to zrobiłeś, możesz utworzyć DebugLog (), WarningLog () itd.).

Oh, i pamiętaj #define DEBUG_MODE może być ponownie używany w różnych miejscach w aplikacji. Na przykład w mojej aplikacji używam go do wyłączania sprawdzania kluczy licencyjnych i Zezwalaj na uruchomienie aplikacji tylko wtedy, gdy jest przed określoną datą. To pozwala mi rozpowszechniać ograniczoną czasowo, w pełni funkcjonalną wersję beta przy minimalnym wysiłku z mojej strony.

 196
Author: Marc Charbonneau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-06 22:15:17

Umieść te 3 linie na końcu-prefiksu.plik pch:

#ifndef DEBUG
  #define NSLog(...) /* suppress NSLog when in release mode */
#endif

Nie musisz niczego definiować w swoim projekcie, ponieważ {[1] } jest domyślnie zdefiniowane w Ustawieniach budowania podczas tworzenia projektu.

 77
Author: roel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 05:58:16

Wywołania NSLog mogą być pozostawione w kodzie produkcyjnym, ale powinny być tam tylko dla naprawdę wyjątkowych przypadków lub informacji, które są pożądane, które zostaną zalogowane do dziennika systemowego.

Aplikacje, które zaśmiecają dziennik systemowy, są irytujące i wydają się nieprofesjonalne.

 25
Author: Matthew Schinckel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-19 00:47:50

Nie mogę skomentować odpowiedzi marca Charbonneau , więc wrzucę to jako odpowiedź.

Po dodaniu makra do wstępnie skompilowanego nagłówka, możesz użyć konfiguracji budowania celu, aby kontrolować definiowanie (lub brak definiowania) DEBUG_MODE.

Jeśli wybierzesz" debug " aktywna konfiguracja, DEBUG_MODE zostanie zdefiniowana, a Makro rozszerzy się do pełnej definicji NSLog.

Wybranie aktywnej konfiguracji" Release " nie zdefiniuje {[1] } i Twój NSLogging jest pominięty w release build.

Kroki:

  • Target > Get Info
  • Zakładka budowania
  • wyszukaj "makra preprocesora" (lub GCC_PREPROCESSOR_DEFINITIONS)
  • Wybierz Konfigurację: Debug
  • Edycja definicji na tym poziomie
  • Dodaj DEBUG_MODE=1
  • Wybierz Konfigurację: Release
  • confirm DEBUG_MODE nie jest ustawione w GCC_PREPROCESSOR_DEFINITIONS

jeśli pominiesz '=' znak w definicji, otrzymasz błąd z preprocesora

Również wklej ten komentarz (pokazany poniżej) powyżej definicji makra, aby przypomnieć, skąd pochodzi definicja DEBUG_MACRO;)

// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS
// Configuration = Release: <empty>
//               = Debug:   DEBUG_MODE=1
 23
Author: ohhorob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:43

EDIT: The method posted by Marc Charbonneau , and brought to my attention by sho , is far better than this one.

Usunąłem część mojej odpowiedzi, która sugerowała użycie pustej funkcji do wyłączenia logowania, gdy tryb debugowania jest wyłączony. Część, która zajmuje się ustawianiem automatycznego makra preprocesora, jest nadal istotna, więc pozostaje. Edytowałem również nazwę makra preprocesora, aby lepiej pasowało do Marc Odpowiedź Charbonneau.


Aby osiągnąć automatyczne (i oczekiwane) zachowanie w Xcode:

W ustawieniach projektu przejdź do zakładki " Build "i wybierz konfigurację" Debug". Znajdź sekcję "makra preprocesora" i dodaj makro o nazwie DEBUG_MODE.

...

EDIT: Zobacz odpowiedź marca Charbonneau dla właściwego sposobu włączania i wyłączania logowania za pomocą makra DEBUG_MODE.

 11
Author: e.James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:13

Zgadzam się z Mateuszem. Nie ma nic złego w NSLog w kodzie produkcyjnym. W rzeczywistości może być przydatny dla użytkownika. To powiedziawszy, jeśli jedynym powodem, dla którego używasz NSLog, jest pomoc w debugowaniu,to tak, powinno to zostać usunięte przed wydaniem.

Ponadto, ponieważ otagowałeś to jako pytanie iPhone ' a, NSLog pobiera zasoby, które jest czymś, czego iPhone ma niewiele cennego. Jeśli NSLogging cokolwiek na iPhone, to zabiera czas procesora z aplikacji. Użyj go mądrze.

 7
Author: August,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-19 05:07:15

Prosta prawda jest taka, że NSLog jest po prostu wolny.

Ale dlaczego? Aby odpowiedzieć na to pytanie, dowiedzmy się, co robi NSLog, a następnie jak to robi.

Czym dokładnie zajmuje się NSLog?

NSLog robi 2 rzeczy:

Zapisuje komunikaty logowania do urządzenia Apple System Logging (asl). Umożliwia to wyświetlanie komunikatów dziennika w konsoli.app. Sprawdza również, czy strumień stderr aplikacji trafia do terminala (np. gdy aplikacja jest uruchamiana przez Xcode). Jeśli więc zapisuje wiadomość dziennika na stderr (tak, że pojawia się w konsoli Xcode).

Pisanie na STDERR nie wydaje się trudne. Można to osiągnąć za pomocą fprintf i referencji deskryptora pliku stderr. Ale co z asl?

Najlepszą dokumentacją jaką znalazłem o ASL jest 10-częściowy wpis na blogu Petera Hoseya: link

Bez wchodzenia w zbyt wiele szczegółów, najważniejszym punktem (jeśli chodzi o wydajność) jest to:

Aby wysłać wiadomość log do ASL facility, w zasadzie otwierasz połączenie klienta z demonem ASL i wysyłasz wiadomość. Ale-każdy wątek musi używać oddzielnego połączenia klienta. Tak więc, aby być bezpiecznym dla wątku, za każdym razem, gdy nslog jest wywoływany, otwiera nowe połączenie klienta asl, wysyła wiadomość, a następnie zamyka połączenie.

Zasoby można znaleźć tutaj & tutaj .

 4
Author: Andrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-26 13:17:41

Jak wspomniano w innych odpowiedziach, możesz użyć # define, aby zmienić, czy NSLog jest używany, czy nie podczas kompilacji.

Jednak bardziej elastycznym sposobem jest użycie biblioteki logowania, takiej jak Cocoa Lumberjack , która pozwala zmienić, czy coś jest rejestrowane również w czasie działania.

W kodzie zastąp NSLog przez DDLogVerbose lub ddlogerror etc, dodaj # import dla definicji makr itp i ustaw rejestratory, często w metodzie applicationDidFinishLaunching.

Aby mieć ten sam efekt co NSLog kod konfiguracji to

[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
 2
Author: Mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-09 11:20:02

Z punktu widzenia bezpieczeństwa, to zależy od tego, co jest rejestrowane. Jeśli NSLog (lub inne rejestratory) zapisują poufne informacje, należy usunąć rejestrator w kodzie produkcyjnym.

Z punktu widzenia audytu audytor nie chce patrzeć na każde użycie NSLog, aby upewnić się, że nie rejestruje poufnych informacji. On / ona po prostu powie, aby usunąć rejestrator.

Pracuję z obiema grupami. Kontrolujemy kod, piszemy Przewodniki kodowania itp. Nasz przewodnik wymaga, aby logowanie jest wyłączone w kodzie produkcyjnym. Więc wewnętrzne zespoły wiedzą, żeby tego nie próbować;)

Odrzucimy również zewnętrzną aplikację, która loguje się do produkcji, ponieważ nie chcemy akceptować ryzyka związanego z przypadkowym wyciekiem poufnych informacji. Nie obchodzi nas, co powie nam deweloper. To po prostu nie jest warte naszego czasu na dochodzenie.

I pamiętaj, definiujemy "wrażliwy", a nie deweloper;)

Postrzegam również aplikację, która wykonuje wiele logowań jako aplikację gotową implodować. Jest powód, dla którego tak dużo logowania jest wykonywane/potrzebne, a jego zwykle nie stabilność. Jest tam z wątkami "watchdog", które restartują zawieszone usługi.

Jeśli nigdy nie przechodziłeś przez przegląd architektury zabezpieczeń (SecArch), są to rzeczy, na które patrzymy.

 2
Author: jww,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-21 11:38:18

W kodzie Wydania nie powinieneś niepotrzebnie używać printf lub NSLog. Spróbuj zrobić printf lub NSLog tylko wtedy, gdy aplikacja ma coś złego się z nią stało, tj. błąd nieodwracalny.

 1
Author: MaddTheSane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-18 00:59:48

Należy pamiętać, że NSLogs może spowolnić UI / główny wątek. Najlepiej jest usunąć je z wersji kompilacji, chyba że jest to absolutnie konieczne.

 1
Author: psy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-16 23:17:50

Gorąco polecam korzystanie z TestFlight do logowania (za darmo). Ich metoda nadpisze NSLog (używając makra) i pozwoli Ci włączyć/wyłączyć logowanie do ich serwera, dziennika systemowego Apple i dziennika STDERR, dla wszystkich istniejących wywołań do NSLog. Fajną rzeczą jest to, że nadal możesz przeglądać wiadomości dziennika aplikacji wdrożonych do testerów i aplikacji wdrożonych w App Store, bez dzienników pojawiających się w dzienniku systemowym użytkownika. Najlepsze z obu światów.

 0
Author: Joel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-15 07:32:48