Skip to content

File Directories & Root Directory

Logly's root_dir() method sets a default directory for all relative file paths passed to add(). This simplifies configuration by allowing you to specify a single base path instead of repeating it for every sink.

root_dir() Method

Basic Usage

python
from logly import logger

# Set root directory
logger.root_dir("/var/log/myapp")

# These paths are relative to the root
logger.add("app.log")          # /var/log/myapp/app.log
logger.add("errors.log")       # /var/log/myapp/errors.log
logger.add("access.log")       # /var/log/myapp/access.log

INFO

root_dir() creates the directory if it doesn't exist, including all parent directories.

With Path Objects

python
from pathlib import Path
from logly import logger

logger.root_dir(Path("/var/log/myapp"))
logger.add("app.log")  # /var/log/myapp/app.log

Relative Paths

python
from logly import logger

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

# All of these resolve relative to root_dir
logger.add("app.log")                          # /var/log/myapp/app.log
logger.add("errors/app.log")                   # /var/log/myapp/errors/app.log
logger.add("modules/auth/auth.log")            # /var/log/myapp/modules/auth/auth.log

How root_dir Interacts with add()

Relative Paths

When root_dir is set, relative paths are resolved against it:

python
from logly import logger

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

logger.add("app.log")          # Resolves to /var/log/myapp/app.log
logger.add("subdir/app.log")   # Resolves to /var/log/myapp/subdir/app.log

Absolute Paths

Absolute paths are unaffected by root_dir:

python
from logly import logger

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

logger.add("/tmp/debug.log")              # /tmp/debug.log (not affected)
logger.add("/var/log/system.log")         # /var/log/system.log (not affected)

stdout/stderr

Console outputs are not affected by root_dir:

python
from logly import logger

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

logger.add("stderr")           # stderr (not affected)
logger.add("stdout")           # stdout (not affected)
logger.add(sys.stderr)         # stderr (not affected)

Creating Directories Automatically

python
from logly import logger

# root_dir creates the directory tree
logger.root_dir("/var/log/myapp/modules/auth")

# All parent directories are created
logger.add("auth.log")  # /var/log/myapp/modules/auth/auth.log

WARNING

Directory creation requires write permissions to the parent path. The method will raise an error if the directory cannot be created.

Production Directory Setup Patterns

Standard Production Layout

python
from logly import logger

# Production root
logger.root_dir("/var/log/myapp")

# Application logs
logger.add(
    "app.log",
    level="INFO",
    rotation="daily",
    retention="30 days",
    compression="gzip",
)

# Error logs
logger.add(
    "errors.log",
    level="ERROR",
    rotation="daily",
    retention="90 days",
    compression="gzip",
)

# Access logs
logger.add(
    "access.log",
    level="INFO",
    rotation="daily",
    retention="7 days",
)

Multi-Service Layout

python
from logly import logger

logger.root_dir("/var/log/services")

# API service logs
logger.add("api/app.log", level="INFO", rotation="daily")
logger.add("api/errors.log", level="ERROR", rotation="daily")

# Worker service logs
logger.add("worker/app.log", level="INFO", rotation="daily")
logger.add("worker/errors.log", level="ERROR", rotation="daily")

# Gateway logs
logger.add("gateway/access.log", level="INFO", rotation="hourly")

Development Layout

python
from logly import logger
from pathlib import Path

# Use current directory for development
logger.root_dir(Path.cwd() / "logs")

logger.add("dev.log", level="DEBUG")
logger.add("errors.log", level="ERROR")

Environment Variable-Based Directory Configuration

python
import os
from logly import logger

# Configure log directory from environment
log_dir = os.environ.get("LOGLY_LOG_DIR", "/var/log/myapp")
logger.root_dir(log_dir)

logger.add(
    "app.log",
    level="INFO",
    rotation="daily",
    retention="30 days",
    compression="gzip",
)

Using Different Directories Per Environment

python
import os
from logly import logger

env = os.environ.get("APP_ENV", "development")

if env == "production":
    logger.root_dir("/var/log/myapp")
elif env == "staging":
    logger.root_dir("/var/log/myapp-staging")
else:
    logger.root_dir("./logs")

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

Docker/Kubernetes Setup

python
import os
from logly import logger

# In containers, use a mounted volume
log_dir = os.environ.get("LOGLY_LOG_DIR", "/var/log/app")
logger.root_dir(log_dir)

logger.add(
    "app.log",
    level="INFO",
    rotation="100 MB",
    retention="7 days",
    compression="gzip",
    enqueue=True,
)

Subdirectories

Automatic Subdirectory Creation

python
from logly import logger

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

# Creates subdirectories as needed
logger.add("modules/auth/auth.log")     # Creates modules/auth/
logger.add("modules/db/db.log")         # Creates modules/db/
logger.add("http/requests.log")         # Creates http/

Organized by Component

python
from logly import logger

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

# Web server logs
logger.add("web/access.log", level="INFO", rotation="daily")
logger.add("web/error.log", level="ERROR", rotation="daily")

# Database logs
logger.add("db/slow-queries.log", level="WARNING", rotation="daily")
logger.add("db/errors.log", level="ERROR", rotation="daily")

# Background worker logs
logger.add("worker/tasks.log", level="INFO", rotation="daily")
logger.add("worker/errors.log", level="ERROR", rotation="daily")

Complete Example

python
import os
from logly import logger

# Configure root directory from environment
log_root = os.environ.get("LOGLY_LOG_DIR", "/var/log/myapp")
logger.root_dir(log_root)

# Application logs
logger.add(
    "app.log",
    level="INFO",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level:<8} | {message}",
    rotation="daily",
    retention="30 days",
    compression="gzip",
    enqueue=True,
)

# Error logs
logger.add(
    "errors.log",
    level="ERROR",
    rotation="daily",
    retention="90 days",
    compression="gzip",
    enqueue=True,
)

# Debug logs (development only)
if os.environ.get("APP_ENV") != "production":
    logger.add(
        "debug.log",
        level="DEBUG",
        rotation="10 MB",
        retention=5,
    )

# Structured JSON logs
logger.add(
    "structured.json",
    level="WARNING",
    serialize=True,
    rotation="daily",
    retention="60 days",
    compression="gzip",
)

# Console output
logger.add("stderr", level="INFO", colorize=True)

# Log with context
logger.info("Application started in {}", os.environ.get("APP_ENV", "development"))
logger.complete()

Troubleshooting

Permission Denied

If root_dir() fails with a permission error, ensure the process has write access to the parent directory:

python
from logly import logger

try:
    logger.root_dir("/var/log/myapp")
except PermissionError:
    # Fall back to user directory
    logger.root_dir(os.path.expanduser("~/logs"))

Directory Already Exists

python
from logly import logger

# This is safe - root_dir won't fail if directory exists
logger.root_dir("/var/log/myapp")  # Works even if directory already exists

Path Does Not Exist Yet

python
from logly import logger

# root_dir creates the full path including parent directories
logger.root_dir("/var/log/myapp/subdir/deep")
# All directories are created automatically

Released under the MIT License.