Logging is a crucial aspect in React Native app development projects as it is one of the easiest and fastest methods for debugging the app at the developmental phase itself. Logging provides detailed information feedback about the issue while the code is running. It also helps developers to understand an app’s behavior.
But, logging should be carried out during the app development process; it isn’t beneficial anymore, once the app gets deployed. This is because these logs are generated on the client side. Hence, during the post-deployment phase, the errors detected via logs will be accessible only to the users and get lost in their browsers. The development team can identify these errors only if a user fills up a bug report, which is least likely to happen. Users will mostly abandon the app instead of reporting the problem.
This post provides all-inclusive insights regarding logging in React Native projects and methods to resolve limitations. But, before we dive deeper, let’s take a sneak peek into the architecture of a React Native App.
React Native Architecture/Execution Environment
The React Native execution environment comprises three major threads – the “Native” thread, the “JS” thread, and a background thread that handles the shadow node. These threads communicate with each other over a library named “Bridge.”
Logging in React Native: Key Steps to Consider
Now, let’s gather comprehensive insights about logging in React Native environment.
How to read Logs?
The JavaScript logs are visible inside the “console” part of the “developers’ tools” section. You’ll find “developers’ tools” in the browser that is used for remote JavaScript debugging. But, React Native developers can view these logs when the debugger is connected and this might slow down the app execution process to a certain extent. So, what’s the solution? You need to employ commands like react-native log-ios (for iOS apps) react-native log-android (for Android apps) to ensure that your device doesn’t slow down while logging is going on. This way, you also come to know more about what’s going on in the entire app and not just the JavaScript thread.
Let’s discuss this in detail for providing you with more clarity on reading Logs!
Console Logs
To view Console logs, you need to run the command npx expo start and connect a device; the Console logs will appear in the terminal process. The runtime sends these logs to the Expo CLI through web sockets. Here, you get low-fidelity logs as the dev tools are not directly connected to the engine. To generate higher-fidelity logs, you can employ advanced logging functions such as console.table. For this, you need to create a development build using Hermes and then connect the inspector. Hermes is a JS engine optimized for the React Native environment. Hermes improves an app’s start-up time by ahead-of-time JS compilation into bytecode.
System Logs
These types of logs are beneficial if you wish to view logs for all that’s taking place on your device and also the logs generated by the operating system as well as by other apps. You need to employ the following commands in the terminal for this purpose.
For Android devices: npx react-native log-android
For iOS devices: react-native log-npxios
How to write Logs?
Here’s how to write logs! Your output to the React Native Console log appears in the Application logs. It’s important to use the proper log level while writing logs. Besides the console.log, there are other log levels like console.info, console.warn, console.debug, etc. Each of these logs has a specific purpose and provides a more granular control on the level of information needed. You can use console.info to figure out whether a set of events took place as per the expected pattern. console.warn is used if some unexpected instances occur; for example, a server response that is not entirely incorrect but looks questionable. consoe.debug is used when you require temporary logs for resolving issues.
The Importance of Logging Libraries
It’s advisable to use a logging library while writing logs as it will save logs based on different levels as per the client’s requirement. The logs will be saved in an encrypted file format and log messages will be sent or displayed for the developers’ reference. Such ready-to-use loggers save time and effort for developers.
If proper log files are not present in the production environment, it becomes challenging to debug issues. This is because log files are the only source of information that helps you to debug unexpected issues or disconnected errors. The usage of logging libraries addresses this limitation.
React Native Logging Libraries: Examples
React-native-file-logger
React-native-file-logger is a file-logger for the react native environment and can append messages from console calls into log files employing file loggers from Logback (for Android) CocoaLumberjack (for iOS). Configure it using the command: FileLogger.configure(). Once configured, it will automatically log all the existing console.log/debug/… calls into a file.
React-native-file-logger is written in TypeScript and offers an optional file-rolling policy. The files are rolled based on the size and the time needed. The rolling policy is highly customizable. You can customize the log level for file output and the log directory, a path where log files are stored. Moreover, if you do not wish to use console calls for file logging, you have the option to directly write messages to the log file using your logger API.
This logger can also e-mail file logs to developers without having to depend on any other library. The logger employs React Native’s undocumented global._inspectorLog. Using React-native-file-logger, you can intercept console calls and retrieve the formatted log message.
react-native-logs
This React Native logger comes with custom “log levels” and “transports” like file writing, colored console, etc. The severity of each log level is displayed; log levels are arranged in ascending order based on their degree of importance. Thereafter, “transport” manages the logs. “Transport” is a functionality that saves, displays, sends log messages.
For installation, run either of these two commands:
npm install –save react-native-logs
or
yarn add react-native-logs
Now set the ball rolling! Go to react-native-logs and from there,
import { logger }.
Then run the command var log = logger.createLogger
The “createLogger” method enables you to create a simple logger that offers warn, debug, error levels. For customizing this logger, you need to pass a configuration object to the “createLogger” method.
Coming to “transport,” developers can write their own “transport” specifications for sending logs to a Cloud service. You also get to choose from several default “transport” options like hideDate, hideLevel, loggerName, dateFormat, etc.; if you set the parameter – transportOptions. Here, you would also be able to add new options that get passed to transports and can overwrite the pre-set transport options.
The severity level of logs can be set; for this, you need to pass the name (string) of the level that is of the least importance. Here, you can overwrite any config.severity option that has been set when the logger was created.
How to Handle Different types of Errors displayed by Logs?
All warnings errors in the development builds appear inside a LogBox present in the app. This LogBox is disabled automatically during the release of the production builds. Remember, that ignoring logs is not a good practice and should be the last resort. And, if you had to ignore any log due to some unavoidable reason, do create a task for fixing those logs later on.
Console Errors
You can view the console errors warnings in the form of on-screen notifications with a yellow or a red badge. The number of warnings and errors is also displayed. For reading the console warnings and errors, you need to click the notification. Thereafter, full-screen information about the log will appear and you’ll be able to paginate through every log present inside the console.
You can hide the aforementioned notifications by employing the command: LogBox.ignoreAllLogs(). This approach comes in handy while you are giving product demos. You can also hide notifications following the “per-log” approach. Here, you need to type the command: LogBox.ignoreLogs(). This approach can be used to handle noisy warnings that you can’t fix; for instance, the ones in a third-party dependency.
Syntax errors
Whenever there’s a Syntax error, a full-screen LogBox error appears. The LogBox shows you the stack trace as well as the location of the Syntax error. Such an error cannot be dismissed as it denotes an invalid JS execution that must necessarily be resolved before you continue with the app development process. This is how you need to act for dismissing Syntax errors. Fix the error. Then, you can use either of these two ways – Enable Fast Refresh and save it as “automatically dismiss” or disable Fast Refresh and reload using the command cmd+r.
Unhandled JS Errors
The previously unhandled JavaScript errors display a full-screen LogBox automatically, showing the error source. You can dismiss or minimize such errors to view the application’s state when these errors crop up. However, addressing these errors is highly recommended.
Bottomline:
I hope you have gathered actionable insights on the various approaches to logging in React Native. To create a top-class React Native app, the development team must be well-equipped to address unexpected events errors. And, logging helps you to find out the root cause of errors and makes it easy for the developers to resolve issues. However, you must carry out the logging process appropriately to reap its benefits without affecting the UX. Therefore, it’s important to pick an experienced React Native app development company to execute your software development project.