Collecting logs#
S-CORE applications log via mw::log from the logging module
(score_logging). This chapter shows how the platform info service and its consumer log, how the logging is
configured and how the logs are collected: on the console and as DLT (Diagnostic Log and Trace), the log format
which is used in the automotive domain.
Logging in the code#
The service creates a logger for its context and writes log messages with a log level:
1#include "score/mw/log/logger.h"
2
3auto& logger = score::mw::log::CreateLogger("PINF", "platform info");
4logger.LogInfo() << "platform_info_service: offering " + std::string{kInstanceSpecifier} + " for S-CORE " +
5 ToString(platform_info);
6logger.LogError() << "platform_info_service: cannot offer service: " << std::string{offered.error().Message()};
PINF is the context id of the messages. Together with the application id from the configuration below,
it identifies the source of each message. The Bazel target needs the dependency @score_logging//score/mw/log.
Logging configuration#
Which messages are written where is configured per process in a JSON file. The service uses deploy/platform_info/etc/logging.json:
1{
2 "appId": "PINS",
3 "appDesc": "Platform info service",
4 "logLevel": "kInfo",
5 "logLevelThresholdConsole": "kInfo",
6 "logMode": "kConsole|kRemote"
7}
Entry |
Meaning |
|---|---|
|
Application id of the process in the logs (up to four characters), |
|
Lowest log level that is logged, e.g. |
|
Lowest log level that is written to the console |
|
Where the logs go: |
mw::log uses the file given in the environment variable MW_LOG_CONFIG_FILE. If it is not set, mw::log takes the first
existing file of ../etc/logging.json relative to the directory of the executable, etc/logging.json and
logging.json in the working directory. In addition, an optional ECU-wide file /etc/ecu_logging_config.json
is read. The service is started in /usr/bin/platform_info on the target and finds etc/logging.json there;
the consumer gets its configuration via MW_LOG_CONFIG_FILE. Without it, the consumer would pick up the
etc/logging.json of the service when started in the same directory, and log with the application id PINS.
Console logs#
With kConsole, the messages are printed to the console of the process, e.g. when the service is started
as described in the building source code chapter:
2026/11/13 13:22:11.6131644 818992094 000 ECU1 PINS PINF log info verbose 1 platform_info_service: offering score/platform/info for S-CORE known_good 2026-08-28T09:19:12Z
Each line contains the time stamp, the ECU id (ECU1), the application id (PINS), the context id (PINF)
and the log level (info), followed by the message. Messages of the S-CORE modules used by the application appear
with their own context ids, e.g. lola for mw::com.
DLT logs and the datarouter#
With kRemote, the processes hand their messages to the datarouter, the logging daemon of score_logging.
The datarouter collects the messages of all processes on the target and sends them as DLT messages via UDP multicast
to 239.255.42.99, port 3490. The channels are configured in its
log-channels.json.
On the reference images, the datarouter is deployed under /usr/bin/datarouter, next to the platform info service.
If no datarouter runs, the DLT output is dropped; the console output remains.
To collect the DLT logs of the platform info service on your Linux machine, run the following commands in the reference integration:
Build the datarouter and
dlt-receive.dlt-receivefrom the COVESA dlt-daemon project is provided by the Integration Testing Framework, with an extension for UDP multicast:bazel build --config=linux-x86_64 @score_logging//score/datarouter @score_itf//third_party/dlt:dlt-receive
Start
dlt-receiveand store the received messages in a file.--net-ifis the IP address of the network interface of your machine, e.g. as shown byhostname -I:bazel-bin/external/score_itf++_repo_rules+dlt_daemon/dlt-receive -o /tmp/platform_info.dlt \ --udp --net-if <your IP address> --port 3490 --mcast-ip 239.255.42.99 &
Start the datarouter in the directory that contains its configuration:
(cd deploy/logging && ../../bazel-bin/external/score_logging+/score/datarouter/datarouter --no_adaptive_runtime &)
Start the service and the consumer as described in the building source code chapter. Then stop the datarouter and
dlt-receive, e.g. withpkill datarouterandpkill dlt-receive.Open
/tmp/platform_info.dltin a DLT viewer, e.g. dlt-viewer, and filter for the application idsPINSandPINC. Besides the messages of the datarouter itself (application idDR), the recording contains, for example:SCPP PINS PINF platform_info_service: offering score/platform/info for S-CORE known_good 2026-08-28T09:19:12Z ... SCPP PINC PINF platform_info_consumer: found the platform info service SCPP PINC PINF platform_info_consumer: S-CORE version check passed (8 modules match) SCPP PINS PINF platform_info_service: stopped
SCPPis the ECU id which the datarouter sets for its DLT channels inlog-channels.json.
Other tools, e.g. Wireshark or Chipmunk, and the setup of the network interfaces are described in the DLT capture guide of the logging module.
Logs collected by the platform integration test#
In the reference integration, the logs are also collected automatically. The platform integration test test_platform_run.py runs the showcase S-CORE Platform Run on the Linux image, in which the launch manager starts the datarouter, the platform info service and then the consumer. While the showcase runs, the test records all DLT messages on the host and checks, for example, that the consumer reported the successful version check:
("PINC", "PINF", r"platform_info_consumer: S-CORE version check passed"),
The recording is stored as platform_run.dlt in the undeclared test outputs
(bazel-testlogs/platform_integration_tests/platform_run/platform_run/test.outputs/, packed into
outputs.zip unless Bazel runs with --nozip_undeclared_test_outputs). In CI, it is uploaded as
artifact platform-run-dlt-<commit> of the workflow
test_and_docs.yml,
so you can download and open the logs of every pull request in a DLT viewer.