Skip to content
Edit this page

Template String Formatting

This example demonstrates how to use Logly's template string formatting feature to customize log output with placeholders. Template strings allow you to control exactly how your logs appear.

Python 3.14 Template Strings vs. Logly Format Strings

Important: Python 3.14 introduces template strings (t-strings) with t"..." syntax for creating Template objects. This is different from Logly's format strings:

  • Python 3.14 t-strings: t"Hello {name}" creates a Template object for general templating
  • Logly format strings: "{time:YYYY-MM-DD} | {level} | {message}" for log formatting

Logly uses its own format system optimized for logging with time patterns, levels, and automatic field handling. See Python 3.14 Support Guide for details.

Overview

Template strings support placeholders that are replaced with actual log data:

  • Built-in placeholders: {time}, {level}, {message}
  • Time format specs (v0.1.6+): {time:YYYY-MM-DD HH:mm:ss} - Custom timestamp formatting (Loguru-style)
  • Extra field placeholders: {module}, {function}, {filename}, {lineno}, {any_custom_field}
  • Special placeholders: {extra} (all remaining fields as key=value pairs)

All placeholders are case-insensitive.

Time Format Specifications (New in v0.1.6)

You can now customize timestamp formats using Loguru-style patterns:

Supported Format Patterns

Pattern Description Example
YYYY 4-digit year 2025
YY 2-digit year 25
MMMM Full month name October
MMM Abbreviated month Oct
MM 2-digit month 10
dddd Full weekday name Saturday
ddd Abbreviated weekday Sat
DD 2-digit day 11
HH 2-digit hour (24h) 13
hh 2-digit hour (12h) 01
mm 2-digit minute 45
ss 2-digit second 32
SSS Milliseconds 123
SSSSSS Microseconds 123456
A AM/PM AM
a am/pm am
ZZ Timezone offset with colon +00:00
Z Timezone offset +0000

Time Format Examples

from logly import logger

# Date only
logger.add("logs/dates.log", format="{time:YYYY-MM-DD} | {level} | {message}")
logger.info("Date format example")
# Output: 2025-10-11 | INFO | Date format example

# Full datetime
logger.add("logs/datetime.log", format="{time:YYYY-MM-DD HH:mm:ss} [{level}] {message}")
logger.info("DateTime format")
# Output: 2025-10-11 13:45:32 [INFO] DateTime format

# With milliseconds
logger.add("logs/precise.log", format="{time:HH:mm:ss.SSS} | {message}")
logger.info("Precise timing")
# Output: 13:45:32.123 | Precise timing

# ISO 8601 style
logger.add("logs/iso.log", format="{time:YYYY-MM-DDTHH:mm:ss} {level} {message}")
logger.info("ISO format")
# Output: 2025-10-11T13:45:32 INFO ISO format

# Month names
logger.add("logs/readable.log", format="{time:DD MMM YYYY} | {message}")
logger.info("Readable date")
# Output: 11 Oct 2025 | Readable date

# European format
logger.add("logs/european.log", format="{time:DD/MM/YYYY HH:mm} {message}")
logger.info("European style")
# Output: 11/10/2025 13:45 European style

logger.complete()

Code Example

from logly import logger

# Configure logger with filename/lineno enabled
logger.configure(level="INFO", show_filename=True, show_lineno=True)

# Example 1: Simple format
logger.add("console", format="{time} [{level}] {message}")
logger.info("Application started")

# Example 2: Detailed format with placeholders
logger.add(
    "logs/detailed.log",
    format="{time} | {level:8} | {module}:{function} | {message}"
)
logger.info("Processing request", user_id=123, endpoint="/api/users")

# Example 3: Format with filename and line number
logger.add(
    "logs/debug.log",
    format="{level}: {filename}:{lineno} - {message}"
)
logger.info("Debug message with location info")

logger.info("Debug message with location info")

logger.complete()

# Read and display file contents
print("\nDetailed log content:")
with open("logs/detailed.log", 'r', encoding='utf-8') as f:
    print(f.read())

print("\nDebug log content:")
with open("logs/debug.log", 'r', encoding='utf-8') as f:
    print(f.read())

# Cleanup
logger.remove(1)
logger.remove(2)
logger.remove(3)

Expected Output

2025-01-15T14:32:10.123456+00:00 [INFO] Starting application
2025-01-15T14:32:10.125789+00:00 | INFO     | __main__:main | Processing request | user_id=123 | endpoint=/api/users
INFO: template-strings.md:42 - Debug message with location info

What Happens

First sink (console with simple format): - Shows time, level in brackets, and message - Extra fields (user_id, endpoint) are automatically appended with | separator

Second sink (file with detailed format): - Uses {module}:{function} to show where the log came from - {level:8} pads the level name to 8 characters for alignment - Extra fields are appended after the message

Third sink (file with filename:lineno format): - Uses {filename}:{lineno} to show the source location - Only shows filename and lineno when show_filename=True and show_lineno=True are configured

Key Concepts

Placeholder Rules

  1. Case-insensitive: {TIME}, {time}, and {Time} all work the same
  2. Auto-append: Extra fields not in the format are automatically appended
  3. Missing placeholders: Unknown placeholders like {unknown} are left as-is
  4. Width specification: {level:8} pads the level to 8 characters

Common Patterns

Simple console logging:

logger.add("console", format="{time:HH:mm:ss} [{level}] {message}")

Detailed file logging:

logger.add("app.log", format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level:8} | {module}:{function} | {message} | {extra}")

Structured JSON-like:

logger.add("structured.log", 
          format='{{"ts": "{time:YYYY-MM-DDTHH:mm:ss}", "lvl": "{level}", "msg": "{message}", "fields": "{extra}"}}')

Request logging:

logger.add("requests.log",
          format="{time:YYYY-MM-DD HH:mm:ss} | {method} {path} | status={status_code} | duration={duration_ms}ms")

Custom readable format:

logger.add("readable.log",
          format="{time:dddd, DD MMMM YYYY at HH:mm:ss} - {level} - {message}")
# Output: Saturday, 11 October 2025 at 13:45:32 - INFO - Application started

Best Practices

  1. Console vs File: Use simpler formats for console, detailed for files
  2. Include {extra}: Use {extra} placeholder to explicitly capture all context fields
  3. Consistent width: Use {level:8} for aligned output (note: width specs not yet implemented)
  4. Time formats: Choose appropriate time format for your use case:
  5. HH:mm:ss for console (quick reference)
  6. YYYY-MM-DD HH:mm:ss.SSS for logs (precise timestamps)
  7. YYYY-MM-DDTHH:mm:ss for ISO 8601 compatibility
  8. Performance: Simpler formats are slightly faster to process
  9. Auto-append behavior: Without {extra}, custom templates won't auto-append extra fields (v0.1.6+)

Python 3.14 Considerations

If you're using Python 3.14, be aware of the distinction between language features and Logly features:

Python 3.14 Template Strings (NOT used in Logly)

from string.templatelib import Template

# This is Python 3.14's NEW template string feature
name = "Alice"
age = 30
tmpl: Template = t"Hello {name}, you are {age} years old"

# Template object properties
print(tmpl.strings)        # ('Hello ', ', you are ', ' years old')
print(tmpl.interpolations)  # (name, age)
print(str(tmpl))           # 'Hello Alice, you are 30 years old'

Logly Format Strings (Used for logging)

from logly import logger

# This is Logly's format string system (similar to Loguru)
logger.add(
    "app.log",
    format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level} | {message} | {extra}"
)

logger.info("User action", username="Alice", age=30)
# Output: 2025-10-11 13:45:32.123 | INFO | User action | username=Alice | age=30

Key Differences

Feature Python 3.14 t-strings Logly Format Strings
Syntax t"text {var}" "text {placeholder}"
Purpose General templating Log formatting
Returns Template object Formatted log string
Time Formats Not supported {time:YYYY-MM-DD} etc.
Log Levels Not supported {level}
Auto-append Not supported Extra fields auto-append
Use Case App templates, SQL, etc. Logging only

For more details on using Python 3.14 with Logly, see the Python 3.14 Support Guide.

See Also