function Trace(transaction) {
  if (!transaction) {
    throw new Error('All traces must be associated with a transaction.')
  }

  this.transaction = transaction

  const root = new TraceSegment({
    config: transaction.agent.config,
    name: 'ROOT',
    collect: transaction.collect,
    isRoot: true
  })
  root.start()
  transaction.incrementCounters()

  this.intrinsics = Object.create(null)
  this.segments = new SegmentTree(root)
  this.root = this.segments.root.segment
  this.totalTimeCache = null

  this.custom = new Attributes(ATTRIBUTE_SCOPE, MAXIMUM_CUSTOM_ATTRIBUTES)
  this.attributes = new Attributes(ATTRIBUTE_SCOPE)

  // sending displayName if set by user
  const displayName = transaction.agent.config.getDisplayHost()
  const hostName = transaction.agent.config.getHostnameSafe()
  if (displayName !== hostName) {
    this.attributes.addAttribute(DESTINATIONS.TRANS_COMMON, 'host.displayName', displayName)

    this.displayName = displayName
  }
  this.domain = null
}
A Trace holds the root of the Segment graph and produces the final
serialization of the transaction trace.

@param {Transaction} transaction The transaction bound to the trace.