Skip to content

Commit

Permalink
remove transaction from trace segment
Browse files Browse the repository at this point in the history
  • Loading branch information
svetlanabrennan committed Oct 9, 2024
1 parent d532983 commit 3b15868
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 54 deletions.
4 changes: 2 additions & 2 deletions lib/transaction/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,8 @@ Transaction.prototype._markAsWeb = function _markAsWeb(rawURL) {
}
}
}
// TODO: pass in tx
this.baseSegment.markAsWeb(this)

this.baseSegment.markAsWeb(this.transaction)
}

/**
Expand Down
76 changes: 29 additions & 47 deletions lib/transaction/trace/segment.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const hashes = require('../../util/hashes')
const { Attributes } = require('../../attributes')
const ExclusiveCalculator = require('./exclusive-time-calculator')
const SpanContext = require('../../spans/span-context')
const probe = require('../../../lib/util/probe')

const NAMES = require('../../metrics/names')
const STATE = {
Expand All @@ -28,31 +29,18 @@ const ATTRIBUTE_SCOPE = 'segment'
* @classdesc
* TraceSegments are inserted to track instrumented function calls. Each one is
* bound to a transaction, given a name (used only internally to the framework
* @param transaction
* for now), and has one or more children (that are also part of the same
* transaction), as well as an associated timer.
* @param {Transaction} transaction
* The transaction to which this segment will be bound.
* @param config
* @param {string} name
* Human-readable name for this segment (e.g. 'http', 'net', 'express',
* 'mysql', etc).
* @param {?Function} recorder
* Callback that takes a segment and a scope name as attributes (intended to be
* used to record metrics related to the segment).
*/
function TraceSegment(transaction, name, recorder) {
function TraceSegment(config, name, transaction) {
this.name = name
this.transaction = transaction

++transaction.numSegments
++transaction.agent.totalActiveSegments
++transaction.agent.segmentsCreatedInHarvest

if (recorder) {
transaction.addRecorder(recorder.bind(null, this))
}

this.attributes = new Attributes(ATTRIBUTE_SCOPE)

this.config = config
this.children = []

// Generate a unique id for use in span events.
Expand All @@ -73,12 +61,12 @@ function TraceSegment(transaction, name, recorder) {
this.async = true
this.ignore = false

this.probe('new TraceSegment')
probe('new TraceSegment', transaction, this.name)
}

TraceSegment.prototype.getSpanContext = function getSpanContext() {
const config = this.transaction.agent.config
const spansEnabled = config.distributed_tracing.enabled && config.span_events.enabled
const config = this.config
const spansEnabled = this.config.distributed_tracing.enabled && config.span_events.enabled

if (!this._spanContext && spansEnabled) {
this._spanContext = new SpanContext()
Expand Down Expand Up @@ -108,8 +96,7 @@ TraceSegment.prototype.getAttributes = function getAttributes() {
}

TraceSegment.prototype.getSpanId = function getSpanId() {
const conf = this.transaction.agent.config
const enabled = conf.span_events.enabled && conf.distributed_tracing.enabled
const enabled = this.config.span_events.enabled && this.config.distributed_tracing.enabled
if (enabled) {
return this.id
}
Expand All @@ -125,23 +112,14 @@ TraceSegment.prototype.isInCallbackState = function isInCallbackState() {
return this.state === STATE.CALLBACK
}

TraceSegment.prototype.probe = function probe(action) {
// move probing from transaction to a utility
if (this.transaction.traceStacks) {
this.transaction.probe(action, { segment: this.name })
}
}

/**
* For use when a transaction is ending. The transaction segment should
* be named after the transaction it belongs to (which is only known by
* the end).
*/
// TODO: pass in tx
TraceSegment.prototype.setNameFromTransaction = function setNameFromTransaction() {
const transaction = this.transaction

// transaction name and transaciton segment name must match
TraceSegment.prototype.setNameFromTransaction = function setNameFromTransaction(transaction) {
// transaction name and transaction segment name must match
this.name = transaction.getFullName()

// partialName is used to name apdex metrics when recording
Expand All @@ -156,10 +134,9 @@ TraceSegment.prototype.setNameFromTransaction = function setNameFromTransaction(
* finally, marking the trace segment as being a web segment copies the
* segment's parameters onto the transaction.
*/
// TODO: pass in tx
TraceSegment.prototype.markAsWeb = function markAsWeb() {
const transaction = this.transaction
this.setNameFromTransaction()

TraceSegment.prototype.markAsWeb = function markAsWeb(transaction) {
this.setNameFromTransaction(transaction)

const traceAttrs = transaction.trace.attributes.get(DESTINATIONS.TRANS_TRACE)
Object.keys(traceAttrs).forEach((key) => {
Expand All @@ -173,9 +150,10 @@ TraceSegment.prototype.markAsWeb = function markAsWeb() {
* A segment attached to something evented (such as a database
* cursor) just finished an action, so set the timer to mark
* the timer as having a stop time.
* @param transaction
*/
TraceSegment.prototype.touch = function touch() {
this.probe('Touched')
TraceSegment.prototype.touch = function touch(transaction) {
this.probe('Touched', transaction, this.name)
this.timer.touch()
this._updateRootTimer()
}
Expand All @@ -191,12 +169,13 @@ TraceSegment.prototype.start = function start() {

/**
* Stop timing the related action.
* @param transaction
*/
TraceSegment.prototype.end = function end() {
TraceSegment.prototype.end = function end(transaction) {
if (!this.timer.isActive()) {
return
}
this.probe('Ended')
this.probe('Ended', transaction, this.name)
this.timer.end()
this._updateRootTimer()
}
Expand All @@ -216,6 +195,8 @@ TraceSegment.prototype.finalize = function finalize() {
* Helper to set the end of the root timer to this segment's root if it is later
* in time.
*/

// TODO: pass in tx?
TraceSegment.prototype._updateRootTimer = function _updateRootTimer() {
const root = this.transaction.trace.root
if (this.timer.endsAfter(root.timer)) {
Expand All @@ -236,20 +217,21 @@ TraceSegment.prototype._isEnded = function _isEnded() {
/**
* Add a new segment to a scope implicitly bounded by this segment.
*
* @param config
* @param {string} childName New human-readable name for the segment.
* @param recorder
* @param segmentsSeen
* @param transactionId
* @returns {TraceSegment} New nested TraceSegment.
*/
TraceSegment.prototype.add = function add(childName, recorder) {
TraceSegment.prototype.add = function add(config, childName, segmentsSeen, transactionId) {
if (this.opaque) {
logger.trace('Skipping child addition on opaque segment')
return this
}
logger.trace('Adding segment %s to %s in %s', childName, this.name, this.transaction.id)
const segment = new TraceSegment(this.transaction, childName, recorder)
const config = this.transaction.agent.config
logger.trace('Adding segment %s to %s in %s', childName, this.name, transactionId)
const segment = new TraceSegment(config, childName)

if (this.transaction.trace.segmentsSeen++ >= config.max_trace_segments) {
if (segmentsSeen++ >= config.max_trace_segments) {
segment._collect = false
}
this.children.push(segment)
Expand Down
23 changes: 18 additions & 5 deletions lib/transaction/tracer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function getSegment() {
// TODO: Remove/replace external uses to tracer.getSpanContext()
function getSpanContext() {
const currentSegment = this.getSegment()
return currentSegment && currentSegment.getSpanContext()
return currentSegment && currentSegment.getSpanContext(this.tracer.agent.config)
}

function createSegment(name, recorder, _parent) {
Expand All @@ -76,10 +76,23 @@ function createSegment(name, recorder, _parent) {
)
return null
}
// pass in agent config
// increment the transaction and agent counters here
return parent.add(name, recorder)
// after segment is created add the recorder to the transaction

++parent.transaction.numSegments
++parent.transaction.agent.totalActiveSegments
++parent.transaction.agent.segmentsCreatedInHarvest

const segment = parent.add(
parent.transaction.agent.config,
name,
parent.transaction.trace.segmentsSeen,
parent.transaction.id
)

if (recorder) {
this.transaction.addRecorder(recorder.bind(null, segment))
}

return segment
}

function addSegment(name, recorder, parent, full, task) {
Expand Down
12 changes: 12 additions & 0 deletions lib/util/probe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright 2024 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

'use strict'

module.exports = function probe(action, transaction, name) {
if (transaction.traceStacks) {
transaction.probe(action, { segment: name })
}
}

0 comments on commit 3b15868

Please sign in to comment.