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.
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
1extern enum MvStatus mvServerLoggingInit(uint8_t *buffer,2uint32_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 |
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 |
MV_STATUS_INVALIDBUFFERSIZE | size is out of bounds |
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.
1const uint32_t log_buffer_size = 2048;2static uint8_t log_buffer[2048] __attribute__((aligned(512))) = {0} ;34// Initialize logging with the standard system call5enum MvStatus status = mvServerLoggingInit(log_buffer, log_buffer_size);6assert(status == MV_STATUS_OKAY);
Issue an application log message
1extern enum MvStatus mvServerLog(uint8_t *message,2uint16_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 |
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.
1const uint32_t log_buffer_size = 2048;2static uint8_t log_buffer[2048] __attribute__((aligned(512))) = {0} ;34bool initiate_logging() {5enum MvStatus status = mvServerLogInit(log_buffer, log_buffer_size);6return (status == MV_STATUS_OKAY);7}89void end_logging() {10// Pass in a null buffer pointer to end logging11enum MvStatus status = mvServerLogInit(NULL, 0);12}1314// Patch printf() to use the new logging mechanism15int _write(int file, char *ptr, int length) {16if (file != STDOUT_FILENO) {17errno = EBADF;18return -1;19}2021// Write out the message string. Confirm that Microvisor22// has accepted the request to write data to the channel.23enum MvStatus status = mvServerLog((const uint8_t*)ptr, length);24while (status != MV_STATUS_OKAY) {25if (status == MV_STATUS_NO_LOGGING) {26if (initiate_logging()) {27status = mvServerLog((const uint8_t*)ptr, length);28}29continue;30} else {31// Can't write to the log -- fail32errno = EIO;33return -1;34}35}3637// Written the string; return the length to indicate success38return length;39}