newrelic / newrelic/elixir_agent
Absinthe transaction naming is applied on the success path only, so exceptions report under the endpoint default name
Nobody has claimed this yet.
- Dominant language
- Elixir
- Stars
- 268
- Forks
- 107
- Avg merge
- 9h 5m
- Merged PRs (30d)
- 2
Description
Summary
NewRelic.Telemetry.Absinthe names the transaction from [:absinthe, :execute, :operation, :stop]. Absinthe emits that event from a pipeline phase (Absinthe.Phase.Telemetry), not from :telemetry.span/3. Anything that unwinds the pipeline instead of returning a result skips the phase, so the event never fires and framework_name is never set.
The result is that GraphQL transaction naming is applied on the success path only. Every uncaught resolver exception reports under the endpoint default name (WebTransaction/Phoenix/MyApp.Endpoint/POST for a forwarded route) instead of the operation.
In our production app this is total: across ~120M named GraphQL transactions over three days, not one is flagged error IS true. Every GraphQL exception sits in the fallback bucket. "Which operation is failing?" is unanswerable from the transaction name.
Requests whose process is killed mid-flight (client disconnect) are unnamed for the same reason.
Validation and parse errors are not affected — those jump to Phase.Document.Result and still reach the stop phase.
Versions
new_relic_agent1.41.0absinthe1.11.0
Reproduction
Mix.install([{:absinthe, "1.11.0"}, {:telemetry, "~> 1.0"}])
defmodule Sch do
use Absinthe.Schema
query do
field :ok_field, :string, resolve: fn _, _ -> {:ok, "fine"} end
field :boom, :string, resolve: fn _, _ -> raise "boom" end
end
end
:telemetry.attach_many(
:probe,
[[:absinthe, :execute, :operation, :start], [:absinthe, :execute, :operation, :stop]],
fn event, _, _, _ -> IO.inspect(List.last(event), label: "operation") end,
nil
)
pipeline = Absinthe.Pipeline.for_document(Sch, [])
Absinthe.Pipeline.run("query { okField }", pipeline)
# operation: :start
# operation: :stop <- named
try do
Absinthe.Pipeline.run("query { boom }", pipeline)
rescue
_ -> :ok
end
# operation: :start
# <- no :stop, so no framework_name, so no transaction name
Root cause
Absinthe emits no :exception event for operations or for field resolution. Its telemetry documentation lists one only for middleware.batch. So there is no event the agent could subscribe to instead.
Possible fixes
- Name the transaction from something that survives an unwind. The
:startevent fires beforePhase.Parse, so no operation exists there — the agent would need a hook afterPhase.Document.CurrentOperation. - Raise the missing
:exceptionevent with Absinthe, then handle it here. - Document the gap, so users know exception attribution needs a workaround.
Workaround we use
An Absinthe phase inserted before Absinthe.Phase.Document.Execution.Resolution that computes the same name and calls NewRelic.set_transaction_name/1. It duplicates the agent's private transaction_name/2 and collect_deepest_path/1, which we would rather not maintain — hence this issue.
Happy to open a PR if you have a preferred direction.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading NewRelic.Telemetry.Absinthe and Absinthe.Phase.Telemetry, then run the Mix.install reproduction for successful and unwound operations. Compare the available telemetry points and choose a direction for naming transactions on exceptions; done means resolver exceptions and client-disconnect unwinds receive the operation name without regressing validation or parse errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- elixir
- Domain
- api, backend-api-design
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100