Skip to content

SRGSSR/srglogger-apple

Repository files navigation

SRG Logger logo

GitHub releases platform SPM compatible GitHub license

About

The SRG Logger library provides a simple way to unify logging between SRG SSR libraries and applications, but can be used by any other application or library as well.

Five logging levels are available, which should match most needs:

  • Verbose for detailed technical information.
  • Debug for debugging information.
  • Info for information that may be helpful for troubleshooting errors.
  • Warning for information about conditions which might lead to a failure.
  • Error for information about failures.

The library automatically bridges with standard logging frameworks, in the following order:

  • If your project uses CocoaLumberjack, messages will be forwarded to it.
  • If your project can use Apple unified logging, available starting from iOS 10, tvOS 10 and watchOS 3, messages will be forwarded to the system console.

If neither is available, no logging will take place. You can install a verbose NSLog based logger, provided as well, if you need a quick way to setup logging (this logger logs all messages and can slow down your application).

The library does not provide any logging to NSLogger. You can namely automatically bridge CocoaLumberjack into NSLogger using Cédric Luthi's interface between them.

Compatibility

The library is suitable for applications running on iOS 12, tvOS 12, watchOS 5 and above. The project is meant to be compiled with the latest Xcode version.

Contributing

If you want to contribute to the project, have a look at our contributing guide.

Integration

The library must be integrated using Swift Package Manager directly within Xcode. You can also declare the library as a dependency of another one directly in the associated Package.swift manifest.

Usage

When you want to use classes or functions provided by the library in your code, you must import it from your source files first. In Objective-C:

@import SRGLogger;

or in Swift:

import SRGLoggerSwift

This requires your target to link against the corresponding Swift package product.

Logging messages

To log a message, simply call the macro corresponding to the desired level. In Objective-C:

SRGLogInfo(@"com.myapp", @"Weather", @"The temperature is %@", @(temperature));

or in Swift:

SRGLogInfo(subsystem: "com.myapp", category: "Weather", message: "The temperature is \(temperature)")

You can provide two optional arguments when logging a message:

  • A subsystem, here com.myapp, which identifies the library or application you log from.
  • A category, here Weather, which identifies which part of the code the log is related to.

To avoid specifiying the subsystem in your application or library each time you call the macro, you can define your own set of helpers which always set this value consistently, for example in Objective-C:

#define MyAppLogVerbose(category, format, ...) SRGLogVerbose(@"com.myapp", category, format, ##__VA_ARGS__)
#define MyAppLogDebug(category, format, ...)   SRGLogDebug(@"com.myapp", category, format, ##__VA_ARGS__)
#define MyAppLogInfo(category, format, ...)    SRGLogInfo(@"com.myapp", category, format, ##__VA_ARGS__)
#define MyAppLogWarning(category, format, ...) SRGLogWarning(@"com.myapp", category, format, ##__VA_ARGS__)
#define MyAppLogError(category, format, ...)   SRGLogError(@"com.myapp", category, format, ##__VA_ARGS__)

or in Swift:

func MyAppLogVerbose(category: String?, message: String, file: String = #file, function: String = #function, line: UInt = #line) {
    SRGLogVerbose(subsystem: "com.myapp", category: category, message: message, file: file, function: function, line: line)
}

func MyAppLogDebug(category: String?, message: String, file: String = #file, function: String = #function, line: UInt = #line) {
    SRGLogDebug(subsystem: "com.myapp", category: category, message: message, file: file, function: function, line: line)
}

func MyAppLogInfo(category: String?, message: String, file: String = #file, function: String = #function, line: UInt = #line) {
    SRGLogInfo(subsystem: "com.myapp", category: category, message: message, file: file, function: function, line: line)
}

func MyAppLogWarning(category: String?, message: String, file: String = #file, function: String = #function, line: UInt = #line) {
    SRGLogWarning(subsystem: "com.myapp", category: category, message: message, file: file, function: function, line: line)
}

func MyAppLogError(category: String?, message: String, file: String = #file, function: String = #function, line: UInt = #line) {
    SRGLogError(subsystem: "com.myapp", category: category, message: message, file: file, function: function, line: line)
}

Interfacing with other loggers

If the default log handler does not suit your needs (or if you simply want to inhibit logging), set a new handler to forward the messages and contextual information to your other logger. In Objective-C:

[SRGLogger setLogHandler:^(NSString * _Nonnull (^ _Nonnull message)(void), SRGLogLevel level, NSString *const  _Nullable subsystem, NSString *const  _Nullable category, const char * _Nonnull file, const char * _Nonnull function, NSUInteger line) {
    // Foward information to another logger
}];

or in Swift:

SRGLogger.setLogHandler { (message, level, subsystem, category, file, function, line) in
    // Foward information to another logger
}

Thread-safety

Logging can be performed from any thread.

Apple unified logging troubleshooting

If you are using Apple unified logging and do not see the logs:

  1. Check that the scheme you use does not have the OS_ACTIVITY_MODE environment variable set to disable, or OS_ACTIVITY_DT_MODE set to NO.

  2. If you do not see lower level logs in the Console.app, ensure that the items Include Info Messages and Include Debug Messages are checked in the console Action menu. If these options are grayed out, try updating the logging configuration for your subsystem first by running the following command from a terminal:

    $ sudo log config --mode "level:debug" --subsystem <subsystem>
    
  3. Use the search to locate entries for your application name, and right-click on an entry to filter by application, subsystem or category

  4. Read the official documentation if you still have issues

Credits

This logger implementation is heavily based on a Cédric Luthi's Stack Overflow post.

License

See the LICENSE file for more information.