How you can integrate FullStory Logs with your iOS App Logging Framework

Recording Logs can help you troubleshoot app issues, as well as uncover unintended behavior. In this guide, we're going to review a few popular logging frameworks and how you can integrate them with FullStory.

CocoaLumberjack

CocoaLumberjack uses `DDAbstractLogger`. More info can be found here.

Guide

Installation instructions are on their github.

A way you use FullStory with CocoaLumberjack is by creating a class for logging that inherits

 `DDAbstractLogger`. 

FSLumberjackLogger.swift (Link)

import Foundation
import FullStory
import CocoaLumberjack

class FSLumberjackLogger : DDAbstractLogger {

You may have multiple loggers in your project so to keep track you will want to use the `DDLoggerName` to return a logger name.


    override var loggerName: DDLoggerName {
        return DDLoggerName("com.fullstory.logger")
    }

Finally you can create a logMessage method.

func logMessage(logMessage: DDLogMessage) {
     guard let logFormatter = self.logFormatter else {
            return
     }
     guard let messageBody = logFormatter.format(message: logMessage) else {
            return
     }

     let logLevel: FSEventLogLevel

     switch (logMessage.flag) {
     case .error:
            logLevel = FSLOG_ERROR
     case .warning:
            logLevel = FSLOG_WARNING
     case .info:
            logLevel = FSLOG_INFO
     case .debug:
            logLevel = FSLOG_DEBUG
     default:
            logLevel = FSLOG_INFO
        }

  FS.log(with: logLevel, message: messageBody)
}

Now you to add this do your AppDelegate’s didFinishLaunchingWithOptions (Link):

        DDLog.add(FSLumberjackLogger())

The result of this will be that you can use `DDLogs` convenient methods anywhere you import `CocoaLumberjack`. (Link) The methods are as follows:

  • DDLogVerbose
  • DDLogDebug
  • DDLogInfo
  • DDLogWarn
  • DDLogError
DDLogVerbose("DDLogVerbose log message")
DDLogDebug("DDLogDebug log message")
DDLogInfo("DDLogInfo log message")
DDLogWarn("DDLogWarn log message")
DDLogError("DDLogError log message")

Calling these methods would produce the following result in a given session’s console:

Screen_Shot_2020-05-14_at_9.29.33_AM.png

 

Willow

Willow uses a LogWriter protocol that you can implement. 

Guide

Installation instructions are on their github.

First you will want to make a file (It can be called FSWillowLogger...). Make sure that you import FullStory & Willow:

import FullStory
import Willow


Then I would make a method that would switch off of the LogLevel called out by willow and return FullStory’s event log level enum “FSEventLogLevel”.

func logLevelToFS(logLevel: LogLevel) -> FSEventLogLevel {
    switch logLevel {
      case .error:
          return FSLOG_ERROR
      case .warn:
          return FSLOG_WARNING
      case .debug:
          return FSLOG_DEBUG
      default:
          return FSLOG_INFO
    }
}


With Willow you can make an open class subclassing `LogWriter`.

open class FSWillowLogger: LogWriter { }


Now you want to add some convenient methods so you can use the logger to write FullStory logs:

 

  open func writeMessage(_ message: String, logLevel: LogLevel) {
         FS.log(with: logLevelToFS(logLevel: logLevel),  message: message)
    }

   open func writeMessage(_ message: LogMessage, logLevel: LogLevel) {
         let message = "\(message.name): \(message.attributes)"
         FS.log(with: logLevelToFS(logLevel: logLevel),  message: message)
    }


SwiftyBeaver
 

SwiftyBeaver has a BaseDestination class you can extend.

Setup

Instructions for install are in their github.

First you will want to make a file called FSSwiftyBeaverDestination.swift.

Next make sure to import SwiftyBeaver:

 

import FullStory
import SwiftyBeaver


Then I would make a method that would switch off of the
SwiftyBeaver.Level called out by SwiftyBeaver and return FullStory’s event log level enum:

 

func logLevelToFS(logLevel: SwiftyBeaver.Level) -> FSEventLogLevel {
    switch logLevel {
        case .debug:
            return FSLOG_DEBUG
        case .verbose:
            return FSLOG_DEBUG
        case .warning:
            return FSLOG_WARNING
        case .error:
            return FSLOG_ERROR
        default:
            return FSLOG_INFO
    }
}



Then you can make a class
FSSwiftyBeaverDestination and make sure to inherit from BaseDestination:

 

public class FSSwiftyBeaverDestination: BaseDestination {
    override public func send(_ level: SwiftyBeaver.Level, msg: String, thread: String,
                                file: String, function: String, line: Int, context: Any? = nil) -> String? {
        let formattedString = super.send(level, msg: msg, thread: thread, file: file, function: function, line: line, context: context)
        if let str = formattedString {
            FS.log(with: logLevelToFS(logLevel: level),  message: str)
        }
        return formattedString
    }
}


You can then call the following where you wish to log into the didFinishLaunching method in the AppDelegate:


let fslog = FSSwiftyBeaverDestination()
log.addDestination(fslog)



Need to get in touch with us?

The FullStory Team awaits your every question.

Contact us