Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime logging configuration #1127

Merged
merged 4 commits into from
Nov 22, 2016

Conversation

sergeuz
Copy link
Member

@sergeuz sergeuz commented Sep 23, 2016

This PR adds support for runtime logging configuration, which allows to enable logging on already running system via USB control requests. Some background on the topic can be found here: #1037. Note that this PR is based on the common code from another branch which is being reviewed here: #1126

Parameters that can be configured dynamically: destination stream (Serial, Serial1, USBSerial1), message format (plain text, JSON), message filtering (level and category-based).

This PR also adds basic tools for acceptance testing, such as handling of serial IO, USB requests, application flashing, etc. The test utilizing above functionality can be found here.

I'll be adding further comments directly in the code to provide more details on the implementation.


Doneness:

  • Contributor has signed CLA
  • Problem and Solution clearly stated
  • Code peer reviewed
  • API tests compiled
  • Run unit/integration/application tests on device
  • Add documentation
  • Add to CHANGELOG.md after merging (add links to docs and issues)

Features

  • Added support for runtime logging configuration, which allows to enable logging on already running system via USB control requests.

@@ -78,20 +78,21 @@ void log_set_callbacks(log_message_callback_type log_msg, log_write_callback_typ
}

void log_message_v(int level, const char *category, LogAttributes *attr, void *reserved, const char *fmt, va_list args) {
if (!log_msg_callback && (!log_compat_callback || level < log_compat_level)) {
const log_message_callback_type msg_callback = log_msg_callback;
Copy link
Member Author

@sergeuz sergeuz Sep 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current application callback is copied to a local variable, because LogManager may reset it at any time in multithreaded configuration (turning low-level logging functions to no-op), e.g. when last log handler has been unregistered.

Task* availTask_; // Task pool
Task* firstTask_; // Task queue
Task* lastTask_;
};
Copy link
Member Author

@sergeuz sergeuz Sep 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class implements a simple callback queue where callbacks can be enqueued from an ISR and then invoked asynchronously by a regular thread. The implementation doesn't use os_queue_t and can be used on platforms without concurrency support. Currently, there's a single queue for ISR tasks, and it's processed by the system thread as part of the primary event loop.

size_t request_size; // Request size
size_t reply_size; // Reply size (initialized to 0)
int format; // Data format (as defined by DataFormat enum)
} USBRequest;
Copy link
Member Author

@sergeuz sergeuz Sep 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This structure describes an asynchronous USB request. A request handler processes request data using data and request_size fields, then optionally stores reply data to the same buffer, sets reply_size field accordingly and calls system_set_usb_request_result() function to finalize processing.

typedef bool(*usb_request_app_handler_type)(USBRequest* req, void* reserved);

// Sets application callback for USB requests
void system_set_usb_request_app_handler(usb_request_app_handler_type handler, void* reserved);
Copy link
Member Author

@sergeuz sergeuz Sep 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function allows to set a callback that will be invoked for requests that should be processed in application thread. In current implementation such requests are USB_REQUEST_LOG_CONFIG and USB_REQUEST_CUSTOM.

~USBRequestData();
};

USBRequestData usbReq_;
Copy link
Member Author

@sergeuz sergeuz Sep 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only one active asynchronous USB request at a time is supported.

protected:
virtual void logMessage(const char *msg, LogLevel level, const char *category, const LogAttributes &attr) override;
virtual void write(const char *data, size_t size) override;
};
Copy link
Member Author

@sergeuz sergeuz Sep 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class implements JSON-formatted output for log messages to simplify machine processing.

virtual LogHandler* createHandler(const char *type, LogLevel level, LogCategoryFilters filters, Print *stream,
const JSONValue &params) = 0; // TODO: Use some generic container or a buffer instead of JSONValue
virtual void destroyHandler(LogHandler *handler);
};
Copy link
Member Author

@sergeuz sergeuz Sep 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handler and stream factory classes are extension points of the logging framework and allow to dynamically configure custom log handlers in the same way as built-in ones. This feature is also used for unit testing.

};

typedef FactoryDeleter<LogHandler, LogHandlerFactory, &LogHandlerFactory::destroyHandler> LogHandlerFactoryDeleter;
typedef FactoryDeleter<Print, OutputStreamFactory, &OutputStreamFactory::destroyStream> OutputStreamFactoryDeleter;
Copy link
Member Author

@sergeuz sergeuz Sep 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These custom deleters are used with std::unique_ptr to simplify error handling.

}
const char* const name = category + pos;
// Use binary search to find existent node or position for new node
}
Copy link
Member Author

@sergeuz sergeuz Sep 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code has been refactored to reduce code duplication.

#if PLATFORM_ID != 3
if (stream == &Serial) {
// Uninitializing primary USB serial causes the device to get disconnected from the host
// Serial.end();
Copy link
Member Author

@sergeuz sergeuz Sep 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed by this PR: #1122

@sergeuz sergeuz added this to the 0.7.x milestone Oct 8, 2016
;;
electron)
USB_VENDOR_ID=2b04
USB_PRODUCT_ID=d00a
Copy link
Member

@avtolstoy avtolstoy Oct 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be c00a (otherwise it targets Electron in DFU mode)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Honestly, I don't remember from where I copied these IDs. Since you're working with this branch already, would you mind committing correct IDs?

;;
p1)
USB_VENDOR_ID=2b04
USB_PRODUCT_ID=d008
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be c008 (otherwise it targets P1 in DFU mode)

@sergeuz sergeuz force-pushed the feature/usb_logging_1_of_2 branch 2 times, most recently from 0397166 to b1d7d74 Compare October 22, 2016 00:38
Copy link
Member

@technobly technobly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💥

@technobly technobly merged commit f835972 into feature/usb_logging_1_of_2 Nov 22, 2016
@technobly technobly deleted the feature/usb_logging_2_of_2 branch November 22, 2016 04:23
@technobly technobly removed their assignment Nov 29, 2016
@technobly technobly modified the milestones: 0.7.x, 0.6.1 Nov 29, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants