Repository: newrelic/elixir_agent (elixir)

Issue:
Nested segments
As far I see in the code, there is no support for nested segments for Transactions. Example:
```
defmodule MyMod do
  use NewRelic.Tracer

@trace :outer
def outer() do
  :timer.sleep(1000)
  inner()
end

@trace :inner
def inner() do
  :timer.sleep(1000)
  :ok
  end
end
```

The segments will be sent to NewRelic in flat namespace, i.e there will be no indication that the `inner` function is nested in `outer` part. It may lead to confusing data displayed in the `Transaction traces` in the `Trace details` tab. 


Most likely I will develop this feature in the `elixir-agent` plugin for our purposes (and maybe create PR here later on). Hence my question is:
Where can I find the documentation of REST API of the NewRelic?
I mean the API that the plugin uses for pushing transactions, segments and spans.
I believe there is a support for nested segments in NewRelic in general, so how would look like http  request ?


Pull request:
Improved function and process nesting
This PR improves:
* Function tracers - will be nested inside eachother within the process they are called inside
* Process tracking - processes will be nested mirroring the structure of how they were spawned

These improvements apply to:
* Transaction Traces
* Distributed Traces & Spans

sidekick/ @mattbaker !
closes #18 

Patch:
diff --git a/lib/new_relic/distributed_trace.ex b/lib/new_relic/distributed_trace.ex
index f96e6ee..61c3a69 100644
--- a/lib/new_relic/distributed_trace.ex
+++ b/lib/new_relic/distributed_trace.ex
@@ -69,24 +69,27 @@ defmodule NewRelic.DistributedTrace do
     Process.get(:nr_current_span_attrs) || %{}
   end
 
-  def set_current_span(mfa: mfa) do
-    Process.put(:nr_current_span, mfa)
+  def set_current_span(label: label, ref: ref) do
+    current = {label, ref}
+    previous = Process.get(:nr_current_span)
+    Process.put(:nr_current_span, current)
+    {current, previous}
   end
 
   def get_current_span_guid() do
     case Process.get(:nr_current_span) do
       nil -> generate_guid(pid: self())
-      mfa -> generate_guid(pid: self(), mfa: mfa)
+      {label, ref} -> generate_guid(pid: self(), label: label, ref: ref)
     end
   end
 
-  def clear_current_span() do
-    Process.delete(:nr_current_span)
+  def reset_span(previous: previous) do
+    Process.put(:nr_current_span, previous)
   end
 
   def generate_guid(), do: :crypto.strong_rand_bytes(8) |> Base.encode16() |> String.downcase()
   def generate_guid(pid: pid), do: encode_guid([pid, node()])
-  def generate_guid(pid: pid, mfa: mfa), do: encode_guid([mfa, pid, node()])
+  def generate_guid(pid: pid, label: label, ref: ref), do: encode_guid([label, ref, pid, node()])
 
   def encode_guid(segments) when is_list(segments) do
     segments
diff --git a/lib/new_relic/harvest/collector/span_event/harvester.ex b/lib/new_relic/harvest/collector/span_event/harvester.ex
index 1553387..4bc1756 100644
--- a/lib/new_relic/harvest/collector/span_event/harvester.ex
+++ b/lib/new_relic/harvest/collector/span_event/harvester.ex
@@ -28,11 +28,20 @@ defmodule NewRelic.Harvest.Collector.SpanEvent.Harvester do
 
   # API
 
+  # Label is any term that identifies the thing the span represents
+  #  ex: {m, f, a} for a function call
+  # Reference identifies the unique instance of the span
+  #  ex: make_ref()
+
+  @type label :: any
+  @type span :: {label, reference}
+  @type parent :: {label, reference} | :root
+
   def report_span(
         timestamp_ms: timestamp_ms,
         duration_s: duration_s,
         name: name,
-        mfa: mfa,
+        edge: [span: _span, parent: _parent] = edge,
         category: category,
         attributes: attributes
       ) do
@@ -43,7 +52,7 @@ defmodule NewRelic.Harvest.Collector.SpanEvent.Harvester do
       category: category,
       category_attributes: attributes
     }
-    |> report_span_event(DistributedTrace.get_tracing_context(), mfa)
+    |> report_span_event(DistributedTrace.get_tracing_context(), edge)
   end
 
   def report_span_event(%Event{} = _event, nil = _context, _mfa), do: :no_transaction
@@ -51,11 +60,16 @@ defmodule NewRelic.Harvest.Collector.SpanEvent.Harvester do
   def report_span_event(%Event{} = _event, %DistributedTrace.Context{sampled: false}, _mfa),
     do: :not_sampled
 
-  def report_span_event(%Event{} = event, %DistributedTrace.Context{sampled: true} = context, mfa) do
+  def report_span_event(
+        %Event{} = event,
+        %DistributedTrace.Context{sampled: true} = context,
+        span: span,
+        parent: parent
+      ) do
     event
     |> Map.merge(%{
-      guid: DistributedTrace.generate_guid(pid: self(), mfa: mfa),
-      parent_id: DistributedTrace.generate_guid(pid: self()),
+      guid: generate_guid(span),
+      parent_id: generate_guid(parent),
       trace_id: context.trace_id,
       transaction_id: context.guid,
       sampled: true,
@@ -120,6 +134,11 @@ defmodule NewRelic.Harvest.Collector.SpanEvent.Harvester do
     log_harvest(length(spans))
   end
 
+  def generate_guid(:root), do: DistributedTrace.generate_guid(pid: self())
+
+  def generate_guid({label, ref}),
+    do: DistributedTrace.generate_guid(pid: self(), label: label, ref: ref)
+
   def log_harvest(harvest_size) do
     NewRelic.report_metric({:supportability, SpanEvent}, harvest_size: harvest_size)
     NewRelic.log(:info, "Completed Span Event harvest - size: #{harvest_size}")
diff --git a/lib/new_relic/span/event.ex b/lib/new_relic/span/event.ex
index 657698c..21a204d 100644
--- a/lib/new_relic/span/event.ex
+++ b/lib/new_relic/span/event.ex
@@ -1,27 +1,29 @@
 defmodule NewRelic.Span.Event do
+  # Struct for a Span Event
+  #
+  # * trace_id: Distributed Trace ID
+  #   - trace_id from Transaction
+  # * guid: Segment Identifier
+  # * parent_id: Segment's Parent's GUID
+  #   - id of incoming DT payload OR `guid` of parent segment
+  # * transaction_id: Transaction's guid
+  # * timestamp: Segment start in unix timestamp milliseconds
+  # * duration: Segment elapsed in seconds
+  # * category: http | datastore | generic
+  # * entry_point: Only included if span is First segment
+
   defstruct type: "Span",
             trace_id: nil,
-            # Distributed Trace ID
-            #  = trace_id from Transaction
             guid: nil,
-            # Segment Identifier:
             parent_id: nil,
-            # Segment's Parent's GUID =
-            #   id of incoming DT payload
-            #   OR `guid` of parent segment
             transaction_id: nil,
-            # Transaction's guid
             sampled: nil,
             priority: nil,
             timestamp: nil,
-            # Segment start in unix timestamp milliseconds
             duration: nil,
-            # Segment elapsed in seconds
             name: nil,
             category: nil,
-            # http | datastore | generic
             entry_point: false,
-            # Included if span is First segment
             category_attributes: %{}
 
   @moduledoc false
diff --git a/lib/new_relic/tracer/macro.ex b/lib/new_relic/tracer/macro.ex
index 6f7a15e..4c33f4f 100644
--- a/lib/new_relic/tracer/macro.ex
+++ b/lib/new_relic/tracer/macro.ex
@@ -152,20 +152,23 @@ defmodule NewRelic.Tracer.Macro do
       start_time = System.system_time()
       start_time_mono = System.monotonic_time()
 
-      NewRelic.DistributedTrace.set_current_span(
-        mfa: {unquote(module), unquote(function), unquote(length(args))}
-      )
+      {span, previous_span} =
+        NewRelic.DistributedTrace.set_current_span(
+          label: {unquote(module), unquote(function), unquote(length(args))},
+          ref: make_ref()
+        )
 
       try do
         unquote(body)
       after
         end_time_mono = System.monotonic_time()
-        NewRelic.DistributedTrace.clear_current_span()
+        NewRelic.DistributedTrace.reset_span(previous: previous_span)
 
         Tracer.Report.call(
           {unquote(module), unquote(function), unquote(build_call_args(args))},
           unquote(trace_info),
           inspect(self()),
+          {span, previous_span || :root},
           {start_time, start_time_mono, end_time_mono}
         )
       end
diff --git a/lib/new_relic/tracer/report.ex b/lib/new_relic/tracer/report.ex
index b46389a..44c8bff 100644
--- a/lib/new_relic/tracer/report.ex
+++ b/lib/new_relic/tracer/report.ex
@@ -14,6 +14,7 @@ defmodule NewRelic.Tracer.Report do
         {module, function, args},
         {name, category: :datastore},
         pid,
+        {id, parent_id},
         {start_time, start_time_mono, end_time_mono}
       ) do
     duration_ms = duration_ms(start_time_mono, end_time_mono)
@@ -27,6 +28,8 @@ defmodule NewRelic.Tracer.Report do
       name: name,
       args: args,
       pid: pid,
+      id: id,
+      parent_id: parent_id,
       start_time: start_time,
       start_time_mono: start_time_mono,
       end_time_mono: end_time_mono
@@ -36,7 +39,7 @@ defmodule NewRelic.Tracer.Report do
       timestamp_ms: start_time,
       duration_s: duration_s,
       name: function_name({module, function, arity}, name),
-      mfa: {module, function, arity},
+      edge: [span: id, parent: parent_id],
       category: "datastore",
       attributes: Map.put(NewRelic.DistributedTrace.get_span_attrs(), :args, inspect(args))
     )
@@ -68,6 +71,7 @@ defmodule NewRelic.Tracer.Report do
         {module, function, args},
         {name, category: :external},
         pid,
+        {id, parent_id},
         {start_time, start_time_mono, end_time_mono}
       ) do
     duration_ms = duration_ms(start_time_mono, end_time_mono)
@@ -81,6 +85,8 @@ defmodule NewRelic.Tracer.Report do
       name: name,
       args: args,
       pid: pid,
+      id: id,
+      parent_id: parent_id,
       start_time: start_time,
       start_time_mono: start_time_mono,
       end_time_mono: end_time_mono
@@ -90,7 +96,7 @@ defmodule NewRelic.Tracer.Report do
       timestamp_ms: System.convert_time_unit(start_time, :native, :milliseconds),
       duration_s: duration_s,
       name: function_name({module, function, arity}, name),
-      mfa: {module, function, arity},
+      edge: [span: id, parent: parent_id],
       category: "http",
       attributes: Map.put(NewRelic.DistributedTrace.get_span_attrs(), :args, inspect(args))
     )
@@ -117,7 +123,13 @@ defmodule NewRelic.Tracer.Report do
     )
   end
 
-  def call({module, function, args}, name, pid, {start_time, start_time_mono, end_time_mono})
+  def call(
+        {module, function, args},
+        name,
+        pid,
+        {id, parent_id},
+        {start_time, start_time_mono, end_time_mono}
+      )
       when is_atom(name) do
     duration_ms = duration_ms(start_time_mono, end_time_mono)
     duration_s = duration_ms / 1000
@@ -130,6 +142,8 @@ defmodule NewRelic.Tracer.Report do
       name: name,
       args: args,
       pid: pid,
+      id: id,
+      parent_id: parent_id,
       start_time: start_time,
       start_time_mono: start_time_mono,
       end_time_mono: end_time_mono
@@ -139,7 +153,7 @@ defmodule NewRelic.Tracer.Report do
       timestamp_ms: System.convert_time_unit(start_time, :native, :milliseconds),
       duration_s: duration_s,
       name: function_name({module, function, arity}, name),
-      mfa: {module, function, arity},
+      edge: [span: id, parent: parent_id],
       category: "generic",
       attributes: Map.put(NewRelic.DistributedTrace.get_span_attrs(), :args, inspect(args))
     )
diff --git a/lib/new_relic/transaction/reporter.ex b/lib/new_relic/transaction/reporter.ex
index 9863e4e..e6e2039 100644
--- a/lib/new_relic/transaction/reporter.ex
+++ b/lib/new_relic/transaction/reporter.ex
@@ -106,7 +106,7 @@ defmodule NewRelic.Transaction.Reporter do
         original,
         pid,
         trace_process_spawns: {:list, {pid, timestamp, original}},
-        trace_process_names: {:list, {pid, process_name(pid)}}
+        trace_process_names: {:list, {pid, NewRelic.Util.process_name(pid)}}
       )
     end
   end
@@ -166,14 +166,6 @@ defmodule NewRelic.Transaction.Reporter do
     report_span_events(span_events)
   end
 
-  defp process_name(pid) do
-    case Process.info(pid, :registered_name) do
-      nil -> nil
-      {:registered_name, []} -> nil
-      {:registered_name, name} -> name
-    end
-  end
-
   defp gather_transaction_info(tx_attrs, pid) do
     tx_attrs
     |> transform_name_attrs
@@ -224,15 +216,7 @@ defmodule NewRelic.Transaction.Reporter do
       |> Enum.map(&transform_trace_name_attrs/1)
       |> Enum.map(&struct(Transaction.Trace.Segment, &1))
       |> Enum.group_by(& &1.pid)
-
-    process_segments =
-      process_spawns
-      |> collect_process_segments(process_names, process_exits)
-      |> Enum.map(&transform_trace_time_attrs(&1, tx_attrs.start_time))
-      |> Enum.map(&transform_trace_name_attrs/1)
-      |> Enum.map(&struct(Transaction.Trace.Segment, &1))
-      |> Enum.filter(&function_segments[&1.pid])
-      |> Enum.map(&Map.put(&1, :children, function_segments[&1.pid]))
+      |> Enum.into(%{}, &generate_process_segment_tree(&1))
 
     top_segment =
       tx_attrs
@@ -242,9 +226,20 @@ defmodule NewRelic.Transaction.Reporter do
       |> Enum.map(&transform_trace_name_attrs/1)
       |> Enum.map(&struct(Transaction.Trace.Segment, &1))
       |> List.first()
+      |> Map.put(:id, pid)
 
-    top_children = List.wrap(function_segments[tx_attrs.pid]) ++ process_segments
-    top_segment = Map.put(top_segment, :children, top_children)
+    top_segment =
+      process_spawns
+      |> collect_process_segments(process_names, process_exits)
+      |> Enum.map(&transform_trace_time_attrs(&1, tx_attrs.start_time))
+      |> Enum.map(&transform_trace_name_attrs/1)
+      |> Enum.map(&struct(Transaction.Trace.Segment, &1))
+      |> Enum.sort_by(& &1.relative_start_time)
+      |> Enum.map(&Map.put(&1, :children, function_segments[&1.pid] || []))
+      |> generate_process_tree(root: top_segment)
+
+    top_children = List.wrap(function_segments[inspect(pid)])
+    top_segment = Map.update!(top_segment, :children, &(&1 ++ top_children))
 
     {[top_segment], tx_attrs, tx_error, span_events}
   end
@@ -270,27 +265,6 @@ defmodule NewRelic.Transaction.Reporter do
 
   defp add_cowboy_process_event(spans, _tx_attrs, _pid), do: spans
 
-  defp report_caller_metric(
-         %{
-           "parent.type": parent_type,
-           "parent.account": parent_account_id,
-           "parent.app": parent_app_id,
-           "parent.transportType": transport_type
-         } = tx_attrs
-       ) do
-    NewRelic.report_metric(
-      {:caller, parent_type, parent_account_id, parent_app_id, transport_type},
-      duration_s: tx_attrs[:duration_ms] / 1000
-    )
-  end
-
-  defp report_caller_metric(tx_attrs) do
-    NewRelic.report_metric(
-      {:caller, "Unknown", "Unknown", "Unknown", "Unknown"},
-      duration_s: tx_attrs[:duration_ms] / 1000
-    )
-  end
-
   defp spawned_process_events(tx_attrs, process_spawns, process_names, process_exits) do
     process_spawns
     |> collect_process_segments(process_names, process_exits)
@@ -303,26 +277,22 @@ defmodule NewRelic.Transaction.Reporter do
         priority: tx_attrs[:priority],
         category: "generic",
         name: "Process #{proc.name || proc.pid}",
-        guid: DistributedTrace.generate_guid(pid: proc.raw_pid),
-        parent_id: DistributedTrace.generate_guid(pid: proc.parent_pid),
+        guid: DistributedTrace.generate_guid(pid: proc.id),
+        parent_id: DistributedTrace.generate_guid(pid: proc.parent_id),
         timestamp: proc[:start_time],
         duration: (proc[:end_time] - proc[:start_time]) / 1000
       }
     end)
   end
 
-  defp report_span_events(span_events) do
-    Enum.each(span_events, &Collector.SpanEvent.Harvester.report_span_event/1)
-  end
-
   defp collect_process_segments(spawns, names, exits) do
     for {pid, start_time, original} <- spawns,
         {^pid, name} <- names,
         {^pid, end_time} <- exits do
       %{
         pid: inspect(pid),
-        raw_pid: pid,
-        parent_pid: original,
+        id: pid,
+        parent_id: original,
         name: name,
         start_time: start_time,
         end_time: end_time
@@ -342,7 +312,28 @@ defmodule NewRelic.Transaction.Reporter do
          })
 
   defp transform_trace_name_attrs(
-         %{module: module, function: function, arity: arity, args: args} = attrs
+         %{
+           primary_name: metric_name,
+           secondary_name: class_name,
+           attributes: attributes
+         } = attrs
+       ) do
+    attrs
+    |> Map.merge(%{
+      class_name: class_name,
+      method_name: nil,
+      metric_name: metric_name |> String.replace("/", ""),
+      attributes: attributes
+    })
+  end
+
+  defp transform_trace_name_attrs(
+         %{
+           module: module,
+           function: function,
+           arity: arity,
+           args: args
+         } = attrs
        ),
        do:
          attrs
@@ -358,6 +349,57 @@ defmodule NewRelic.Transaction.Reporter do
       attrs
       |> Map.merge(%{class_name: name || "Process", method_name: nil, metric_name: pid})
 
+  defp generate_process_tree(processes, root: root) do
+    parent_map = Enum.group_by(processes, & &1.parent_id)
+    generate_tree(root, parent_map)
+  end
+
+  defp generate_process_segment_tree({pid, segments}) do
+    parent_map = Enum.group_by(segments, & &1.parent_id)
+    %{children: children} = generate_tree(%{id: :root}, parent_map)
+    {pid, children}
+  end
+
+  defp generate_tree(leaf, parent_map) when map_size(parent_map) == 0 do
+    leaf
+  end
+
+  defp generate_tree(parent, parent_map) do
+    {children, parent_map} = Map.pop(parent_map, parent.id, [])
+
+    children =
+      children
+      |> Enum.sort_by(& &1.relative_start_time)
+      |> Enum.map(&generate_tree(&1, parent_map))
+
+    Map.update(parent, :children, children, &(&1 ++ children))
+  end
+
+  defp report_caller_metric(
+         %{
+           "parent.type": parent_type,
+           "parent.account": parent_account_id,
+           "parent.app": parent_app_id,
+           "parent.transportType": transport_type
+         } = tx_attrs
+       ) do
+    NewRelic.report_metric(
+      {:caller, parent_type, parent_account_id, parent_app_id, transport_type},
+      duration_s: tx_attrs[:duration_ms] / 1000
+    )
+  end
+
+  defp report_caller_metric(tx_attrs) do
+    NewRelic.report_metric(
+      {:caller, "Unknown", "Unknown", "Unknown", "Unknown"},
+      duration_s: tx_attrs[:duration_ms] / 1000
+    )
+  end
+
+  defp report_span_events(span_events) do
+    Enum.each(span_events, &Collector.SpanEvent.Harvester.report_span_event/1)
+  end
+
   defp report_transaction_event(tx_attrs) do
     Collector.TransactionEvent.Harvester.report_event(%Transaction.Event{
       timestamp: tx_attrs.start_time,
diff --git a/lib/new_relic/transaction/trace.ex b/lib/new_relic/transaction/trace.ex
index 8b1cce5..ffcb1a4 100644
--- a/lib/new_relic/transaction/trace.ex
+++ b/lib/new_relic/transaction/trace.ex
@@ -21,6 +21,8 @@ defmodule NewRelic.Transaction.Trace do
               children: [],
               class_name: nil,
               method_name: nil,
+              parent_id: nil,
+              id: nil,
               pid: nil
 
     @moduledoc false
diff --git a/lib/new_relic/util.ex b/lib/new_relic/util.ex
index 62ad7d6..284a0cc 100644
--- a/lib/new_relic/util.ex
+++ b/lib/new_relic/util.ex
@@ -16,6 +16,14 @@ defmodule NewRelic.Util do
   def time_to_ms({megasec, sec, microsec}),
     do: (megasec * 1_000_000 + sec) * 1_000 + round(microsec / 1_000)
 
+  def process_name(pid) do
+    case Process.info(pid, :registered_name) do
+      nil -> nil
+      {:registered_name, []} -> nil
+      {:registered_name, name} -> name
+    end
+  end
+
   def deep_flatten(attrs) when is_list(attrs) do
     Enum.flat_map(attrs, &deep_flatten/1)
   end


Test patch:
diff --git a/test/span_event_test.exs b/test/span_event_test.exs
index bac6cdb..6f0c876 100644
--- a/test/span_event_test.exs
+++ b/test/span_event_test.exs
@@ -82,7 +82,10 @@ defmodule SpanEventTest do
       category_attributes: %{}
     }
 
-    Collector.SpanEvent.Harvester.report_span_event(event, context, mfa)
+    Collector.SpanEvent.Harvester.report_span_event(event, context,
+      span: {mfa, :ref},
+      parent: :root
+    )
 
     [[attrs, _, _]] = TestHelper.gather_harvest(Collector.SpanEvent.Harvester)
 
@@ -96,6 +99,11 @@ defmodule SpanEventTest do
     use NewRelic.Tracer
     @trace :hello
     def hello do
+      do_hello()
+    end
+
+    @trace :do_hello
+    def do_hello do
       Process.sleep(10)
       "world"
     end
@@ -143,6 +151,9 @@ defmodule SpanEventTest do
     [function_event, _, _] =
       Enum.find(span_events, fn [ev, _, _] -> ev[:name] == "SpanEventTest.Traced.hello/0" end)
 
+    [nested_function_event, _, _] =
+      Enum.find(span_events, fn [ev, _, _] -> ev[:name] == "SpanEventTest.Traced.do_hello/0" end)
+
     [task_event, _, _] =
       Enum.find(span_events, fn [ev, _, _] -> String.starts_with?(ev[:name], "Process #PID") end)
 
@@ -156,23 +167,27 @@ defmodule SpanEventTest do
     assert tx_event[:traceId] == "d6b4ba0c3a712ca"
     assert cowboy_event[:traceId] == "d6b4ba0c3a712ca"
     assert function_event[:traceId] == "d6b4ba0c3a712ca"
+    assert nested_function_event[:traceId] == "d6b4ba0c3a712ca"
     assert task_event[:traceId] == "d6b4ba0c3a712ca"
     assert nested_event[:traceId] == "d6b4ba0c3a712ca"
 
     assert cowboy_event[:transactionId] == tx_event[:guid]
     assert function_event[:transactionId] == tx_event[:guid]
+    assert nested_function_event[:transactionId] == tx_event[:guid]
     assert task_event[:transactionId] == tx_event[:guid]
     assert nested_event[:transactionId] == tx_event[:guid]
 
     assert tx_event[:sampled] == true
     assert cowboy_event[:sampled] == true
     assert function_event[:sampled] == true
+    assert nested_function_event[:sampled] == true
     assert task_event[:sampled] == true
     assert nested_event[:sampled] == true
 
     assert tx_event[:priority] == 0.987654
     assert cowboy_event[:priority] == 0.987654
     assert function_event[:priority] == 0.987654
+    assert nested_function_event[:priority] == 0.987654
     assert task_event[:priority] == 0.987654
     assert nested_event[:priority] == 0.987654
 
@@ -181,6 +196,7 @@ defmodule SpanEventTest do
 
     assert cowboy_event[:parentId] == "5f474d64b9cc9b2a"
     assert function_event[:parentId] == cowboy_event[:guid]
+    assert nested_function_event[:parentId] == function_event[:guid]
     assert task_event[:parentId] == cowboy_event[:guid]
     assert nested_event[:parentId] == task_event[:guid]
 
@@ -195,6 +211,9 @@ defmodule SpanEventTest do
     assert nested_event[:component] == "HTTPoison"
     assert nested_event[:args]
 
+    assert nested_function_event[:category] == "generic"
+    assert nested_function_event[:name] == "SpanEventTest.Traced.do_hello/0"
+
     # Ensure these will encode properly
     Jason.encode!(tx_event)
     Jason.encode!(span_events)
@@ -206,7 +225,7 @@ defmodule SpanEventTest do
   describe "Generate span GUIDs" do
     test "for a process" do
       NewRelic.DistributedTrace.generate_guid(pid: self())
-      NewRelic.DistributedTrace.generate_guid(pid: self(), mfa: {:m, :f, 1})
+      NewRelic.DistributedTrace.generate_guid(pid: self(), label: {:m, :f, 1}, ref: make_ref())
     end
   end
 
diff --git a/test/transaction_trace_test.exs b/test/transaction_trace_test.exs
index 3b1587f..996b36e 100644
--- a/test/transaction_trace_test.exs
+++ b/test/transaction_trace_test.exs
@@ -24,7 +24,7 @@ defmodule TransactionTraceTest do
   defmodule ExternalService do
     use NewRelic.Tracer
     @trace {:query, category: :external}
-    def query(n), do: Process.sleep(n)
+    def query(n), do: HelperModule.function(n)
   end
 
   defmodule TestPlugApp do
@@ -43,7 +43,6 @@ defmodule TransactionTraceTest do
           Task.async(fn ->
             ExternalService.query(202)
             Process.sleep(20)
-            HelperModule.function(203)
           end)
           |> Task.await()
         end)
@@ -57,7 +56,7 @@ defmodule TransactionTraceTest do
 
       Task.await(t1)
       Task.await(t2)
-      ExternalService.query(105)
+      ExternalService.query(405)
       send_resp(conn, 200, "transaction_trace")
     end