A Datadog APM tracing library for Elixir.
dd_trace_ex (top-level module DDTrace) is written to match what
Datadog's official dd-trace libraries do. It sends traces to the Datadog
agent in the same format they do, so features like 128-bit trace IDs,
numeric metrics, tracing across services, sampling and manual keep or drop
all behave the way Datadog users expect. dd-trace-js and dd-trace-go were
the reference for how things should work on the wire. Tracing context
lives in the process and follows work into other processes, the API is
small and built around a single trace call, and Phoenix, Ecto and Req
are supported through :telemetry. It is still early, but the core is in
place.
Status:
0.1.0release candidate. This is a first public release, not a mature library: it covers a documented subset of Datadog tracing (see Current limitations), and the API may still change before1.0.
Installation
Add dd_trace_ex to your dependencies:
# mix.exs
defp deps do
[
{:dd_trace_ex, "~> 0.1.0"}
]
endRun mix deps.get, then configure your service and agent connection:
# config/runtime.exs
config :dd_trace_ex,
service: "my_app",
agent_url: "http://localhost:8126"The tracer starts automatically with your application. You need a Datadog Agent with APM enabled to receive the traces. See the setup guide for environment variables and integration setup.
Trace application code
Wrap work in DDTrace.trace. Tags and metrics describe the span being traced:
require DDTrace
DDTrace.trace "orders.import" do
DDTrace.set_tag("order.channel", "web")
DDTrace.set_metric("orders.count", length(orders))
MyApp.Orders.import(orders)
endThe block returns its result. Nested calls create child spans. Exceptions that escape the block are recorded on the span and re-raised.
For a function you want to trace on every call, use a decorator:
defmodule MyApp.Orders do
use DDTrace.Decorators
@decorate trace(name: "orders.import")
def import(orders) do
DDTrace.set_metric("orders.count", length(orders))
# ...
end
endDDTrace.with_trace/3 takes a function when that fits better than a block.
Integrations
Enable Phoenix and Ecto tracing at application startup, before starting your endpoint and repo:
DDTrace.Integrations.Phoenix.setup()
DDTrace.Integrations.Ecto.setup(repo: MyApp.Repo)Phoenix request spans include the route, HTTP status, and incoming trace context. Ecto query spans include SQL and timing information; bind parameter values are excluded.
For Req, attach tracing when building the client:
req =
Req.new(base_url: "https://inventory.example.com")
|> DDTrace.Integrations.Req.attach()
Req.get!(req, url: "/items")Requests through that client produce spans and carry Datadog trace headers to the receiving service.
Trace work across processes
Use DDTrace.Task to carry the current trace into tasks. Create spans
inside the task for the work you want to measure:
require DDTrace
DDTrace.trace "orders.import" do
orders
|> DDTrace.Task.async_stream(fn order ->
DDTrace.trace "order.process" do
MyApp.Orders.process(order)
end
end)
|> Enum.to_list()
endFor messages, GenServers, and other process boundaries, capture the context
with DDTrace.current_context/0 and pass it to the receiving process. Use
parent: when opening its span.
Sampling and logs
The tracer uses sampling rates supplied by the agent. You can also
configure sampling rules or a fixed rate, and override the decision with
DDTrace.keep_trace/0 or DDTrace.drop_trace/0. Dropped traces still reach
the agent; dropping controls retention.
While a span is open, trace and span IDs are available in Logger
metadata. Include these fields in your JSON logs for Datadog log
correlation.
See the setup guide for configuration and logging examples.
Testing
Capture spans in ExUnit without running an agent:
defmodule MyApp.OrdersTest do
use ExUnit.Case, async: true
use DDTrace.Test
test "imports are traced" do
MyApp.Orders.import([])
assert_span "orders.import"
end
endCurrent limitations
- Agent connections support HTTP only; HTTPS and Unix sockets are not supported.
- Sampling applies to whole traces. Keeping individual spans from sampled-out traces is not supported.
- Sampled-out traces are still sent to the agent. The library does not compute APM statistics locally.
License
MIT. See LICENSE.
dd_trace_ex is an independent project. It is not affiliated with,
endorsed by, or sponsored by Datadog, Inc. "Datadog" and "dd-trace" are
trademarks of Datadog, Inc., used here only to describe what this library
interoperates with.