Skip to content

Color Operations & Performance ​

Logly provides a comprehensive color system for styled log output. This guide covers all color operations, ANSI processing, and performance optimization techniques.

Named Colors ​

Logly supports standard ANSI color names for foreground and background styling:

python
from logly import logger

logger.remove()

logger.add("stderr", level="TRACE", colorize=True)

# Standard named colors
logger.level("CUSTOM_RED", no=31, color="red")
logger.level("CUSTOM_GREEN", no=32, color="green")
logger.level("CUSTOM_BLUE", no=33, color="blue")
logger.level("CUSTOM_YELLOW", no=34, color="yellow")
logger.level("CUSTOM_CYAN", no=35, color="cyan")
logger.level("CUSTOM_MAGENTA", no=36, color="magenta")

logger.log("CUSTOM_RED", "Red message")
logger.log("CUSTOM_GREEN", "Green message")
logger.log("CUSTOM_BLUE", "Blue message")

Available named colors:

  • black, red, green, yellow, blue, magenta, cyan, white

Bright Colors ​

Bright variants provide higher-contrast output for better visibility:

python
from logly import logger

logger.remove()

logger.add("stderr", level="TRACE", colorize=True)

logger.level("BRIGHT_RED", no=31, color="bright_red")
logger.level("BRIGHT_GREEN", no=32, color="bright_green")
logger.level("BRIGHT_BLUE", no=33, color="bright_blue")
logger.level("BRIGHT_YELLOW", no=34, color="bright_yellow")
logger.level("BRIGHT_CYAN", no=35, color="bright_cyan")
logger.level("BRIGHT_MAGENTA", no=36, color="bright_magenta")

logger.log("BRIGHT_RED", "Bright red message")
logger.log("BRIGHT_GREEN", "Bright green message")

Available bright colors:

  • bright_black, bright_red, bright_green, bright_yellow, bright_blue, bright_magenta, bright_cyan, bright_white

Compound Styles ​

Combine foreground color with text styles using underscore or space syntax:

Underscore-Separated ​

python
from logly import logger

logger.remove()

logger.add("stderr", level="TRACE", colorize=True)

logger.level("TRACE", no=5, color="dim_cyan")
logger.level("DEBUG", no=10, color="bold_blue")
logger.level("INFO", no=20, color="bold_green")
logger.level("NOTICE", no=25, color="italic_cyan")
logger.level("SUCCESS", no=30, color="bold_green")
logger.level("WARNING", no=40, color="bold_yellow")
logger.level("ERROR", no=50, color="bold_red")
logger.level("FAIL", no=55, color="bold_magenta")
logger.level("CRITICAL", no=60, color="bold_white")

logger.trace("dim cyan trace")
logger.debug("bold blue debug")
logger.error("bold red error")
logger.critical("bold white critical")

Space-Separated ​

python
from logly import logger

logger.remove()

logger.add("stderr", level="TRACE", colorize=True)

logger.level("TRACE", no=5, color="dim cyan")
logger.level("DEBUG", no=10, color="bold blue")
logger.level("INFO", no=20, color="italic green")
logger.level("WARNING", no=40, color="underline yellow")
logger.level("ERROR", no=50, color="bold red")

logger.trace("dim cyan trace")
logger.warning("underline yellow warning")

Available text styles:

  • dim, bold, italic, underline, blink, reverse, strike

Background Colors ​

Named Background Colors ​

Use bg_ or on_ prefix for background colors:

python
from logly import logger

logger.remove()

logger.add("stderr", level="TRACE", colorize=True)

logger.level("INFO", no=20, color="bg_blue")
logger.level("WARNING", no=40, color="on_yellow")
logger.level("ERROR", no=50, color="bg_red")

logger.info("blue background")
logger.warning("yellow background")
logger.error("red background")

Available background prefixes:

  • bg_red, bg_green, bg_blue, bg_yellow, bg_cyan, bg_magenta, bg_white, bg_black
  • on_red, on_green, on_blue, on_yellow, on_cyan, on_magenta, on_white, on_black
  • bg_bright_red, on_bright_cyan, etc.

RGB Background Colors ​

python
from logly import logger

logger.remove()

logger.add("stderr", level="TRACE", colorize=True)

logger.level("INFO", no=20, color="bg_rgb(0, 0, 128)")
logger.level("WARNING", no=40, color="on_rgb(255, 165, 0)")
logger.level("ERROR", no=50, color="on_rgb(255, 0, 0)")

logger.info("navy background")
logger.warning("orange background")
logger.error("red background")

Hex Background Colors ​

python
from logly import logger

logger.remove()

logger.add("stderr", level="TRACE", colorize=True)

logger.level("INFO", no=20, color="bg#000080")
logger.level("WARNING", no=40, color="on#ffa500")
logger.level("ERROR", no=50, color="on#ff0000")

logger.info("navy background")
logger.warning("orange background")
logger.error("red background")

256-Color Background ​

python
from logly import logger

logger.remove()

logger.add("stderr", level="TRACE", colorize=True)

logger.level("INFO", no=20, color="bg_color(196)")
logger.level("WARNING", no=40, color="bgcolor(226)")
logger.level("ERROR", no=50, color="on_color(160)")

logger.info("red background (256-color)")
logger.warning("yellow background (256-color)")

Compound Styles with Background ​

Combine foreground, style, and background:

python
from logly import logger

logger.remove()

logger.add("stderr", level="TRACE", colorize=True)

logger.level("INFO", no=20, color="bold green on black")
logger.level("WARNING", no=40, color="bold yellow on blue")
logger.level("ERROR", no=50, color="bold red on white")

logger.info("bold green on black")
logger.warning("bold yellow on blue")
logger.error("bold red on white")

Rich-Style Markup Tags ​

Use <tag> syntax in format strings for inline coloring. These tags work directly in format strings and log messages.

Color Tags ​

python
from logly import logger

logger.remove()

logger.add(
    "stderr",
    format="<green>{time:HH:mm:ss}</green> | <level>{level:<8}</level> | <level>{message}</level>",
    colorize=True,
)

logger.info("Colored output")

Supported color tags:

  • <red>, <green>, <blue>, <yellow>, <cyan>, <magenta>, <white>, <black>
  • <bright_red>, <bright_green>, <bright_blue>, <bright_yellow>, <bright_cyan>, <bright_magenta>, <bright_white>, <bright_black>

Style Tags ​

python
from logly import logger

logger.remove()

logger.add(
    "stderr",
    format="<bold>{level:<8}</bold> | <dim>{message}</dim>",
    colorize=True,
)

logger.info("Bold and dim text")

Supported style tags:

  • <bold>, <dim>, <italic>, <underline>, <blink>, <strike>, <reverse>

Background Tags ​

python
from logly import logger

logger.remove()

logger.add(
    "stderr",
    format="<bg_red><white>{level:<8}</white></bg_red> | {message}",
    colorize=True,
)

logger.error("Error with red background")

Supported background tags:

  • <bg_red>, <bg_green>, <bg_blue>, <bg_yellow>, <bg_cyan>, <bg_magenta>, <bg_white>, <bg_black>

Combining Tags ​

Stack multiple tags for complex styling:

python
from logly import logger

logger.remove()

logger.add(
    "stderr",
    format=(
        "<green><bold>{time:HH:mm:ss}</bold></green> | "
        "<red><bold>{level:<8}</bold></red> | "
        "<cyan>{message}</cyan>"
    ),
    colorize=True,
)

logger.info("Complex styled output")

Level Tags ​

Use <level> to apply the level's configured color automatically:

python
from logly import logger

logger.remove()

logger.add(
    "stderr",
    format="{time:HH:mm:ss} | <level>{level:<8}</level> | {message}",
    colorize=True,
)

logger.info("Green info")
logger.error("Red error")
logger.warning("Yellow warning")

The colorize() Function ​

Use colorize() to apply ANSI colors to text programmatically:

python
from logly import logger
from logly import colorize

logger.remove()

logger.add("stderr", colorize=True)

# Apply color to a string
red_text = colorize("Error occurred", "red")
bold_text = colorize("Important", "bold")
green_bold = colorize("Success", "bold green")

logger.info("{}", red_text)
logger.info("{}", bold_text)
logger.info("{}", green_bold)

Colorize with Background ​

python
from logly import colorize

# Foreground + background
error_msg = colorize("ERROR", "bold white on_red")
warning_msg = colorize("WARN", "bold black on_yellow")

print(f"{error_msg} Something failed")
print(f"{warning_msg} Something looks off")

The strip_rich_tags() Function ​

Strip Rich-style markup tags from text, leaving only the content:

python
from logly import logger
from logly import strip_rich_tags

logger.remove()

# Create a logger that strips tags for plain text output
logger.add(
    "plain.log",
    format="{time} | {level:<8} | {message}",
    colorize=False,
)

# Original message with tags
message = "<bold>Important</bold>: <red>check the logs</red>"

# Strip tags for plain text file
plain_text = strip_rich_tags(message)
logger.info("{}", plain_text)
# Output: Important: check the logs (no ANSI codes)

Common Use Case ​

python
from logly import logger
from logly import strip_rich_tags

logger.remove()

# Console with colors
logger.add(
    "stderr",
    format="<green>{time:HH:mm:ss}</green> | <level>{level:<8}</level> | {message}",
    colorize=True,
)

# File without colors (tags automatically stripped when colorize=False)
logger.add(
    "app.log",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level:<8} | {message}",
    colorize=False,
)

# Log message with Rich-style tags
logger.info("<bold>User</bold> <green>logged in</green>")
# Console: styled output with colors
# File: User logged in (plain text)

The paint_themed() Function ​

Apply theme-aware coloring that adapts to the current color scheme:

python
from logly import logger
from logly import paint_themed

logger.remove()

logger.add("stderr", colorize=True)

# Theme-aware coloring
success_msg = paint_themed("Operation completed", "success")
error_msg = paint_themed("Something failed", "error")
warning_msg = paint_themed("Check this", "warning")

logger.info("{}", success_msg)
logger.error("{}", error_msg)
logger.warning("{}", warning_msg)

Custom Themes ​

python
from logly import logger
from logly import paint_themed

logger.remove()

# Theme-aware colors come from the built-in theme via paint_themed
logger.add("stderr", colorize=True)

logger.info("{}", paint_themed("Success!", "success"))
logger.error("{}", paint_themed("Failed!", "error"))

Color Caching and Performance ​

Logly caches color escape sequences for optimal performance. Understanding how caching works helps you write efficient color configurations.

How Caching Works ​

python
from logly import logger

logger.remove()

# Color values are cached after first use
# These calls reuse cached escape sequences
logger.add("stderr", colorize=True)
logger.level("CUSTOM", no=35, color="bold red on white")

# The escape sequence for "bold red on white" is computed once
# and reused for all subsequent log calls at this level
for i in range(10000):
    logger.log("CUSTOM", "Message {}", i)

Performance Tips ​

python
from logly import logger

logger.remove()

# Good: Reuse color strings (cached)
ERROR_STYLE = "bold red"
WARNING_STYLE = "yellow"
INFO_STYLE = "green"

logger.level("CUSTOM_ERROR", no=50, color=ERROR_STYLE)
logger.level("CUSTOM_WARNING", no=40, color=WARNING_STYLE)
logger.level("CUSTOM_INFO", no=20, color=INFO_STYLE)

# Good: Use named colors (faster parsing)
logger.level("LEVEL1", no=31, color="red")

# Avoid: Complex RGB colors in hot paths (more parsing overhead)
# Use only when exact color control is needed
logger.level("LEVEL2", no=32, color="rgb(255, 0, 0)")

Performance Comparison ​

Color TypeParsing SpeedUse Case
Named colorsFastestMost log levels
Bright colorsFastHigh-contrast needs
Compound stylesFastBold/italic combinations
256-colorMediumExtended palette
RGB/HexSlowerExact color matching

Disabling Colors Globally ​

Per-Sink Disable ​

python
from logly import logger

logger.remove()

# Console gets colors
logger.add("stderr", colorize=True)

# File gets no colors
logger.add("app.log", colorize=False)

# Another file gets colors
logger.add("colored.log", colorize=True)

logger.error("This message goes to all three sinks")
logger.complete()

Auto-Detection ​

When colorize=None (default), colors auto-detect based on sink type:

python
from logly import logger

logger.remove()

# Auto-detect: stderr/stdout get colors if TTY, files don't
logger.add("stderr")  # colorize=None (auto)
logger.add("app.log")  # colorize=None (auto, off for files)

Environment Variable ​

python
import os
from logly import logger

# Disable colors via environment variable
os.environ["NO_COLOR"] = "1"

logger.remove()
logger.add("stderr")  # Colors disabled by NO_COLOR
logger.info("No colors in output")

Color in Network/File Sinks ​

Network Sinks ​

When sending logs over the network, strip ANSI codes to avoid corrupting data:

python
import json
import urllib.request
from logly import logger


def http_sink(message: str) -> None:
    # Strip ANSI codes before sending
    payload = json.dumps({"log": message}).encode("utf-8")
    request = urllib.request.Request(
        "https://logs.example.com/ingest",
        data=payload,
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    urllib.request.urlopen(request, timeout=5)


logger.add(
    http_sink,
    level="INFO",
    enqueue=True,
    colorize=False,  # Disable colors for network sink
)

File Sinks ​

Control colors per file:

python
from logly import logger

logger.remove()

# Plain text file (no colors)
logger.add(
    "plain.log",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level:<8} | {message}",
    colorize=False,
)

# Colored file (for terminals that support it)
logger.add(
    "colored.log",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level:<8} | {message}",
    colorize=True,
)

logger.info("Goes to both files")
logger.complete()

JSON Output ​

When serialize=True, colors are automatically stripped:

python
from logly import logger

logger.remove()

logger.add("app.json", serialize=True, colorize=True)
logger.info("JSON output has no ANSI codes")
# Output: {"time": "...", "level": "INFO", "message": "JSON output has no ANSI codes"}

Complete Examples ​

Full Color Configuration ​

python
from logly import logger

logger.remove()

# Configure all built-in levels with custom colors
logger.level("TRACE", no=5, color="dim cyan")
logger.level("DEBUG", no=10, color="blue")
logger.level("INFO", no=20, color="green")
logger.level("NOTICE", no=25, color="cyan")
logger.level("SUCCESS", no=30, color="bold green")
logger.level("WARNING", no=40, color="bold yellow")
logger.level("ERROR", no=50, color="bold red")
logger.level("FAIL", no=55, color="bold magenta")
logger.level("CRITICAL", no=60, color="bold red on white")
logger.level("FATAL", no=70, color="bold red on black")

# Register custom levels with colors
logger.level("AUDIT", no=35, color="rgb(255, 128, 0)")
logger.level("METRIC", no=15, color="color(208)")
logger.level("SECURITY", no=45, color="bold red")
logger.level("HIGHLIGHT", no=36, color="reverse")

# Console sink with colors
logger.add("stderr", level="TRACE", colorize=True)

# Test all levels
logger.trace("trace message")
logger.debug("debug message")
logger.info("info message")
logger.notice("notice message")
logger.success("success message")
logger.log("AUDIT", "audit message")
logger.log("METRIC", "metric message")
logger.warning("warning message")
logger.error("error message")
logger.fail("fail message")
logger.log("SECURITY", "security message")
logger.log("HIGHLIGHT", "highlighted message")
logger.critical("critical message")
logger.fatal("fatal message")

logger.complete()

Multi-Sink Color Setup ​

python
from logly import logger

logger.remove()

# Console with Rich-style markup
logger.add(
    "stderr",
    format=(
        "<green>{time:HH:mm:ss}</green> | "
        "<level><bold>{level:<8}</bold></level> | "
        "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> | "
        "<level>{message}</level>"
    ),
    colorize=True,
)

# File without colors
logger.add(
    "app.log",
    format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level:<8} | {filename}:{line} | {message}",
    colorize=False,
    rotation="daily",
    retention="30 days",
)

# JSON without colors
logger.add(
    "app.json",
    serialize=True,
    colorize=False,
)

logger.info("Message with <bold>Rich-style</bold> markup")
logger.complete()

Performance-Optimized Colors ​

python
from logly import logger

logger.remove()

# High-throughput: disable source capture per call, use simple colors
logger.add(
    "app.log",
    level="INFO",
    enqueue=True,
    rotation="100 MB",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level:<8} | {message}",
)
logger.opt(capture=False).info("fast path without source info")

# Console with colors (cached escape sequences)
logger.add(
    "stderr",
    level="INFO",
    format="{time:HH:mm:ss} | <level>{level:<8}</level> | {message}",
    colorize=True,
)

# Pre-compute color strings (cached by Logly)
COLORS = {
    "info": "green",
    "warning": "yellow",
    "error": "bold red",
}

for i in range(100000):
    logger.info("Info message {}", i)
    if i % 10 == 0:
        logger.warning("Warning message {}", i)
    if i % 100 == 0:
        logger.error("Error message {}", i)

logger.complete()

Released under the MIT License.