Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 10 additions & 21 deletions score/mw/log/design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ While the idea of lock-free data structures is not new, the specific rules for t
Starting from this basic idea, the static design is divided into four main parts:

1. `Formatter`
Support different kind of logging formats. The most major one is the [DLT format](<broken_link_g/swh/safe-posix-platform/blob/master/score/mw/log/README.md#dlt-formatted-payload>).
Support different kind of logging formats. The most major one is the [DLT format](../README.md#dlt-formatted-payload).
Another one is the raw format (no special formatting applied). A future extension with other formats will be easy,
separating this concern from the others mentioned below.
2. `Backend`
Expand All @@ -69,13 +69,13 @@ Starting from this basic idea, the static design is divided into four main parts
This design allows that any content streamed by the user into a `LogStream`, will directly end up in the respective slot
implementation.

![Verbose Logging class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/verbose_logging_static.uxf)
![Verbose Logging class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/verbose_logging_static.puml)

![Verbose Logging sequence diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/verbose_logging_sequence.uxf)
![Verbose Logging sequence diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/verbose_logging_sequence.puml)

![Non-Verbose Logging class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/non_verbose_logging_static.uxf)
![Non-Verbose Logging class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/non_verbose_logging_static.puml)

![ErrorDomain class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/error_domain.uxf)
![ErrorDomain class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/error_domain.puml)

### Types of recorders

Expand All @@ -88,28 +88,17 @@ Following recorders are supported:
5. EmptyRecoder - used when logging is off.
Because of the similarity between TextRecorder and FileRecorder it is decided to use the common Backend for both.

![Recorders class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/mw_log_recorders.uxf)

![DataRouterRecorder class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/mw_log_datarouter_recorder.uxf)

### WriterFactory Design

![WriterFactory Design](./write_factory_design.puml)
![Recorders class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/mw_log_recorders.puml)

### High Level Component Diagram - Remote Logging
![Remote logging](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/remote_logging.plantuml)

### Activity diagrams
![Remote logging](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/remote_logging.puml)

![CircularAllocator::AcquireSlotToWrite Activity diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/circular_buffer_allocator_acquireslottowrite.uxf)

![DatarouterMessageClientImpl::ConnectToDatarouter Activity diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/datarouter_message_client_impl_connecttodatarouter.uxf)

![SharedMemoryReader::Read Activity diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/shared_memory_reader_read.uxf)
### Activity diagrams

![SharedMemoryReader::AllocAndWrite Activity diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/shared_memory_writer_allocandwrite.uxf)
![CircularAllocator::AcquireSlotToWrite Activity diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/circular_buffer_allocator_acquireslottowrite.puml)

![WaitFreeStack::TryPush Activity diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/wait_free_stack_trypush.uxf)
![WaitFreeStack::TryPush Activity diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/wait_free_stack_trypush.puml)

### User-Facing APIs

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@startuml circular_buffer_allocator_acquireslottowrite
title Circular Buffer Allocator Acquire Slot To Write
start
:Loop Counter = 0;
repeat :Increment loop counter;
:Atomically
Get slot
Increment next slot index;
:Slot index = claimed slot % circular buffer capacity;
if (Loop counter > circular buffer size) then (Yes)
:Return empty;
stop
else (No)
endif
repeat while (Slot in use?) is (Yes) not (No);
:Mark Slot as in use;
:Return Slot index;
stop
@enduml
6 changes: 3 additions & 3 deletions score/mw/log/design/configuration_design.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ the verbose logging configuration and omit the non-verbose aspect.

The use case diagram below shows three typical use cases supported by the design:

![Use Case Diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/configuration_use_cases.uxf)
![Use Case Diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/configuration_use_cases.puml)

## Class Diagram

Expand All @@ -46,7 +46,7 @@ from the original `mw::log` [design document](README.md). We omit the details
for the `Recorder` and `Runtime` classes, and focus on the new classes
introduced in this design:

![Class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/configuration_static.uxf)
![Class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/configuration_static.puml)

The design is centered around the `RecorderFactory` class, which contains three
static methods for each major use case. By default for on-target logging the
Expand Down Expand Up @@ -89,7 +89,7 @@ file discoverer.
The sequence diagram below depicts the initialization that takes place once when
the user makes the first invokes `mw::log`:

![Class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/configuration_sequence.uxf)
![Class diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/configuration_sequence.puml)

In the diagram, the user calls `mw::log::Error()` to send the first log message
of the program. The `LogStreamFactory` then calls `GetRecorder()` on the
Expand Down
108 changes: 108 additions & 0 deletions score/mw/log/design/configuration_sequence.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
@startuml configuration_sequence
title Configuration Sequence

participant "App" as App
participant "Logger" as LOG
participant "LogStreamFactory" as LSF
participant "Runtime" as RT
participant "RecorderFactory" as RF
participant "TargetConfigReader" as TCR
participant "ConfigurationFileDiscoverer" as CFD
participant "JSON" as JSON
participant "OS" as OS

activate App

App -> LOG **: CreateLogger(...)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The CreateLogger only registers a logger in the container butdoes not trigger the runtime initialization. The initialization is triggered by the first log call. A note would make sense here.

note right of LOG
The initialization of the runtime is triggered by the first log call.
endnote

activate LOG

App -> LOG: LogError()

LOG -> LSF: GetStream(LogLevel)

LSF -> RT: GetRecorder()

alt Runtime instance has not been created
RT -> RT: Constructor
activate RT
end

RT -> RF **: CreateRecorderFactory()

activate RF

RT -> RF: CreateFromConfiguration()


RF -> CFD **: make_unique<ConfigurationFileDiscoverer>(...)
activate CFD

RF -> TCR **: make_unique<TargetConfigReader>(ConfigurationFileDiscoverer)
activate TCR


RF -> TCR: ReadConfig()

TCR -> CFD: FindConfigurationFiles()

note right of CFD
Find and return the existing
config files.
end note

CFD -> OS: access(/etc/ecu_logging_config.json)
alt MW_LOG_CONFIG_FILE is defined
CFD -> OS: access(MW_LOG_CONFIG_FILE)
else MW_LOG_CONFIG_FILE is undefined
CFD -> OS: access(<cwd>/etc/logging.json)
CFD -> OS: access(<cwd>/logging.json)
CFD -> OS: access(<binary path>/../etc/logging.json)
end

CFD -> TCR: Return global and environmental or application config file paths.

TCR -> JSON: FromFile(global_file_path)
JSON -> TCR:

alt MW_LOG_CONFIG_FILE is defined
TCR -> JSON: FromFile(<environmental file path>)
JSON -> TCR:
else MW_LOG_CONFIG_FILE is undefined
TCR -> JSON: FromFile(<app_file_path>)
JSON -> TCR:
end

note right of TCR
Overwrite global configiuration
with environmental or application config file paths.
end note

TCR -> RF: Return Configuration instance

alt "Console only recorder (compile option)"

Create "TextRecorder" as TR
RF -> TR: Create instance with configuration

RF -> ER: if logmode other than KConsole is provided.

else "Datarouter (compile option)"

Create "CompositeRecorder" as CR

RF -> CR
note left of CR
Recorder setup depends on the datarouter configuration.
endnote
end

RF -> RT: Store returned instance

RT -> LSF: Return Recorder reference
LSF -> LOG: LogStream with Recorder

@enduml
26 changes: 26 additions & 0 deletions score/mw/log/design/configuration_use_case.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@startuml configuration_use_cases
left to right direction
title Configuration Use Cases

actor "Developer\nDebug application\ndeployed on target" as Dev1

actor "Developer,\nUnit testing" as Dev2
actor "Performance\nEngineer" as PerfEng

usecase "ECU wide configuration\n--\nECUID = MPP1\nLogLevel = kError" as UC1_ECU
usecase "Application configuration\n--\nAPPID = Para\nLogMode = kRemote | kConsole\nLogLevel = kDebug" as UC1_App

usecase "Print the logs on the console for\nanalysis of unit test failures." as UC2_Console
usecase "No logging.json files" as UC2_Default

usecase "Disable logging completely\nMeasure performance impact of logging" as UC3_Performance

Dev1 --> UC1_ECU : "Use case 1"
Dev1 --> UC1_App : "Use case 1"

Dev2 --> UC2_Console : "Use case 2"
Dev2 --> UC2_Default : "Use case 2"

PerfEng --> UC3_Performance : "Use case 3"

@enduml
2 changes: 1 addition & 1 deletion score/mw/log/design/dependency_graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ implementation details of the backends. Applying the component principles from
[1] the goal here is to structure the dependencies in a way that instable
components depend on stable components.

![Use Case Diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/frontend_dependency_graph.uxf)
![Use Case Diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/frontend_dependency_graph.puml)

The `mw::log` component is divided in a stable frontend and the backends with
the implementation details. The frontend shall be API compatible to the ara::log
Expand Down
6 changes: 3 additions & 3 deletions score/mw/log/design/file_output_backend.md
Original file line number Diff line number Diff line change
Expand Up @@ -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](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/mw_log_file_backend.uxf)
![Static Design](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/mw_log_file_backend.puml)

`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](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/slot_drainer_sequence_design.uxf)
![Sequence Design](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/slot_drainer_sequence_design.puml)

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](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/swh/safe-posix-platform/score/mw/log/design/slot_drainer_action_diagram_design.uxf)
![Action Diagram](https://www.plantuml.com/plantuml/proxy?src=https://raw.githubusercontent.com/eclipse-score/baselibs/refs/heads/main/score/mw/log/design/slot_drainer_action_diagram_design.puml)
56 changes: 56 additions & 0 deletions score/mw/log/design/frontend_dependency_graph.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
@startuml frontend_dependency_graph
title Frontend Dependency Graph

package "mw::log frontend" as frontend {
class score::mw::log::Logger {
+Includes classes and free functions
}
class score::mw::log::detail::LogStreamFactory
class score::mw::log::LogStream
class score::mw::log::detail::Runtime
class score::mw::log::LoggerContainer
class score::mw::log::LogTypes
abstract score::mw::log::Recorder
abstract score::mw::log::IRecorderFactory
}

package "mw::log implementation details" as details {
class score::mw::log::detail::Configuration {}
class score::mw::log::detail::TargetConfigReader {}

class score::mw::log::detail::ConsoleRecorder {}
class score::mw::log::detail::ConsoleRecorderFactory {}
class score::mw::log::detail::EmptyRecorder {}

class score::mw::log::detail::RecorderFactory {}
}


note top of frontend
Frontend contains the public user API,
and the necessary classes to interface
with the recorder interface.
end note

note bottom of details
Instable components shall
depend on stable classes.
end note

score::mw::log::detail::LogStreamFactory ..> score::mw::log::LogStream
score::mw::log::detail::Runtime o-- score::mw::log::LoggerContainer
score::mw::log::detail::Runtime --> score::mw::log::Recorder
score::mw::log::detail::Runtime o-- score::mw::log::Recorder
score::mw::log::detail::Runtime --> score::mw::log::detail::Configuration
score::mw::log::detail::Configuration --> score::mw::log::detail::TargetConfigReader
score::mw::log::Recorder <|-- score::mw::log::detail::EmptyRecorder

score::mw::log::Recorder <|-- score::mw::log::detail::ConsoleRecorder
score::mw::log::IRecorderFactory <|-- score::mw::log::detail::ConsoleRecorderFactory
score::mw::log::detail::ConsoleRecorderFactory ..> score::mw::log::detail::ConsoleRecorder

score::mw::log::LogStream --> score::mw::log::Recorder
score::mw::log::Logger ..> score::mw::log::LogStream
score::mw::log::LoggerContainer o-- score::mw::log::Logger

@enduml
Loading
Loading