Skip to content

Commit 0ea72f6

Browse files
committed
configuration: add log_level to configuration_opts
Add `CollectorBase.setLoggers(logger_names)` as a means for collectors derived from `CollectorBase` to easily configure logging-levels. The new method uses the `collector_opts.logging_level` value (if set in the configuration) to set the logging-level of any loggers given to it.
1 parent 9fc3e8b commit 0ea72f6

File tree

4 files changed

+76
-0
lines changed

4 files changed

+76
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](http://semver.org/) and [Keep a Ch
1010
### New
1111
* Fix \#47 - add environment variables for fundamental parameters
1212
* configuration: add logging section
13+
* configuration: add log_level to configuration_opts
1314

1415
### Changes
1516

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ collectors:
109109
- netdev
110110
collector_opts:
111111
netdev:
112+
log_level: DEBUG
112113
whitelist:
113114
blacklist:
114115
- docker0
@@ -121,6 +122,10 @@ logging:
121122
target: /path/to/my/collector/logfile.log
122123
```
123124
125+
The `collector_opts` can optionally contain a `log_level` entry which
126+
will configure the logging-level for that specific collector. Note that
127+
support for this must be implemented by each individual collector.
128+
124129
Logging can optionally be configured for any logger. The entries must
125130
specify the name of the logger and can optionally specify a
126131
logging-level (default: stay at whatever the default logging-level for

p3exporter/collector/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,25 @@ def collector_name_from_class(self):
5858

5959
return '_'.join(class_name_parts)
6060

61+
def setLoggers(self, logger_names: list | str):
62+
"""Configure the provided logger(s) according to the CollectorConfig.
63+
64+
It is recommended to call this method from the constructor of any
65+
deriving class. Either bump the required p3exporter version or check
66+
dynamically if the method is supported.
67+
68+
:param logger_names: Name or names of loggers to configure.
69+
:type logger_names: list or str
70+
"""
71+
if not isinstance(logger_names, list):
72+
logger_names = [logger_names]
73+
if "log_level" not in self.opts:
74+
return
75+
level = self.opts["log_level"]
76+
for name in logger_names:
77+
logger = logging.getLogger(name)
78+
logger.setLevel(level)
79+
6180

6281
class Collector(object):
6382
"""Base class to load collectors.

tests/test_cases/logging_config.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from p3exporter import setup_logging
2+
from p3exporter.collector import CollectorBase, CollectorConfig
23
import logging
34
import os.path
45
import pytest
@@ -104,3 +105,53 @@ def test_logging_levels(cfg_logging, levels, targets):
104105
handler = added_handlers[0]
105106
assert isinstance(handler, logging.FileHandler)
106107
assert handler.baseFilename == os.path.abspath(targets[i])
108+
109+
110+
class FooCollector(CollectorBase):
111+
pass
112+
113+
114+
data_collectorbase_setloggers = [
115+
pytest.param(None,
116+
["foo", "bar"],
117+
[logging.WARNING, logging.NOTSET, logging.NOTSET],
118+
id="no log_level setting"),
119+
pytest.param("CRITICAL",
120+
"foo",
121+
[logging.WARNING, logging.CRITICAL, logging.NOTSET],
122+
id="single logger-name"),
123+
pytest.param("ERROR",
124+
["foo", "bar"],
125+
[logging.WARNING, logging.ERROR, logging.ERROR],
126+
id="list of loggers"),
127+
pytest.param(20,
128+
["", "foo"],
129+
[logging.INFO, logging.INFO, logging.NOTSET],
130+
id="numeric log_level"),
131+
]
132+
133+
134+
@pytest.mark.parametrize("cfg_log_level,logger_names,expected",
135+
data_collectorbase_setloggers)
136+
def test_collectorbase_setloggers(cfg_log_level, logger_names, expected):
137+
# GIVEN an input config-dictionary
138+
cfg = {
139+
"exporter_name": "Test only",
140+
"collectors": ["foo"],
141+
"collector_opts": {
142+
"foo": {}
143+
},
144+
}
145+
if cfg_log_level is not None:
146+
cfg["collector_opts"]["foo"]["log_level"] = cfg_log_level
147+
148+
# AND a collector-base using this config
149+
collector = FooCollector(CollectorConfig(**cfg))
150+
151+
# WHEN the setLoggers() method is called
152+
collector.setLoggers(logger_names)
153+
154+
# THEN the logging-levels should get changed to the expected
155+
for i, name in enumerate(loggers):
156+
logger = logging.getLogger(name)
157+
assert logger.level == expected[i]

0 commit comments

Comments
 (0)