Application Logging Functions

Microvisor Public Beta

Microvisor is in a pre-release phase and the information contained in this document is subject to change. Some features referenced below may not be fully available until Microvisor’s General Availability (GA) release.

Microvisor currently provides the following system calls to allow applications to configure application logging and to issue log messages. Logged messages are accessed using the Twilio CLI Microvisor plugin.

Application logging is intended for coarse-level feedback and basic debugging, not for fine-grained debugging, for which you should make use of Microvisor’s remote debugging facility. Posted log messages are not guaranteed to be received, and no claim is made as to the order in which they may be delivered. Consequently, you should not use application logging as a data-delivery mechanism.

Application logging can operate when the device is offline: messages will be buffered — up to the number that will fit into the buffer; those that will not fit are discarded — and transmitted when the device comes online. The network connection that is used to relay messages is one your code must establish by making a call to mvRequestNetwork().

When the device is online, the transmission of application log messages to the server is rate limited. If too many messages are posted too frequently, further attempts to post messages will fail with an MV_STATUS_INVALIDBUFFERSIZE error. The Microvisor cloud server may also enforce hold on the posting of messages: this will also be signaled by an error, MV_STATUS_LOGGINGDISABLEDBYSERVER, when the application attempts to post a message.

When Microvisor starts up, it will establish a network connection if it can. This connection will then be used to transmit issued log messages until your application makes use of networking with a call to mvRequestNetwork(), if it ever does. When your application makes that call, Microvisor cedes network state management to it, and you will need to maintain the connection for as long as you want logging to continue. If you disconnect the network, posted messages will continue to be added to the buffer until it has no room for more, or you reconnect.

Application logging functions

Return values and errors

All of the functions described below return a 32-bit integer that is one of the values from the standard Microvisor enumeration MvStatus. All possible error values for a given system call are provided with each function’s description.

Success is always signaled by a return value of zero (MV_STATUS_OKAY).


Establish application logging via the Microvisor cloud


extern enum MvStatus mvServerLoggingInit(uint8_t *buffer, 
                                         uint32_t size);


Parameter Description
buffer A pointer to the non-secure memory which Microvisor will reserve for log message storage
size The size of the buffer in bytes. This must be at least 512 bytes

Possible errors

Error Value Description
MV_STATUS_PARAMETERFAULT buffer does not reference memory accessible to the application
MV_STATUS_INVALIDBUFFERALIGNMENT The value of buffer is not suitably aligned, i.e., on a word boundary


The application calls mvServerLoggingInit() to initiate application logging. It passes a pointer to a suitably sized and aligned block of memory, and the size of the block. Microvisor will take ownership of this memory and use it as holding space for messages subsequently posted using mvServerLog() and as a buffer from which to transmit those messages one at a time over a connection it establishes when application logging is started.

The store must be at least 512 bytes in size and aligned to 512 bytes.

static uint8_t log_buffer[LOG_BUFFER_SIZE] __attribute__((aligned(512))) = {0} ;

While the device remains disconnected, the store will accumulate messages until it is full or there is insufficient space for the subsequent message. Pending messages will be issued when the device reconnects provided it has not been power-cycled. Power-cycling the device or restarting the application — for example, by deploying updated application code — will eliminate the buffer and any messages it contains.

If the device disconnects and later reconnects while the application is still running, it is not necessary to restart application logging.

The buffer cannot be reconfigured on the fly. If you need to resize the buffer, close the current buffer and then re-call mvServerLoggingInit() with a new, larger buffer.

To close a buffer and cease application logging, call mvServerLoggingInit() and pass null as the buffer pointer. Any unsent messages will be lost on closure. The buffer memory will be returned to the application.


This code sets up logging with a suitably sized (for our hypothetical application) and aligned buffer.

const uint32_t log_buffer_size = 2048;
static uint8_t log_buffer[2048] __attribute__((aligned(512))) = {0} ;

// Initialize logging with the standard system call
enum MvStatus status = mvServerLoggingInit(log_buffer, log_buffer_size);
assert(status == MV_STATUS_OKAY);


Issue an application log message


extern enum MvStatus mvServerLog(uint8_t *message, 
                                 uint16_t length);


Parameter Description
message A pointer to non-secure memory holding the log entry string
length The length of the log entry string in bytes

Possible errors

Error Value Description
MV_STATUS_UNAVAILABLE Application logging has not been started by a call to mvServerLoggingInit()
MV_STATUS_LOGGINGDISABLEDBYSERVER Logging has been disabled by the Microvisor cloud server
MV_STATUS_PARAMETERFAULT message does not reference memory accessible to the application
MV_STATUS_LOGMESSAGETOOLONG message exceeds the maximum allowed size, 1024 bytes
MV_STATUS_INVALIDBUFFERSIZE There is insufficient space in the application logging buffer for the message


Call mvServerLog() to post a message to the application log. The message is a sequence of bytes for which you must also specify its length — Microvisor does not rely on the use of the nul character as a string terminator. Messages can be no more than 1024 bytes in size.

The call will fail immediately if application logging has not been initiated with an earlier call to mvServerLoggingInit(), if the application logging buffer is full or has insufficient space for the message, or the message is longer than the permitted maximum size.


This code traps the standard C function printf() so that its output is routed via Microvisor application logging.

const uint32_t log_buffer_size = 2048;
static uint8_t log_buffer[2048] __attribute__((aligned(512))) = {0} ;

bool initiate_logging() {
  enum MvStatus status = mvServerLogInit(log_buffer, log_buffer_size);
  return (status == MV_STATUS_OKAY);

void end_logging() {
  // Pass in a null buffer pointer to end logging
  enum MvStatus status = mvServerLogInit(NULL, 0);

// Patch printf() to use the new logging mechanism
int _write(int file, char *ptr, int length) {
  if (file != STDOUT_FILENO) {
    errno = EBADF;
    return -1;

  // Write out the message string. Confirm that Microvisor
  // has accepted the request to write data to the channel.
  enum MvStatus status = mvServerLog((const uint8_t*)ptr, length);
  while (status != MV_STATUS_OKAY) {
    if (status == MV_STATUS_NO_LOGGING) {
      if (initiate_logging()) {
        status = mvServerLog((const uint8_t*)ptr, length);
    } else {
      // Can't write to the log -- fail
      errno = EIO;
      return -1;

  // Written the string; return the length to indicate success
  return length;