Repository: eclipse-iceoryx/iceoryx2
Pull request #474: [#396] Read and set LogLevel from environment variable
Author: login: zmostafa
Created: 2024-10-16T14:18:18Z | Merged: 2025-03-12T20:21:04Z

## Notes for Reviewer
<!-- Items in addition to the checklist below that the reviewer should look for -->

Adds functionality to set the log level from the environment.

I went for @elBoberido proposal solution, where I read an environment variable called `IOX2_LOG_LEVEL` and set the LogLevel, with its value at runtime.

## Pre-Review Checklist for the PR Author

1. [x] Add sensible notes for the reviewer
1. [x] PR title is short, expressive and meaningful
1. [x] Relevant issues are linked in the [References](#references) section
1. [x] Every source code file has a copyright header with `SPDX-License-Identifier: Apache-2.0 OR MIT`
1. [x] Branch follows the naming format (`iox2-123-introduce-posix-ipc-example`)
1. [x] Commits messages are according to this [guideline][commit-guidelines]
    - [x] Commit messages have the issue ID (`[#123] Add posix ipc example`)
    - [x] Commit author matches [Eclipse Contributor Agreement][eca] (and ECA is signed)
1. [x] Tests follow the [best practice for testing][testing]
1. [x] Changelog updated [in the unreleased section][changelog] including API breaking changes
1. [x] Assign PR to reviewer
1. [x] All checks have passed (except `task-list-completed`)

[commit-guidelines]: https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
[eca]: http://www.eclipse.org/legal/ECA.php
[testing]: https://github.com/eclipse-iceoryx/iceoryx/blob/master/doc/website/concepts/best-practice-for-testing.md
[changelog]: https://github.com/eclipse-iceoryx/iceoryx2/blob/main/doc/release-notes/iceoryx2-unreleased.md

## Checklist for the PR Reviewer

- [x] Commits are properly organized and messages are according to the guideline
- [x] Unit tests have been written for new behavior
- [x] Public API is documented
- [x] PR title describes the changes

## Post-review Checklist for the PR Author

1. [x] All open points are addressed and tracked via issues

## References

<!-- Use either 'Closes #123' or 'Relates to #123' to reference the corresponding issue. -->

Closes #396 <!-- Add issue number after '#' -->


Linked issue #123: `iceoryx2-cal::hash` Introduce uuid type and make it convertable to `FileName`
## Brief feature description

All over the code the `uuid` is used as basis for a files and therefore for the `FileName`. It is always safe to convert the uuid to a file name, nevertheless the user has to write `unsafe {}` blocks with a safety statement that it is safe. A better approach would be to bake this all in, into its own uuid type.


Diff:
diff --git a/.cargo/config.toml b/.cargo/config.toml
index 3fda991ea2..c3175a79ca 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -4,6 +4,7 @@ rustdocflags = ["-D", "warnings"]
 [env]
 RUST_TEST_THREADS = "1"
 RUST_BACKTRACE = "1"
+IOX2_LOG_LEVEL = "Trace"
 
 [target.debug]
 rustflags = ["-Z", "sanitizer=address"]
diff --git a/FAQ.md b/FAQ.md
index 62b08f54f6..8300906950 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -4,18 +4,18 @@
 
 iceoryx2 stores all data in shared memory, which imposes certain restrictions.
 Only data that is self-contained and does not use pointers to reference itself
-is allowed. This is because shared memory is mapped at different offsets in
-each process, rendering absolute pointers invalid. Additionally, if the data
+is allowed. This is because shared memory is mapped at different offsets in each
+process, rendering absolute pointers invalid. Additionally, if the data
 structure uses the heap, it is stored locally within a process and cannot be
-accessed by other processes. As a result, data types such as `String`, `Vec`,
-or `HashMap` cannot be used as payload types.
+accessed by other processes. As a result, data types such as `String`, `Vec`, or
+`HashMap` cannot be used as payload types.
 
 Additionally, every data type must be annotated with `#[repr(C)]`. The Rust
 compiler may reorder the members of a struct, which can lead to undefined
 behavior if another process expects a different ordering.
 
-To address this, iceoryx2 provides shared-memory-compatible data types. You
-can refer to the [complex data types example](examples/rust/complex_data_types),
+To address this, iceoryx2 provides shared-memory-compatible data types. You can
+refer to the [complex data types example](examples/rust/complex_data_types),
 which demonstrates the use of `FixedSizeByteString` and `FixedSizeVec`.
 
 ## How To Define Custom Data Types (Rust)
@@ -53,11 +53,11 @@ Take a look at the
 
 ## How To Make 32-bit and 64-bit iceoryx2 Applications Interoperatable
 
-This is currently not possible since we cannot guarantee to have the same
-layout of the data structures in the shared memory. On 32-bit architectures
-64-bit POD are aligned to a 4 byte boundary but to a 8 byte boundary on
-64-bit architectures. Some additional work is required to make 32-bit and
-64-bit applications interoperabel.
+This is currently not possible since we cannot guarantee to have the same layout
+of the data structures in the shared memory. On 32-bit architectures 64-bit POD
+are aligned to a 4 byte boundary but to a 8 byte boundary on 64-bit
+architectures. Some additional work is required to make 32-bit and 64-bit
+applications interoperabel.
 
 ## My Transmission Type Is Too Large, Encounter Stack Overflow On Initialization
 
@@ -71,8 +71,8 @@ than the available stack size.
 ## 100% CPU Load When Using The WaitSet
 
 The WaitSet wakes up whenever an attachment, such as a `Listener` or a `socket`,
-has something to read. If you do not handle all notifications, for example,
-with `Listener::try_wait_one()`, the WaitSet will wake up immediately again,
+has something to read. If you do not handle all notifications, for example, with
+`Listener::try_wait_one()`, the WaitSet will wake up immediately again,
 potentially causing an infinite loop and resulting in 100% CPU usage.
 
 ## Does iceoryx2 Offer an Async API?
@@ -105,31 +105,57 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 supports different log levels
+`trace, debug, info, warning, error, fatal`
 
 ## How to set the log level
 
+iceoryx2 provides different APIs which can be used to set the log level
+directly in the code or read the configured log level by environment variable
+
+`export IOX2_LOG_LEVEL=Trace`
+
+then in the `main.rs` call one of the functions to set the log level
+
 ```rust
 use iceoryx2::prelude::*
 
 // ...
 
+// Reads LogLevel from env and defaults to LogLevel INFO
+// if the environment variable is not set or has an unsupported value
+set_log_level_from_env_or_default();
+
+// Reads LogLevel from env and sets it with a user-given value
+// if the environment variable is not set or has an unsupported value  
+set_log_level_from_env_or(LogLevel::DEBUG);
+
+// sets LogLevel programmatically with a supported user-given value
+// and does not try to read the environment variable
 set_log_level(LogLevel::Trace);
 ```
 
+**Note**: While working on iceoryx2, it gets its default logging level from
+`.cargo/config.toml`, but this can be over-ridden by using the APIs that reads
+environment variable `IOX2_LOG_LEVEL` or set the log level directly in the code.
+
 ## A crash leads to the failure `PublishSubscribeOpenError(UnableToOpenDynamicServiceInformation)`
 
-When an application crashes, some resources may remain in the system and need
-to be cleaned up. This issue is detected whenever a new iceoryx2 instance is
-created, removed, or when someone opens the service that the crashed process
-had previously opened. On the command line, you may see a message like this:
+When an application crashes, some resources may remain in the system and need to
+be cleaned up. This issue is detected whenever a new iceoryx2 instance is
+created, removed, or when someone opens the service that the crashed process had
+previously opened. On the command line, you may see a message like this:
 
 ```ascii
 6 [W] "Node::<iceoryx2::service::ipc::Service>::cleanup_dead_nodes()"
@@ -139,9 +165,9 @@ had previously opened. On the command line, you may see a message like this:
 ```
 
 However, for successful cleanup, the process attempting the cleanup must have
-sufficient permissions to remove the stale resources of the dead process. If
-the cleanup fails due to insufficient permissions, the process that attempted
-the cleanup will continue without removing the resources.
+sufficient permissions to remove the stale resources of the dead process. If the
+cleanup fails due to insufficient permissions, the process that attempted the
+cleanup will continue without removing the resources.
 
 Generally, it is not necessary to manually clean up these resources, as other
 processes should detect and handle the cleanup when creating or removing nodes,
@@ -151,6 +177,7 @@ Nevertheless, there are three different approaches to initiate stale resource
 cleanup:
 
 1. **Using the iceoryx2 API**:
+
    ```rust
    Node::<ipc::Service>::list(Config::global_config(), |node_state| {
      if let NodeState::<ipc::Service>::Dead(view) = node_state {
@@ -166,7 +193,7 @@ cleanup:
 2. **Using the command line tool**: `iox2 node -h` (NOT YET IMPLEMENTED)
 
 3. **Manual cleanup**: Stop all running services and remove all shared memory
-    files with the `iox2` prefix from:
+   files with the `iox2` prefix from:
    * POSIX: `/dev/shm/`, `/tmp/iceoryx2`
    * Windows: `c:\Temp\iceoryx2`
 
diff --git a/doc/release-notes/iceoryx2-unreleased.md b/doc/release-notes/iceoryx2-unreleased.md
index b5c18d9fe8..9d04579a41 100644
--- a/doc/release-notes/iceoryx2-unreleased.md
+++ b/doc/release-notes/iceoryx2-unreleased.md
@@ -11,6 +11,8 @@
     conflicts when merging.
 -->
 
+* Read LogLevel from environment variable
+    [#396](https://github.com/eclipse-iceoryx/iceoryx2/issues/396)
 * Lookup config file in default locations
     [#442](https://github.com/eclipse-iceoryx/iceoryx2/issues/442)
 * Introduce `socket_pair` abstraction in POSIX wrapper
diff --git a/iceoryx2-bb/log/src/lib.rs b/iceoryx2-bb/log/src/lib.rs
index 23af0ab956..b8ed833b01 100644
--- a/iceoryx2-bb/log/src/lib.rs
+++ b/iceoryx2-bb/log/src/lib.rs
@@ -153,6 +153,8 @@ use iceoryx2_pal_concurrency_sync::iox_atomic::IoxAtomicU8;
 use core::{fmt::Arguments, sync::atomic::Ordering};
 use std::sync::Once;
 
+use std::env;
+
 #[cfg(feature = "logger_tracing")]
 static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();
 
@@ -162,10 +164,10 @@ static DEFAULT_LOGGER: logger::log::Logger = logger::log::Logger::new();
 #[cfg(not(any(feature = "logger_log", feature = "logger_tracing")))]
 static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();
 
-const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;
+const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Info;
 
 static mut LOGGER: Option<&'static dyn Log> = None;
-static LOG_LEVEL: IoxAtomicU8 = IoxAtomicU8::new(DEFAULT_LOG_LEVEL);
+static LOG_LEVEL: IoxAtomicU8 = IoxAtomicU8::new(DEFAULT_LOG_LEVEL as u8);
 static INIT: Once = Once::new();
 
 pub trait Log: Send + Sync {
@@ -185,6 +187,44 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(log_level_string: &str, log_level_fallback: LogLevel) -> LogLevel {
+        match log_level_string.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!(
+                    "Invalid value for 'IOX2_LOG_LEVEL' environment variable!\
+                \nFound: {:?}\
+                \nAllowed is one of: fatal, error, warn, info, debug, trace\
+                \nSetting log level as : {:?}",
+                    log_level_string, log_level_fallback
+                );
+                log_level_fallback
+            }
+        }
+    }
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL" or default it wiht LogLevel::INFO
+pub fn set_log_level_from_env_or_default() {
+    set_log_level_from_env_or(DEFAULT_LOG_LEVEL);
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL", and if the environment variable
+/// doesn't exits it sets it with a user-defined logging level
+pub fn set_log_level_from_env_or(v: LogLevel) {
+    let log_level = env::var("IOX2_LOG_LEVEL")
+        .ok()
+        .map(|s| LogLevel::from_str_fuzzy(&s, v))
+        .unwrap_or(v);
+    set_log_level(log_level);
+}
+
 /// Sets the current log level. This is ignored for external frameworks like `log` or `tracing`.
 /// Here you have to use the log-level settings of that framework.
 pub fn set_log_level(v: LogLevel) {
@@ -204,7 +244,6 @@ pub fn set_logger<T: Log + 'static>(value: &'static T) -> bool {
         unsafe { LOGGER = Some(value) };
         set_logger_success = true;
     });
-
     set_logger_success
 }
 
diff --git a/iceoryx2/src/prelude.rs b/iceoryx2/src/prelude.rs
index c472ea4a47..c052d00791 100644
--- a/iceoryx2/src/prelude.rs
+++ b/iceoryx2/src/prelude.rs
@@ -25,6 +25,8 @@ pub use iceoryx2_bb_elementary::alignment::Alignment;
 pub use iceoryx2_bb_elementary::placement_default::PlacementDefault;
 pub use iceoryx2_bb_elementary::CallbackProgression;
 pub use iceoryx2_bb_log::set_log_level;
+pub use iceoryx2_bb_log::set_log_level_from_env_or;
+pub use iceoryx2_bb_log::set_log_level_from_env_or_default;
 pub use iceoryx2_bb_log::LogLevel;
 pub use iceoryx2_bb_posix::file_descriptor::{FileDescriptor, FileDescriptorBased};
 pub use iceoryx2_bb_posix::file_descriptor_set::SynchronousMultiplexing;


Reviews:
user: login: xieyuschen
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-16T14:26:14Z
user: login: xieyuschen
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-16T14:33:32Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-16T18:59:31Z
user: login: elBoberido
body: @zmostafa great to have you back :)

I guess you need to sign the ECA. It can be done as individual contributor if you do the contributions in your spare time.
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-10-16T23:16:05Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-17T18:24:06Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-17T18:52:44Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-17T18:54:52Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-10-17T23:51:08Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-10-17T23:55:54Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-10-18T00:04:58Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-21T18:20:19Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-10-29T17:19:23Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-30T12:48:45Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-10-30T12:54:22Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-01T16:56:12Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-11-02T08:59:16Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-05T22:17:40Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-08T14:03:19Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-08T14:05:05Z
user: login: elBoberido
body: @zmostafa sorry for the slow response. I was quite busy the last days, but I try to improve on my response time :)
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-08T14:21:50Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-11-08T14:51:43Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-11-08T15:06:04Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-08T15:53:56Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-12T18:41:48Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-11-12T18:57:26Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-11-12T19:07:22Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-13T12:58:23Z
user: login: orecham
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-11-13T13:50:32Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-13T15:15:49Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-13T15:18:59Z
user: login: orecham
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-11-13T16:18:06Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2024-11-14T14:05:43Z
user: login: orecham
body: The FreeBSD CI issue is not related to this PR - you can ignore it. Maybe also the Windows issue. 

Once the remaining open conversation is resolved I will help take care of the CI issues.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T11:29:13Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T13:37:49Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T13:37:56Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T13:38:04Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T15:15:52Z
user: login: elBoberido
body: Looks good. There is an open PR to fix the FreeBSD and Windows build issue. Once merged, you can rebase to make the CI happy.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T15:33:49Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T14:33:03Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T14:36:07Z
user: login: elBoberido
body: Thanks for your patience. It seems that with each of your commits, there are some new suggestions from our side, but this is just nitpicking at a high level :)
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-09T18:21:34Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T20:36:55Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-09T20:38:00Z
user: login: elBoberido
body: Okay, I think the next round will be merged :)
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-09T21:55:41Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T10:25:10Z
user: login: zmostafa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T10:36:53Z
user: login: elBoberido
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-10T12:28:11Z
user: login: elBoberido
body: Thanks for your patience. We could merge the PR but it seems there is a merge conflict in a file. Could you please rebase to the latest main?
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-03-12T15:50:01Z
user: login: elBoberido
body: Okay, this will be the next one to be merged once the CI is finished
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-03-12T17:23:25Z
user: login: elBoberido
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-12T19:19:05Z

Review comments:
diff_hunk: @@ -179,6 +188,27 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl FromStr for LogLevel {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
path: iceoryx2-bb/log/src/lib.rs
user: login: xieyuschen
body: I have wrote a part of it this afternoon, but you go ahead. Cool!

if it never returns an error, why not return LogLevel directly?
created_at: 2024-10-16T14:24:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -36,7 +36,9 @@ impl Default for Logger {
 }
 
 impl Logger {
-    pub const fn new() -> Self {
+    pub fn new() -> Self {
+        init_log_level();
path: iceoryx2-bb/log/src/logger/console.rs
user: login: xieyuschen
body: i think it's better to do lazy initialization in `get_log_level` and ensure all loggers get level by `get_log_level`. needn't call `init_log_level` everywhere.
created_at: 2024-10-16T14:33:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -36,7 +36,9 @@ impl Default for Logger {
 }
 
 impl Logger {
-    pub const fn new() -> Self {
+    pub fn new() -> Self {
+        init_log_level();
path: iceoryx2-bb/log/src/logger/console.rs
user: login: zmostafa
body: @xieyuschen Thanks, that's much better indeed.
created_at: 2024-10-16T18:59:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -159,9 +161,14 @@ static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();
 static DEFAULT_LOGGER: logger::log::Logger = logger::log::Logger::new();
 
 #[cfg(not(any(feature = "logger_log", feature = "logger_tracing")))]
-static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();
+pub static DEFAULT_LOGGER: Lazy<logger::console::Logger> =
+    Lazy::new(logger::console::Logger::new);
 
 const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;
+pub static ENV_LOG_LEVEL: Lazy<LogLevel> = Lazy::new(|| {
+    let log_level_str = env::var("IOX2_LOG_LEVEL").unwrap_or_else(|_| "Info".to_string());
+    LogLevel::from_str(&log_level_str) // Default to Info
+});
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: This is great. I had something else in mind when I created the issue but this idea is better :)

My only concern is the allocation with `String`, which is a hurdle for ASIL-D. But that can be solved with a feature flag later on.

I would also suggest to use `.map(LogLevel::from_str).unwrap_or(DEFAULT_LOG_LEVEL)`. This is one less allocation.

The lazy initialization is problematic in this case. Let's assume the following scenario
- set env variable to trace
- start process A
- set env variable to fatal
- start process B
- process A reads the env variable and sets it to fatal instead of trace

Since the initialization is dependent on an external state, the evaluation should be done when the application starts.
created_at: 2024-10-16T22:55:46Z
author_association: MEMBER
diff_hunk: @@ -179,6 +186,20 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str(s: &str) -> LogLevel {
+        match s {
+            "Trace" => LogLevel::Trace,
+            "Debug" => LogLevel::Debug,
+            "Info" => LogLevel::Info,
+            "Warn" => LogLevel::Warn,
+            "Error" => LogLevel::Error,
+            "Fatal" => LogLevel::Fatal,
+            _ => LogLevel::Info,
+        }
+    }
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: What do you think about making this a bit more relaxed by normalizing the input string to lower case. In this case the function name would be more like `from_str_fuzzy`.

I think it would be good to use `printf` and tell the user that the env variable contains an invalid string.

Finally, you can use `DEFAULT_LOG_LEVEL` for the default match arm.
created_at: 2024-10-16T23:02:58Z
author_association: MEMBER
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: Doesn't this prevent to set the log level programmatically?

I think you need to wrap this in a similar fashion like `INIT.call_once` and also do the call in `set_log_level`, similar to how it is done in `set_logger` but inside and outside of the `call_once` call.
created_at: 2024-10-16T23:04:09Z
author_association: MEMBER
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido yes, calling it in `get_log_level` will override any value being set programmatically.
But do you meant calling it inside `get_logger` for once? I tried your proposal inside `get_log_level` but the init was not successful, but when i had it in `get_logger` just after `LOGGER` init, it seems to be the right place for init.

```
pub fn get_logger() -> &'static dyn Logger {
    INIT.call_once(|| {
        unsafe { LOGGER = Some(&*DEFAULT_LOGGER) };
        println!("setting env var");
        LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
    });

    unsafe { *LOGGER.as_ref().unwrap() }
}

```
created_at: 2024-10-17T18:24:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -179,6 +186,20 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str(s: &str) -> LogLevel {
+        match s {
+            "Trace" => LogLevel::Trace,
+            "Debug" => LogLevel::Debug,
+            "Info" => LogLevel::Info,
+            "Warn" => LogLevel::Warn,
+            "Error" => LogLevel::Error,
+            "Fatal" => LogLevel::Fatal,
+            _ => LogLevel::Info,
+        }
+    }
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: I had to change the return from the function to `u8` instead of `LogLevle` and updated the code accordingly 
created_at: 2024-10-17T18:52:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -159,9 +161,14 @@ static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();
 static DEFAULT_LOGGER: logger::log::Logger = logger::log::Logger::new();
 
 #[cfg(not(any(feature = "logger_log", feature = "logger_tracing")))]
-static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();
+pub static DEFAULT_LOGGER: Lazy<logger::console::Logger> =
+    Lazy::new(logger::console::Logger::new);
 
 const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;
+pub static ENV_LOG_LEVEL: Lazy<LogLevel> = Lazy::new(|| {
+    let log_level_str = env::var("IOX2_LOG_LEVEL").unwrap_or_else(|_| "Info".to_string());
+    LogLevel::from_str(&log_level_str) // Default to Info
+});
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: 1. Can you explain more about string allocation? how do you track/bench them?
2. about the scenario you mentioned, is not it what should be in the first place? since we might run different instance of application from or within the same shell/env? so each application will utilize its logger? 
created_at: 2024-10-17T18:54:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: Oh, I was not clear enough. You need to create a second static variable, e.g. `INIT_LOG_LEVEL`. The `INIT` variable could also be renamed to `INIT_LOGGER`.

So, no matter if `set_log_level` or `get_log_level` is called first, the `LOG_LEVEL` variable will be initialized only once with the entry from the env variable.
created_at: 2024-10-17T23:51:08Z
author_association: MEMBER
diff_hunk: @@ -179,6 +186,20 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str(s: &str) -> LogLevel {
+        match s {
+            "Trace" => LogLevel::Trace,
+            "Debug" => LogLevel::Debug,
+            "Info" => LogLevel::Info,
+            "Warn" => LogLevel::Warn,
+            "Error" => LogLevel::Error,
+            "Fatal" => LogLevel::Fatal,
+            _ => LogLevel::Info,
+        }
+    }
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: Oh, you can also change the type of `DEFAULT_LOG_LEVEL` and `ENV_LOG_LEVEL` to `LogLevel`. Then there is only two `as u8` required when it is stored into `LOG_LEVEL` :)
created_at: 2024-10-17T23:55:54Z
author_association: MEMBER
diff_hunk: @@ -159,9 +161,14 @@ static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();
 static DEFAULT_LOGGER: logger::log::Logger = logger::log::Logger::new();
 
 #[cfg(not(any(feature = "logger_log", feature = "logger_tracing")))]
-static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();
+pub static DEFAULT_LOGGER: Lazy<logger::console::Logger> =
+    Lazy::new(logger::console::Logger::new);
 
 const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;
+pub static ENV_LOG_LEVEL: Lazy<LogLevel> = Lazy::new(|| {
+    let log_level_str = env::var("IOX2_LOG_LEVEL").unwrap_or_else(|_| "Info".to_string());
+    LogLevel::from_str(&log_level_str) // Default to Info
+});
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: 1. There would be [heaptrack](https://apps.kde.org/de/heaptrack/) as a nice gui to track all heap allocation. But in this case I just know that `String` will allocate on the heap from its documentation.
2. Each application will utilize its own logger instance but if the reading of the env variable is delayed, application A might read the value which was set after it was started and meant to be the value for application B.
created_at: 2024-10-18T00:04:58Z
author_association: MEMBER
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido Can you take a look on the last commit? I hope this is what you were asking for :) 
created_at: 2024-10-21T18:20:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: @zmostafa almost. The `INIT_LOG_LEVEL` calls need to be moved to `set_log_level` and `get_log_level` :)
created_at: 2024-10-29T17:19:23Z
author_association: MEMBER
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido I moved the call to the functions mentioned above, now `INIT_LOG_LEVEL` is done in `set_log_level` and `get_log_level`
created_at: 2024-10-30T12:48:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido I tested the changes on my terminal, even with setting an unknown trace level like `blabla` and printed a warning message to the user, and set the loglevel to default `Info` 
where should I document the new feature for debug LogLevel? FAQ file has a paragraph on setting log level programatically, should this get into the README.MD file? 
created_at: 2024-10-30T12:54:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: @zmostafa looks good. I think the FAQ would be a good candidate for this.

Could you please:
- also look into the other open discussion
- rebase to that we can trigger the CI
- try what happens when `IOX2_LOG_LEVEL` is set in the `env` section of `.cargo/config.toml` and also set as env variable in the terminal?
  - if the env variable set via the terminal has a higher priority than when set via `.cargo/config.toml`, then we could set the log level in `.cargo/config.toml` to trace, so that all iceoryx developer get the detailed log by default but can still control it by setting a custom level in `.bashrc`
created_at: 2024-11-01T16:56:11Z
author_association: MEMBER
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido Branch is rebased.
setting IOX2_LOG_LEVEL in terminal takes precedence over setting it in `.cargo/config.toml` I added the env variable to `.cargon/config.toml` and configured it to Trace, also mentioned this precedence in FAQ.md 
created_at: 2024-11-02T08:59:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: @zmostafa it seems there is still a merge conflict in `iceoryx2-bb/log/src/lib.rs`. Can you do another rebase?
created_at: 2024-11-05T22:17:40Z
author_association: MEMBER
diff_hunk: @@ -187,6 +208,7 @@ pub fn set_log_level(v: LogLevel) {
 
 /// Returns the current log level
 pub fn get_log_level() -> u8 {
+    LOG_LEVEL.store(*ENV_LOG_LEVEL as u8, Ordering::Relaxed);
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: @zmostafa okay, the branch is no mergeable. The markdown linter is now happy, though
created_at: 2024-11-08T14:03:19Z
author_association: MEMBER
diff_hunk: @@ -159,9 +161,14 @@ static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();
 static DEFAULT_LOGGER: logger::log::Logger = logger::log::Logger::new();
 
 #[cfg(not(any(feature = "logger_log", feature = "logger_tracing")))]
-static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();
+pub static DEFAULT_LOGGER: Lazy<logger::console::Logger> =
+    Lazy::new(logger::console::Logger::new);
 
 const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;
+pub static ENV_LOG_LEVEL: Lazy<LogLevel> = Lazy::new(|| {
+    let log_level_str = env::var("IOX2_LOG_LEVEL").unwrap_or_else(|_| "Info".to_string());
+    LogLevel::from_str(&log_level_str) // Default to Info
+});
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: @zmostafa can you please revert the lazy initialization for the logger
created_at: 2024-11-08T14:05:05Z
author_association: MEMBER
diff_hunk: @@ -134,6 +134,20 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 
 ## How to set the log level
 
+iceoryx2 gets the logging level from either the code, or the environment variable `IOX2_LOG_LEVEL`
+the developer can set this environment variable with one of the supported levels:
+```Trace, Debug, Info, Warning, Error, Fatal``` 
+
+`export IOX2_LOG_LEVEL=Trace`
+
+or via `.cargo/config.toml` 
path: FAQ.md
user: login: elBoberido
body: What do you think about writing first about how to set the environment variable and then just list the supported log levels ... maybe even as separate FAQ entry like `What are the supported log levels`?

I also think the markdown linter complains about using more than on back-tick for inline code blocks and only on back-tick for a code block in a separate line.

You can run the linter locally by this command
```sh
internal/scripts/check_markdown_linting.sh
```

created_at: 2024-11-08T14:16:14Z
author_association: MEMBER
diff_hunk: @@ -134,6 +134,20 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 
 ## How to set the log level
 
+iceoryx2 gets the logging level from either the code, or the environment variable `IOX2_LOG_LEVEL`
path: FAQ.md
user: login: elBoberido
body: This is a little bit unclear. Can you rephrase it with the hint that the default log level can be set via the environment variable. If the user decides to set it explicitly via the code, that one has precedence over the environment variable.
created_at: 2024-11-08T14:16:21Z
author_association: MEMBER
diff_hunk: @@ -134,6 +134,20 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 
 ## How to set the log level
 
+iceoryx2 gets the logging level from either the code, or the environment variable `IOX2_LOG_LEVEL`
+the developer can set this environment variable with one of the supported levels:
+```Trace, Debug, Info, Warning, Error, Fatal``` 
+
+`export IOX2_LOG_LEVEL=Trace`
+
+or via `.cargo/config.toml` 
path: FAQ.md
user: login: zmostafa
body: @elBoberido no need to apologize, you are running a company now, how hard it can be? :D 
created_at: 2024-11-08T14:51:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -134,6 +134,20 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 
 ## How to set the log level
 
+iceoryx2 gets the logging level from either the code, or the environment variable `IOX2_LOG_LEVEL`
path: FAQ.md
user: login: zmostafa
body: @elBoberido I know i am bad at documentation, i try to write as fewer words as possible, but let's see how it looks like now
created_at: 2024-11-08T15:06:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -58,24 +58,22 @@ insufficient, a new publisher with a larger `max_slice_len` can be created.
 
 <!-- markdownlint-disable -->
 
-> [!IMPORTANT]
-> Be aware that the history of the old publisher is lost when it is
+> [!IMPORTANT] Be aware that the history of the old publisher is lost when it is
path: FAQ.md
user: login: elBoberido
body: Oh no, does the script have some autocorrection?
This breaks the github [alerts syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts). `> [!IMPORTANT]` must be on a separate line than the content
created_at: 2024-11-08T15:53:17Z
author_association: MEMBER
diff_hunk: @@ -58,24 +58,22 @@ insufficient, a new publisher with a larger `max_slice_len` can be created.
 
 <!-- markdownlint-disable -->
 
-> [!IMPORTANT]
-> Be aware that the history of the old publisher is lost when it is
+> [!IMPORTANT] Be aware that the history of the old publisher is lost when it is
path: FAQ.md
user: login: elBoberido
body: @zmostafa can you please revert those changes. It breaks the alert syntax. Please also have a look at the other open point.
created_at: 2024-11-12T18:41:48Z
author_association: MEMBER
diff_hunk: @@ -58,24 +58,22 @@ insufficient, a new publisher with a larger `max_slice_len` can be created.
 
 <!-- markdownlint-disable -->
 
-> [!IMPORTANT]
-> Be aware that the history of the old publisher is lost when it is
+> [!IMPORTANT] Be aware that the history of the old publisher is lost when it is
path: FAQ.md
user: login: zmostafa
body: @elBoberido hmmm, I think i did, are you sure you are looking at the latest commit? 
I will check the other point about reverting the lazy init, did not see that
created_at: 2024-11-12T18:57:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -159,9 +161,14 @@ static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();
 static DEFAULT_LOGGER: logger::log::Logger = logger::log::Logger::new();
 
 #[cfg(not(any(feature = "logger_log", feature = "logger_tracing")))]
-static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();
+pub static DEFAULT_LOGGER: Lazy<logger::console::Logger> =
+    Lazy::new(logger::console::Logger::new);
 
 const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;
+pub static ENV_LOG_LEVEL: Lazy<LogLevel> = Lazy::new(|| {
+    let log_level_str = env::var("IOX2_LOG_LEVEL").unwrap_or_else(|_| "Info".to_string());
+    LogLevel::from_str(&log_level_str) // Default to Info
+});
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido I reverted back the DEFAULT_LOGGER lazy initialization
created_at: 2024-11-12T19:07:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -58,24 +58,22 @@ insufficient, a new publisher with a larger `max_slice_len` can be created.
 
 <!-- markdownlint-disable -->
 
-> [!IMPORTANT]
-> Be aware that the history of the old publisher is lost when it is
+> [!IMPORTANT] Be aware that the history of the old publisher is lost when it is
path: FAQ.md
user: login: elBoberido
body: @zmostafa I hope to look at the latest commit :sweat_smile:

I did a Ctrl+F5, which should reload everything and dismiss caches but I still see `> [!IMPORTANT]` on the same line as `Be aware that ...`
created_at: 2024-11-13T12:58:18Z
author_association: MEMBER
diff_hunk: @@ -58,24 +58,22 @@ insufficient, a new publisher with a larger `max_slice_len` can be created.
 
 <!-- markdownlint-disable -->
 
-> [!IMPORTANT]
-> Be aware that the history of the old publisher is lost when it is
+> [!IMPORTANT] Be aware that the history of the old publisher is lost when it is
path: FAQ.md
user: login: orecham
body: Note I believe this happens because the auto-corrector does not recognise GitHub-style admonitions, so you need to manually ensure these are on their own line otherwise the auto corrector will try and do line length correction with it on the same line.

Not ideal, I know, but the idea is for the corrector to fix around 90% of the issues which should save more time than manually fixing these small edge cases (e.g. manually fixing all line lengths).
created_at: 2024-11-13T13:50:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -58,24 +58,22 @@ insufficient, a new publisher with a larger `max_slice_len` can be created.
 
 <!-- markdownlint-disable -->
 
-> [!IMPORTANT]
-> Be aware that the history of the old publisher is lost when it is
+> [!IMPORTANT] Be aware that the history of the old publisher is lost when it is
path: FAQ.md
user: login: elBoberido
body: Can we skip line breaks in the auto-corrector? It's just a styling issue, not a rendering issue and it seems to break the github admonitions.
created_at: 2024-11-13T15:15:49Z
author_association: MEMBER
diff_hunk: @@ -159,9 +161,14 @@ static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();
 static DEFAULT_LOGGER: logger::log::Logger = logger::log::Logger::new();
 
 #[cfg(not(any(feature = "logger_log", feature = "logger_tracing")))]
-static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();
+pub static DEFAULT_LOGGER: Lazy<logger::console::Logger> =
+    Lazy::new(logger::console::Logger::new);
 
 const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;
+pub static ENV_LOG_LEVEL: Lazy<LogLevel> = Lazy::new(|| {
+    let log_level_str = env::var("IOX2_LOG_LEVEL").unwrap_or_else(|_| "Info".to_string());
+    LogLevel::from_str(&log_level_str) // Default to Info
+});
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: Can you do the same for `ENV_LOG_LEVEL`
created_at: 2024-11-13T15:18:58Z
author_association: MEMBER
diff_hunk: @@ -58,24 +58,22 @@ insufficient, a new publisher with a larger `max_slice_len` can be created.
 
 <!-- markdownlint-disable -->
 
-> [!IMPORTANT]
-> Be aware that the history of the old publisher is lost when it is
+> [!IMPORTANT] Be aware that the history of the old publisher is lost when it is
path: FAQ.md
user: login: orecham
body: I believe this is the line length corrector causing this. If disabled, then users would need to ensure line length limits were maintained, either manually or with an IDE. I deduced that this would be a larger annoyance for contributors than fixing these more limited edge cases. 

Of course, we could check if the auto corrector could be updated to recognise the GitHub admonitions.
created_at: 2024-11-13T16:18:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -58,24 +58,22 @@ insufficient, a new publisher with a larger `max_slice_len` can be created.
 
 <!-- markdownlint-disable -->
 
-> [!IMPORTANT]
-> Be aware that the history of the old publisher is lost when it is
+> [!IMPORTANT] Be aware that the history of the old publisher is lost when it is
path: FAQ.md
user: login: elBoberido
body: Well, I would argue that one is not only an annoyance but breaks the rendering of the readme if the reviewer does not pay attention and the other one is a choice by ourselves and does not break the rendering if the line is too long. I would rather deactivate the line length detection than having to keep in mind to check for broken admonitions in the PR.
created_at: 2024-11-14T14:05:43Z
author_association: MEMBER
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: you are using unknown logging level {:?}", s);
+                println!("Warning: setting log level as : Info");
+                DEFAULT_LOG_LEVEL
+            }
+        }
+    }
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL"
+pub fn init_log_level() {
+    let log_level = env::var("IOX2_LOG_LEVEL")
+        .ok()
+        .map(|s| LogLevel::from_str_fuzzy(&s))
+        .unwrap_or(LogLevel::Info);
path: iceoryx2-bb/log/src/lib.rs
user: login: orecham
body: ```suggestion
        .unwrap_or(DEFAULT_LOG_LEVEL);
```
created_at: 2025-03-06T10:42:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: you are using unknown logging level {:?}", s);
path: iceoryx2-bb/log/src/lib.rs
user: login: orecham
body: ```suggestion
                println!("Error: unknown logging level {:?}", s);
```

nitpick: prefer logs to be in passive form (what when wrong, not who did it)
created_at: 2025-03-06T10:47:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -105,17 +105,40 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`Trace, Debug, Info, Warning, Error, Fatal`
 
 ## How to set the log level
 
+iceoryx2 gets its default logging level from `.cargo/config.toml` , but this can
+be over-ridden by environment variable `IOX2_LOG_LEVEL` the developer can set
+this environment variable with one of the supported levels.
+
+`export IOX2_LOG_LEVEL=Trace`
+
+then in the main.rs call the function to read the environment variable
+```rust
path: FAQ.md
user: login: orecham
body: ```suggestion
then in the main.rs call the function to read the environment variable

```rust
```
created_at: 2025-03-06T11:06:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -159,9 +161,14 @@ static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();
 static DEFAULT_LOGGER: logger::log::Logger = logger::log::Logger::new();
 
 #[cfg(not(any(feature = "logger_log", feature = "logger_tracing")))]
-static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();
+pub static DEFAULT_LOGGER: Lazy<logger::console::Logger> =
+    Lazy::new(logger::console::Logger::new);
 
 const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;
+pub static ENV_LOG_LEVEL: Lazy<LogLevel> = Lazy::new(|| {
+    let log_level_str = env::var("IOX2_LOG_LEVEL").unwrap_or_else(|_| "Info".to_string());
+    LogLevel::from_str(&log_level_str) // Default to Info
+});
path: iceoryx2-bb/log/src/lib.rs
user: login: orecham
body: @zmostafa I think this alternative approach for reading the log level from the `env` encounters the same issue outlined above.

If the environment changes between application starting and `init_log_level()` being called, the application might use the wrong log level.

That being said, I do not immediately see a good way to prevent this and I think the previous approach with `Lazy` was actually better since the user didn't need to explicitly do anything and reading the `env` would likely occur earlier.

@elBoberido What did you have in mind as an alternative?
created_at: 2025-03-06T11:12:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -58,24 +58,22 @@ insufficient, a new publisher with a larger `max_slice_len` can be created.
 
 <!-- markdownlint-disable -->
 
-> [!IMPORTANT]
-> Be aware that the history of the old publisher is lost when it is
+> [!IMPORTANT] Be aware that the history of the old publisher is lost when it is
path: FAQ.md
user: login: orecham
body: Will fix the linter after this PR: https://github.com/eclipse-iceoryx/iceoryx2/issues/637
created_at: 2025-03-06T11:29:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: you are using unknown logging level {:?}", s);
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @orecham Done
created_at: 2025-03-06T13:37:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -105,17 +105,40 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`Trace, Debug, Info, Warning, Error, Fatal`
 
 ## How to set the log level
 
+iceoryx2 gets its default logging level from `.cargo/config.toml` , but this can
+be over-ridden by environment variable `IOX2_LOG_LEVEL` the developer can set
+this environment variable with one of the supported levels.
+
+`export IOX2_LOG_LEVEL=Trace`
+
+then in the main.rs call the function to read the environment variable
+```rust
path: FAQ.md
user: login: zmostafa
body: Done
created_at: 2025-03-06T13:37:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: you are using unknown logging level {:?}", s);
+                println!("Warning: setting log level as : Info");
+                DEFAULT_LOG_LEVEL
+            }
+        }
+    }
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL"
+pub fn init_log_level() {
+    let log_level = env::var("IOX2_LOG_LEVEL")
+        .ok()
+        .map(|s| LogLevel::from_str_fuzzy(&s))
+        .unwrap_or(LogLevel::Info);
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: Done
created_at: 2025-03-06T13:38:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -159,9 +161,14 @@ static DEFAULT_LOGGER: logger::tracing::Logger = logger::tracing::Logger::new();
 static DEFAULT_LOGGER: logger::log::Logger = logger::log::Logger::new();
 
 #[cfg(not(any(feature = "logger_log", feature = "logger_tracing")))]
-static DEFAULT_LOGGER: logger::console::Logger = logger::console::Logger::new();
+pub static DEFAULT_LOGGER: Lazy<logger::console::Logger> =
+    Lazy::new(logger::console::Logger::new);
 
 const DEFAULT_LOG_LEVEL: u8 = LogLevel::Info as u8;
+pub static ENV_LOG_LEVEL: Lazy<LogLevel> = Lazy::new(|| {
+    let log_level_str = env::var("IOX2_LOG_LEVEL").unwrap_or_else(|_| "Info".to_string());
+    LogLevel::from_str(&log_level_str) // Default to Info
+});
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: @orecham the issue is the same but the time window where the env variable can be changed and influence a previously started process is minimal. With the lazy approach, this could be arbitrarily long
created_at: 2025-03-06T15:15:52Z
author_association: MEMBER
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : Info");
+                DEFAULT_LOG_LEVEL
+            }
+        }
+    }
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL"
+pub fn init_log_level() {
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: What do you think about renaming this to `init_log_level_from_env_or_default` to make it more clear what happens. Since there is already a `set_log_level` function, it might even make sense to call this `set_log_level_from_env_or_default` to make it more consistent. Finally, there could be a `set_log_level_from_env_or(log_level)` function which combines the two and set's the log_level only when the env variable is not set.
created_at: 2025-03-06T15:26:22Z
author_association: MEMBER
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : Info");
+                DEFAULT_LOG_LEVEL
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: ```suggestion
                println!("Warning: setting log level as : {}", DEFAULT_LOG_LEVEL);
                DEFAULT_LOG_LEVEL
```
I hope this works :sweat_smile: 
If not, then you would need to implement `Display`
created_at: 2025-03-06T15:31:53Z
author_association: MEMBER
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : Info");
+                DEFAULT_LOG_LEVEL
+            }
+        }
+    }
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL"
+pub fn init_log_level() {
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido Done and rebsed my branch to main to squash the commits for a cleaner histroy
created_at: 2025-03-09T14:33:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : Info");
+                DEFAULT_LOG_LEVEL
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido using `{:?}` for printing `DEFAULT_LOG_LEVEL` worked

```
Error: unknown logging level "BlaBla"
Warning: setting log level as : Info
Trigger event with id 1 ...
```
created_at: 2025-03-09T14:36:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -105,17 +105,41 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`Trace, Debug, Info, Warning, Error, Fatal`
 
 ## How to set the log level
 
+iceoryx2 gets its default logging level from `.cargo/config.toml` , but this can
path: FAQ.md
user: login: elBoberido
body: This is only valid for developers working in the iceoryx2 repository and also only if the new functions are used. Developers using iceoryx2 can also set the environment variable in their `.cargo/config.toml`. Can you please rephrase this to just saying that it can be set programmatically and via environment variable and developers are able to set the env variable in their `.cargo/config.toml` for their developer setup, like it is done in the iceoryx2 repo?

Initially, I liked the idea of always checking for the environment variable but your changes to have the explicit call makes sense, else the user would have no choice of preventing to use the environment variable, which could be a problem for safety critical deployments. This also follows the paradigm of iceoryx2, to not be opinionated about it's usage and leave this decision to the user.
created_at: 2025-03-09T17:33:56Z
author_association: MEMBER
diff_hunk: @@ -65,6 +65,7 @@
 
 * Remove obsolete POSIX wrapper
     [#594](https://github.com/eclipse-iceoryx/iceoryx2/issues/594)
+* Read LogLevel from environment variable [#396](https://github.com/eclipse-iceoryx/iceoryx2/issues/396)
path: doc/release-notes/iceoryx2-unreleased.md
user: login: elBoberido
body: nitpicking: just for the next time. Nowadays, we do not just append the issues to the list but add them sorted by the issue number. We hope that this helps to prevent merge conflicts when there are multiple open PRs.

Btw, I think this can also count as new feature instead of a refactoring :)
created_at: 2025-03-09T17:42:58Z
author_association: MEMBER
diff_hunk: @@ -185,6 +188,45 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : {:?}", DEFAULT_LOG_LEVEL);
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: @elfenpiff is there a function which could be used here to use the same formatting like the logger?
created_at: 2025-03-09T17:47:56Z
author_association: MEMBER
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : Info");
+                DEFAULT_LOG_LEVEL
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: Nice. I'm not sure if `Error` as well as `Warning` should be used. At this location one can also not yet specify which log level will be used, since this function could also be used with the `set_log_level_from_env_or`.
Just for comparison, this is the output from iceoryx classic
```
puts("Invalid value for 'IOX_LOG_LEVEL' environment variable!'");
puts("Found:");
puts(logLevelString);
puts("Allowed is one of: off, fatal, error, warn, info, debug, trace");
```
I think more important than specifying the log level that is actually set, is to inform the user about the opions
created_at: 2025-03-09T17:58:53Z
author_association: MEMBER
diff_hunk: @@ -105,17 +105,41 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`Trace, Debug, Info, Warning, Error, Fatal`
path: FAQ.md
user: login: elBoberido
body: Just noticed, in iceoryx1 we used all lower space strings. For consistency, we probably should do the same in iceoryx2. Of course, we can keep the behavior that variants like `TrAcE` also work.
created_at: 2025-03-09T18:01:16Z
author_association: MEMBER
diff_hunk: @@ -185,6 +188,45 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : {:?}", DEFAULT_LOG_LEVEL);
+                DEFAULT_LOG_LEVEL
+            }
+        }
+    }
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL" or default it wiht LogLevel::INFO
+pub fn set_log_level_from_env_or_default() {
+    let log_level = env::var("IOX2_LOG_LEVEL")
+        .ok()
+        .map(|s| LogLevel::from_str_fuzzy(&s))
+        .unwrap_or(DEFAULT_LOG_LEVEL);
+    ENV_LOG_LEVEL.set(log_level).unwrap();
+    set_log_level(*ENV_LOG_LEVEL.get().unwrap());
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: Please just delegate to `set_log_level_from_env_or`
created_at: 2025-03-09T18:02:57Z
author_association: MEMBER
diff_hunk: @@ -185,6 +188,45 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : {:?}", DEFAULT_LOG_LEVEL);
+                DEFAULT_LOG_LEVEL
+            }
+        }
+    }
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL" or default it wiht LogLevel::INFO
+pub fn set_log_level_from_env_or_default() {
+    let log_level = env::var("IOX2_LOG_LEVEL")
+        .ok()
+        .map(|s| LogLevel::from_str_fuzzy(&s))
+        .unwrap_or(DEFAULT_LOG_LEVEL);
+    ENV_LOG_LEVEL.set(log_level).unwrap();
+    set_log_level(*ENV_LOG_LEVEL.get().unwrap());
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL", and if the environment variable
+/// doesn't exits it sets it with a user-defined logging level
+pub fn set_log_level_from_env_or(v: LogLevel) {
+    let log_level = env::var("IOX2_LOG_LEVEL")
+        .ok()
+        .map(|s| LogLevel::from_str_fuzzy(&s))
+        .unwrap_or(v);
+    ENV_LOG_LEVEL.set(log_level).unwrap();
+    set_log_level(*ENV_LOG_LEVEL.get().unwrap());
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: With the latest changes, I think you can remove `ENV_LOG_LEVEL` entirely and just use
```suggestion
    set_log_level(log_level);
```
created_at: 2025-03-09T18:03:31Z
author_association: MEMBER
diff_hunk: @@ -105,17 +105,41 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`Trace, Debug, Info, Warning, Error, Fatal`
 
 ## How to set the log level
 
+iceoryx2 gets its default logging level from `.cargo/config.toml` , but this can
+be over-ridden by environment variable `IOX2_LOG_LEVEL` the developer can set
+this environment variable with one of the supported levels.
+
+`export IOX2_LOG_LEVEL=Trace`
+
+then in the main.rs call the function to read the environment variable
+
+```rust
+use iceoryx2::prelude::*
+
+// ...
+
+set_log_level_from_env_or_default();
+```
+
+Developers can also set the logging level from within the code which will take
+precedence over the environment variable:
+
 ```rust
 use iceoryx2::prelude::*
path: FAQ.md
user: login: elBoberido
body: What do you think of adding all three options to set the log level in the same code block? Maybe by adding an additional comment above each option?
created_at: 2025-03-09T18:10:46Z
author_association: MEMBER
diff_hunk: @@ -21,3 +21,4 @@ iceoryx2-pal-concurrency-sync = { workspace = true }
 termsize = { workspace = true }
 log = { workspace = true, optional = true }
 tracing = { workspace = true, optional = true }
+once_cell = { workspace = true }
path: iceoryx2-bb/log/Cargo.toml
user: login: elBoberido
body: I think this can be removed
created_at: 2025-03-09T18:17:27Z
author_association: MEMBER
diff_hunk: @@ -37,5 +37,6 @@ rust_library(
     deps = [
         "//iceoryx2-pal/concurrency-sync:iceoryx2-pal-concurrency-sync",
         "@crate_index//:termsize",
+        "@crate_index//:once_cell",
path: iceoryx2-bb/log/BUILD.bazel
user: login: elBoberido
body: This also
created_at: 2025-03-09T18:17:34Z
author_association: MEMBER
diff_hunk: @@ -185,6 +188,34 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : Info");
+                DEFAULT_LOG_LEVEL
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido makes sense, I changed it to 
```
println!(
                    "Invalid value for 'IOX_LOG_LEVEL' environment variable!\
                \nFound: {:?}\
                \nAllowed is one of: fatal, error, warn, info, debug, trace\
                \nSetting log level as : {:?}",
                    s, DEFAULT_LOG_LEVEL
                );
```
created_at: 2025-03-09T20:36:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,6 +188,45 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!("Error: unknown logging level {:?}", s);
+                println!("Warning: setting log level as : {:?}", DEFAULT_LOG_LEVEL);
+                DEFAULT_LOG_LEVEL
+            }
+        }
+    }
+}
+
+/// Sets the log level by reading environment variable "IOX2_LOG_LEVEL" or default it wiht LogLevel::INFO
+pub fn set_log_level_from_env_or_default() {
+    let log_level = env::var("IOX2_LOG_LEVEL")
+        .ok()
+        .map(|s| LogLevel::from_str_fuzzy(&s))
+        .unwrap_or(DEFAULT_LOG_LEVEL);
+    ENV_LOG_LEVEL.set(log_level).unwrap();
+    set_log_level(*ENV_LOG_LEVEL.get().unwrap());
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: @elBoberido less code :sweat_smile: 
created_at: 2025-03-09T20:38:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -185,6 +187,44 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!(
+                    "Invalid value for 'IOX_LOG_LEVEL' environment variable!\
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: nitpick :)
```suggestion
                    "Invalid value for 'IOX2_LOG_LEVEL' environment variable!\
```
created_at: 2025-03-09T21:29:26Z
author_association: MEMBER
diff_hunk: @@ -185,6 +187,44 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!(
+                    "Invalid value for 'IOX_LOG_LEVEL' environment variable!\
+                \nFound: {:?}\
+                \nAllowed is one of: fatal, error, warn, info, debug, trace\
+                \nSetting log level as : {:?}",
+                    s, DEFAULT_LOG_LEVEL
+                );
+                DEFAULT_LOG_LEVEL
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: At this location we do not know which log level the user has chosen as fallback, the default one or a custom one. A workaround could be to pass the fallback log level to this function or just skip the actual value and print that the fallback log level is used.
created_at: 2025-03-09T21:31:09Z
author_association: MEMBER
diff_hunk: @@ -105,31 +105,54 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`trace, debug, info, warning, error, fatal`
 
 ## How to set the log level
 
+While developing, iceoryx2 gets its default logging level from `.cargo/config.toml`, 
+but this can be over-ridden by using environment variable `IOX2_LOG_LEVEL` that can
+be set with one of the supported levels.
path: FAQ.md
user: login: elBoberido
body: Sorry being picky about this. The default log level is defined in `iceoryx2-bb/log/src/lib.rs`. The `.cargo/config.toml` file is just a convenient way to set the environment variable for the specific project. If the environment variable was explicitly set by the user, that one will have precedence over the one in the toml file.

Since this section is not only about the environment variable, but in general about setting the log level, the emphasis should be about setting the log level programmatically and also with the environment variable. It can be mentioned that for convenience the environment variable can be set in the toml file, but that's only important for developers since that won't work in a deployment, which is probably what they are looking for when reading this document. Note, for iceoryx developers, there is the FAQ_ICEORYX2_DEVS.md.
created_at: 2025-03-09T21:52:11Z
author_association: MEMBER
diff_hunk: @@ -105,31 +105,54 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`trace, debug, info, warning, error, fatal`
 
 ## How to set the log level
 
+While developing, iceoryx2 gets its default logging level from `.cargo/config.toml`, 
+but this can be over-ridden by using environment variable `IOX2_LOG_LEVEL` that can
+be set with one of the supported levels.
+
+`export IOX2_LOG_LEVEL=Trace`
+
+then in the `main.rs` call the function to read the environment variable
path: FAQ.md
user: login: elBoberido
body: ```suggestion
then in the `main.rs` call one of the functions to set the log level
```
created_at: 2025-03-09T21:53:07Z
author_association: MEMBER
diff_hunk: @@ -105,31 +105,54 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`trace, debug, info, warning, error, fatal`
 
 ## How to set the log level
 
+While developing, iceoryx2 gets its default logging level from `.cargo/config.toml`, 
+but this can be over-ridden by using environment variable `IOX2_LOG_LEVEL` that can
+be set with one of the supported levels.
+
+`export IOX2_LOG_LEVEL=Trace`
+
+then in the `main.rs` call the function to read the environment variable
+
 ```rust
 use iceoryx2::prelude::*
 
 // ...
 
+// Reads LogLevel from env and defaults to LogLevel INFO
+// if the environemnt variable has an unsupported value
path: FAQ.md
user: login: elBoberido
body: Small typo. Also, if the env variable is not set, the default log level will be used.
```suggestion
// if the environment variable is not set or has an unsupported value
```
created_at: 2025-03-09T21:53:33Z
author_association: MEMBER
diff_hunk: @@ -105,31 +105,54 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`trace, debug, info, warning, error, fatal`
 
 ## How to set the log level
 
+While developing, iceoryx2 gets its default logging level from `.cargo/config.toml`, 
+but this can be over-ridden by using environment variable `IOX2_LOG_LEVEL` that can
+be set with one of the supported levels.
+
+`export IOX2_LOG_LEVEL=Trace`
+
+then in the `main.rs` call the function to read the environment variable
+
 ```rust
 use iceoryx2::prelude::*
 
 // ...
 
+// Reads LogLevel from env and defaults to LogLevel INFO
+// if the environemnt variable has an unsupported value
+set_log_level_from_env_or_default();
+
+// Reads LogLevel from env and sets it with a user-given value
+// if the environemnt variable has an unsupported value 
path: FAQ.md
user: login: elBoberido
body: Same here :)
```suggestion
// if the environment variable is not set or has an unsupported value 
```
created_at: 2025-03-09T21:53:38Z
author_association: MEMBER
diff_hunk: @@ -105,31 +105,54 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`trace, debug, info, warning, error, fatal`
 
 ## How to set the log level
 
+While developing, iceoryx2 gets its default logging level from `.cargo/config.toml`, 
+but this can be over-ridden by using environment variable `IOX2_LOG_LEVEL` that can
+be set with one of the supported levels.
+
+`export IOX2_LOG_LEVEL=Trace`
+
+then in the `main.rs` call the function to read the environment variable
+
 ```rust
 use iceoryx2::prelude::*
 
 // ...
 
+// Reads LogLevel from env and defaults to LogLevel INFO
+// if the environemnt variable has an unsupported value
+set_log_level_from_env_or_default();
+
+// Reads LogLevel from env and sets it with a user-given value
+// if the environemnt variable has an unsupported value 
+set_log_level_from_env_or(LogLevel::DEBUG);
+
+// sets LogLevel programmatically with a supported user-given value
+// this will take precedence over LogLevel defined by an environment variable
path: FAQ.md
user: login: elBoberido
body: This might be ambiguous. One could assume that the env variable is still read but not used. What do you think about just `and does not try to read the environment variable`
created_at: 2025-03-09T21:53:46Z
author_association: MEMBER
diff_hunk: @@ -185,6 +187,44 @@ pub enum LogLevel {
     Fatal = 5,
 }
 
+impl LogLevel {
+    fn from_str_fuzzy(s: &str) -> LogLevel {
+        match s.to_lowercase().as_str() {
+            "trace" => LogLevel::Trace,
+            "debug" => LogLevel::Debug,
+            "info" => LogLevel::Info,
+            "warn" => LogLevel::Warn,
+            "error" => LogLevel::Error,
+            "fatal" => LogLevel::Fatal,
+            _ => {
+                println!(
+                    "Invalid value for 'IOX_LOG_LEVEL' environment variable!\
path: iceoryx2-bb/log/src/lib.rs
user: login: zmostafa
body: :face_with_peeking_eye: copy&paste 
created_at: 2025-03-10T10:25:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -105,31 +105,54 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`trace, debug, info, warning, error, fatal`
 
 ## How to set the log level
 
+While developing, iceoryx2 gets its default logging level from `.cargo/config.toml`, 
+but this can be over-ridden by using environment variable `IOX2_LOG_LEVEL` that can
+be set with one of the supported levels.
path: FAQ.md
user: login: zmostafa
body: @elBoberido your repo, your picky rules
If I understand this correctly, I should remove the part that talks about setting it in the toml file, and focus only on the environment variable, right?
created_at: 2025-03-10T10:36:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -188,7 +188,7 @@ pub enum LogLevel {
 }
 
 impl LogLevel {
-    fn from_str_fuzzy(s: &str) -> LogLevel {
+    fn from_str_fuzzy(s: &str, v: LogLevel) -> LogLevel {
path: iceoryx2-bb/log/src/lib.rs
user: login: elBoberido
body: With two variables, a single character for the name makes it later hard to reason about the semantics. Please rename them. Options would be `log_level_string` and `log_level_fallback`
created_at: 2025-03-10T12:19:42Z
author_association: MEMBER
diff_hunk: @@ -127,23 +127,23 @@ be set with one of the supported levels.
 
 `export IOX2_LOG_LEVEL=Trace`
 
-then in the `main.rs` call the function to read the environment variable
+then in the `main.rs` call one of the functions to set the log level
 
 ```rust
 use iceoryx2::prelude::*
 
 // ...
 
 // Reads LogLevel from env and defaults to LogLevel INFO
-// if the environemnt variable has an unsupported value
+// if the environment variable has an unsupported value
path: FAQ.md
user: login: elBoberido
body: ```suggestion
// if the environment variable is not set or has an unsupported value
```
created_at: 2025-03-10T12:20:23Z
author_association: MEMBER
diff_hunk: @@ -105,31 +105,54 @@ But you can also use a crate like [ctrlc](https://docs.rs/ctrlc/latest/ctrlc/).
 ## How to use `log` or `tracing` as default log backend
 
 * **log**, add the feature flag `logger_log` to the dependency in `Cargo.toml`
-    ```toml
-    iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
-    ```
+  ```toml
+  iceoryx2 = { version = "0.1.0", features = ["logger_log"]}
+  ```
 * **tracing**, add the feature flag `logger_tracing` to the dependency in
   `Cargo.toml`
-    ```toml
-     iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
-    ```
+  ```toml
+   iceoryx2 = { version = "0.1.0", features = ["logger_tracing"]}
+  ```
+
+## Supported log levels
+
+iceoryx2 support different log levels
+`trace, debug, info, warning, error, fatal`
 
 ## How to set the log level
 
+While developing, iceoryx2 gets its default logging level from `.cargo/config.toml`, 
+but this can be over-ridden by using environment variable `IOX2_LOG_LEVEL` that can
+be set with one of the supported levels.
path: FAQ.md
user: login: elBoberido
body: The focus needs to be both, the environmental variable and the programmatically way. In a safety environment one will probably not use environment variables but just set the log level programmatically. The toml file can be mentioned, but it should only be a side note and not leave the impression that it is the main way to do it.
created_at: 2025-03-10T12:28:01Z
author_association: MEMBER

PR comments:
user: login: xieyuschen
created_at: 2024-10-16T14:27:39Z
body: Moreover, please follow the convention here:

- title: `[#396]: Read and set LogLevel from environment variable`
author_association: CONTRIBUTOR
user: login: elfenpiff
created_at: 2024-10-16T15:29:35Z
body: @zmostafa hey hey ... you are back. I am happy to see your PR plopping up here.
author_association: CONTRIBUTOR
user: login: zmostafa
created_at: 2024-10-16T17:47:51Z
body: @elfenpiff you have to thank Jeff for the motivation, and thanks for the nice words as expected from you.

You guys are the best :heart: 
author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2024-11-07T11:52:44Z
body: ## [Codecov](https://app.codecov.io/gh/eclipse-iceoryx/iceoryx2/pull/474?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=eclipse-iceoryx) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 0.00%. Comparing base [(`32b3f8b`)](https://app.codecov.io/gh/eclipse-iceoryx/iceoryx2/commit/32b3f8b917de895b037192dbcb4f113c7b31d5bb?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=eclipse-iceoryx) to head [(`1198f7d`)](https://app.codecov.io/gh/eclipse-iceoryx/iceoryx2/commit/1198f7d3a5590febcab10e09b299d75c0c92617e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=eclipse-iceoryx).
> Report is 4 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://app.codecov.io/gh/eclipse-iceoryx/iceoryx2/pull/474/graphs/tree.svg?width=650&height=150&src=pr&token=FN3YFXTJCI&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=eclipse-iceoryx)](https://app.codecov.io/gh/eclipse-iceoryx/iceoryx2/pull/474?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=eclipse-iceoryx)

```diff
@@     Coverage Diff     @@
##   main   #474   +/-   ##
===========================
===========================

```

</details>
<details><summary>🚀 New features to boost your workflow: </summary>

- ❄ [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: elBoberido
created_at: 2024-12-03T22:47:46Z
body: @zmostafa I just wanted to check if you're waiting on anything from our side. If you need more time before continuing with the PR, feel free to take as much time as you need :)
author_association: MEMBER
user: login: elBoberido
created_at: 2025-01-19T16:34:36Z
body: @zmostafa we would really like to have this PR merged. Are you still planing to finish the remaining issues? It's totally fine if you need more time or decided to move to other tasks but it would be great to get an update from you :)
author_association: MEMBER
user: login: zmostafa
created_at: 2025-03-05T13:49:35Z
body: @elBoberido I am so sorry for ghosting this MR like this, I am not happy with my attitude here, please accept my apology :) 
I tried to refactor the merge request based on my memory of what is required, since I removed the lazy init, i added a new method `init_log_level` which will read the env var at application start and set the log level, i tested it locally but did not commit the example code for that.
Also. set_log_level take precedence when called after it to set the log level, hope my understanding is correct here, if not, happy to correct it. 


@orecham Thanks for getting in touch, i owe you much man! 
author_association: CONTRIBUTOR
user: login: zmostafa
created_at: 2025-03-06T13:39:17Z
body: @orecham Regarding your last comment, I do not know why you see the old implementation for `ENV_LOG_LEVEL` it should have been replaced with `pub static ENV_LOG_LEVEL: OnceLock<LogLevel> = OnceLock::new();` in the new implementation
author_association: CONTRIBUTOR
user: login: orecham
created_at: 2025-03-06T13:42:27Z
body: > @orecham Regarding your last comment, I do not know why you see the old implementation for `ENV_LOG_LEVEL` it should have been replaced with `pub static ENV_LOG_LEVEL: OnceLock<LogLevel> = OnceLock::new();` in the new implementation

@zmostafa 

The last comment is actually part of this thread: https://github.com/eclipse-iceoryx/iceoryx2/pull/474#discussion_r1983165595

I did see your new version - it seems to have the same problem from reading the environment as the old one though, or am I misunderstanding?
author_association: CONTRIBUTOR
user: login: elBoberido
created_at: 2025-03-06T15:12:14Z
body: > I am so sorry for ghosting this MR like this, I am not happy with my attitude here, please accept my apology :)

@zmostafa no need to be sorry. You don't have the luxury to work full time on iceoryx and any contribution from you is appreciated :)
author_association: MEMBER
user: login: zmostafa
created_at: 2025-03-12T17:15:50Z
body: @elBoberido My patience? :D How should i thank you for yours then? 
author_association: CONTRIBUTOR
user: login: elBoberido
created_at: 2025-03-12T17:26:32Z
body: @zmostafa it seems the CI is fighting to keep the PR open :D

The markdown linter is complaining

> FAQ.md:124:81 MD013/line-length Line length [Expected: 80; Actual: 149]
> FAQ.md:148:81 MD013/line-length Line length [Expected: 80; Actual: 235]
author_association: MEMBER
user: login: elBoberido
created_at: 2025-03-12T20:22:45Z
body: @zmostafa congrats to your first PR on iceoryx2. The next ones wil be easier. If you like, you could expose the two new functions also to the C and C++ bindings and also adjust the examples
author_association: MEMBER