pynenc.util.log

Logging utilities for Pynenc.

Context-aware logging with three output formats:

  • ColoredFormatter: ANSI-colored terminal output with context prefixes

  • PlainTextFormatter: Plain text for non-TTY / log files

  • JsonFormatter: Structured JSON for containers and cloud log aggregators

Timestamps include the local timezone offset (e.g. 2026-03-05 07:56:07.476+01:00).

Key components:

  • PynencContextFilter: Injects runner/invocation context into log records

  • _PynencFormatterBase: Shared TZ-aware timestamps and context prefix logic

  • create_logger: Factory that wires formatter, stream, and filter from config

Module Contents

Classes

Colors

ANSI color codes for terminal coloring.

PynencContextFilter

Injects Pynenc execution context into every log record.

_PynencFormatterBase

Base formatter: TZ-aware timestamps, context prefix building, ID truncation.

ColoredFormatter

ANSI-colored formatter with context prefixes for interactive terminals.

PlainTextFormatter

Plain text formatter with context prefixes, compatible with pynmon log explorer.

JsonFormatter

Structured JSON formatter for containers and cloud log aggregators.

Functions

_format_tz_offset

Format timezone offset as ±HH:MM from struct_time.

_auto_detect_colors

Return True if stream is an interactive TTY (uvicorn/click/rich convention).

_resolve_stream

Map "stdout"/"stderr" to the corresponding sys stream.

create_logger

Create a configured logger for a Pynenc app.

Data

API

pynenc.util.log._TRUNCATE_LENGTH

8

class pynenc.util.log.Colors[source]

ANSI color codes for terminal coloring.

RESET

‘\x1b[0m’

RED

‘\x1b[31m’

GREEN

‘\x1b[32m’

YELLOW

‘\x1b[33m’

BLUE

‘\x1b[34m’

CYAN

‘\x1b[36m’

RED_BG

‘\x1b[41m’

WHITE

‘\x1b[37m’

class pynenc.util.log.PynencContextFilter(app_id: str, conf: pynenc.conf.config_pynenc.ConfigPynenc)[source]

Bases: logging.Filter

Injects Pynenc execution context into every log record.

Initialization

Parameters:
  • app_id (str) – The application identifier.

  • conf (ConfigPynenc) – App configuration (read dynamically).

filter(record: logging.LogRecord) bool[source]

Populate record with runner_ctx, invocation_id, task_id, compact_log_context.

class pynenc.util.log._PynencFormatterBase(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)[source]

Bases: logging.Formatter

Base formatter: TZ-aware timestamps, context prefix building, ID truncation.

Initialization

Initialize the formatter with specified format strings.

Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.

Use a style parameter of ‘%’, ‘{’ or ‘$’ to specify that you want to use one of %-formatting, :meth:str.format ({}) formatting or

Class:

string.Template formatting in your format string.

… versionchanged:: 3.2 Added the style parameter.

formatTime(record: logging.LogRecord, datefmt: str | None = None) str[source]

Produce YYYY-MM-DD HH:MM:SS.mmm±HH:MM timestamp.

_build_context_prefix(record: logging.LogRecord) str[source]

Build CLS(id)UUID:task.key prefix from record context attributes.

_build_context_dict(record: logging.LogRecord) dict[str, Any][source]

Extract untruncated context fields as a dict for structured output.

_format_runner_ctx_display(runner_ctx: RunnerContext | None, compact_context: bool) str | None[source]

Format runner context as CLS(id) or Parent(id).Child(id).

_maybe_truncate(value: str, truncate: bool) str[source]

Truncate to _TRUNCATE_LENGTH chars when truncate is True.

_maybe_compact_class_name(class_name: str, compact: bool) str[source]

Abbreviate to capital letters (e.g. PersistentProcessRunner → PPR).

class pynenc.util.log.ColoredFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)[source]

Bases: pynenc.util.log._PynencFormatterBase

ANSI-colored formatter with context prefixes for interactive terminals.

Initialization

Initialize the formatter with specified format strings.

Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.

Use a style parameter of ‘%’, ‘{’ or ‘$’ to specify that you want to use one of %-formatting, :meth:str.format ({}) formatting or

Class:

string.Template formatting in your format string.

… versionchanged:: 3.2 Added the style parameter.

LEVEL_COLORS

None

format(record: logging.LogRecord) str[source]

Format with ANSI colors and [context] prefix.

class pynenc.util.log.PlainTextFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)[source]

Bases: pynenc.util.log._PynencFormatterBase

Plain text formatter with context prefixes, compatible with pynmon log explorer.

Initialization

Initialize the formatter with specified format strings.

Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.

Use a style parameter of ‘%’, ‘{’ or ‘$’ to specify that you want to use one of %-formatting, :meth:str.format ({}) formatting or

Class:

string.Template formatting in your format string.

… versionchanged:: 3.2 Added the style parameter.

format(record: logging.LogRecord) str[source]

Format with [context] prefix, no ANSI codes.

class pynenc.util.log.JsonFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)[source]

Bases: pynenc.util.log._PynencFormatterBase

Structured JSON formatter for containers and cloud log aggregators.

Uses severity as the level key (Google Cloud Logging convention, also recognized by Datadog, AWS CloudWatch, and ELK). Includes a text field with the human-readable representation for pynmon log explorer compatibility.

Initialization

Initialize the formatter with specified format strings.

Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.

Use a style parameter of ‘%’, ‘{’ or ‘$’ to specify that you want to use one of %-formatting, :meth:str.format ({}) formatting or

Class:

string.Template formatting in your format string.

… versionchanged:: 3.2 Added the style parameter.

format(record: logging.LogRecord) str[source]

Emit one JSON object per line with structured context fields.

pynenc.util.log._format_tz_offset(ct: time.struct_time) str[source]

Format timezone offset as ±HH:MM from struct_time.

pynenc.util.log._auto_detect_colors(stream: Any) bool[source]

Return True if stream is an interactive TTY (uvicorn/click/rich convention).

pynenc.util.log._resolve_stream(log_stream: str) Any[source]

Map "stdout"/"stderr" to the corresponding sys stream.

pynenc.util.log.create_logger(app: pynenc.app.Pynenc, use_colors: bool | None = None, log_format: LogFormat | str | None = None, stream: Any | None = None) logging.Logger[source]

Create a configured logger for a Pynenc app.

Resolution order for each setting: explicit parameter → app.conf → auto-detect.

Parameters:
  • app (Pynenc) – The app instance for which the logger is created.

  • use_colors (bool | None) – Override color setting (None = auto-detect TTY).

  • log_format (LogFormat | str | None) – Override log format (None = from config).

  • stream (Any | None) – Override output stream (None = from config).

Returns:

The created logger.

Raises:

ValueError – If the logging level is invalid.