# Setting up the tracer

This guide walks a new application from zero to traces in Datadog: add
the dependency, point the tracer at an agent, name the service, and turn
on the integrations. Every setting named here is described in full in
`DDTrace.Config` — that module is the reference; this page is the path
through it.

## Install

Add the dependency:

```elixir
# mix.exs
defp deps do
  [
    {:dd_trace_ex, "~> 0.1.0"}
  ]
end
```

That is the whole installation. `dd_trace_ex` is an OTP application that
starts with your release: there is no tracer module to define, no child
to add to your supervision tree, and no `use` line in your application.
Code that calls the `trace/2` macro needs a `require DDTrace` (or an
`import`); everything else on the module is plain functions.

## Point it at an agent

Spans travel to a [Datadog agent](https://docs.datadoghq.com/agent/),
which forwards them to Datadog. The tracer assumes the standard address,
`http://localhost:8126`, so a host with a local agent needs nothing
configured.

When the agent lives elsewhere — another container, a sidecar, a node
port — say where, either way:

```elixir
config :dd_trace_ex, agent_url: "http://datadog-agent:8126"
```

or through the environment the agent's own images already speak:
`DD_TRACE_AGENT_URL`, or `DD_AGENT_HOST` and `DD_TRACE_AGENT_PORT`.
Only `http://` URLs are supported.

An unreachable agent never harms the application: submissions fail, the
failure is logged, and the request that produced the spans is unaffected.

## Name the service

Three values identify everything the tracer sends — the service's name,
its deployment environment, and its version. Datadog calls this
[unified service tagging](https://docs.datadoghq.com/getting_started/tagging/unified_service_tagging/).

```elixir
# config/runtime.exs
config :dd_trace_ex, service: "storefront"
```

The same three arrive as `DD_SERVICE`, `DD_ENV` and `DD_VERSION` with no
config at all — every setting resolves from application config first,
then its `DD_*` environment variable, then its default. Application
config wins, matching the other Datadog tracers. Naming the service in
config and leaving `env` and `version` to the environment is the usual
split: the name is the application's to state, and the other two are
facts about the deployment.

A tracer configured with no service ships spans as
`unnamed-elixir-service`: visible in the UI, and there to be recognized
as a tracer nobody configured.

## Verify

The tracer logs its resolved settings in one line at boot:

    [info] dd_trace_ex started, config: %{service: "storefront", env: "prod", ...}

The same facts are available on demand from `DDTrace.info/0`. Then open
a span and watch it arrive:

```elixir
require DDTrace

DDTrace.trace "smoke.test" do
  :ok
end
```

Spans buffer and flush on a cadence, so give it a few seconds before
looking for the trace in Datadog's UI.

## Trace Phoenix requests

One call at startup, before the endpoint:

```elixir
# lib/my_app/application.ex
def start(_type, _args) do
  DDTrace.Integrations.Phoenix.setup()

  children = [MyAppWeb.Endpoint, ...]
  Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)
end
```

Every request becomes a `"phoenix.request"` span, resourced by its route
pattern, carrying the standard `http.*` tags, and joined to the caller's
trace when the request arrived with `x-datadog-*` headers.
`DDTrace.Integrations.Phoenix` documents the options: a `filter:` for
health checks, a `request:` hook for custom tags, and what the endpoint
has to have (the `Plug.Telemetry` line every generated endpoint already
contains).

## Trace Ecto queries

One call per repo, also at startup:

```elixir
DDTrace.Integrations.Ecto.setup(repo: MyApp.Repo)
```

Every query becomes a span with the SQL as its resource, the
connection's `db.*` tags, and Ecto's queue/query/decode breakdown as
numeric metrics, landing under whatever trace the query ran inside.
`DDTrace.Integrations.Ecto` documents the options and the decisions
behind them — most notably that bind parameters never leave the
database.

## Trace outbound Req requests

One call where the client is built:

```elixir
req =
  Req.new(base_url: "https://api.github.com")
  |> DDTrace.Integrations.Req.attach()

Req.get!(req, url: "/repos/elixir-lang/elixir")
```

Every request through an attached client becomes an `"http.request"`
span under whatever trace it ran inside, with the `x-datadog-*` headers
injected before it goes out, so the service on the other end continues
the trace. A client you do not attach is not traced.
`DDTrace.Integrations.Req` documents the options and what counts as an
error — the 4xx window, the inverse of the server's.

## Trace your own functions

The `trace/2` block macro is the primitive; the decorator is the same
span without restructuring the function:

```elixir
defmodule MyApp.Orders do
  use DDTrace.Decorators

  @decorate trace()
  def process(order) do
    DDTrace.set_tag("order.channel", order.channel)
    # ...
  end
end
```

See `DDTrace` for the block macro, the mutators, and crossing processes;
`DDTrace.Decorators` for decorating whole modules.

## Continue traces across services

Outbound, an attached Req client injects the trace's headers by itself.
Any other HTTP client carries the trace the same way, by hand:

```elixir
headers = DDTrace.inject([{"content-type", "application/json"}])
Finch.build(:post, url, headers, body) |> Finch.request(MyApp.Finch)
```

Inbound, the Phoenix integration extracts automatically. A non-HTTP
entry point extracts by hand with `DDTrace.extract/1` and opens its span
with `parent:`.

## Correlate logs with traces

While a span is open, the process's `Logger` metadata carries the
`dd.trace_id` family of keys, which Datadog's UI uses to link a log line
to its trace. Any JSON logger that emits metadata gets this for free. A
`metadata:` allowlist has to spell the keys as the quoted atoms they are:

```elixir
config :logger, :default_formatter,
  metadata: [:request_id, :"dd.trace_id", :"dd.span_id", :"dd.service"]
```

`metadata: :all` needs no list. `DDTrace.Config` has the full story,
including turning injection off.

## Assert on spans in tests

`use DDTrace.Test` in a test module captures every span the test
finishes — no agent involved — and imports `assert_span` and friends:

```elixir
use ExUnit.Case, async: true
use DDTrace.Test

test "processing an order is traced" do
  MyApp.Orders.process(order)

  assert_span "order.process", resource: "ImportOrders"
end
```

`DDTrace.Test` documents the matchers and how spans find their test
across processes.

## Every setting

The table in `DDTrace.Config` lists every setting, its `DD_*` variable,
and its default — tracing on/off, the agent address, log injection, the
`x-datadog-tags` budget, which HTTP statuses count as errors, and the
shutdown flush budget. Bad configuration degrades the tracer; it never
stops the host application from booting.
