[[installation]]
== Installation

[source,cmd]
----
$ python -m pip install ecs-logging
----

[float]
[[gettingstarted]]
== Getting Started

`ecs-logging-python` has formatters for the standard library
https://docs.python.org/3/library/logging.html[`logging`] module
and the https://www.structlog.org/en/stable/[`structlog`] package.

[float]
[[logging]]
=== Standard Library `logging` Module

[source,python]
----
import logging
import ecs_logging

# Get the Logger
logger = logging.getLogger("app")
logger.setLevel(logging.DEBUG)

# Add an ECS formatter to the Handler
handler = logging.StreamHandler()
handler.setFormatter(ecs_logging.StdlibFormatter())
logger.addHandler(handler)

# Emit a log!
logger.debug("Example message!", extra={"http.request.method": "get"})
----

[source,json]
----
{
    "@timestamp": "2020-03-20T18:11:37.895Z",
    "log.level": "debug",
    "message": "Example message!",
    "ecs": {
        "version": "1.6.0"
    },
    "http": {
      "request": {
        "method": "get"
      }
    },
    "log": {
        "logger": "app",
        "origin": {
            "file": {
                "line": 14,
                "name": "test.py"
            },
            "function": "func"
        },
        "original": "Example message!"
    }
}
----

[float]
==== Excluding Fields

You can exclude fields from being collected by using the `exclude_fields` option
in the `StdlibFormatter` constructor:

[source,python]
----
from ecs_logging import StdlibFormatter

formatter = StdlibFormatter(
    exclude_fields=[
        # You can specify individual fields to ignore:
        "log.original",
        # or you can also use prefixes to ignore
        # whole categories of fields:
        "process",
        "log.origin",
    ]
)
----

[float]
==== Limiting Stack Traces

The `StdlibLogger` automatically gathers `exc_info` into ECS `error.*` fields.
If you'd like to control the number of stack frames that are included
in `error.stack_trace` you can use the `stack_trace_limit` parameter
(by default all frames are collected):

[source,python]
----
from ecs_logging import StdlibFormatter

formatter = StdlibFormatter(
    # Only collects 3 stack frames
    stack_trace_limit=3,
)
formatter = StdlibFormatter(
    # Disable stack trace collection
    stack_trace_limit=0,
)
----

[float]
[[structlog]]
=== Structlog Example

Note that the structlog processor should be the last processor in the list,
as it handles the conversion to JSON as well as the ECS field enrichment.

[source,python]
----
import structlog
import ecs_logging

# Configure Structlog
structlog.configure(
    processors=[ecs_logging.StructlogFormatter()],
    wrapper_class=structlog.BoundLogger,
    context_class=dict,
    logger_factory=structlog.PrintLoggerFactory(),
)

# Get the Logger
logger = structlog.get_logger("app")

# Add additional context
logger = logger.bind(**{
    "http": {
        "version": "2",
        "request": {
            "method": "get",
            "bytes": 1337,
        },
    },
    "url": {
        "domain": "example.com",
        "path": "/",
        "port": 443,
        "scheme": "https",
        "registered_domain": "example.com",
        "top_level_domain": "com",
        "original": "https://example.com",
    }
})

# Emit a log!
logger.debug("Example message!")
----

[source,json]
----
{
  "@timestamp": "2020-03-26T13:08:11.728Z",
  "ecs": {
    "version": "1.6.0"
  },
  "http": {
    "request": {
      "bytes": 1337,
      "method": "get"
    },
    "version": "2"
  },
  "log": {
    "level": "debug"
  },
  "message": "Example message!",
  "url": {
    "domain": "example.com",
    "original": "https://example.com",
    "path": "/",
    "port": 443,
    "registered_domain": "example.com",
    "scheme": "https",
    "top_level_domain": "com"
  }
}
----

[float]
[[correlation]]
== Elastic APM Log Correlation

`ecs-logging-python` supports automatically collecting  {ecs-ref}/ecs-tracing.html[ECS tracing fields]
from the https://github.com/elastic/apm-agent-python[Elastic APM Python agent] in order to
{apm-py-ref}/logs.html[correlate logs to spans, transactions and traces] in Elastic APM.

You can also quickly turn on ECS-formatted logs in your python app by setting
{apm-py-ref}/configuration.html#config-log_ecs_reformatting[`LOG_ECS_REFORMATTING=override`]
in the Elastic APM Python agent.

[float]
[[filebeat]]
== Install Filebeat

The best way to collect the logs once they are ECS-formatted is with https://www.elastic.co/beats/filebeat[Filebeat]:

include::{ecs-repo-dir}/setup.asciidoc[tag=configure-filebeat]
