defmodule NewRelic.Tracer do
@moduledoc """
Function Tracing
To enable function tracing in a particular module, `use NewRelic.Tracer`,
and annotate the functions you want to `@trace`.
Traced functions will report as:
- Segments in Transaction Traces
- Span Events in Distributed Traces
- Special custom attributes on Transaction Events
#### Notes:
* Traced functions will *not* be tail-call-recursive. **Don't use this for recursive functions**.
#### Example
```elixir
defmodule MyModule do
use NewRelic.Tracer
@trace :func
def func do
# Will report as `MyModule.func/0`
end
end
```
#### Categories
To categorize External Service calls you must give the trace annotation a category.
You may also call `NewRelic.set_span` to provide better naming for metrics & spans, and additonally annotate the outgoing HTTP headers with the Distributed Tracing context to track calls across services.
```elixir
defmodule MyExternalService do
use NewRelic.Tracer
@trace {:request, category: :external}
def request(method, url, headers) do
NewRelic.set_span(:http, url: url, method: method, component: "HttpClient")
headers ++ NewRelic.distributed_trace_headers(:http)
HttpClient.request(method, url, headers)
end
end
```
This will:
* Post `External` metrics to APM
* Add custom attributes to Transaction events:
- `external_call_count`
- `external_duration_ms`
- `external.MyExternalService.query.call_count`
- `external.MyExternalService.query.duration_ms`
Transactions that call the traced `ExternalService` functions will contain `external_call_count` attribute
```elixir
get "/endpoint" do
ExternalService.request(:get, url, headers)
send_resp(conn, 200, "ok")
end
```
#### Arguments
By default, arguments are inspected and recorded along with traces. You can opt-out of function argument tracing on individual tracers:
```elixir
defmodule SecretModule do
use NewRelic.Tracer
@trace {:login, args: false}
def login(username, password) do
# do something secret...
end
end
```
This will prevent the argument values from becoming part of Transaction Traces.
This may also be configured globally via `Application` config. See `NewRelic.Config` for details.
"""
defmacro __using__(_args) do
quote do
require NewRelic
require NewRelic.Tracer.Macro
require NewRelic.Tracer.Report
Module.register_attribute(__MODULE__, :nr_tracers, accumulate: true)
Module.register_attribute(__MODULE__, :nr_last_tracer, accumulate: false)
@before_compile NewRelic.Tracer.Macro
@on_definition NewRelic.Tracer.Macro
end
end
end