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.
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
_10extern enum MvStatus mvServerLoggingInit(uint8_t *buffer, _10 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 |
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.
_10static 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.
_10const uint32_t log_buffer_size = 2048;_10static uint8_t log_buffer[2048] __attribute__((aligned(512))) = {0} ;_10_10// Initialize logging with the standard system call_10enum MvStatus status = mvServerLoggingInit(log_buffer, log_buffer_size);_10assert(status == MV_STATUS_OKAY);
Issue an application log message
_10extern enum MvStatus mvServerLog(uint8_t *message, _10 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 |
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.
_39const uint32_t log_buffer_size = 2048;_39static uint8_t log_buffer[2048] __attribute__((aligned(512))) = {0} ;_39_39bool initiate_logging() {_39 enum MvStatus status = mvServerLogInit(log_buffer, log_buffer_size);_39 return (status == MV_STATUS_OKAY);_39}_39_39void end_logging() {_39 // Pass in a null buffer pointer to end logging_39 enum MvStatus status = mvServerLogInit(NULL, 0);_39}_39_39// Patch printf() to use the new logging mechanism_39int _write(int file, char *ptr, int length) {_39 if (file != STDOUT_FILENO) {_39 errno = EBADF;_39 return -1;_39 }_39_39 // Write out the message string. Confirm that Microvisor_39 // has accepted the request to write data to the channel._39 enum MvStatus status = mvServerLog((const uint8_t*)ptr, length);_39 while (status != MV_STATUS_OKAY) {_39 if (status == MV_STATUS_NO_LOGGING) {_39 if (initiate_logging()) {_39 status = mvServerLog((const uint8_t*)ptr, length);_39 }_39 continue;_39 } else {_39 // Can't write to the log -- fail_39 errno = EIO;_39 return -1;_39 }_39 }_39_39 // Written the string; return the length to indicate success_39 return length;_39}