LogHandler
LogHandler is the application-wide logging singleton. It accepts messages
from any thread through a thread-safe interface and routes them to the in-app
log display, an on-disk CSV log file, and (when enabled) a separate debug log
file. Most code interacts with it exclusively through the free-function
convenience wrappers; direct calls to the singleton are reserved for connection
setup and experiment-lifecycle management.
Free-function API
Five free functions provide thread-safe logging from any context. They are
declared in loghandler.h, which also pulls in
using namespace Qt::Literals::StringLiterals, making _s and _L1
string-literal suffixes available in every translation unit that includes it.
bcLog(u"message"_s); // Normal severity (default)
bcLog(u"message"_s, LogHandler::Warning); // Explicit severity
bcDebug(u"detail"_s); // Debug severity
bcWarn(u"condition"_s); // Warning severity
bcError(u"failure"_s); // Error severity
bcHighlight(u"milestone"_s); // Highlight severity
Prefer these free functions over calling LogHandler::instance().log()
directly. Do not use qDebug() or emit logMessage() in new code.
MessageCode severity
The MessageCode enum classifies each log entry:
Level |
Use for |
|---|---|
|
Connection outcomes, experiment milestones, user-initiated state changes |
|
Automatically-corrected mismatches the user should know about |
|
Failures requiring user action or indicating data-loss risk |
|
Major milestones such as experiment start and end |
|
Hardware lifecycle events, configuration loading, protocol details, parameter traces; written to the debug log file only when debug logging is enabled |
HardwareObject helpers
HardwareObject subclasses use the member helpers hwLog,
hwWarn, hwError, and hwDebug, which prepend the device key to every
message before forwarding it to the corresponding free function — see
HardwareObject for their signatures. These helpers are not part of
LogHandler’s own API.
Singleton and instance method
LogHandler::instance() returns a reference to the application-wide
singleton. The log(text, type) instance method is the underlying
implementation that all free functions call. It is also the slot target for
logMessage() and logMessageWithTime() shim slots that keep legacy
emit logMessage(...) call sites compiling.
On-disk log files
LogHandler writes to two log files under the active data path:
Main log — receives all messages of severity
Normal,Warning,Error, andHighlight.Debug log — receives
Debug-severity messages. Writing to this file is enabled only when debug logging is active (controlled at runtime via ApplicationConfigManager’ssetDebugLogging(); theApplicationConfigManager::debugLoggingChangedsignal connects toLogHandler::setDebugLoggingat application startup).
beginExperimentLog(num, msg) opens a per-experiment log file for the
duration of an acquisition; endExperimentLog() closes it. These are called
by MainWindow and BatchManager at the experiment lifecycle boundaries.
Display helpers
formatForDisplay(text, type, t) returns a formatted QString suitable
for insertion into the in-app log text widget. The sendLogMessage signal
carries this formatted string; iconUpdate carries the severity code so the
tab icon can reflect the highest-severity unacknowledged message.
API Reference
-
class LogHandler : public QObject
Application-wide logging singleton.
LogHandler routes log messages to the in-app display, an on-disk main log file, and (when enabled) a separate debug log file. All public methods and the free-function wrappers are thread-safe.
Normal code should use the free functions (
bcLog,bcDebug,bcWarn,bcError,bcHighlight) rather than callinginstance()directly.HardwareObjectsubclasses should use thehwLog/hwWarn/hwError/hwDebugmember helpers instead.Public Types
-
enum MessageCode
Severity level for a log message.
Values:
-
enumerator Normal
Connection outcomes, experiment milestones, user-initiated state changes.
-
enumerator Warning
Automatically-corrected mismatches the user should know about.
-
enumerator Error
Failures requiring user action or indicating data-loss risk.
-
enumerator Highlight
Major milestones such as experiment start and end.
-
enumerator Debug
Hardware lifecycle, configuration loading, protocol details; debug-log only.
-
enumerator Normal
Public Functions
-
explicit LogHandler(bool logToFile = true, QObject *parent = nullptr)
Construct a LogHandler.
- Parameters:
logToFile – Whether to write messages to disk (true by default).
parent – Qt parent object.
-
~LogHandler()
-
void log(QAnyStringView text, MessageCode type = Normal)
Log a message at the specified severity.
Accepts any string type accepted by
QAnyStringView(QString, QStringView, QLatin1StringView, const char *) without constructing a temporary QString. Thread-safe.- Parameters:
text – Message text.
type – Severity level (default:
Normal).
Public Slots
-
void logMessage(const QString &text, const MessageCode type = Normal)
Log a message; shim for legacy
emitlogMessage() call sites.Forwards to
log(). Prefer the free functions in new code.- Parameters:
text – Message text.
type – Severity level (default:
Normal).
-
void logMessageWithTime(const QString &text, const MessageCode type = Normal, QDateTime t = QDateTime::currentDateTime())
Log a message with an explicit timestamp.
Forwards to
log()using the supplied timestamp instead of the current time. Used when replaying stored messages at a known time.- Parameters:
text – Message text.
type – Severity level (default:
Normal).t – Explicit timestamp.
-
void beginExperimentLog(int num, const QString &msg)
Open a per-experiment log file for the duration of an acquisition.
Called at experiment start. All subsequent messages are also written to the experiment-specific log file until
endExperimentLog()is called.- Parameters:
num – Experiment number (used to derive the file path).
msg – Initial message written to the experiment log.
-
void endExperimentLog()
Close the per-experiment log file opened by
beginExperimentLog().
-
void setDebugLogging(bool enabled)
Enable or disable writing of Debug-severity messages to the debug log file.
Connected to
ApplicationConfigManager::debugLoggingChangedat application startup so runtime configuration changes propagate automatically.- Parameters:
enabled – True to write Debug messages to the debug log file.
Signals
-
void sendLogMessage(QString)
Emitted with the formatted message string for display.
Connect to a
QTextEdit::appendslot to update the in-app log view.
-
void iconUpdate(LogHandler::MessageCode)
Emitted with the severity of each new message.
Connect to update a tab icon or status indicator to reflect the highest-severity unacknowledged message.
Public Static Functions
-
static LogHandler &instance()
Return a reference to the application-wide singleton instance.
-
static QString formatForDisplay(const QString &text, MessageCode type, QDateTime t = QDateTime::currentDateTime())
Format a message for display in the in-app log widget.
Prepends a timestamp and a severity indicator to text. Called internally before emitting
sendLogMessage.- Parameters:
text – Message text.
type – Severity level.
t – Timestamp (defaults to the current date/time).
- Returns:
Formatted string ready for insertion into a QTextEdit.
Private Functions
-
void doLog(const QString &text, MessageCode type, const QDateTime &t)
-
void writeToFile(const QString &text, MessageCode type, const QDateTime &t)
Private Members
-
std::atomic<int> d_currentExperimentNum = {-1}
-
std::atomic<bool> d_logToFile = {true}
-
std::atomic<bool> d_debugLogging = {false}
-
QMutex d_fileMutex
Private Static Attributes
-
static LogHandler *s_instance = nullptr
-
enum MessageCode
-
void bcLog(QAnyStringView text, LogHandler::MessageCode type = LogHandler::Normal)
Log a message at Normal severity (or an explicit severity).
Thread-safe. Forwards to
LogHandler::instance().log(). This is the preferred logging entry point for most code.- Parameters:
text – Message text (any string type accepted by QAnyStringView).
type – Severity level (default:
LogHandler::Normal).
-
void bcDebug(QAnyStringView text)
Log a message at Debug severity.
The message is written to the debug log file only when debug logging is enabled via
ApplicationConfigManager::setDebugLogging().- Parameters:
text – Message text.
-
void bcWarn(QAnyStringView text)
Log a message at Warning severity.
- Parameters:
text – Message text.
-
void bcError(QAnyStringView text)
Log a message at Error severity.
- Parameters:
text – Message text.
-
void bcHighlight(QAnyStringView text)
Log a message at Highlight severity.
- Parameters:
text – Message text.