ZeppOS Visual Logger: On-Screen Logs on Your Device
August 17, 2023

With Visual Logger, you get exactly what you expect – all the logs you asked for, displayed directly on your emulator or physical device. Plus, with a built-in filter for repeated messages, Visual Logger shines in its ability to deliver the insights you need, exactly where you need them. Here are some key features that make Visual Logger stand out:

  • It allows you to display log messages on the screen of your device, making it easy to see what’s happening in your code in real-time.
  • It supports different log levels, such as “LOG”, “INFO”, “WARN”, “ERROR” and “DEBUG“, allowing you to categorize your log messages and easily identify issues.
  • It provides a variety of customization options, such as changing the text size, text color, background color, and line count, allowing you to tailor the appearance of the visual log to your needs.
  • It supports both console logging and visual logging, giving you the flexibility to choose how you want to view your log messages.
  • It includes features such as the automatic removal of old messages after a timeout and the ability to include a prefix in log messages, making it easier to manage and organize your log output.

⚡️ Quickstart

You can install the Visual Logger into your ongoing project from the NPM registry or download it directly from GitHub.

Visual Logger for ZeppOS 2.0+ [GitHub]

npm i @silver-zepp/vis-log

Visual Logger for ZeppOS 1.0 [GitHub]

Then include it in your project:

// install -> npm i @silver-zepp/vis-log
import VisLog from "@silver-zepp/vis-log";
const vis = new VisLog("index.js");

And use it the usual console.log(...) or logger.log(...) style:

vis.log("Hello World!");
vis.warn("Warning Here");
vis.info("This is your info");
vis.error("Here's an error");

Here's the result: You get clean logs on your device, and also they are mirrored with a help of a built-in log instance, which gives us colorful console logs with filtered levels.

ⓘ Important: If you don’t see the logger try refreshing it. It might be buried behind other widgets! Try always keeping it drawn the last.

vis.refresh(); // refresh the logger if you can't see it

We have prepared a sample project for you to play with, which you can download from the git repo.

The strong sides of a Visual Logger

ⓘ Example 1: Switch logger's position in real-time with a single click.

Visual Logger feature examples

You’ve seen the first example in the gif above, so let’s quickly walk through the rest of them and then dive deeper into their implementation.

ⓘ Example 2: The repeated messages do not clog the screen.

ⓘ Example 3: Show it only when you need it, hide all the other times.

ⓘ Example 4: Change its looks, to better cater to your app's theme.

Customizing your logger

Let’s have a closer look at some of the most important settings

vis.updateSettings({ line_count: 5 })

[ line_count ]: specifies the number of messages (lines) before recycling them. If you’re planning to use a larger font size you might consider lowering the amount of lines visible. Or in case you want to have a logger that barely takes any screen space, you can just put it to 1.

vis.updateSettings({ timeout_enabled: true })

[ timeout_enabled ]: will make messages disappear after a timeout. Disable it when you don’t want to miss a message by going AFK for a minute.

vis.updateSettings({ log_from_top: false })

[ log_from_top ]: by default the logger stays on top of the screen and logs messages towards the bottom. Disable this if you want your messages to come from bottom to top.

vis.updateSettings({ prefix_enabled: false })

[ prefix_enabled ]: this is mostly self-explanatory but you can disable it if you, for example, want to integrate the chat app inside your actual mini-app. This can be easily achieved with Visual Logger.

vis.updateSettings({ padding_multiplier: 1.5 })
vis.updateSettings({ margin: text_size })

[ padding_multiplier ] & [ margin ]: you want to play with these values (mostly increase) in case your app is designed for a “designWidth” that is not equal to 480. By default, the margin is enabled only when Visual Logger is run on a round-shaped screen, and its value is equal to the text size.

The rest of the settings are not that important but you can read more about what they do just by looking at hints provided by your IntelliSense, they all are explained with JSDoc.

Here are all the default settings of your logger, they are already applied so you don’t have to specify any of these for the logger to work out of the box.

 line_count: 5,
 log_from_top: true,
 timeout_enabled: true,
 visual_log_enabled: true,
 background_color: 0x333333,
 text_color: 0x000000,
 text_size: 16,
 console_log_enabled: true,
 prefix_enabled: true,
 text_style: hmUI.text_style.ELLIPSIS,
 padding_multiplier: 1.5,
 margin: 16,
 filename: "",

Note: To change the text_style, make sure to import the hmUI namespace or assign the enum values manually. Here are their numerical values for reference:

hmUI.text_style.CHAR_WRAP   = 0
hmUI.text_style.WRAP        = 1
hmUI.text_style.ELLIPSIS    = 2
hmUI.text_style.NONE        = 3

So if you want to change the text style you can go with one of these approaches

import * as hmUI from "@zos/ui";
   text_style: hmUI.text_style.WRAP

import VisLog, { hmUI } from "./path-to-vis/vis-log";
   text_style: hmUI.text_style.WRAP

vis.updateSettings({ text_style: 1 })

Real-World use case scenario

Here’s an example case where Visual Logger already played a key role, helping with the development of the Mini Chess game. We can observe how the AI thinks right on the screen of the physical device!

*current example shows its work on the Bip 5 Emulator. And is running a debug version of the game that looks different than the end product.

Is Visual Logger a full replacement for a traditional logger?

Not at all. By its nature, it has the limitation of any software that runs inside the virtual machine – it cannot print internal error logs, like this one for example:

So when you have a typo in your code, your app will probably not compile/run which means the logger won’t run as well. And you will have to check the console. But when your code is clean from errors, this tool is all you need for 90% of the time.

✨️ Addressing the Elephant in the Room

Unsurprisingly, having a proper logger or debugger can substantially reduce the development time of our apps. Thankfully we have a console logger but its implementation is pretty weak:

  • You need to manually scroll to see the new logs. They are not automatically scrolled through.
  • There are random message separator characters “” that add unnecessary holes between logged messages.
  • There are a lot of internal logs that bring very little value to the end user, the mini-app developer.
  • The repeated consequent messages are not being counted, which makes the logs look spammy, especially when you are trying to debug something that sits in a loop.
  • And also there’s a memory leak. When you log too many messages, the Huami OS Simulator just drops the connection with a running VM.

How can we improve our traditional logger?

The default logger isn’t that bad but to be way better it needs to have messages auto-scroller. Interestingly enough we don’t even need to implement anything, all that is needed to be done is to reverse the order of messages

[ from top to bottom ] -> [  from bottom to top ].

That simple, just make the new messages appear at the top, in front of the previous ones. This is in fact a nowadays logging standard – new logs appear at the top. So you don’t have to scroll a million lines down through something you have already seen ten times.