Skip to content

Logging Strategy

lmarceau edited this page Apr 25, 2023 · 7 revisions

Goal

Define the guidelines of logging in Firefox for iOS. Any logs added in the project should follow the outlined principles here. Logs should also be reviewed from time to time to ensure we log with the right level and avoid blind spots.

Motivation

Logs have a natural tendency to become bloated and noisy overtime. As a developer, often we think it’s more useful to log something than not “just in case”. This makes logs hard to comprehend in the long run, which defeats the purpose of logging. If you can’t debug anything with your logs because they are too noisy, then it’s like not having logs at all. Having the right balance between too much and not enough is a fine line.

The goal of logging is to be able to debug issues during development or in production. This logging strategy will probably need to be adjusted while we learn more about our application and how to mitigate our blind spots, but aims at least to get the conversation going, so we have common ground to discuss.

What should we log

We should always give the log level, category and time, so it can be easier to filter the logs. Any logs filed should be reviewed thoroughly to make sure sensitive information isn’t listed.

Good logs ensure we don’t have many blind spots when we debug “in the wild” app sessions. If you weren’t able to isolate a problem with logs and had to resort to guessing what happened on your own device, then we have a blind spot.

Excessive logging can cause performance issues, as it takes up valuable resources. It also increases the size of our log files, which can be difficult to manage and analyze. To avoid excessive logging, make sure we only log what is necessary for debugging purposes. This means that you should focus on logging warnings and fatal errors.

Logging levels

Log levels are kept to a minimum to make sure they are relevant and useful. If your log isn't important enough to make it to this list, then it shouldn't be logged. If you hesitate between debug and info level, then you should use debug.

Debug level

Log levels are kept to a minimum to make sure they are relevant and useful. If your log isn't important enough to make it to this list, then it shouldn't be logged. If you hesitate between debug and info level, then you should use debug.

Info level

INFO messages are like the normal behaviour of applications. They state what happened. For example, if a particular service stopped or started, or you added something to the database, or a view was shown or hidden. These entries are nothing to worry about during usual operations. The information logged using the INFO log is usually informative, and it does not necessarily require you to follow up on it.

Warning level

The WARNING log level is used when you have detected an unexpected application problem. This means you are not quite sure whether the problem will recur or remain. You may not notice any harm to your application at this point. This issue is usually a situation that stops specific processes from running. This log level is used when a severe issue is stopping functions within the application from operating efficiently. Most of the time, the application will continue to run, but eventually, it will need to be addressed by creating a ticket for it. Note that errors in code doesn’t necessarily should be logged as warning in logs.

Often errors are expected and encountered in normal running applications. For example, an API call that returns 500 should be handled gracefully and logged as an info level rather than warning level. On another note, if you can’t parse the data received from an API call, then this probably is a warning log level.

Fatal level

FATAL means that the application is about to stop a serious problem or corruption from happening. The FATAL level of logging shows that the application’s situation is catastrophic, such that an important function is not working. For example, you can use FATAL log level if the application is unable to connect to the database.

Logging category

The logging category can be used to define a component of our app. We have to define the category based on the context of your usage, which will make it easier to filter logs depending on the area of the application we are working on. You can find here the different log categories currently defined.

Logging sensitive data

Whenever we’re logging, it’s tempting to collect as much information as possible to be able to solve problems further down the line. Logs can be sent to third-party tools like Sentry, and once sent it makes it much harder to retrieve and properly delete this user’s data if there was any problem with it. That being said, this is why any logs added should be thoroughly reviewed to ensure no sensitive data is contained in it.

Referring to our data collection categories at Mozilla, we should only collect technical data or interaction data in logs (so categories 1 and 2). If you’re ever found in a position where some data is part of an object, and it shouldn’t be logged, please use the LoggingExcluded property wrapper to ensure that data isn’t logged.

As a refresher, some sensitive data in Firefox for iOS can include:

  • Session identification values like user identifiers
  • URLs, history, bookmarks, etc.
  • Passwords, name, email address
  • Location associated with an identifier

We should also be careful to avoid logging:

  • API Tokens
  • HTTP responses
  • Database path

How should we log

Using the logging abstraction through our DefaultLogger, we can log to console or file with the different log levels and categories defined. First consider what message you want to send, then review if it fits in our log levels and categories. If it fits in, then think if this message should also be sent to Sentry. By default, we don’t send our logs to Sentry.

How to use the log

We’re currently using SwiftyBeaver as our base logger, so this section is heavily dependent on this tool.

Console

By default, the logs will appear in the Xcode console like the following. The heart colour helps visualize the log level. The format is currently in this order:

  • Date with time
  • 💜 Log level
  • [Category]
  • Name of file
  • Message

Screen Shot 2023-01-27 at 6 05 06 PM

Document

It’s possible to get the log file from the Files iOS application, as described in the wiki page. Please follow the instructions to get “Firefox logs”. The new log file will be under the same Logs folder, but named “Firefox.log”.

Filters

It’s possible to have filters either in console or in file using SwiftyBeaver. For example, if you’re working on BVC and you want to only see logs related to that class, you can add a filter in the DefaultSwiftyBeaverBuilder like the following:

console.addFilter(Filters.Path.contains("BrowserViewController", minLevel: .info))

You can add filters on path, functions or messages. Please see more information on filters in the SwiftyBeaver documentation.

Clone this wiki locally