Preserve unpacked `extra` in LogRecord

The logging module has some support for structured logs via the extra parameter (logger.info(..., extra={"foo": "bar"})), but it is handicapped by the unpacking of extra into LogRecord.__dict__.

Two issues this leads to:

  1. Every library needs to write code to separate user defined attributes from built-in ones (eg: python-json-logger or opentelmetry-sdk)
  2. Keys that are not valid Python identifiers still get upacked, which is in general not great.

Since a large fraction of logging is now structured and meant to ingestion into various logging services (vs. being read from the console by a human), good support for structured logs is more important than ever.

I think the easiest step forward would be to check if there is an "__extra__" (or something like this) key and, if not, safe a reference to whatever the user passed in.
Then filters / formatters / etc. could access LogRecord.__extra__ without logic to separate out attributes and without having to access LogRecord.__dict__ directly to support non-valid identifiers.