Skip to main content

gen3logging

Logging routines to centralize format.

Basic usage


In the parent/root module:

from gen3logging import get_logger

logger = get_logger("{{service_name}}", log_level='info')
logger.info('Hello world!')

In a child module:

from gen3logging import get_logger

logger = get_logger(__name__)
logger.info('Hello world!')

logger = get_logger(__name__, log_level='debug')
logger.debug('I am a child logger but I now have my own custom log level!')

You must set the logging level on the parent logger!

Inheritance is by dotted name, so the root logger's name must be a prefix of the child module's __name__. Naming the root after the top-level package (a module in fence/auth.py has __name__ == "fence.auth", which inherits from fence) is what makes this work. A root name that is not a prefix of its modules' names gets no children.

The default log_level argument in get_logger is None, which means the default logging level for new loggers is NOTSET. This means that child loggers whose levels were not explicitly set will inherit logging levels and handlers from ancestor loggers. This makes it easier to do things like change application-wide logging levels by just setting the level on the parent logger. Levels and handlers can still be individually set on child nodes by providing a log_level argument.

See more about Python logging here.

Parameters


get_logger takes:

  • logger_name - name of the logger, or None for the root logger
  • file_name (default: None) - if present, the logger will output logs to a file as well as stdout
  • log_level (default: None) - one of notset, debug, info, warning, warn, error, critical, in any case. Anything else raises ValueError
  • format (default: None, meaning the format below) - %-style format string for text output
  • json_logs (default: None, meaning the GEN3_JSON_LOGS env var decides) - emit JSON instead of text

file_name, format and json_logs only apply when a logger first gets its handlers, on the first call that sets a level other than notset. Calling get_logger again for the same logger keeps its existing handlers, so set GEN3_JSON_LOGS to switch a whole service to JSON regardless of call order.

Output format


By default logs are plain text:

[2025-01-15 12:22:04,031][      fence][   INFO] user logged in

When OpenTelemetry is active, trace context is appended automatically:

[2025-01-15 12:22:04,031][      fence][   INFO] user logged in [trace_id=4bf92f3577b34da6a3ce929d0e0e4736 span_id=00f067aa0ba902b7 service=fence]

The suffix carries only the fields that are available, and is absent entirely when none are. It follows the message, ahead of any traceback or stack. gen3logging does not depend on OpenTelemetry: populate these by installing opentelemetry-instrumentation-logging and calling LoggingInstrumentor().instrument(). Nothing needs to change here to pick them up, and nothing fails when they are missing.

trace_id and span_id are either a usable id or absent.

Any %-style format string can replace the default:

logger = get_logger("gen3foo", log_level='info', format="%(levelname)s %(message)s")

Enabling JSON Logs


Set json_logs=True to emit one JSON object per line instead of the default format:

logger = get_logger("gen3foo", log_level='info', json_logs=True)
{"timestamp": "2025-01-15T18:22:04.031Z", "logger": "fence.auth", "level": "INFO", "message": "user logged in", "trace_id": null, "span_id": null, "service": null}
Key Value
timestamp ISO 8601 UTC, millisecond precision
logger logger name
level level name, e.g. INFO
message the formatted message, with %-style arguments interpolated
trace_id, span_id, service OpenTelemetry correlation, null when unavailable
exception traceback text, present only on records that carry exception info
stack_info stack text, present only on records logged with stack_info=True

Fields passed through a logging call's extra= are not included.

Because the message and traceback are JSON-escaped, a multi-line traceback stays on a single log line and can be parsed by a log aggregator without stitching.

To turn JSON on for a deployment without a code change, set the GEN3_JSON_LOGS environment variable:

GEN3_JSON_LOGS=true

An explicit json_logs argument always wins over the environment variable, so a service can force either format. When json_logs is omitted the environment variable decides, and when neither is set, output is text. Enabling JSON supersedes any format string.

Migrating from cdislogging


  1. Replace the cdislogging dependency with gen3logging>=2.0.0.
  2. Replace from cdislogging import ... with from gen3logging import ....

That is the whole migration. Output is identical to cdislogging 1.2.0 until you enable JSON or instrument with OpenTelemetry.

NOTE: The library also now contains a PEP 561 py.typed marker, which tells type checkers to enforce our typing.

Metadata

Release files for gen3logging 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gen3logging 2.0.0
File Size Uploaded
gen3logging-2.0.0.tar.gz 10.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gen3logging 2.0.0
File Interpreter ABI Platform
gen3logging-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 22.5 kB

Release files / gen3logging-2.0.0.tar.gz

Download URL gen3logging-2.0.0.tar.gz
Size 10.4 kB
Tags Source
SHA-256 checksum
How to use checksums
0c337f47132c16152a69de93e58e83a9b97123e67008a530d32d6d88dd9693eb
BLAKE2b-256 checksum
How to use checksums
5648789b277168e45395294fa809cdb56ab5a58cc1e7275a797ce91347fe165e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.13.16 Linux/6.17.0-1022-azure

Release files / gen3logging-2.0.0-py3-none-any.whl

Download URL gen3logging-2.0.0-py3-none-any.whl
Size 12.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
43b8adae8698e72481b9ba6ffe5c1ecdebc25e772b79f5cd7a4b890a5e03d89b
BLAKE2b-256 checksum
How to use checksums
0cf92eb951c0a7285a5773fa8c12b95c8af4949a2af5c81763814b1339410fc0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.13.16 Linux/6.17.0-1022-azure

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page