Skip to content

Logger API

The Logger class is the primary interface for all logging operations. Import it from logly:

python
from logly import logger

Log Methods

log(level, message, *args, **kwargs)

Log a message at the specified level.

python
logger.log("INFO", "Message at INFO level")
logger.log("CUSTOM", "Message at custom level")

Parameters:

  • level (str): The log level name (e.g., "INFO", "ERROR")
  • message (str): The log message
  • *args: Format string arguments
  • **kwargs: Additional context fields

Returns: dict[str, object] | None - record dict if opt(record=True), else None


trace(message, *args, **kwargs)

Log at TRACE level (numeric 5).

python
logger.trace("Fine-grained trace: {var}", var=value)

debug(message, *args, **kwargs)

Log at DEBUG level (numeric 10).

python
logger.debug("Debug info: {data}", data=payload)

info(message, *args, **kwargs)

Log at INFO level (numeric 20).

python
logger.info("Application started on port {port}", port=8000)

notice(message, *args, **kwargs)

Log at NOTICE level (numeric 25).

python
logger.notice("Configuration reloaded")

success(message, *args, **kwargs)

Log at SUCCESS level (numeric 30).

python
logger.success("Deployment completed!")

warning(message, *args, **kwargs)

Log at WARNING level (numeric 40).

python
logger.warning("Disk usage above {pct}%", pct=90)

error(message, *args, **kwargs)

Log at ERROR level (numeric 50).

python
logger.error("Database connection failed")

fail(message, *args, **kwargs)

Log at FAIL level (numeric 55).

python
logger.fail("Task failed: {reason}", reason="timeout")

critical(message, *args, **kwargs)

Log at CRITICAL level (numeric 60).

python
logger.critical("System memory exhausted")

fatal(message, *args, **kwargs)

Log at FATAL level (numeric 70).

python
logger.fatal("Unrecoverable error - shutting down")

audit(message, *args, **kwargs)

Log at AUDIT level (must be registered first).

python
logger.level("AUDIT", no=35, color="<green>")
logger.audit("User performed action")

Configuration Methods

add(sink, **kwargs)

Add a new sink to the logger. Returns a sink ID string.

python
sink_id = logger.add("app.log", level="INFO", rotation="daily")

Parameters:

ParameterTypeDefaultDescription
sinkstr | Path | Callable | objectFile path, callable, or sink object
levelstr"INFO"Minimum log level for this sink
formatstr | NoneNoneCustom format string
rotationstr | int | NoneNoneRotation policy (e.g., "daily", "10 MB")
retentionstr | int | NoneNoneRetention policy (e.g., "30 days")
compressionstr | NoneNoneCompression codec (e.g., "gzip", "zip")
enqueueboolFalseUse queue-based async worker
colorizebool | NoneNoneEnable ANSI color output
backtraceboolFalseInclude backtrace on exceptions
diagnoseboolFalseInclude variable values on exceptions
filterCallable | NoneNoneCustom filter function
serializeboolFalseOutput as JSON
pretty_jsondict | PrettyJsonConfig | NoneNoneJSON formatting options
patchCallable | NoneNonePatch function for all records
encodingstr"utf-8"File encoding
delayboolFalseDelay file opening until first write
contextCallable | NoneNoneContext variable factory
catchboolTrueCatch sink errors silently
modestr"append"File mode: "append" or "overwrite"
bufferingint-1File buffering level
loopAbstractEventLoop | NoneNoneEvent loop for async sinks
openerCallable | NoneNoneCustom file opener

Returns: str - sink ID for use with remove()

Built-in Sink Objects:

SinkDescription
HttpJsonSinkHTTP JSON log shipping
BatchHttpJsonSinkBatched HTTP JSON log shipping
TcpSinkTCP socket logging
UdpSinkUDP socket logging
SyslogSinkSystem syslog logging

Example with BatchHttpJsonSink:

python
from logly import BatchHttpJsonSink, logger

sink = BatchHttpJsonSink(
    url="https://logs.example.com/ingest",
    batch_size=100,
    flush_interval=5.0,
)
logger.add(sink, level="INFO")

remove(sink_id)

Remove a sink by its ID.

python
logger.remove(sink_id)

configure(**kwargs)

Configure the logger with a complete configuration dict.

python
logger.configure(
    handlers=[
        {"sink": "stdout", "level": "INFO"},
        {"sink": "app.log", "level": "DEBUG"},
    ],
    extra={"app_name": "myapp"},
)

Parameters:

  • handlers (list[dict[str, Any]]): List of sink configuration dicts
  • extra (dict[str, Any]): Default extra fields for all records
  • levels (list[dict[str, Any]]): Custom level definitions
  • patcher (Callable): Global patcher function
  • activation (list[tuple[str, bool]]): Level activation pairs

level(name, no=None, color=None, icon=None)

Get or create a custom log level.

python
# Get existing level
level_obj = logger.level("INFO")
print(level_obj.name)  # "INFO"
print(level_obj.no)  # 20
print(level_obj.color)  # None
print(level_obj.icon)  # None

# Create custom level
logger.level("AUDIT", no=35, color="<green><bold>", icon="🔒")

Parameters:

  • name (str): Level name
  • no (int | None): Numeric value
  • color (str | None): ANSI color markup
  • icon (str | None): Level icon

Returns: Level - level object with .name, .no, .color, .icon attributes


reinstall()

Re-add all previously configured sinks. Useful after context changes.

python
logger.reinstall()

enable(*module_names)

Enable logging for specific modules.

python
logger.enable("myapp")

disable(*module_names)

Disable logging for specific modules.

python
logger.disable("myapp")

complete()

Wait for all pending log messages to be processed (async workers).

python
logger.complete()

root_dir(path)

Set the root directory for relative file paths.

python
logger.root_dir("/var/log/myapp")

Optimization Methods

opt(**kwargs)

Configure logging behavior for subsequent calls.

python
# Record mode - return the record dict
record = logger.opt(record=True).info("Hello")

# Lazy evaluation - defer string formatting
logger.opt(lazy=True).info("Expensive: {data}", data=compute())

# Raw mode - skip format processing
logger.opt(raw=True).info("Raw message: {time}")

# Exception mode - include exception info
logger.opt(exception=True).info("Failed")

# Colors mode - enable ANSI color in message
logger.opt(colors=True).info("<green>Success!</green>")

# Depth mode - capture caller info from N frames up
logger.opt(depth=2).info("Called from caller")

# Backtrace - include backtrace on exception
logger.opt(backtrace=True).info("Error context")

# Diagnose - include variable values on exception
logger.opt(diagnose=True).info("Debug context")

# Capture - capture context from specified keys
logger.opt(capture=["user_id"]).info("User action")

Parameters:

ParameterTypeDefaultDescription
exceptionbool | type | tupleNoneInclude exception info
recordboolFalseReturn record dict
lazyboolFalseDefer string formatting
colorsboolFalseEnable ANSI color
rawboolFalseSkip format processing
depthint0Caller frame depth
capturelist[str] | NoneNoneKeys to capture from context
backtracebool | NoneNoneOverride backtrace setting
diagnosebool | NoneNoneOverride diagnose setting
ansibool | NoneNoneAlias for colors

bind(**kwargs)

Create a new logger with persistent context fields.

python
user_logger = logger.bind(user_id="12345", request_id="abc")
user_logger.info("Action performed")
# Output includes: user_id=12345 request_id=abc

Returns: Self - new logger with bound context


patch(patcher)

Create a new logger with a record patcher function.

python
patched = logger.patch(lambda record: record.update({"env": "production"}))
patched.info("Running in production")

Parameters:

  • patcher (Callable[[dict], None]): Function that modifies the record dict

Returns: Self - new logger with patcher applied


contextualize(**kwargs)

Context manager for scoped context fields.

python
with logger.contextualize(request_id="abc-123"):
    logger.info("Scoped to request")
    # request_id is automatically included

Exception Methods

catch(exception=Exception, level="ERROR", reraise=False, onerror=None, exclude=None, default=None)

Context manager for automatic exception logging.

python
# Basic usage
with logger.catch():
    risky_operation()

# Exclude specific exceptions
with logger.catch(exclude=(ValueError, KeyError)):
    optional_operation()

# Custom error handling
with logger.catch(onerror=lambda e: send_alert(str(e))):
    critical_operation()

# Return default on exception
result = logger.catch(default=None)(risky_function)()

# Re-raise after logging
with logger.catch(reraise=True):
    dangerous_operation()

Parameters:

ParameterTypeDefaultDescription
exceptiontype | tupleExceptionException types to catch
levelstr"ERROR"Log level for caught exceptions
reraiseboolFalseRe-raise after logging
onerrorCallable | NoneNoneCallback on exception
excludetype | tuple | NoneNoneException types to exclude (re-raise)
defaultAnysentinelDefault return value on exception

Parse Method

parse(path, pattern=None, *, cast=None, chunk=65536, encoding="utf-8")

Parse log files using regex patterns. This is a static method.

python
# Parse all log lines
entries = logger.parse("app.log")

# Custom pattern
entries = logger.parse(
    "app.log",
    pattern=r"(?P<time>\d{4}-\d{2}-\d{2}) (?P<level>\w+) (?P<message>.+)",
)

# With type casting
entries = logger.parse(
    "app.log",
    pattern=r"(?P<time>\S+) (?P<level>\w+) (?P<message>.+)",
    cast={"time": "datetime", "level": "int"},
)

Parameters:

ParameterTypeDefaultDescription
pathstr | PathLog file path
patternstr | NoneNoneRegex pattern with named groups
castdict | NoneNoneType casting rules
chunkint65536Read chunk size
encodingstr"utf-8"File encoding

Returns: list[dict] - parsed log entries

Properties

levels

Get the current level registry.

python
for level_name, level_no, color in logger.levels:
    print(f"{level_name}: {level_no}")

Builtin Levels

LevelNumericColor
TRACE5Gray
DEBUG10Blue
INFO20Green
NOTICE25Cyan
SUCCESS30Green (bold)
WARNING40Yellow
ERROR50Red
FAIL55Red (bold)
CRITICAL60Red (bold, bg)
FATAL70Red (bold, bg)

Released under the MIT License.