diff options
author | Dominik Holland <dominik.holland@qt.io> | 2019-10-10 17:21:37 +0200 |
---|---|---|
committer | Dominik Holland <dominik.holland@qt.io> | 2019-10-10 18:29:50 +0200 |
commit | 9338ef08af7803f0d39830830547b44bb3373e34 (patch) | |
tree | 34db1d6dcfa7ad83cbaa21333b647d29104b0de3 /src/geniviextras/qdltregistration.cpp | |
parent | 2df528532d293327599f1c5107415ddb34035c5c (diff) |
geniviextras: Add better handling for long messages
DLT silently drops too long messages and produces
empty lines instead.
This changes introduces a behavior enum which helps
to configure geniviextras to truncate or split the
long messages.
Change-Id: I325c8e8da25c9456ee56d29bce0779b016c01917
Fixes: AUTOSUITE-1187
Reviewed-by: Robert Griebl <robert.griebl@qt.io>
Diffstat (limited to 'src/geniviextras/qdltregistration.cpp')
-rw-r--r-- | src/geniviextras/qdltregistration.cpp | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/src/geniviextras/qdltregistration.cpp b/src/geniviextras/qdltregistration.cpp index 47abe21..14b2130 100644 --- a/src/geniviextras/qdltregistration.cpp +++ b/src/geniviextras/qdltregistration.cpp @@ -73,10 +73,47 @@ QDltRegistration *globalDltRegistration() QT_END_NAMESPACE +// helper functions to split or truncate a utf8 correctly (not between a composed character) +namespace QtGeniviExtrasPrivate { + + static constexpr int MAX_MSG_LEN = DLT_USER_BUF_MAX_SIZE - 10; + + QByteArray utf8_mid(const QByteArray &buffer, int position, int len) + { + int max = qMin(position + len, buffer.size()); + int end = max; + // move from the maximum length backwards so we don't cut in-between a multi-byte char + for (; end > position && end < buffer.size(); --end) { + if ((buffer[end] & 0xC0) != 0x80) + break; + } + // if we can't find a good position for a split (e.g. a invalid utf-8 string) take the max + // len for the split + if (end == position) + end = max; + return buffer.mid(position, end - position); + } + + QVector<QByteArray> utf8_split(const QByteArray &buffer, int len) + { + QVector<QByteArray> split; + int position = 0; + do { + const QByteArray mid = utf8_mid(buffer, position, len); + split.append(mid); + position += mid.size(); + } while (position < buffer.size()); + + return split; + } +} + + QDltRegistrationPrivate::QDltRegistrationPrivate(QDltRegistration *parent) : q_ptr(parent) , m_dltAppRegistered(false) , m_registerOnFirstUse(false) + , m_longMessageBehavior(QDltRegistration::LongMessageBehavior::Truncate) { } @@ -249,6 +286,31 @@ DltLogLevelType QDltRegistrationPrivate::severity2dltLevel(QtMsgType type) types of a QLoggingCategory whenever the log level of a dlt context changes. */ +/*! + \enum QDltRegistration::LongMessageBehavior + + This enum type describes the available options for long messages. + + \value Truncate Truncate the message to the maximum size. + \value Split Split the message into several smaller ones. + \value Pass Pass the message as is to DLT. This option has the least performance impact, but + DLT might ignore the message if it is too long and produce just an empty line instead. + + \since 5.12.4 +*/ + +/*! + \property QDltRegistration::longMessageBehavior + \brief Defines the handling of messages that are too long for DLT to handle correctly + + DLT defines that a message has a maximum size of about 1k (The real value depends on the DLT + version used). + + The default behavior is to truncate the message to the maximum supported length. + + \since 5.12.4 +*/ + QDltRegistration::QDltRegistration(QObject *parent) : QObject(parent) , d_ptr(new QDltRegistrationPrivate(this)) @@ -370,6 +432,18 @@ void QDltRegistration::registerUnregisteredContexts() } } +void QDltRegistration::setLongMessageBehavior(QDltRegistration::LongMessageBehavior config) +{ + Q_D(QDltRegistration); + d->m_longMessageBehavior = config; +} + +QDltRegistration::LongMessageBehavior QDltRegistration::longMessageBehavior() const +{ + Q_D(const QDltRegistration); + return d->m_longMessageBehavior; +} + /*! Unregisters the application with the dlt-daemon. The registered application as well as all registered dlt context will be deleted. @@ -408,7 +482,30 @@ void QDltRegistration::messageHandler(QtMsgType msgType, const QMessageLogContex DltLogLevelType logLevel = globalDltRegistration()->d_ptr->severity2dltLevel(msgType); - DLT_LOG(*dltCtx, logLevel, DLT_STRING(qPrintable(qFormatLogMessage(msgType, msgCtx, msg)))); + const QByteArray fullMessage = qFormatLogMessage(msgType, msgCtx, msg).toUtf8(); + + if (Q_UNLIKELY(fullMessage.size() > QtGeniviExtrasPrivate::MAX_MSG_LEN)) { +#if GENIVIEXTRAS_DEBUG + std::cout << "LOG MESSAGE TOO LONG" << std::endl; +#endif + if (globalDltRegistration()->longMessageBehavior() == LongMessageBehavior::Truncate) { +#if GENIVIEXTRAS_DEBUG + std::cout << "TRUNCATE" << std::endl; +#endif + DLT_LOG(*dltCtx, logLevel, DLT_UTF8(QtGeniviExtrasPrivate::utf8_mid(fullMessage, 0, QtGeniviExtrasPrivate::MAX_MSG_LEN))); + return; + } else if (globalDltRegistration()->longMessageBehavior() == LongMessageBehavior::Split) { +#if GENIVIEXTRAS_DEBUG + std::cout << "SPLIT" << std::endl; +#endif + const QVector<QByteArray> split = QtGeniviExtrasPrivate::utf8_split(fullMessage, QtGeniviExtrasPrivate::MAX_MSG_LEN); + for (const QByteArray &m : split) + DLT_LOG(*dltCtx, logLevel, DLT_UTF8(m)); + return; + } + } + + DLT_LOG(*dltCtx, logLevel, DLT_UTF8(fullMessage)); } /*! |