Better Stack Python logging

Start logging in 3 steps

Where do you want to collect your logs from?

Logging from Django

Collect logs from your Django application.

1. Install

Install Better Stack Python PyPI package:

Install logtail-python
pip3 install logtail-python

2. Setup

Set up Django Better Stack handler in settings.py:

Set up Better Stack handler
LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    'handlers': {
        'logtail': {
            'class': 'logtail.LogtailHandler',
            'source_token': '$SOURCE_TOKEN',
            'host': 'https://$INGESTING_HOST',
        },
    },
    "loggers": {
        "": {
            "handlers": [
                "logtail",
            ],
            "level": "INFO",
        },
    },
}


3. Start logging

Use Python logger as usual:

Send logs to Better Stack
import logging
logger = logging.getLogger(__name__)
logger.error('Something bad happened.')
logger.info('Log message with structured logging.', extra={
    'item': "Orange Soda",
    'price': 100.00
})

You should see your logs in Better Stack → Live tail.

Python 3.10 or higher is required

Pip version 20.0.2 or higher is required.

Logging from Python

Collect logs from your Python code.

1. Install

Install Better Stack Python PyPI package:

Install logtail-python
pip3 install logtail-python

2. Setup

Set up Python logger with Better Stack:

Set up Better Stack handler
from logtail import LogtailHandler
import logging

handler = LogtailHandler(
    source_token='$SOURCE_TOKEN', 
    host='https://$INGESTING_HOST',
)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
logger.handlers = []
logger.addHandler(handler)


3. Start logging

Use Python logger as usual:

Send logs to Better Stack
logger.error('Something bad happened.')
logger.info('Log message with structured logging.', extra={
    'item': "Orange Soda",
    'price': 100.00
})

You should see your logs in Better Stack → Live tail.

Python 3.10 or higher is required

Pip version 20.0.2 or higher is required.

Logging from RQ workers

RQ runs each job in a forked process that exits without the usual Python shutdown, so logs written inside a job would never be sent. The Better Stack worker class sends them before the job process exits.

1. Setup

Configure the logtail handler as in the Django or Python setup above.

2. Start the worker

Start RQ with the Better Stack worker class:

Start an RQ worker
rq worker --worker-class logtail.rq.Worker

With django-rq, set the worker class in settings.py instead:

Set the worker class for django-rq
RQ = {
    "WORKER_CLASS": "logtail.rq.Worker",
}

Logs from the worker process itself are sent as usual.

logtail-python 0.4.1 or higher is required

Older versions do not include the worker class.

Need help?

Please let us know at hello@betterstack.com.
We're happy to help! 🙏

Additional information

Interested in learning more about Python log levels and using formatters to customize your logs? Check out our Comprehensive Guide to Logging in Python.

Missing logs from the end of your application run?

Make sure your application terminates gracefully, giving the logger enough time to finish the request to Better Stack.

Use sys.exit() to end your application.

Using os._exit() would terminate all threads immediately, potentially dropping your logs.

Logs not arriving at all?

Errors while building a log record are dropped together with the record by default, so a misconfiguration can leave you with no logs and no error message. While debugging, set raise_exceptions to True to see the exception instead:

Raise handler errors while debugging
handler = LogtailHandler(
    source_token='$SOURCE_TOKEN',
    host='https://$INGESTING_HOST',
    raise_exceptions=True,
)


In Django, add 'raise_exceptions': True to the logtail handler in LOGGING.

Enrich log context

Add custom data to multiple log lines using with block:

Enrich logs with context

with logtail.context(user={ 'id': 123 }):
    logger.info('User logged in.')
    # More code here ...
    logger.info('User bought a python.')

Log exceptions

Use logger.exception() to log exceptions with traceback:

Log exception traceback
try:
    nonexisting_function()
except Exception as Argument:
    logger.exception("Error occurred while calling non-existing function.")

Handler options

Pass these as keyword arguments to LogtailHandler, or as keys of the logtail handler in Django LOGGING:

Option Default Description
host EU region Ingesting host of your source.
timeout 30 Seconds to wait for each request to Better Stack.
buffer_capacity 1000 Logs are sent in batches of up to this many records.
flush_interval 1 Seconds after which a batch is sent even if it is not full.
drop_extra_events True Drop new logs while the buffer is full. Set to False to block the application instead.
include_extra_attributes True Send every value passed in extra. Set to False to send only dictionaries.
raise_exceptions False Raise errors while building a log record instead of dropping the record.

Example project

Want to try a more detailed example?
See our Python example project on GitHub.