diff --git a/README.md b/README.md index 306317c0..69117610 100644 --- a/README.md +++ b/README.md @@ -1,118 +1,47 @@ -# C++ & Rust Bazel Template Repository +# Logging -This repository serves as a **template** for setting up **C++ and Rust projects** using **Bazel**. -It provides a **standardized project structure**, ensuring best practices for: +This module provides components (`mw::log`, `datarouter`, `score_log_bridge`) for +safety-critical logging (Diagnostic Log and Trace) in embedded automotive systems. -- **Build configuration** with Bazel. -- **Testing** (unit and integration tests). -- **Documentation** setup. -- **CI/CD workflows**. -- **Development environment** configuration. - ---- - -## 📂 Project Structure - -| File/Folder | Description | -| ----------------------------------- | ------------------------------------------------- | -| `README.md` | Short description & build instructions | -| `score/` | Source files for the module | -| `tests/` | Unit tests (UT) and integration tests (IT) | -| `examples/` | Example files used for guidance | -| `docs/` | Documentation (Doxygen for C++ / mdBook for Rust) | -| `.github/workflows/` | CI/CD pipelines | -| `.vscode/` | Recommended VS Code settings | -| `.bazelrc`, `MODULE.bazel`, `BUILD` | Bazel configuration & settings | -| `project_config.bzl` | Project-specific metadata for Bazel macros | -| `LICENSE.md` | Licensing information | -| `CONTRIBUTION.md` | Contribution guidelines | +See the [module documentation](docs/index.rst) for the full overview, repository layout, and component +architecture. --- ## 🚀 Getting Started -### 1️⃣ Clone the Repository - -```sh -git clone https://github.com/eclipse-score/YOUR_PROJECT.git -cd YOUR_PROJECT -``` +### 2️⃣ Build & Run Tests -### 2️⃣ Build the Examples of module +See the [Quick Start](docs/index.rst) section of the module documentation for the exact `bazel build`/ +`bazel test` commands (including the platform `--config` and `--test_tag_filters` needed to select +unit, component, or QNX/QEMU integration tests). -> DISCLAIMER: Depending what module implements, it's possible that different -> configuration flags needs to be set on command line. +> TIP: For a single release-artifact target, provide a `:release_artifacts` filegroup per module +> (e.g. `bazel build //score/:release_artifacts`) — final decision is up to the module +> maintainer. -To build all targets of the module the following command can be used: +--- -```sh -bazel build //score/... -``` +## 📖 Documentation -This command will instruct Bazel to build all targets that are under Bazel -package `score/`. The ideal solution is to provide single target that builds -artifacts, for example: +Documentation lives in `docs/` and is built with `docs-as-code` (Sphinx). Build it locally with: ```sh -bazel build //score/:release_artifacts +bazel build //:docs ``` -where `:release_artifacts` is filegroup target that collects all release -artifacts of the module. - -> NOTE: This is just proposal, the final decision is on module maintainer how -> the module code needs to be built. - -### 3️⃣ Run Tests - -```sh -bazel test //tests/... -``` +See the [module documentation](docs/index.rst) for the rendered content. --- -## 🛠 Tools & Linters - -The template integrates **tools and linters** from **centralized repositories** to ensure consistency across projects. +## ✅ Quality -- **C++:** `clang-tidy`, `cppcheck`, `Google Test` -- **Rust:** `clippy`, `rustfmt`, `Rust Unit Tests` -- **CI/CD:** GitHub Actions for automated builds and tests +See the [Quality](docs/index.rst) section of the module documentation for the existing tooling and the +KPIs each one gates in CI (static analysis/linters, sanitizers, coverage, test tiers, traceability, license compliance). --- -## 📖 Documentation - -- A **centralized docs structure** is planned. - ---- - -## ⚙️ `project_config.bzl` - -This file defines project-specific metadata used by Bazel macros, such as `dash_license_checker`. - -### 📌 Purpose - -It provides structured configuration that helps determine behavior such as: - -- Source language type (used to determine license check file format) -- Safety level or other compliance info (e.g. ASIL level) - -### 📄 Example Content - -```python -PROJECT_CONFIG = { - "asil_level": "QM", # or "ASIL-A", "ASIL-B", etc. - "source_code": ["cpp", "rust"] # Languages used in the module -} -``` - -### 🔧 Use Case - -When used with macros like `dash_license_checker`, it allows dynamic selection of file types - (e.g., `cargo`, `requirements`) based on the languages declared in `source_code`. - ## IDE support ### Rust diff --git a/docs/components/datarouter/detailed_design/logging_architecture.md b/docs/components/datarouter/detailed_design/logging_architecture.md new file mode 120000 index 00000000..3fce7883 --- /dev/null +++ b/docs/components/datarouter/detailed_design/logging_architecture.md @@ -0,0 +1 @@ +../../../../score/datarouter/doc/design/logging_architecture.md \ No newline at end of file diff --git a/docs/components/datarouter/detailed_design/shm_apis.md b/docs/components/datarouter/detailed_design/shm_apis.md new file mode 120000 index 00000000..97ce8f5f --- /dev/null +++ b/docs/components/datarouter/detailed_design/shm_apis.md @@ -0,0 +1 @@ +../../../../score/datarouter/doc/design/shm_apis.md \ No newline at end of file diff --git a/docs/components/datarouter/index.rst b/docs/components/datarouter/index.rst index 87afb0d0..592ae102 100644 --- a/docs/components/datarouter/index.rst +++ b/docs/components/datarouter/index.rst @@ -13,24 +13,24 @@ # ******************************************************************************* -Data Router Documentation +Datarouter ========================= -This section is reserved for data router-specific documentation. - -.. comp:: Data Router - :id: comp__data_router +.. comp:: Datarouter + :id: comp__datarouter :security: YES - :safety: ASIL_B + :safety: QM :status: valid :implements: logic_arc_int__logging__logging :belongs_to: feat__logging - This is the datarouter component responsible for routing log messages to remote Diagnostics Log and Trace (DLT) backend. + Datarouter is the DLT (Diagnostic log and trace) daemon executable. It reads records from source shared-memory ring buffers, manages source + sessions, routes messages to configured channels via UDP multicast, and reports source statistics and message drops. .. toctree:: :titlesonly: :maxdepth: 1 - :glob: - * + requirements/index + detailed_design/logging_architecture + detailed_design/shm_apis diff --git a/docs/components/datarouter/requirements.rst b/docs/components/datarouter/requirements/index.rst similarity index 95% rename from docs/components/datarouter/requirements.rst rename to docs/components/datarouter/requirements/index.rst index 2213d652..24fd3337 100644 --- a/docs/components/datarouter/requirements.rst +++ b/docs/components/datarouter/requirements/index.rst @@ -32,7 +32,7 @@ Datarouter Services :safety: QM :derived_from: feat_req__logging__compat_dlt, feat_req__logging__log_sinks_network :status: valid - :belongs_to: comp__data_router + :belongs_to: comp__datarouter Datarouter shall implement DLT server component. Datarouter provides the functionality to send messages using DLT protocol over UDP multicast transport. @@ -44,7 +44,7 @@ Datarouter Services :safety: QM :derived_from: feat_req__logging__compat_dlt, feat_req__logging__config_log_filter, feat_req__logging__config_entity_id :status: valid - :belongs_to: comp__data_router + :belongs_to: comp__datarouter DLT server shall support multiple log channels as specified in AUTOSAR Diagnostic, Log and Trace Protocol Specification. The following parameters shall be configurable statically via @@ -60,7 +60,7 @@ Datarouter Services :safety: QM :derived_from: feat_req__logging__filtering_log_levels, feat_req__logging__filtering_entity_id, feat_req__logging__config_log_filter :status: valid - :belongs_to: comp__data_router + :belongs_to: comp__datarouter DLT server shall support filtering of messages within each channel. The filter shall be parametrized with application ID, context ID, log level threshold. Initial filter set shall @@ -74,7 +74,7 @@ Datarouter Services :safety: QM :derived_from: feat_req__logging__compat_dlt :status: valid - :belongs_to: comp__data_router + :belongs_to: comp__datarouter DLT server shall provide support for verbose DLT messages. Messages sent from mw::log library shall be sent via DLT using verbose mode. @@ -89,7 +89,7 @@ DLT Quotas :safety: QM :derived_from: feat_req__logging__config_buffer_size, feat_req__logging__resource_comm_channel :status: valid - :belongs_to: comp__data_router + :belongs_to: comp__datarouter The component shall have the DLT bandwidth quota configuration in the file located at ``./etc/log-channels.json`` relative to the application specific location ``/opt/``. @@ -101,7 +101,7 @@ DLT Quotas :safety: QM :derived_from: feat_req__logging__message_loss_handling, feat_req__logging__qos_message_handling :status: valid - :belongs_to: comp__data_router + :belongs_to: comp__datarouter It shall be possible to configure the action to drop DLT messages when a quota is exceeded. diff --git a/docs/design_decisions/explicit_init.rst b/docs/components/mw_log/design_decisions/explicit_init.rst similarity index 97% rename from docs/design_decisions/explicit_init.rst rename to docs/components/mw_log/design_decisions/explicit_init.rst index b3128db3..4d38495d 100644 --- a/docs/design_decisions/explicit_init.rst +++ b/docs/components/mw_log/design_decisions/explicit_init.rst @@ -48,4 +48,4 @@ Explicit initialization of logging **Justification for the Decision** - Explicit logging initialization will simplify logging initialization in multi-language environments. + Explicit logging initialization will simplify logging initialization in multi-language environments. \ No newline at end of file diff --git a/docs/components/mw_log/detailed_design/datarouter_backend/README.md b/docs/components/mw_log/detailed_design/datarouter_backend/README.md new file mode 120000 index 00000000..d8f2edc1 --- /dev/null +++ b/docs/components/mw_log/detailed_design/datarouter_backend/README.md @@ -0,0 +1 @@ +../../../../../score/mw/log/design/backend/datarouter_backend/README.md \ No newline at end of file diff --git a/docs/components/mw_log/detailed_design/file_output_backend.md b/docs/components/mw_log/detailed_design/file_output_backend.md new file mode 120000 index 00000000..4e203407 --- /dev/null +++ b/docs/components/mw_log/detailed_design/file_output_backend.md @@ -0,0 +1 @@ +../../../../score/mw/log/design/backend/file_output_backend.md \ No newline at end of file diff --git a/docs/components/mw_log/detailed_design/index.rst b/docs/components/mw_log/detailed_design/index.rst new file mode 100644 index 00000000..ac686185 --- /dev/null +++ b/docs/components/mw_log/detailed_design/index.rst @@ -0,0 +1,12 @@ +mw::log backend Detailed Design +=============================== + +The backend composition and recorder relationships are shown below: + +.. uml:: ../../../../score/mw/log/design/backend/mw_log_recorders.puml + +.. toctree:: + :maxdepth: 1 + + file_output_backend + datarouter_backend/README diff --git a/docs/components/mw/log/index.rst b/docs/components/mw_log/index.rst similarity index 58% rename from docs/components/mw/log/index.rst rename to docs/components/mw_log/index.rst index 2742b25c..fd85dc2b 100644 --- a/docs/components/mw/log/index.rst +++ b/docs/components/mw_log/index.rst @@ -13,11 +13,9 @@ # ******************************************************************************* -Logging Documentation +mw::log ===================== -This section is reserved for middleware-specific documentation. - .. comp:: Logging Component :id: comp__mw_logging :security: YES @@ -26,11 +24,18 @@ This section is reserved for middleware-specific documentation. :implements: logic_arc_int__logging__logging :belongs_to: feat__logging - This is the logging component library responsible for selecting the appropriate log sinks based on configuration at runtime. It can perform tasks such as log formatting, filtering, and composite backend selection based on runtime context and configuration. The logging component is designed to be extensible, allowing for custom logging backend to be added as needed. + This is the logging middleware library responsible for providing conrete backends for the supported recorder + implementations. The logging component is designed to be extensible, allowing supported as well as custom logging + backend to be added as needed. + + The ``mw::log`` implementation spans the ``score_baselibs`` (frontend) and ``score_logging`` (backend) + repositories; see the :doc:`feature architecture ` for the repository boundary + and cross-repository contract. .. toctree:: :titlesonly: :maxdepth: 1 - :glob: - * + requirements/index + detailed_design/index + design_decisions/explicit_init diff --git a/docs/components/mw/log/requirements.rst b/docs/components/mw_log/requirements/index.rst similarity index 100% rename from docs/components/mw/log/requirements.rst rename to docs/components/mw_log/requirements/index.rst diff --git a/docs/features/architecture/_assets/mw_log_repository_boundary.puml b/docs/features/architecture/_assets/mw_log_repository_boundary.puml new file mode 100644 index 00000000..4e8dca59 --- /dev/null +++ b/docs/features/architecture/_assets/mw_log_repository_boundary.puml @@ -0,0 +1,63 @@ +@startuml mw_log_architecture +title mw::log (ASIL B): repository boundary + +skinparam componentStyle rectangle +skinparam packageStyle rectangle +skinparam linetype ortho + +package "score_baselibs" as Baselibs #LightYellow { + component "mw::log Frontend API\n(logger, log_stream, runtime)" as Frontend + component "Console Backend\n(static, built-in)" as Console + component "score_log Rust Facade\n(score_log, score_log_fmt,\nscore_log_fmt_macro)" as RustFacade + artifact "Frontend safety plan\n+ AoU forwarding (Usage Contract)" as FrontendPlan #line.dashed + + Frontend -down-> Console : static composition (baseline) + Frontend .. FrontendPlan +} + +package "score_logging" as Logging #LightBlue { + component "mw::log Concrete Recorders\n(file, remote/DLT, slog)" as Recorders + component "Backend Integration\ntargets (file, remote/datarouter, ...)" as Integration + component "Rust Log Bridge\n(score_log_bridge + adapter.cpp)" as RustBridge + component "Rust Bridge C++ Init API\n(score_log_bridge_cpp_init)" as RustCppInit + artifact "Backend safety plan\n+ AoU forwarding (Integration Contract)" as BackendPlan #line.dashed + + Recorders -down-> Integration : static registration + Recorders .. BackendPlan +} + +Recorders .up.> Frontend : implements Recorder interface\n(static registration via backend_table, baseline) + +RustBridge -up-> RustFacade : implements score_log\nlogger backend +RustBridge -right-> Frontend : adapter.cpp calls\nRuntime::GetRecorder() (FFI) +RustBridge .up.> Recorders : direct static link\n(score/issues/2848) +RustCppInit -down-> RustBridge : set_default_logger (FFI)\nconfigures default logger + +package "Optional Future Evolution" as Future #WhiteSmoke { + component "Runtime Plugin Loading\n(dlopen-based)" as Runtime +} + +Runtime .[#gray]right.> Frontend : experimental only + +note bottom of Future + Not an assumed production + commitment; decision-gated. +end note + +note as N1 + Each repo owns its own phase gates, + safety plan, and governance; the only + cross-repo contract is the Recorder + interface + static backend_table + registration (plugin_api.h is an + existing C ABI seam, not used + for static composition). The Rust + bridge reaches the Frontend/Recorders + the same way, via direct static + linkage rather than backend_table. +end note + +Baselibs -[hidden]down-> N1 +Logging -[hidden]down-> N1 + +@enduml diff --git a/docs/features/architecture/_assets/remote_logging.puml b/docs/features/architecture/_assets/remote_logging.puml new file mode 100644 index 00000000..c56c875e --- /dev/null +++ b/docs/features/architecture/_assets/remote_logging.puml @@ -0,0 +1,107 @@ +@startuml "Remote Logging High-level Overview" + +skinparam linetype ortho + +skinparam component { + BackgroundColor<> #E8F4FA + BackgroundColor<> #FDEBD0 +} +skinparam node { + BackgroundColor<> #FDEBD0 +} + +frame "ECU" { + together { + node FeatureApplication <> { + component ApplicationLogic + package "mw::log lib" as lt1 { + component "Frontend API\n(Logger, LogStream, TRACE)" as lt1_frontend <> + component "Remote Backend" as lt1_backend <> { + component "/dev/shmem/fa_*" as shmem_fa <> + } + lt1_frontend ..> lt1_backend : registers as\nbackend/recorder + } + + ApplicationLogic --> lt1_frontend : verbose <> + ApplicationLogic --> lt1_frontend : non-verbose <> + } + + node SystemApplication <> { + component SystemApplicationLogic + package "mw::log lib" as lt2 { + component "Frontend API\n(Logger, LogStream, TRACE)" as lt2_frontend <> + component "Remote Backend" as lt2_backend <> { + component "/dev/shmem/sa_*" as shmem_sa <> + } + lt2_frontend ..> lt2_backend : registers as\nbackend/recorder + } + + SystemApplicationLogic --> lt2_frontend : verbose <> + } + + node RustApplication <> { + component RustApplicationLogic + package "score_log + bridge" as lt3 { + component "score_log Facade\n(score_log, score_log_fmt)" as lt3_frontend <> + component "score_log_bridge\n(adapter.cpp)" as lt3_bridge <> + component "Remote Backend" as lt3_backend <> { + component "/dev/shmem/ra_*" as shmem_ra <> + } + lt3_frontend ..> lt3_bridge : implements\nLog trait + lt3_bridge ..> lt3_backend : FFI, direct static link\n(Runtime::GetRecorder) + } + + RustApplicationLogic --> lt3_frontend : score_log! macros\n(info!, error!, ...) + } + } + note top of SystemApplication + E.g.: StartupManager, etc. + end note + + node Datarouter <> <> { + node SourceSession1 { + } + node SourceSession2 { + } + node SourceSession3 { + } + } + + package "Operating System" { + node NetworkStack <> { + + } + } +} + +lt1_backend ..> shmem_fa : write +lt2_backend ..> shmem_sa : write +lt3_backend ..> shmem_ra : write + +shmem_fa <.. Datarouter : read +shmem_sa <.. Datarouter : read +shmem_ra <.. Datarouter : read + +FeatureApplication -[hidden]right-> SystemApplication +SystemApplication -[hidden]right-> RustApplication +FeatureApplication -[hidden]down-> Datarouter +SystemApplication -[hidden]down-> Datarouter +RustApplication -[hidden]down-> Datarouter +lt1_backend -[hidden]down-> SourceSession1 +lt2_backend -[hidden]down-> SourceSession2 +lt3_backend -[hidden]down-> SourceSession3 + +lt1_backend <-0)-> SourceSession1 : message_passing +lt2_backend <-0)-> SourceSession2 : message_passing +lt3_backend <-0)-> SourceSession3 : message_passing + +Datarouter -(0-> [NetworkStack]: socket +[NetworkStack] -r-> Multicast: sends UDP multicast + +legend right + |Color| Repository | Contents | + |<#E8F4FA>| **score_baselibs** | mw::log frontend API (Logger, LogStream, TRACE) | + |<#FDEBD0>| **score_logging** | mw::log remote backend (shmem writer) + datarouter daemon | +endlegend + +@enduml diff --git a/docs/features/architecture/index.rst b/docs/features/architecture/index.rst new file mode 100644 index 00000000..de445186 --- /dev/null +++ b/docs/features/architecture/index.rst @@ -0,0 +1,67 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Logging Feature Architecture +============================= + +The logging feature has two parts: the ``mw::log`` library that applications +link against and ship as part of their own binary, and the ``datarouter`` +daemon that runs as its own process. Applications never talk to ``datarouter`` +directly; ``mw::log``'s remote backend writes log records into a shared-memory +segment and hands control over to ``datarouter`` through a shared-memory and +`mw::com message-passing `_ +session; guaranteeing Freedom from interference (FFI) for the application and its +logging subsystem. Rust applications reach that same remote backend too, via +the ``score_log_bridge`` described below, so ``datarouter`` sees one uniform +set of sessions regardless of which frontend produced them. + +mw::log +------- + +The ``mw::log`` library spans across two repositories: + +``score_baselibs/score/mw/log`` provides the Cpp frontend API, console backend, static recorder composition and +the ``score_log`` Rust facade that gives Rust code the same API surface, modelled on Rust's own ``log`` crate. +This allows `baselibs `_ and `mw::com `_ +to log to the same backends as applications, and providing a common logging API for all +components. The library is linked into applications and shipped as part of their binary. + +``score_logging/score/mw/log`` provides concrete file, remote/DLT, and slog +recorders, plus the ``score_log_bridge`` that implements score_log +`Log` trait and forwards records over FFI into those same +recorders, so a Rust application ends up writing through the identical +remote backend. + +Both repositories own their own safety plan, phase gates, and governance. The +cross-repository contract is the Recorder interface and static ``backend_table`` +registration. The existing C ABI seam is not used for static composition. +Runtime plugin loading remains experimental and is not a supported +production capability. + +.. uml:: _assets/mw_log_repository_boundary.puml + +Datarouter +---------- + +The Datarouter is the Diagnostic log and trace (DLT) daemon. +See :doc:`the Datarouter component ` +for its requirements and detailed design. + +The diagram highlights the logging components and traces the +remote DLT path a log message takes once it leaves an application, including +a Rust application whose ``score_log_bridge`` registers as a recorder the same +way the C++ remote backend does and writes into its own shared-memory segment +for ``datarouter`` to read. + +.. uml:: _assets/remote_logging.puml diff --git a/docs/features/logging/architecture/index.rst b/docs/features/logging/architecture/index.rst deleted file mode 100644 index 8d0d1407..00000000 --- a/docs/features/logging/architecture/index.rst +++ /dev/null @@ -1,43 +0,0 @@ -Logging Module View -################### - - -.. mod:: Logging - :id: mod__logging_repo - :status: valid - :safety: ASIL_B - :security: YES - :includes: comp__data_router, comp__mw_logging - - The logging module provides a standardized logging framework for C++ and Rust projects using Bazel build system. It includes components for log routing allowing for flexible log management and integration with various logging backends. The module is designed to be extensible and configurable to meet the needs of different applications and environments. - -.. mod_view_sta:: Logging module view - :id: mod_view_sta__logging__logging_view - :includes: comp__data_router, comp__mw_logging - :belongs_to: mod__logging - - .. needarch:: - :scale: 50 - :align: center - - {{ draw_module(need(), needs) }} - - - -Logging Feature Architecture -############################ - -.. feat_arc_sta:: Feature Architecture Logging - :id: feat_arc_sta__logging__static_view - :security: YES - :safety: ASIL_B - :status: valid - :includes: logic_arc_int__logging__logging - :fulfils: feat_req__logging__log_sources_user_app - :belongs_to: feat__logging - - .. needarch:: - :scale: 50 - :align: center - - {{ draw_component(need(), needs) }} diff --git a/docs/index.rst b/docs/index.rst index 486953ef..94aa94f1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,10 +12,10 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -Logging Documentation +Logging ===================== -This documentation describes the structure, usage and configuration of the Bazel-based C++/Rust logging module. +This module provides components for safety-critical logging (incl. DLT) in embedded automotive systems. .. contents:: Table of Contents :depth: 2 @@ -24,33 +24,55 @@ This documentation describes the structure, usage and configuration of the Bazel Overview -------- -This repository provides a standardized setup for projects using **C++** or **Rust** and **Bazel** as a build system. -It integrates best practices for build, test, CI/CD and documentation. +``score_logging`` delivers three distinct logging components: -Requirements ------------- - -.. stkh_req:: Example Functional Requirement - :id: stkh_req__docgen_enabled__example - :status: valid - :safety: QM - :security: YES - :reqtype: Functional - :valid_from: v1.0.0 - :rationale: Ensure documentation builds are possible for all modules +- ``mw::log`` is the logging middleware library. + Applications use the frontend API owned by `score_baselibs `_, + while `score_logging `_ provides the concrete + file, remote/DLT, and system recorder backend implementations. +- ``datarouter`` is the DLT daemon executable. + It reads records from source shared-memory ring buffers, manages source + sessions, routes messages to configured channels via UDP multicast, and reports source statistics and message drops. +- ``score_log_bridge`` is a Rust library that implements the ``score_log`` facade + using the C++ ``mw::log`` recorder + through a layout-checked FFI adapter. - -Project Layout --------------- +Repository Layout +----------------- The logging module includes the following top-level structure: -- ``score/``: Main C++/Rust sources -- ``tests/``: Unit and integration tests -- ``examples/``: Usage examples - ``docs/``: Documentation using ``docs-as-code`` +- ``examples/``: Dash-tool license-check +- ``quality/``: integration-test (QEMU) environment configs and sanitizer suppression files (ASan/LSan/TSan/UBSan). +- ``score/mw/log/``: ``mw::log`` recorders and concrete backends and Rust bridge +- ``score/datarouter/``: DLT daemon and supporting libraries +- ``score/test/``: Component and Integration tests +- ``scripts/``: developer-tooling helpers +- ``third_party/``: bazel wiring for external tooling deps +- ``tools/``: developer-tooling - ``.github/workflows/``: CI/CD pipelines +Architecture +------------ + +.. toctree:: + :titlesonly: + :maxdepth: 1 + + features/architecture/index + +Components +---------- + +.. toctree:: + :titlesonly: + :maxdepth: 1 + :glob: + + components/mw_log/index.rst + components/datarouter/index.rst + Quick Start ----------- @@ -60,54 +82,45 @@ To build the module: bazel build //score/... -To run tests: +To run the supported test suites: .. code-block:: bash - bazel test //tests/... - -Configuration -------------- + # Unit tests on the Linux host + bazel test --config=x86_64-linux --test_tag_filters=unit //score/... -The ``project_config.bzl`` file defines metadata used by Bazel macros. + # Component tests in Docker + bazel test --config=x86_64-linux --test_tag_filters=integration //score/test/component/... -Example: + # Integration tests on QNX/QEMU + bazel test --config=x86_64-qnx --test_tag_filters=integration //score/test/integration/... -.. code-block:: python +Quality +------- - PROJECT_CONFIG = { - "asil_level": "QM", - "source_code": ["cpp", "rust"] - } - -This enables conditional behavior (e.g., choosing ``clang-tidy`` for C++ or ``clippy`` for Rust). - -Additional documentation ------------------------- - -.. toctree:: - :maxdepth: 1 +Existing tooling and the KPIs each one gates in CI (see ``.github/workflows/``): - features/logging/architecture/index - design_decisions/explicit_init +- **Static analysis** — ``clang-tidy`` on every C++ target; ``clippy``/``rustfmt`` (``rustfmt.toml``) for Rust. +- **Sanitizers** — ASan/UBSan/LSan/TSan runs per PR, suppressions are placed in ``quality/sanitizer/``. +- **Code coverage** — C++ line/branch coverage report, excluding integration-tagged tests. +- **Test suites** — Google Test/Rust unit tests (Linux), component (Docker), and integration (QNX/QEMU) tests run separately. +- **License compliance** — Dash license scan of C++/Rust dependencies. +- **Copyright & format** — header and formatting checks on every change. -Components -========== +Stats +----- .. toctree:: :titlesonly: :maxdepth: 1 - :glob: - - components/datarouter/index.rst - components/mw/log/index.rst + verification_report/stats.rst -Requirements ------------- +Guides +--------- .. toctree:: + :titlesonly: :maxdepth: 1 - :glob: - logging/stats.rst + module/manuals/index diff --git a/docs/module/manuals/config/configuration.md b/docs/module/manuals/config/configuration.md new file mode 120000 index 00000000..30e49d0a --- /dev/null +++ b/docs/module/manuals/config/configuration.md @@ -0,0 +1 @@ +../../../../score/datarouter/doc/guideline/configuration.md \ No newline at end of file diff --git a/docs/module/manuals/config/etc/log-channels.json b/docs/module/manuals/config/etc/log-channels.json new file mode 120000 index 00000000..abc7fdde --- /dev/null +++ b/docs/module/manuals/config/etc/log-channels.json @@ -0,0 +1 @@ +../../../../../score/datarouter/doc/guideline/etc/log-channels.json \ No newline at end of file diff --git a/docs/module/manuals/config/etc/logging.json b/docs/module/manuals/config/etc/logging.json new file mode 120000 index 00000000..7c916076 --- /dev/null +++ b/docs/module/manuals/config/etc/logging.json @@ -0,0 +1 @@ +../../../../../score/datarouter/doc/guideline/etc/logging.json \ No newline at end of file diff --git a/docs/module/manuals/examples/dlt_capture_demo.md b/docs/module/manuals/examples/dlt_capture_demo.md new file mode 120000 index 00000000..44e8f425 --- /dev/null +++ b/docs/module/manuals/examples/dlt_capture_demo.md @@ -0,0 +1 @@ +../../../../score/datarouter/doc/guideline/dlt_capture_demo.md \ No newline at end of file diff --git a/docs/module/manuals/examples/file_based_local.md b/docs/module/manuals/examples/file_based_local.md new file mode 120000 index 00000000..a9f4d2e1 --- /dev/null +++ b/docs/module/manuals/examples/file_based_local.md @@ -0,0 +1 @@ +../../../../score/datarouter/doc/guideline/file_based_local.md \ No newline at end of file diff --git a/docs/module/manuals/index.rst b/docs/module/manuals/index.rst new file mode 100644 index 00000000..d3343ea8 --- /dev/null +++ b/docs/module/manuals/index.rst @@ -0,0 +1,28 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Manuals +======= + +Start with the `mw::log Usage Guide `_ to learn how to instrument your application with the logging API. + +The guides below then walk through configuration and typical logging setups, from basic to advanced: + +.. toctree:: + :titlesonly: + :maxdepth: 1 + + config/configuration + examples/file_based_local + examples/dlt_capture_demo diff --git a/docs/logging/stats.rst b/docs/verification_report/stats.rst similarity index 93% rename from docs/logging/stats.rst rename to docs/verification_report/stats.rst index badfdfb4..42563dfc 100644 --- a/docs/logging/stats.rst +++ b/docs/verification_report/stats.rst @@ -1,7 +1,7 @@ .. _log_statistics: -Component Requirements Statistics -================================= +Quality Stats +============== Overview -------- @@ -86,7 +86,9 @@ Details About Testcases ------------------------ .. needpie:: Test Types Used In Testcases - :labels: static-code-analysis, structural-statement-coverage, structural-branch-coverage, walkthrough, inspection, interface-test, requirements-based, resource-usage, control-flow-analysis, data-flow-analysis, fault-injection, struct-func-cov, struct-call-cov + :labels: static-code-analysis, structural-statement-coverage, structural-branch-coverage, walkthrough, inspection, + interface-test, requirements-based, resource-usage, control-flow-analysis, data-flow-analysis, fault-injection, + struct-func-cov, struct-call-cov :legend: type == 'testcase' and test_type == 'static-code-analysis' diff --git a/project_config.bzl b/project_config.bzl index 67aee1f8..e920b198 100644 --- a/project_config.bzl +++ b/project_config.bzl @@ -12,6 +12,7 @@ # ******************************************************************************* # project_config.bzl PROJECT_CONFIG = { - "asil_level": "QM", - "source_code": ["rust"], + # Module is mixed-criticality (mw::log backends ASIL_B, datarouter QM); highest level is declared here. + "asil_level": "ASIL_B", + "source_code": ["cpp", "rust"], } diff --git a/score/datarouter/doc/design/logging_architecture.md b/score/datarouter/doc/design/logging_architecture.md index cc4b882b..d2209b5d 100644 --- a/score/datarouter/doc/design/logging_architecture.md +++ b/score/datarouter/doc/design/logging_architecture.md @@ -50,9 +50,9 @@ The following constraints influenced the logging infrastructure design: ## Context The diagram below illustrates the logging framework context: -[context-ecu](uml/context-ecu.puml) +CONTEXT_ECU -Applications write log data through logging interfaces [^logging_vs_tracing]. +Applications write log data through logging interfaces. The logging framework transmits data to the following sinks: @@ -66,7 +66,7 @@ The logging framework transmits data to the following sinks: ### Process structure -[context-highlevel](uml/context-highlevel.puml) +CONTEXT_HIGHLEVEL The logging framework implements multiple components to meet system goals: @@ -105,7 +105,7 @@ The system defines the following visitors: 2. `TRACE(S)` is a C++ **function template** (not a preprocessor macro). Its call chain at runtime is: -```c++ +```text TRACE(arg) → LogEntry::Instance().TryWriteIntoSharedMemory(arg) → SharedMemoryWriter::AllocAndWrite(serialize_fn, type_id, size) @@ -117,7 +117,7 @@ On the first call for a given type `T`, `LogEntry::Instance()` (a Meyers sing The diagram below illustrates the high-level class structure of the datarouter component. -[package-datarouter](uml/package-datarouter.puml) +PACKAGE_DATAROUTER ## Runtime view @@ -127,12 +127,12 @@ Applications access logging functionality through `mw::log`. Initialization stage 1 executes when the first log request occurs. This may occur in global object constructors before the `main()` function executes, causing implicit initialization that creates necessary singletons automatically. The activity diagram below depicts the first-run process: -[seq-trace](uml/seq-trace.puml) +SEQ_TRACE ### mw::log implementation The `mw::log` implementation creates log records and commits them atomically to shared memory on flush. -[log-filtering-client-end](uml/dlt_message_filtering_frontend.puml) +DLT_MESSAGE_FILTERING_FRONTEND ### Ring buffer and linear allocator buffer @@ -143,15 +143,21 @@ Shared memory IPC provides optimal speed and flexibility for this implementation The Datarouter-Client Session uses [message_passing](https://github.com/eclipse-score/communication/tree/main/score/message_passing) IPC for the initial connection, buffer acquire requests, notifications, and disconnections. The `DataRouterRecorder` sets up the session when it is created and closes it when it is destroyed. In between, the datarouter keeps one `IServerConnection` handle per client and drives the log acquisition from the server side. -The main idea is to keep clients independent, so that one non-responsive client should not stall the datarouter. This matters because the datarouter serves all clients from a single thread, one after another on each periodic tick, so a single blocking call would hold up every other client. To avoid this, the datarouter asks for buffers (to read) using non-blocking QNX pulses (`IServerConnection::Notify()`), which return right away and never wait on the client. So if a client is slow or stuck, its pulse simply stays unanswered while the healthy clients keep getting served. See [session_sequence_diagram](uml/client_session_interaction_sequence.puml) for the full flow. +The main idea is to keep clients independent, so that one non-responsive client should not stall the datarouter. This matters because the datarouter serves all clients from a single thread, one after another on each periodic tick, so a single blocking call would hold up every other client. To avoid this, the datarouter asks for buffers (to read) using non-blocking QNX pulses (`IServerConnection::Notify()`), which return right away and never wait on the client. So if a client is slow or stuck, its pulse simply stays unanswered while the healthy clients keep getting served. See below for the full flow. + +CLIENT_SESSION_INTERACTION_SEQUENCE + +However, with such a design there are risks of stale sessions. A small per-session watchdog limits how long the datarouter waits for an acquire response. If a client keeps missing its deadline, the watchdog cleans up the stale session, but first it does a best-effort read of the client's last buffer so no logs are lost unnecessarily. See below. -However, with such a design there are risks of stale sessions. A small per-session watchdog limits how long the datarouter waits for an acquire response. If a client keeps missing its deadline, the watchdog cleans up the stale session, but first it does a best-effort read of the client's last buffer so no logs are lost unnecessarily. See [activity_watchdog_session](uml/activity_watchdog_session_lifecycle.puml). +ACTIVITY_WATCHDOG_SESSION_LIFECYCLE -The setup also handles an early-disconnect race, wherein if a client crashes while the datarouter is still building its session, the connect and disconnect paths work together to throw away the half-built session instead of keeping a dangling connection pointer. The client can then reconnect cleanly afterwards. See [early_disconnect_race](uml/sequence_early_disconnect_race.puml). +The setup also handles an early-disconnect race, wherein if a client crashes while the datarouter is still building its session, the connect and disconnect paths work together to throw away the half-built session instead of keeping a dangling connection pointer. The client can then reconnect cleanly afterwards. See below. + +SEQUENCE_EARLY_DISCONNECT_RACE ### datarouter -[log-filtering-datarouter](uml/dlt_message_filtering_backend.puml) +DLT_MESSAGE_FILTERING_BACKEND ### Application-side library configuration @@ -161,15 +167,6 @@ The system reads configuration from the `logging.json` file located in `/opt/> { - component ApplicationLogic - component "mw::log lib" as lt1 { - component "/dev/shmem/fa_*" as shmem_fa <> - } +skinparam linetype ortho - ApplicationLogic --> lt1 : verbose <> - ApplicationLogic --> lt1 : non-verbose <> - } +skinparam component { + BackgroundColor<> #E8F4FA + BackgroundColor<> #FDEBD0 +} +skinparam node { + BackgroundColor<> #FDEBD0 +} - node SystemApplication <> { - component SystemApplicationLogic - component "mw::log lib" as lt2 { - component "/dev/shmem/sa_*" as shmem_sa <> +frame "ECU" { + together { + node FeatureApplication <> { + component ApplicationLogic + package "mw::log lib" as lt1 { + component "Frontend API\n(Logger, LogStream, TRACE)" as lt1_frontend <> + component "Remote Backend" as lt1_backend <> { + component "/dev/shmem/fa_*" as shmem_fa <> + } + lt1_frontend ..> lt1_backend : registers as\nbackend/recorder + } + + ApplicationLogic --> lt1_frontend : verbose <> + ApplicationLogic --> lt1_frontend : non-verbose <> } - SystemApplicationLogic --> lt2 : verbose <> + node SystemApplication <> { + component SystemApplicationLogic + package "mw::log lib" as lt2 { + component "Frontend API\n(Logger, LogStream, TRACE)" as lt2_frontend <> + component "Remote Backend" as lt2_backend <> { + component "/dev/shmem/sa_*" as shmem_sa <> + } + lt2_frontend ..> lt2_backend : registers as\nbackend/recorder + } + + SystemApplicationLogic --> lt2_frontend : verbose <> + } } note top of SystemApplication E.g.: StartupManager, etc. end note - node Datarouter <> { + node Datarouter <> <> { + node SourceSession1 { + } + node SourceSession2 { + } } - note left of Datarouter - Central logging daemon - end note package "Operating System" { node NetworkStack <> { } } - - node Subscriber1 { - - } - - note left of Subscriber1 - Data consumer, - e.g., PersistentLogger, etc. - end note - } -lt1 ..> shmem_fa : write -lt2 ..> shmem_sa : write +lt1_backend ..> shmem_fa : write +lt2_backend ..> shmem_sa : write shmem_fa <.. Datarouter : read shmem_sa <.. Datarouter : read -Datarouter <-0)-> Subscriber1 +FeatureApplication -[hidden]right-> SystemApplication +FeatureApplication -[hidden]down-> Datarouter +SystemApplication -[hidden]down-> Datarouter +lt1_backend -[hidden]down-> SourceSession1 +lt2_backend -[hidden]down-> SourceSession2 -note as n1 - publish/subscribe - interface -end note -n1 .. Datarouter -n1 .. Subscriber1 +lt1_backend <-0)-> SourceSession1 : message_passing +lt2_backend <-0)-> SourceSession2 : message_passing Datarouter -(0-> [NetworkStack]: socket [NetworkStack] -r-> Multicast: sends multicast +legend right + |Color| Repository | Contents | + |<#E8F4FA>| **score_baselibs** | mw::log frontend API (Logger, LogStream, TRACE) | + |<#FDEBD0>| **score_logging** | mw::log remote backend (shmem writer) + datarouter daemon | +endlegend + @enduml diff --git a/score/datarouter/doc/design/uml/context-highlevel.puml b/score/datarouter/doc/design/uml/context-highlevel.puml index 4d57073e..30d40688 100644 --- a/score/datarouter/doc/design/uml/context-highlevel.puml +++ b/score/datarouter/doc/design/uml/context-highlevel.puml @@ -1,16 +1,14 @@ -@startuml +@startuml context-highlevel -title Implementation approach - -frame "Adaptive AUTOSAR ECU" { +frame "ECU" { node AdaptiveApplication { component ApplicationLogic - interface "mw::log" as aralog1 - component "mw::log implementation" as aralog1_impl + interface "mw::log" as mwlog1 + component "mw::log implementation" as mwlog1_impl - aralog1 - aralog1_impl - ApplicationLogic --> aralog1 : verbose - ApplicationLogic --> aralog1 : non-verbose + mwlog1 - mwlog1_impl + ApplicationLogic --> mwlog1 : verbose + ApplicationLogic --> mwlog1 : non-verbose } note right of AdaptiveApplication @@ -22,29 +20,28 @@ frame "Adaptive AUTOSAR ECU" { node SystemApplication { component SystemApplicationLogic - interface "mw::log" as aralog2 - component "mw::log implementation" as aralog2_impl + interface "mw::log" as mwlog2 + component "mw::log implementation" as mwlog2_impl - aralog2 - aralog2_impl - SystemApplicationLogic --> aralog2 : verbose + mwlog2 - mwlog2_impl + SystemApplicationLogic --> mwlog2 : verbose } note right of SystemApplication - e.g. SOME/IP daemon, - ABAC component, etc. + e.g. StartupApp end note node Datarouter { } note right of Datarouter - central logging daemon + DLT logging daemon end note } boundary "UDP Multicast" as udp -aralog1_impl --> Datarouter : write -aralog2_impl --> Datarouter : write +mwlog1_impl --> Datarouter : write +mwlog2_impl --> Datarouter : write Datarouter --> udp: "send DLT messages:" diff --git a/score/datarouter/doc/guideline/configuration.md b/score/datarouter/doc/guideline/configuration.md index 48cdb753..1e6bb344 100644 --- a/score/datarouter/doc/guideline/configuration.md +++ b/score/datarouter/doc/guideline/configuration.md @@ -4,7 +4,7 @@ The JSON-based configuration system provides predictable and manageable logging ## logging.json file -**Reference**: score/mw/log/design/configuration_design.md +[logging.json configuration](https://github.com/eclipse-score/baselibs/tree/main/score/mw/log#configuration) ### Logging Context @@ -17,7 +17,7 @@ When logging to different contexts you are able to filter the logs coming from a ### How configuration works - There is a list of logging contexts in the config file on the application side. You do not have to call any ```InitLogging()``` function in your code. Just use the logging API. - The configuration file has a fixed name ```logging.json``` and resides in the directory of the adaptive application's configuration data (**/opt/<AppName>/etc**). -- Developers have control over respective log output, and use [DLT Viewer](broken_link_ac/wiki/display/PSP/DLT+Viewer) or similar tools to read the logs. +- Developers have control over respective log output, and use DLT Viewer or similar tools to read the logs. ### Example Configuration file for an application (optional) is structured as follows: ```json diff --git a/score/datarouter/doc/guideline/file_based_local.md b/score/datarouter/doc/guideline/file_based_local.md index d9dce2ad..208338f2 100644 --- a/score/datarouter/doc/guideline/file_based_local.md +++ b/score/datarouter/doc/guideline/file_based_local.md @@ -2,7 +2,7 @@ You sometimes want to get a log in the filesystem. No matter if qemu or normal, this should work. Though you can set it up at application level only, it can bring significant benefits for offline analysis. -1. take a look at the following document regarding configuration of logging: [xpad doc](broken_link_g/xpad/documentation/blob/master/guidelines/logging/configuration.md) +1. take a look at the following document regarding configuration of logging [logging.json](https://github.com/eclipse-score/baselibs/tree/main/score/mw/log#configuration) The following config will set App1 to write into /tmp/App1.dlt diff --git a/score/mw/log/design/backend/BUILD b/score/mw/log/design/backend/BUILD new file mode 100644 index 00000000..b420f289 --- /dev/null +++ b/score/mw/log/design/backend/BUILD @@ -0,0 +1,41 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +load( + "@score_tooling//bazel/rules/rules_score:rules_score.bzl", + "architectural_design", +) + +architectural_design( + name = "mw_log_backend_architectural_design", + dynamic = [ + "datarouter_backend/datarouter_backend_datarouterbackend.puml", + "datarouter_backend/datarouter_message_client_impl_connecttodatarouter.puml", + "datarouter_backend/shared_memory_reader_read.puml", + "datarouter_backend/shared_memory_writer_allocandwrite.puml", + "datarouter_backend/verbose_logging_sequence.puml", + ], + static = [ + "datarouter_backend/README.md", + "datarouter_backend/datarouter_class_diagram.puml", + "datarouter_backend/inter_process_communication.puml", + "datarouter_backend/mw_log_datarouter_recorder.puml", + "datarouter_backend/mw_log_shared_memory_reader.puml", + "datarouter_backend/verbose_logging_static.puml", + "datarouter_backend/write_factory_design.puml", + "file_output_backend.md", + "mw_log_file_backend.puml", + "mw_log_recorders.puml", + ], + visibility = ["//visibility:public"], +) diff --git a/score/mw/log/design/backend/datarouter_backend/README.md b/score/mw/log/design/backend/datarouter_backend/README.md index 1a402d16..26dc474c 100644 --- a/score/mw/log/design/backend/datarouter_backend/README.md +++ b/score/mw/log/design/backend/datarouter_backend/README.md @@ -43,25 +43,24 @@ are as follows: In the Datarouter backend the goal is to safely and efficiently transfer the log messages from the user process to the Datarouter process. -The inter-process communication takes place via shared memory and the [message -passing library](../../../com/message_passing/design/README.md). This library -only supports unidirectional message transport. As we need bidirectional +The inter-process communication takes place via shared memory and the message +passing library. This library only supports unidirectional message transport. As we need bidirectional communication over the side channel, we establish two independent unidirectional channels. On the highest level of abstraction we see the ASIL-B qualified client process on the one side and the datarouter process on the other -![Inter-process communication](./score/mw/log/design/backend/datarouter_backend/inter_process_communication.puml). +INTER_PROCESS_COMMUNICATION. The logs are written by the client into shared memory and read-out by datarouter. Freedom of interference is ensured since the datarouter process has read-only access to the shared-memory. In order to reuse the logging buffers in shared-memory the client may overwrite them after datarouter has acknowledged it has successfully read them. This acknowledgement is sent via the -safety-qualified message passing library. +safety-qualified [message passing library](https://github.com/eclipse-score/communication/blob/main/score/message_passing/dependability/software_architectural_design/client-server.md). ## Class diagram -![Class diagram](./score/mw/log/design/backend/datarouter_backend/datarouter_class_diagram.puml) +DATAROUTER_CLASS_DIAGRAM The class diagram above shows the relevant classes client-side and in Datarouter. Client-side the `DatarouterBackend` contains a circular allocator @@ -82,14 +81,14 @@ access to the ring buffer between Datarouter and the client. ## Activity diagrams -![DataRouterBackend::DataRouterBackend Activity diagram](./score/mw/log/design/backend/datarouter_backend/datarouter_backend_datarouterbackend.puml) +DATAROUTER_BACKEND_DATAROUTERBACKEND ## Lock-free Shared Memory Design The log messages from apps are transferred to Datarouter through shared memory. For lock- and wait-free data exchange we use the `WaitFreeAlternatingWriter` as -documented [here](../../detail/wait_free_producer_queue/README.md) as part of -the `SharedMemoryWriter` class. The data in shared memory is layed out in +documented [here](https://github.com/eclipse-score/logging/blob/main/score/mw/log/detail/wait_free_producer_queue/README.md) as part of the `SharedMemoryWriter` class. +The data in shared memory is layed out in consecutive and contiguous segments: 1. Control structure `mw::log::detail::SharedData` at offset = 0. @@ -201,7 +200,7 @@ readable without synchronization. Only after reading the remaining data from the ring buffer, should Datarouter unmap the shared memory page. Then the OS should free up the used resources. -![SharedMemoryReader Class diagram](./score/mw/log/design/backend/datarouter_backend/mw_log_shared_memory_reader.puml) +MW_LOG_SHARED_MEMORY_READER ## Limited impact of incoming messages in the logging client @@ -225,9 +224,7 @@ after each incoming request. ## Message exchange between Logging Clients and Datarouter The side channel in logging is needed to synchronize the access to the data in -shared memory between the client and Datarouter. Previously, the channel was -implemented using unix domain sockets. Here, we replace unix domain sockets by -[message passing](../../../com/message_passing/design/README.md). +shared memory between the client and Datarouter. Datarouter periodically scans for new clients and initiates the message exchange. In the message exchange between Datarouter and the Clients, diff --git a/score/mw/log/design/backend/file_output_backend.md b/score/mw/log/design/backend/file_output_backend.md index 34999898..17f47ef0 100644 --- a/score/mw/log/design/backend/file_output_backend.md +++ b/score/mw/log/design/backend/file_output_backend.md @@ -31,17 +31,17 @@ or onto the console. `MessageBuilder` is responsible for serving data in correct order of flushing into file or console and stores some of common parts of the header. -![Static Design](./score/mw/log/design/backend/mw_log_file_backend.puml) +MW_LOG_FILE_BACKEND `SlotDrainer` is responsible for storing and disposal of already serialized data. First data gets inserted into circular buffer. After that step program flow enters a loop that iterates over available slots in ring buffer and then by means of `NonBlockingWriter` iterates over all spans of each message. -![Sequence Design](./score/mw/log/design/slot_drainer_sequence_design.puml) +SlotDrainerSequenceDesign Flush procedure exits whenever all available data is written to the file or writing procedure would block i.e. write operation reports that number of bytes written is less then requested. -![Action Diagram](./score/mw/log/design/slot_drainer_action_diagram_design.puml) +SlotDrainerActionDiagram