Beautiful, colored, and boxed logging for Python.
Project description
crisplogs
Beautiful, structured terminal logging for Python
One function call to get production-ready logs with colors, box decorations, structured data, and file output. Zero runtime dependencies.
from crisplogs import setup_logging
logger = setup_logging()
logger.info("Server started on port 8000")
logger.warning("Disk usage at 85%", extra={"mount": "/dev/sda1"})
logger.error("Connection failed", extra={"host": "db.internal", "retries": 3})
INFO 2025-09-08 12:30:45 [root] app.py:5 - Server started on port 8000
WARNING 2025-09-08 12:30:45 [root] app.py:6 - Disk usage at 85% [mount=/dev/sda1]
ERROR 2025-09-08 12:30:45 [root] app.py:7 - Connection failed [host=db.internal retries=3]
Table of Contents
- Installation
- Quick Start
- Output Styles
- Options
- Structured Data (Extras)
- File Logging
- Named Loggers
- Advanced Usage
- API Reference
- Examples
- License
Installation
pip install crisplogs
Quick Start
from crisplogs import setup_logging
logger = setup_logging()
logger.debug("Loading configuration...")
logger.info("Server started on port 8000")
logger.warning("Disk usage at 85%")
logger.error("Failed to connect to database")
logger.critical("System is shutting down")
All five log levels are supported: DEBUG, INFO, WARNING, ERROR, CRITICAL.
Output Styles
crisplogs ships with four output styles. Set the style option to switch between them.
Default (no box)
Colored single-line output. Each level gets its own color.
logger = setup_logging() # or style=None
INFO 2025-09-08 12:30:45 [root] app.py:5 - Server started
WARNING 2025-09-08 12:30:46 [root] app.py:6 - Disk usage high
ERROR 2025-09-08 12:31:12 [root] db.py:45 - Connection failed
short-fixed
Fixed-width box with left border. Clean and consistent.
logger = setup_logging(style="short-fixed")
┌──────────────────────────────────────────────────────────────────────────────────
│ INFO 12:30:45 [root] app.py:5 - Server started
└──────────────────────────────────────────────────────────────────────────────────
short-dynamic
Full border that adjusts to fit the message width.
logger = setup_logging(style="short-dynamic")
┌──────────────────────────────────────────────────────────┐
│ INFO 12:30:45 [root] app.py:5 - Server started │
└──────────────────────────────────────────────────────────┘
long-boxed
Word-wrapped box with left border. Best for long messages and structured data.
logger = setup_logging(style="long-boxed", width=80)
┌──────────────────────────────────────────────────────────────────────────────────
│ INFO 12:34:56 [root] app.py:10 - This is a long message that wraps neatly
│ across multiple lines without breaking words [user_id=42 action=login]
└──────────────────────────────────────────────────────────────────────────────────
Combining styles with color
All styles work with or without color:
setup_logging(colored=True, style="long-boxed") # colored + boxed
setup_logging(colored=False, style="short-fixed") # plain + boxed
setup_logging(colored=True, style=None) # colored, no box
setup_logging(colored=False) # plain text
Options
setup_logging(**options)
| Option | Type | Default | Description |
|---|---|---|---|
colored |
bool |
True |
Enable ANSI colors in console output |
style |
"short-fixed" | "short-dynamic" | "long-boxed" | None |
None |
Box decoration style |
level |
Level |
"DEBUG" |
Minimum log level for console |
width |
int |
100 |
Box width in characters |
datefmt |
str |
"%Y-%m-%d %H:%M:%S" |
Timestamp format |
log_colors |
dict |
built-in scheme | Custom colors per level |
extra_format |
"inline" | "json" | "pretty" |
"inline" |
How structured data is rendered |
file |
str | None |
None |
Path to log file (ANSI auto-stripped) |
file_level |
Level | None |
same as level |
Minimum level for file output |
name |
str |
"" |
Logger name ("" = root logger) |
capture_caller_info |
bool |
True |
Capture file path and line number |
Log Levels
| Level | Value | Use for |
|---|---|---|
DEBUG |
10 | Detailed diagnostic information |
INFO |
20 | Routine operational messages |
WARNING |
30 | Something unexpected but recoverable |
ERROR |
40 | A failure that needs attention |
CRITICAL |
50 | System-level failure |
# Only show WARNING and above on console
logger = setup_logging(level="WARNING")
logger.debug("hidden") # filtered out
logger.info("hidden") # filtered out
logger.warning("shown") # displayed
logger.error("shown") # displayed
Date Format Tokens
| Token | Output | Example |
|---|---|---|
%Y |
4-digit year | 2025 |
%m |
Month (01-12) | 09 |
%d |
Day (01-31) | 08 |
%H |
Hour 24h (00-23) | 14 |
%M |
Minute (00-59) | 30 |
%S |
Second (00-59) | 45 |
%I |
Hour 12h (01-12) | 02 |
%p |
AM/PM | PM |
%f |
Microseconds | 123456 |
%% |
Literal % |
% |
setup_logging(datefmt="%H:%M:%S") # 14:30:45
setup_logging(datefmt="%d/%m/%Y %H:%M") # 08/09/2025 14:30
setup_logging(datefmt="%I:%M %p") # 02:30 PM
Custom Colors
Override colors for any log level. Supports basic colors, modifiers, backgrounds, and combinations:
setup_logging(log_colors={
"DEBUG": "thin_white",
"INFO": "bold_green",
"WARNING": "bold_yellow",
"ERROR": "bold_red,bg_white",
"CRITICAL": "bold_white,bg_red",
})
Available colors: black, red, green, yellow, blue, purple/magenta, cyan, white
Modifiers: bold_, thin_/dim_, italic_, underline_
Backgrounds: bg_red, bg_blue, bg_white, etc.
Combine with commas: "bold_red,bg_white"
Default color scheme
| Level | Color |
|---|---|
DEBUG |
cyan |
INFO |
green |
WARNING |
yellow |
ERROR |
red |
CRITICAL |
bold_red |
Structured Data (Extras)
Attach key-value context to any log message via the extra argument:
logger.info("User signed up", extra={"user_id": 101, "plan": "pro"})
logger.error("Payment failed", extra={"order_id": 5524, "gateway": "stripe"})
Control how extras are rendered with the extra_format option:
"inline" (default)
INFO ... - User signed up [user_id=101 plan=pro]
"json"
INFO ... - User signed up {"user_id": 101, "plan": "pro"}
"pretty"
INFO ... - User signed up
{
"user_id": 101,
"plan": "pro"
}
setup_logging(extra_format="json")
setup_logging(extra_format="pretty", style="long-boxed") # great combo
Note: Extras are rendered in the default (no box) and
long-boxedstyles. Short box styles (short-fixed,short-dynamic) do not display extras to preserve layout alignment.
File Logging
Write logs to a file alongside console output. ANSI codes are automatically stripped so log files stay clean.
logger = setup_logging(file="logs/app.log")
Set a separate level threshold for the file — useful for verbose console output with a quieter file:
logger = setup_logging(
level="DEBUG", # console: show everything
file="logs/app.log",
file_level="WARNING", # file: only WARNING and above
)
Named Loggers
Use named loggers to identify which part of your application produced each message:
from crisplogs import setup_logging, get_logger
# Configure root logger once at startup
setup_logging(level="INFO")
# Get named loggers anywhere in your app
db_logger = get_logger("db")
api_logger = get_logger("api")
db_logger.info("Connected to PostgreSQL") # [db] in output
api_logger.info("Listening on :8080") # [api] in output
Named loggers inherit the root logger's configuration (handlers, formatters). Use setup_logging(name="...") to configure a specific logger independently.
Advanced Usage
Performance Tuning
Caller info capture (stack frame inspection) runs on every log call. Disable it in high-throughput scenarios:
logger = setup_logging(capture_caller_info=False)
# Logs will show <unknown>:0 instead of real file:line
Check Level Before Logging
Skip expensive serialization when the message would be filtered:
import logging
if logger.isEnabledFor(logging.DEBUG):
logger.debug("Full state dump", extra={"state": expensive_serialize(app_state)})
Cleanup
from crisplogs import reset_logging, remove_logger
remove_logger("db") # remove and close one logger
reset_logging() # close all loggers (useful in tests)
Custom Formatter
Use LogFormatter directly for full control:
from crisplogs import LogFormatter
formatter = LogFormatter(
datefmt="%H:%M:%S",
log_colors={"INFO": "bold_cyan"},
colored=True,
box=True,
full_border=True,
width="auto", # or a fixed integer
word_wrap=False,
extra_format="json",
)
Custom Handler
Build on logging.Handler for custom destinations (HTTP, database, external service):
import logging
from crisplogs import LogFormatter
class MyHandler(logging.Handler):
def emit(self, record):
msg = self.format(record)
# send to your destination
send_to_external_service(msg)
handler = MyHandler()
handler.setFormatter(LogFormatter(log_colors={}, colored=False, datefmt="%H:%M:%S"))
logger = setup_logging(name="myapp")
logger.addHandler(handler)
API Reference
Functions
| Function | Returns | Description |
|---|---|---|
setup_logging(**options) |
Logger |
Configure and register a logger |
get_logger(name="") |
Logger |
Get a logger by name (inherits root config) |
reset_logging() |
None |
Close all handlers, clear the registry |
remove_logger(name) |
bool |
Remove and close a single logger |
Classes
| Class | Description |
|---|---|
LogFormatter |
Configurable formatter covering all output styles |
CleanFileHandler |
File handler with automatic ANSI stripping |
Constants
| Constant | Description |
|---|---|
DEFAULT_LOG_COLORS |
Default color scheme for each level |
__version__ |
Package version string |
Examples
See the examples/ directory for runnable scripts:
python examples/basic.py # default colored output
python examples/box_styles.py # all box styles
python examples/custom_colors.py # custom color scheme
python examples/extra_fields.py # structured data
python examples/file_logging.py # console + file output
python examples/level_filtering.py # level thresholds
python examples/named_loggers.py # named logger hierarchy
python examples/plain_output.py # no colors
python examples/custom_date_format.py
python examples/demo.py # full feature walkthrough
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file crisplogs-0.2.0.tar.gz.
File metadata
- Download URL: crisplogs-0.2.0.tar.gz
- Upload date:
- Size: 22.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7fa8ae66e99a0401f57da67f6d51d37d842668365f90397334ae37afac376aaf
|
|
| MD5 |
182aa2b5db7936eac2902d1ec3f07365
|
|
| BLAKE2b-256 |
87e8f1fee1fd997464c4cb35c1abc710c3f9b5360f69176714a1bb02bd96d7d4
|
File details
Details for the file crisplogs-0.2.0-py3-none-any.whl.
File metadata
- Download URL: crisplogs-0.2.0-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cdb93735c5ccb8c600200f4dd4c9aec9510c0347358d5677da5fcc2722f33b01
|
|
| MD5 |
52c14d7bf80d617c00c55a6790ced2fa
|
|
| BLAKE2b-256 |
b1e17ca2b0be364444fcef11ab425b396995453aa66c41be549984fa2090281f
|