Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InstrumentLoggerAdaptor store instrument_name and type in record #5297

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/changes/newsfragments/5297.improved
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The InstrumentLoggerAdapter has been updated to store the `instrument_name` and `instrument_type`
as fields on log records rather than the instrument it self. This enables opentelemetry to attache
the fields to a transmitted LogRecord for better filtering.
31 changes: 19 additions & 12 deletions qcodes/logger/instrument_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class InstrumentLoggerAdapter(logging.LoggerAdapter):
The context data gets stored in the `extra` dictionary as a property of the
Adapter. It is filled by the ``__init__`` method::

>>> LoggerAdapter(log, {'instrument': self.full_name})
>>> LoggerAdapter(log, {'instrument': instrument_instance})

"""

Expand All @@ -40,11 +40,17 @@ def process(
"""
Returns the message and the kwargs for the handlers.
"""
kwargs['extra'] = self.extra
jenshnielsen marked this conversation as resolved.
Show resolved Hide resolved
assert self.extra is not None
inst = self.extra['instrument']
extra = dict(self.extra)
inst = extra.pop("instrument")

full_name = getattr(inst, "full_name", None)
return f"[{full_name}({type(inst).__name__})] {msg}", kwargs
instr_type = str(type(inst).__name__)

kwargs["extra"] = extra
kwargs["extra"]["instrument_name"] = str(full_name)
kwargs["extra"]["instrument_type"] = instr_type
return f"[{full_name}({instr_type})] {msg}", kwargs


class InstrumentFilter(logging.Filter):
Expand All @@ -54,27 +60,28 @@ class InstrumentFilter(logging.Filter):
properties as specified in the `extra` dictionary which is a property of
the adapter.

Here the ``instrument`` property gets used to reject records that don't
Here the ``instrument_name`` property gets used to reject records that don't
originate from the list of instruments that has been passed to the
``__init__`` method.
"""
def __init__(self, instruments: Union['InstrumentBase',
Sequence['InstrumentBase']]):
# This local import is necessary to avoid a circular import dependency.
# The alternative is to merge this module with the instrument.base,
# which is also not favorable.
super().__init__()
if not isinstance(instruments, collections.abc.Sequence):
instrument_seq: Sequence['InstrumentBase'] = (instruments,)
instrument_seq: Sequence[str] = (instruments.full_name,)
else:
instrument_seq = instruments
instrument_seq = [inst.full_name for inst in instruments]
self.instrument_set = set(instrument_seq)

def filter(self, record: logging.LogRecord) -> bool:
inst: Optional["InstrumentBase"] = getattr(record, "instrument", None)
inst: Optional[str] = getattr(record, "instrument_name", None)
if inst is None:
return False
return not self.instrument_set.isdisjoint(inst.ancestors)

insrument_match = any(
inst.startswith(instrument_name) for instrument_name in self.instrument_set
jenshnielsen marked this conversation as resolved.
Show resolved Hide resolved
)
return insrument_match


def get_instrument_logger(instrument_instance: 'InstrumentBase',
Expand Down