Packages

A Datadog APM tracing library for Elixir: Datadog-native spans, per-process trace context, and Phoenix, Ecto and Req integrations.

Current section

Files

Jump to
Raw

mix.exs

defmodule DDTrace.MixProject do
use Mix.Project
@version "0.1.0"
@source_url "https://github.com/luisgabrielroldan/dd_trace_ex"
# OTP's own `:json` reads the agent's sampling-rate feedback, and it
# arrived in 27 (`.tool-versions` pins 28). Refused here, by name, rather
# than as an undefined-module error in the middle of a compile.
@otp_floor 27
def project do
if String.to_integer(System.otp_release()) < @otp_floor do
Mix.raise(
"dd_trace_ex needs Erlang/OTP #{@otp_floor} or later, found #{System.otp_release()}"
)
end
[
app: :dd_trace_ex,
version: @version,
elixir: "~> 1.19",
start_permanent: Mix.env() == :prod,
elixirc_paths: elixirc_paths(Mix.env()),
deps: deps(),
# Test fixtures are compiled like library code so their protocol impls
# are seen, which also puts them in front of the coverage tool. They
# are not the library.
#
# The floor belongs under `:summary` — that is what reads it. Written
# at the top level it is accepted, ignored, and silently replaced by
# mix's own default, so the gate would pass whatever it said.
test_coverage: [
summary: [threshold: 90],
ignore_modules: [~r/^DDTrace\.Support\./]
],
dialyzer: [
plt_local_path: "priv/plts",
plt_core_path: "priv/plts",
flags: [:error_handling, :extra_return, :missing_return, :unmatched_returns]
],
name: "dd_trace_ex",
description: description(),
package: package(),
source_url: @source_url,
aliases: aliases(),
docs: docs()
]
end
defp description do
"A Datadog APM tracing library for Elixir: Datadog-native spans, " <>
"per-process trace context, and Phoenix, Ecto and Req integrations."
end
# The file list is written out rather than left to hex's default, which
# takes all of `priv/` — and `priv/plts` is where dialyzer's tables live,
# twelve megabytes of local analysis cache that has no business in a
# release. Naming the files also means the setup guide ships, which the
# default list has no reason to know about.
#
# `.formatter.exs` is here because it exports `locals_without_parens` for
# `assert_span` and friends; an application that writes
# `import_deps: [:dd_trace_ex]` reads it from the package.
defp package do
[
licenses: ["MIT"],
links: %{"GitHub" => @source_url},
files: ~w(lib guides/setup.md .formatter.exs mix.exs README.md LICENSE)
]
end
def application do
[
# DDTrace.Test needs ExUnit, and only a test suite ever calls it.
extra_applications: extra_applications(),
mod: {DDTrace.Application, []}
]
end
# The headless OTP interpreter pauses real calls in concurrency tests.
# It is not a runtime dependency of the library.
defp extra_applications do
applications = [:logger, ex_unit: :optional]
if Mix.env() == :test, do: [:debugger, :tools | applications], else: applications
end
# Protocol implementations are consolidated before the suite runs, so a
# `defimpl` written in a `.exs` test file is never seen. Test fixtures that
# implement a protocol have to be compiled like library code.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_env), do: ["lib"]
defp deps do
[
{:msgpax, "~> 2.4"},
{:decorator, "~> 1.4", runtime: false},
{:finch, "~> 0.19"},
{:telemetry, "~> 1.0"},
# Test-only: the integration is proven by driving a real Phoenix
# pipeline, and the library itself depends on neither. Event metadata
# and the conn are read structurally.
{:phoenix, "~> 1.7", only: :test},
{:plug, "~> 1.15", only: :test},
# Test-only for the same reason: the Ecto integration is proven by
# driving real queries through a real repo. Adapter modules are
# matched as atoms and repo functions called duck-typed, so the
# library depends on neither Ecto nor any driver.
{:ecto_sql, "~> 3.10", only: :test},
{:ecto_sqlite3, "~> 0.17", only: :test},
# Test-only again: the Req integration is proven by driving real
# requests through Req's own step pipeline. The request struct is
# matched structurally and the steps are plain functions, so the
# library does not depend on Req.
{:req, "~> 0.5", only: :test},
{:jason, "~> 1.4", only: [:dev, :test]},
{:ex_doc, "~> 0.34", only: :dev, runtime: false},
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}
]
end
# The snapshot tests need the dd-apm-test-agent container; `test/README.md`
# says how to start it. The load harness needs the same container;
# `bench/load.exs` says what it measures.
defp aliases do
["test.agent": ["test --include agent"], bench: ["run bench/load.exs"]]
end
# An alias that runs the suite has to say so, or mix refuses to run it
# outside the test environment.
def cli, do: [preferred_envs: ["test.agent": :test]]
defp docs do
[
main: "DDTrace",
source_ref: "v#{@version}",
source_url: @source_url,
extras: ["README.md", "guides/setup.md", "LICENSE"],
groups_for_modules: groups_for_modules()
]
end
# Grouped by what a reader is doing when they need the module, so the
# sidebar answers "where do I look" rather than listing ten names
# alphabetically. `DDTrace` itself stays ungrouped: it is the entry point
# and the docs' main page.
defp groups_for_modules do
[
Tracing: [DDTrace.Decorators],
"Crossing processes": [DDTrace.Task, DDTrace.Task.Supervisor, DDTrace.SpanContext],
"Reading a span": [DDTrace.Span],
"Keys and values": [DDTrace.Tags, DDTrace.Priority, DDTrace.Kind],
Integrations: [
DDTrace.Integrations.Phoenix,
DDTrace.Integrations.Ecto,
DDTrace.Integrations.Req,
DDTrace.Integrations.HTTP
],
Testing: [DDTrace.Test],
Configuration: [DDTrace.Config]
]
end
end