Overly verbose logs produced by 3rd party libraries can be hidden in Swift by setting OS_ACTIVITY_MODE
environmnet variable to disable
in your run scheme - as shown on the image below.
That silences all NSLog
output from your app. I want to disable it only for certain calls. I tried to set the environment variable like this:
setenv("OS_ACTIVITY_MODE", "disable", 1)
And like this
putenv(UnsafeMutablePointer<Int8>(mutating: ("OS_ACTIVITY_MODE=disable" as NSString).utf8String))
The environment is changed as verified by calling print(ProcessInfo.processInfo.environment)
but there unlike specifying it in XCode run scheme, the logs are not affected.
Why doesn't it work and how to fix it?
When you set OS_ACTIVITY_MODE to disable
, you disable all log outputs for processes that have access to this environment variable, for example the simulators.
When you set the value to either info
or debug
it enables the corresponding logging mode unless it is disabled in the logging preferences for certain log categories.
So in order to enable only a certain log category, you have to enable OS_ACTIVITY_MODE, that is, set it either to info
or debug
or leave it at the default, and then disable logging for all other categories.
For more information how to do this see the man page for log, type man log
in the console.
In the console type:
xcrun simctl spawn booted log config --status
That basically means: apply log config -status
to all booted simulators.
This may print the following to your console:
System mode = INFO STREAM_LIVE PRIVATE_DATA
xcrun simctl spawn booted log config --status --subsystem com.mycompany.myapp --category network
This may print the below to the console:
Mode for 'com.mycompany.myapp(network)' INFO PERSIST_DEFAULT
For help, the tools xcrun simctl
and log
have nifty man pages and help pages.
For example:
type log config --help
into the console, it prints:
usage: log config [options] --mode <modes>
or: log config [options] --status
or: log config [options] --reset
description:
Read or configure settings for the logging system. Configuration
can act system-wide; or on a subsystem, category, or process level.
options:
--category <name> Get/set settings for a given category
--mode <modes> Enable given modes
--process <pid> | <name> Get/set settings for a given process
--reset Reset settings to defaults
--status Show current settings
--subsystem <name> Get/set settings for a given subsystem
modes:
Modes can be specified as a comma-separated list of key:value pairs.
Valid keys and their values are:
level off | default | info | debug
persist off | default | info | debug
stream live | default
xcrun simctl spawn booted log config --mode "level:debug" --subsystem com.mycompany.myapp --category network
Get the status again for this sybsystem and category will print:
Mode for 'com.mycompany.myapp(network)' DEBUG PERSIST_DEFAULT
Because environment variables are usually read only once, when the program starts.
In libdispatch 442.1.4, the OS_ACTIVITY_MODE
variable is read in _voucher_init
to determine a value of an internal variable; _voucher_init
is in turn called in libdispatch_init
, which is called only once at program startup. Interestingly, I cannot find this code in later versions of the library; perhaps it has been moved somewhere else. But it doesn’t really matter; the same principle applies. Setting the value of an environment variable will usually have no effect on already-initialised code, and can only be used to influence child processes.
As for solutions, I don’t have an easy one. Personally, I would try finding some method to disable logging in the specific library in question, or to filter the messages out: in the worst case, I’d put a couple of my own NSLog
calls with messages controlled by me before and after calls to the library, and tell a filter to ignore everything between the two.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With