# EPF Cohort 6 – Week 14 Update
>Additional: create a [wiki PR](https://github.com/eth-protocol-fellows/protocol-studies/pull/460) for the **Consensus-spec-tests recommendation** mentioned in the previous update.
## Progress this week
I tackled a new task: researching and implementing a way to **dynamically change the tracing log level during runtime**.
---
Previously, the [tracing subscriber](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/index.html) was initialized directly with a static EnvFilter. This meant that the log levels were fixed at startup and could not be changed dynamically during program execution:
```
fmt()
.with_env_filter(filter)
.compact()
.with_thread_ids(true)
.with_target(true)
.with_file(false)
.with_line_number(true)
.with_ansi(enable_ansi)
.init();
```
> The variable **filter** holds the initial log configuration for each specific crate, either defined through hardcoded defaults or provided via environment variables.
---
While digging through the tracing-subscriber documentation, I explored two key modules:
- [registry](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/registry/index.html) - provides the Registry type, which acts as the base Subscriber and allows stacking multiple layers. This is the default mechanism for storing spans and events that other layers can query.
- [reload](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/reload/index.html) - provides a Layer wrapper that allows another layer or filter to be dynamically reloaded at runtime.
By combining these, I was able to set up the tracing subscriber with reload layers, which means that the log level can now be changed dynamically during execution.
---
Now, the initialization uses `reload::Layer`, which wraps the **filter** in a reloadable layer and returns a handle. This handle can later be used at runtime to update log directives dynamically:
```
let (filter_layer, handle) = reload::Layer::new(filter);
tracing_subscriber::registry()
.with(fmt::layer()
.compact()
.with_thread_ids(true)
.with_target(true)
.with_file(false)
.with_line_number(true)
.with_ansi(enable_ansi))
.with(filter_layer)
.init();
Ok(handle)
```
> Returned **handle** allows calling **`.modify(...)`** at any point to adjust directives dynamically.
I tackled this problem in [issue](https://github.com/sntntn/grandine/issues/16)
## Next Steps
Next, I am working on implementing an **API** to **trigger** log level changes at runtime.
Also, I considered exposing this via console commands, but since Grandine’s client often runs inside Docker, the console is not practical. Following Saulious’ suggestion, the API approach is the most suitable.
## Resources
- [Grandine forked repo](https://github.com/sntntn/grandine/tree/feature/dynamic-tracing-config)
- [Roadmap through phases](https://github.com/eth-protocol-fellows/cohort-six/blob/master/projects/Grandine-Implementing-Tokio-Tracing-For-Debugging-And-Performance-Analysis.md#roadmap)
- [registry - tracing_subscriber](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/registry/index.html)
- [reload - tracing_subscriber](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/reload/index.html)