Skip to content

Commit c6cf365

Browse files
committed
Update the logging config actor configuration format
The logging configuration was changed to make it compatible with the configuration generated by the UI, which doesn't quote sub-key properly. To do this, the logger name needs to be specified explicitly now (the configuration key was used as the name before). Signed-off-by: Leandro Lucarella <[email protected]>
1 parent 62afee8 commit c6cf365

File tree

5 files changed

+86
-25
lines changed

5 files changed

+86
-25
lines changed

RELEASE_NOTES.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,37 @@
88

99
* Includes a major update of the numpy dependency to v2.x.
1010

11+
* The logging configuration was changed, and now the logger name needs to be specified explicitly (the configuration key was used as the name before). This is to be compatible with configuration generated by the UI, which doesn't quote sub-key properly.
12+
13+
- Before:
14+
15+
```toml
16+
[logging.loggers."frequenz.sdk.config"]
17+
level = "DEBUG"
18+
```
19+
20+
- Now:
21+
22+
```toml
23+
[logging.loggers.frequenz_config]
24+
name = "frequenz.sdk.config"
25+
level = "DEBUG"
26+
```
27+
28+
* The logging configuration now uses a separate class for the root logger configuration: `RootLoggerConfig`.
29+
30+
- Before:
31+
32+
```py
33+
LoggingConfig(root_logger=LoggerConfig(level="ERROR"))
34+
```
35+
36+
- Now:
37+
38+
```py
39+
LoggingConfig(root_logger=RootLoggerConfig(level="ERROR"))
40+
```
41+
1142
## New Features
1243

1344
<!-- Here goes the main new features and examples or instructions on how to use them -->

src/frequenz/sdk/config/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,12 @@ async def run(self) -> None:
424424
"""
425425

426426
from ._base_schema import BaseConfigSchema
427-
from ._logging_actor import LoggerConfig, LoggingConfig, LoggingConfigUpdatingActor
427+
from ._logging_actor import (
428+
LoggerConfig,
429+
LoggingConfig,
430+
LoggingConfigUpdatingActor,
431+
RootLoggerConfig,
432+
)
428433
from ._manager import ConfigManager, InvalidValueForKeyError, wait_for_first
429434
from ._managing_actor import ConfigManagingActor
430435
from ._util import load_config
@@ -437,6 +442,7 @@ async def run(self) -> None:
437442
"LoggerConfig",
438443
"LoggingConfig",
439444
"LoggingConfigUpdatingActor",
445+
"RootLoggerConfig",
440446
"load_config",
441447
"wait_for_first",
442448
]

src/frequenz/sdk/config/_logging_actor.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525

2626

2727
@dataclass(frozen=True, kw_only=True)
28-
class LoggerConfig:
29-
"""A configuration for a logger."""
28+
class RootLoggerConfig:
29+
"""A configuration for the root logger."""
3030

3131
level: LogLevel = field(
3232
default="NOTSET",
@@ -36,15 +36,29 @@ class LoggerConfig:
3636
},
3737
},
3838
)
39-
"""The log level for the logger."""
39+
"""The log level for the root logger."""
40+
41+
42+
@dataclass(frozen=True, kw_only=True)
43+
class LoggerConfig(RootLoggerConfig):
44+
"""A configuration for a logger."""
45+
46+
name: str = field(
47+
metadata={
48+
"metadata": {
49+
"description": "The name of the logger that will be affected by this "
50+
"configuration."
51+
},
52+
},
53+
)
4054

4155

4256
@dataclass(frozen=True, kw_only=True)
4357
class LoggingConfig:
4458
"""A configuration for the logging system."""
4559

46-
root_logger: LoggerConfig = field(
47-
default_factory=lambda: LoggerConfig(level="INFO"),
60+
root_logger: RootLoggerConfig = field(
61+
default_factory=lambda: RootLoggerConfig(level="INFO"),
4862
metadata={
4963
"metadata": {
5064
"description": "Default default configuration for all loggers.",
@@ -73,10 +87,12 @@ class LoggingConfigUpdatingActor(Actor):
7387
[logging.root_logger]
7488
level = "INFO"
7589
76-
[logging.loggers."frequenz.sdk.actor.power_distributing"]
90+
[logging.loggers.power_dist]
91+
name = "frequenz.sdk.actor.power_distributing"
7792
level = "DEBUG"
7893
79-
[logging.loggers."frequenz.channels"]
94+
[logging.loggers.chan]
95+
name = "frequenz.channels"
8096
level = "DEBUG"
8197
```
8298
@@ -184,10 +200,12 @@ def _reconfigure(self, config_update: LoggingConfig | Exception | None) -> None:
184200
def _update_logging(self, config: LoggingConfig) -> None:
185201
"""Configure the logging level."""
186202
# If the logger is not in the new config, set it to NOTSET
187-
loggers_to_unset = self._current_config.loggers.keys() - config.loggers.keys()
188-
for logger_id in loggers_to_unset:
189-
_logger.debug("Unsetting log level for logger '%s'", logger_id)
190-
logging.getLogger(logger_id).setLevel(logging.NOTSET)
203+
old_names = {old.name for old in self._current_config.loggers.values()}
204+
new_names = {new.name for new in config.loggers.values()}
205+
loggers_to_unset = old_names - new_names
206+
for logger_name in loggers_to_unset:
207+
_logger.debug("Unsetting log level for logger '%s'", logger_name)
208+
logging.getLogger(logger_name).setLevel(logging.NOTSET)
191209

192210
self._current_config = config
193211
_logger.info(
@@ -196,12 +214,12 @@ def _update_logging(self, config: LoggingConfig) -> None:
196214
logging.getLogger().setLevel(self._current_config.root_logger.level)
197215

198216
# For each logger in the new config, set the log level
199-
for logger_id, logger_config in self._current_config.loggers.items():
217+
for logger_config in self._current_config.loggers.values():
200218
_logger.info(
201219
"Setting log level for logger '%s' to '%s'",
202-
logger_id,
220+
logger_config.name,
203221
logger_config.level,
204222
)
205-
logging.getLogger(logger_id).setLevel(logger_config.level)
223+
logging.getLogger(logger_config.name).setLevel(logger_config.level)
206224

207225
_logger.info("Logging config update completed.")

tests/config/test_logging_actor.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
LoggerConfig,
1717
LoggingConfig,
1818
LoggingConfigUpdatingActor,
19+
RootLoggerConfig,
1920
load_config,
2021
)
2122

@@ -25,15 +26,15 @@ def test_logging_config() -> None:
2526
config_raw = {
2627
"root_logger": {"level": "DEBUG"},
2728
"loggers": {
28-
"frequenz.sdk.actor": {"level": "INFO"},
29-
"frequenz.sdk.timeseries": {"level": "ERROR"},
29+
"actor": {"name": "frequenz.sdk.actor", "level": "INFO"},
30+
"timeseries": {"name": "frequenz.sdk.timeseries", "level": "ERROR"},
3031
},
3132
}
3233
config = LoggingConfig(
33-
root_logger=LoggerConfig(level="DEBUG"),
34+
root_logger=RootLoggerConfig(level="DEBUG"),
3435
loggers={
35-
"frequenz.sdk.actor": LoggerConfig(level="INFO"),
36-
"frequenz.sdk.timeseries": LoggerConfig(level="ERROR"),
36+
"actor": LoggerConfig(name="frequenz.sdk.actor", level="INFO"),
37+
"timeseries": LoggerConfig(name="frequenz.sdk.timeseries", level="ERROR"),
3738
},
3839
)
3940

@@ -92,10 +93,12 @@ async def test_logging_config_updating_actor(
9293

9394
# Send first config
9495
expected_config = LoggingConfig(
95-
root_logger=LoggerConfig(level="ERROR"),
96+
root_logger=RootLoggerConfig(level="ERROR"),
9697
loggers={
97-
"frequenz.sdk.actor": LoggerConfig(level="DEBUG"),
98-
"frequenz.sdk.timeseries": LoggerConfig(level="ERROR"),
98+
"actor": LoggerConfig(name="frequenz.sdk.actor", level="DEBUG"),
99+
"timeseries": LoggerConfig(
100+
name="frequenz.sdk.timeseries", level="ERROR"
101+
),
99102
},
100103
)
101104
await mock_config_manager.config_channel.new_sender().send(expected_config)
@@ -121,9 +124,9 @@ async def test_logging_config_updating_actor(
121124

122125
# Update config
123126
expected_config = LoggingConfig(
124-
root_logger=LoggerConfig(level="WARNING"),
127+
root_logger=RootLoggerConfig(level="WARNING"),
125128
loggers={
126-
"frequenz.sdk.actor": LoggerConfig(level="INFO"),
129+
"actor": LoggerConfig(name="frequenz.sdk.actor", level="INFO"),
127130
},
128131
)
129132
await mock_config_manager.config_channel.new_sender().send(expected_config)

tests/config/test_manager.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ def config_file(self, tmp_path: pathlib.Path) -> pathlib.Path:
250250
value = 42
251251
252252
[logging.loggers.test]
253+
name = "test"
253254
level = "DEBUG"
254255
"""
255256
)
@@ -276,6 +277,7 @@ async def test_full_config_flow(self, config_file: pathlib.Path) -> None:
276277
value = 43
277278
278279
[logging.loggers.test]
280+
name = "test"
279281
level = "INFO"
280282
"""
281283
)
@@ -313,6 +315,7 @@ async def test_full_config_flow_without_logging(
313315
value = 43
314316
315317
[logging.loggers.test]
318+
name = "test"
316319
level = "DEBUG"
317320
"""
318321
)

0 commit comments

Comments
 (0)