Is it true that one should not use NSLog() on prod

2019-01-01 09:55发布

I was told this a few times in this very site, but I wanted to make sure this is really the case.

I was expecting to be able to sprinkle NSLog function calls throughout my code, and that Xcode/gcc would automatically strip those calls out when building my Release/Distribution builds.

Should I avoid using this? If so, what alternatives are most common between experienced Objective-C programmers?

12条回答
临风纵饮
2楼-- · 2019-01-01 10:17

The simple truth is that NSLog is just plain slow.

But why? To answer that question, let's find out what NSLog does, and then how it does it.

What does NSLog do exactly?

NSLog does 2 things:

It writes log messages to the Apple System Logging (asl) facility. This allows log messages to show up in Console.app. It also checks to see if the application's stderr stream is going to a terminal (such as when the application is being run via Xcode). If so it writes the log message to stderr (so that it shows up in the Xcode console).

Writing to STDERR doesn't sound difficult. That can be accomplished with fprintf and the stderr file descriptor reference. But what about asl?

The best documentation I've found about ASL is a 10 part blog post from Peter Hosey: link

Without going into too much detail, the highlight (as it concerns performance) is this:

To send a log message to the ASL facility, you basically open a client connection to the ASL daemon and send the message. BUT - each thread must use a separate client connection. So, to be thread safe, every time NSLog is called it opens a new asl client connection, sends the message, and then closes the connection.

Resources could be found here & here.

查看更多
步步皆殇っ
3楼-- · 2019-01-01 10:17

I would highly recommend using TestFlight for logging (free). Their method will override NSLog (using a macro) and allow you to turn on/off logging to their server, Apple System log and STDERR log, for all your existing calls to NSLog. The nice thing about this is you can still review your log messages for apps deployed to testers and apps deployed in the App Store, without the logs appearing on the user's system log. The best of both worlds.

查看更多
长期被迫恋爱
4楼-- · 2019-01-01 10:20

I can't comment on Marc Charbonneau's answer, so I'll post this as an answer.

Further to adding the macro to your pre-compiled header, you can use the Target build configurations to control the defining (or lack of defining) the DEBUG_MODE.

If you select "Debug" active configuration, DEBUG_MODE will be defined, and the macro expands to the full NSLog definition.

Selecting the "Release" active configuration will not define DEBUG_MODE and your NSLogging is omitted from the release build.

Steps:

  • Target > Get Info
  • Build tab
  • Search for "PreProcessor Macros" (or GCC_PREPROCESSOR_DEFINITIONS)
  • Select Configuration: Debug
  • Edit Definition at this Level
  • Add DEBUG_MODE=1
  • Select Configuration: Release
  • confirm DEBUG_MODE is not set in GCC_PREPROCESSOR_DEFINITIONS

if you omit the '=' character in the definition, you will get an error from the preprocessor

Also, paste this comment (shown below) above the macro definition to remind you where the DEBUG_MACRO define comes from ;)

// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS
// Configuration = Release: <empty>
//               = Debug:   DEBUG_MODE=1
查看更多
闭嘴吧你
5楼-- · 2019-01-01 10:22

Keep in mind that NSLogs can slow down the UI / main thread. It is best to remove them from release builds unless absolutely necessary.

查看更多
素衣白纱
6楼-- · 2019-01-01 10:25

From a security point of view, it depends on what is being logged. If NSLog (or other loggers) is writing sensitive information, then you should remove the logger in production code.

From an auditing point of view, the auditor does not want to look at each use of NSLog to ensure its not logging sensitive information. He/she will simply tell you to remove the logger.

I work with both groups. We audit code, write the coding guides, etc. Our guide requires that logging is disabled in production code. So the internal teams know not to try it ;)

We will also reject an external app that logs in production because we don't want to accept the risk associated with accidentally leaking sensitive information. We don't care what the developer tells us. Its simply not worth our time to investigate.

And remember, we define 'sensitive', and not the developer ;)

I also perceive an app which performs lots of logging as an app ready to implode. There's a reason so much logging is performed/needed, and its usually not stability. Its right up there with 'watchdog' threads that restart hung services.

If you have never been through a Security Architecture (SecArch) review, these are the sorts of things we look at.

查看更多
伤终究还是伤i
7楼-- · 2019-01-01 10:27

Put this 3 lines at the end of -prefix.pch file:

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

You don't need to define anything into your project, because DEBUG is defined in your build setting by default when you create your project.

查看更多
登录 后发表回答