Atatus Python APM Agent allows you to correlate application logs with traces by automatically adding identifiers such as trace.id, transaction.id, and span.id. This makes it easier to move from a log entry to the exact trace or error inside the Atatus dashboard.

Log Correlation

Log correlation lets you trace individual requests across systems by automatically adding correlation identifiers (trace, transaction, and span IDs) to your logs. With log correlation enabled, the Atatus Python Agent automatically injects these identifiers into your application logs:

Field Description
trace.id Uniquely identifies a request across distributed services
transaction.id Marks the primary transaction being traced
span.id Refers to the specific operation within a transaction

These IDs connect your logs with traces, making it easy to jump from a log entry to its related transaction in the Atatus dashboard.

How Log Correlation Works in Atatus

Atatus integrates with the built-in Python logging module to:

  • Automatically add correlation fields to log records
  • Support plain-text and structured logs (JSON)
  • Keep original log format intact while appending tracing metadata

Setting Up Log Correlation in Python

Use the AtatusFormatter to enrich logs with trace context.

from logging import getLogger, StreamHandler, DEBUG
from atatus.handlers.logging import LoggingFilter, Formatter as AtatusFormatter

# Configure handler (StreamHandler or FileHandler)
handler = StreamHandler()  # or FileHandler("app.log")

# Add LoggingFilter only if Python version < 3.2
handler.addFilter(LoggingFilter())

# Add Atatus Formatter to inject trace, transaction & span IDs
handler.setFormatter(
    AtatusFormatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
)

# Setup logger
logger = getLogger(__name__)
logger.addHandler(handler)
logger.setLevel(DEBUG)

logger.info("This is a log with Atatus trace context")
logger.error("Integration failed")

Example log output:

2025-01-01 12:00:00 - app - INFO - This is a log with Atatus trace context | atatus trace.id=abc123 transaction.id=xyz456 span.id=789def
2025-01-01 12:00:01 - app - ERROR - Integration failed | atatus trace.id=abc123 transaction.id=xyz456 span.id=789def

Structlog Integration

For applications using structlog, the Atatus agent provides a dedicated processor that adds correlation identifiers to structured log events.

from structlog import wrap_logger
from structlog.processors import JSONRenderer
from atatus.handlers.structlog import structlog_processor

logger = wrap_logger(
    logger=None,
    processors=[structlog_processor, JSONRenderer()]
)

logger.info("user_logged_in", user_id=123)

Using Custom Formatters

If you’re not using structured logging, you can still include APM identifiers by using the Atatus-provided Formatter.

import logging
from atatus.handlers.logging import Formatter as AtatusFormatter

# Create file handler
fh = logging.FileHandler('custom.log')

# Apply Atatus Formatter to inject APM identifiers
formatter = AtatusFormatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
fh.setFormatter(formatter)

This formatter automatically extends your format string by including the Atatus APM identifiers:

%(asctime)s - %(name)s - %(levelname)s - %(message)s |
atatus transaction.id=%(atatus_transaction_id)s
trace.id=%(atatus_trace_id)s
span.id=%(atatus_span_id)s

To extract these APM identifiers from plaintext logs, configure a Grok processor in your Elasticsearch ingest pipeline or Logstash configuration.

Example Grok Pattern:

{
  "description": "Extract Atatus APM correlation identifiers from log messages",
  "processors": [
    {
      "grok": {
        "field": "message",
        "patterns": [
          "%{GREEDYDATA:msg} \\| atatus transaction.id=%{DATA:transaction.id} trace.id=%{DATA:trace.id} span.id=%{DATA:span.id}"
        ]
      }
    }
  ]
}