You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/Logging.md
+50-29Lines changed: 50 additions & 29 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ Updates as of mid February
7
7
8
8
# Logging for Python in DUNE-DAQ
9
9
10
-
Welcome, fellow logging enthusiast! This page provides a user's guide to how logging is done in Python in the context of DUNE-DAQ.
10
+
Welcome, fellow beavers! This page provides a user's guide to how logging is done in Python in the context of DUNE-DAQ.
11
11
12
12
## Basics
13
13
@@ -130,12 +130,15 @@ As shown above, initialising a logging instance with a specific handler is as ea
130
130
The core philosophy of the logging framework in daqpytools is that each logger should only have _one_ instance of a specific type of logger. This means that while a single logger can have both a Rich and a Stream handler, a single logger cannot have _two_ Rich handlers to prevent duplicating messages.
131
131
132
132
133
-
Please refer to the docstrings for the most up to date definitions on the options and what handlers may or may not be included.
133
+
Please refer to the docstrings for the most up to date definitions on the options and what handlers may or may not be included. There are some exceptions which are clearly labelled in the document. Choosing which handler to trigger on a per-message instance is an advanced feature of logging in DUNE-DAQ, so please refer to the advanced section of this guide.
134
134
135
135
136
-
### Subsec of existing handlers, filters, and walkthrough
136
+
### Walkthrough of existing handlers and filters
137
+
138
+
As seen in the previous section, there are several handlers and filters that are present in the daqpytools that may readily be used. What follows will be a brief description of each handlers as well as a quick example, but for more complete docs please refer to the docstrings and the logging demonstrator.
139
+
140
+
Remember that by default, any messages received by the logger will be transmitted to _all_ available handlers that are attached to the logger.
137
141
138
-
As seen in the previous section, there are several handlers and filters that are present in the daqpytools that may readily be used. What follows will be a brief description of each handlers as well as a quick example, but for more complete docs please refer to the docstrings and the logging demonstrator
139
142
140
143
#### Rich handler
141
144
@@ -213,7 +216,7 @@ The basic logic is as follows.
213
216
5. After `time_limit` seconds after the last message, the filter gets reset, allowing messages to be sent once more
214
217
215
218
216
-
For the throttle filter, a 'log record' is **uniquely** defined by the record's pathname and linenumber. Therefore, 50 records that contain the same 'messege' but defined in different line numbers in the script will not be erroneously filtered.
219
+
For the throttle filter, a 'log record' is **uniquely** defined by the record's pathname and linenumber. Therefore, 50 records that contain the same 'message' but defined in different line numbers in the script will not be erroneously filtered.
217
220
218
221
219
222
An example is as follows:
@@ -248,58 +251,76 @@ Which will behave as expected.
248
251
**Note**
249
252
By default, throttle filters obtained via `get_daq_logger` will be initialised with an `initial_treshold` of 30 and a `time_limit` of 30.
250
253
254
+
**Note**
255
+
Similarly to the ERS Kafka handler, this filter is not enabled by default, hence requiring the use of HandlerTypes. See the Advanced section for more info.
251
256
252
257
### Advanced logging
253
258
259
+
The above walkthrough should be sufficient for the vast majority of logging. However, there are a few advanced features in daqpytools that would benefit the user. These mainly are targetted towards a high degree of customisability for the user, including the ability to choose which of the attached handlers will transmit a given message, and automatic routing of messages to certain handlers.
254
260
255
-
#### Context
261
+
#### Choosing handlers with HandlerTypes
256
262
257
-
#### Handler streams
263
+
Lets say you have a logger with an attached Rich handler and File handler as below, and that there are two messages you want to log. However, one of them should only be sent to the file, and the other one should be sent to the terminal via the rich handler.
These can be done by using the `HandlerTypes` enum. The loggers defined here have a special ability to read which HandlerTypes are supplied and to only transmit to the required handlers.
261
270
271
+
There is a very specific syntax that must be followed involving the `extra` kwarg:
262
272
263
-
#### Using ERS
273
+
```
274
+
from daqpytools.logging.handlers import HandlerType
264
275
276
+
log.info("This will only be sent to the Rich", extra={"handlers": [HandlerType.Rich]})
277
+
log.info("This will only be sent to the File", extra={"handlers": [HandlerType.File]})
278
+
log.info("You can even send to both", extra={"handlers": [HandlerType.Rich, HandlerType.File]})
279
+
```
265
280
281
+
Naturally, if tell the logger to transmit a message where the associated Handler is not attached will cause it to do nothing. For example above, using HandlerTypes.Stream will do nothing.
266
282
267
283
268
284
285
+
#### The need for handler streams
269
286
287
+
Within the DUNE DAQ ecosystem, there are several other configurations that interplay. These include the OpMon and ERS, which require several handlers for each configuration. These can be best thought of as 'streams' which interact with several other handlers, as shown in an example below.
270
288
289
+

271
290
272
-
## Basic info
273
-
basically see your presentation
291
+
The native implemention in drunc and most applications is referred to as the 'Base' stream, which will only require interactions with the Rich, File, and Stream handlers. **This is why the ERS Kafka Handler and the Throttle filter need to be 'activated' with HandlerTypes**.
274
292
275
-
- the basics of python logging
276
-
- handlers
277
-
- inheritance
278
-
- log levels
293
+
The ERS configuration is defined in OKS, [for example here](https://github.com/DUNE-DAQ/daqsystemtest/blob/974965be6e96aff969c69a380ed34aa96705e802/config/daqsystemtest/ccm.data.xml#L189), and are automatically parsed by daqpytools as they get used. A special feature of the ERS configuration is that the relevant Handlers are severity-level dependent; ERS Fatal and ERS info may have a different set of handler requirements
279
294
280
-
## User story
281
-
And then talk about the features in daqpytools as a user
295
+
#### Log Handler Conf
282
296
283
-
- Best practices on initialising loggers
284
-
- How to deal with handlertypes
285
-
- How to deal with handlerconf
286
-
- integratoin with ers
287
297
288
-
## Advanced handlers (WIP as of Dec 2025)
298
+
To deal with the constraints set above, a handler configuration dataclass called `LogHandlerConf` is constructed to define the relevant configurations and a system of filters is initialised with every handler. When passing a log record that needs to be processed via a specific stream, the log record and the handler configuration is passed to the relevant logger, after which it is processed.
289
299
290
-
Aside from the core set of loggers and handlers defined natively in drunc, there are several other configurations that interplay with drunc. These can be best thought of as 'streams' which in interact with several other handlers.
300
+
An example of which is shown in the logging demonstrator, copied here.
The native implementation in drunc is referred to as the 'base' stream and interacts with the three core handlers already discussed.
295
-
Other streams include the 'Opmon' stream interacting with its own set of handlers, and the 'ERS' stream that interacts with different handlers based on the log message's severity level.
The 'ERS' configuration is configured in OKS ([for example here](https://github.com/DUNE-DAQ/daqsystemtest/blob/974965be6e96aff969c69a380ed34aa96705e802/config/daqsystemtest/ccm.data.xml#L189)), and are automatically parsed by drunc and daqpytools as they get used.
298
309
299
-
To deal with the constraints set above, a handler configuration dataclass is constructed to define the relevant configurations and a system of filters is initialised with every handler. When passing a log record that needs to be processed via a specific stream, the log record and the handler configuration is passed to the relevant logger, after which it is processed.
310
+
#### Using ERS
311
+
By default, the LogHandlerConf does not initialise the ERS stream because it requires the ERS environment variables to be defined. Should these variables exists, there are two ways to initialise the ERS stream with the LogHandlerConf.
300
312
313
+
```python
314
+
# By default init_ers is false
315
+
# When this is the case, ERS Streams are _not_ defined. Will survive without ERS envs being defined
0 commit comments