Skip to content

Commit c2daa11

Browse files
cjr125Christopher Roberts
authored andcommitted
feat: added spanContextCallback
1 parent 21534b8 commit c2daa11

File tree

7 files changed

+113
-24
lines changed

7 files changed

+113
-24
lines changed

docs/configuration.asciidoc

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,9 @@ NOTE: If APM Server is deployed in an origin different than the page’s origin,
428428
* *Type:* Function
429429
* *Default:* `null`
430430

431-
`transactionContextCallback` allows the agent to specify a function to be called when starting automatically instrumented transactions and spans and return
432-
context to be set as tags. This enables the agent to capture the context when instrumented events are fired from files which do not import the RUM agent library.
431+
`transactionContextCallback` allows the agent to specify a function to be called when starting automatically instrumented transactions and return context to
432+
be set as tags. This enables the agent to capture data such as call stack frames and variable values from the scope when instrumented events are fired from
433+
files which do not import the RUM agent library.
433434

434435
The following example illustrates an example which captures the stack trace:
435436

@@ -448,4 +449,35 @@ var options = {
448449
return { stack };
449450
}
450451
}
451-
----
452+
----
453+
454+
455+
[function]
456+
[[span-context-callback]]
457+
==== `spanContextCallback`
458+
459+
* *Type:* Function
460+
* *Default:* `null`
461+
462+
`spanContextCallback` allows the agent to specify a function to be called when starting automatically instrumented spans and return context to be set as tags.
463+
This enables the agent to capture data such as call stack frames and variable values from the scope when instrumented events are fired from files which do
464+
not import the RUM agent library.
465+
466+
The following example illustrates an example which captures the stack trace:
467+
468+
[source,js]
469+
----
470+
var options = {
471+
spanContextCallback: () => {
472+
let stack
473+
try {
474+
throw new Error('')
475+
}
476+
catch (error) {
477+
stack = (error as Error).stack || ''
478+
}
479+
stack = stack.split('\n').map(function (line) { return line.trim(); })
480+
return { stack };
481+
}
482+
}
483+
----

packages/rum-core/src/common/config-service.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ class Config {
9696
session: false,
9797
apmRequest: null,
9898
sendCredentials: false,
99-
transactionContextCallback: null
99+
transactionContextCallback: null,
100+
spanContextCallback: null
100101
}
101102

102103
this.events = new EventHandler()

packages/rum-core/src/performance-monitoring/span.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@ class Span extends SpanBase {
3939
this.action = fields[2]
4040
}
4141
this.sync = this.options.sync
42+
43+
if (
44+
this.options.spanContextCallback &&
45+
typeof this.options.spanContextCallback === 'function'
46+
) {
47+
let tags
48+
try {
49+
tags = this.options.spanContextCallback()
50+
this.addLabels(tags)
51+
} catch (e) {
52+
console.error('Failed to execute span context callback', e)
53+
}
54+
}
4255
}
4356

4457
end(endTime, data) {

packages/rum-core/src/performance-monitoring/transaction-service.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class TransactionService {
101101

102102
createOptions(options) {
103103
const config = this._config.config
104-
let presetOptions = {
104+
let presetOptions = {
105105
transactionSampleRate: config.transactionSampleRate
106106
}
107107
if (config.transactionContextCallback) {
@@ -110,6 +110,12 @@ class TransactionService {
110110
transactionContextCallback: config.transactionContextCallback
111111
}
112112
}
113+
if (config.spanContextCallback) {
114+
presetOptions = {
115+
...presetOptions,
116+
spanContextCallback: config.spanContextCallback
117+
}
118+
}
113119
let perfOptions = extend(presetOptions, options)
114120
if (perfOptions.managed) {
115121
perfOptions = extend(
@@ -493,13 +499,6 @@ class TransactionService {
493499
)
494500
}
495501

496-
if (this._config.config.transactionContextCallback) {
497-
options = {
498-
...options,
499-
tags: this._config.config.transactionContextCallback()
500-
}
501-
}
502-
503502
const span = tr.startSpan(name, type, options)
504503
if (__DEV__) {
505504
this._logger.debug(

packages/rum-core/src/performance-monitoring/transaction.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,16 @@ class Transaction extends SpanBase {
5555
this.sampleRate = this.options.transactionSampleRate
5656
this.sampled = Math.random() <= this.sampleRate
5757

58-
if (this.options.transactionContextCallback) {
59-
this.options = {
60-
...this.options,
61-
tags: this.options.transactionContextCallback()
58+
if (
59+
this.options.transactionContextCallback &&
60+
typeof this.options.transactionContextCallback === 'function'
61+
) {
62+
let tags
63+
try {
64+
tags = this.options.transactionContextCallback()
65+
this.addLabels(tags)
66+
} catch (e) {
67+
console.error('Failed to execute transaction context callback', e)
6268
}
6369
}
6470
}
@@ -103,7 +109,17 @@ class Transaction extends SpanBase {
103109
if (this.ended) {
104110
return
105111
}
106-
const opts = extend({}, options)
112+
let opts = extend({}, options)
113+
114+
if (
115+
this.options.spanContextCallback &&
116+
typeof this.options.spanContextCallback === 'function'
117+
) {
118+
opts = {
119+
...opts,
120+
spanContextCallback: this.options.spanContextCallback
121+
}
122+
}
107123

108124
opts.onEnd = trc => {
109125
this._onSpanEnd(trc)

packages/rum-core/test/performance-monitoring/transaction-service.spec.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -652,18 +652,19 @@ describe('TransactionService', function () {
652652
transaction.end(pageLoadTime + 1000)
653653
})
654654

655-
it('should capture tags from dispatch context', done => {
655+
it('should capture tags from transaction dispatch context', done => {
656656
config.setConfig({
657657
transactionContextCallback: () => {
658658
let stack
659659
try {
660660
throw new Error('')
661-
}
662-
catch (error) {
661+
} catch (error) {
663662
stack = error.stack || ''
664663
}
665-
stack = stack.split('\n').map(function (line) { return line.trim(); })
666-
return { stack };
664+
stack = stack.split('\n').map(function (line) {
665+
return line.trim()
666+
})
667+
return { stack }
667668
}
668669
})
669670
const transactionService = new TransactionService(logger, config)
@@ -674,11 +675,37 @@ describe('TransactionService', function () {
674675
)
675676

676677
tr1.onEnd = () => {
677-
expect(tr1.options.tags.stack).toBeTruthy()
678+
expect(tr1.context.tags.stack).toBeTruthy()
678679
done()
679680
}
680681
tr1.end()
681682
})
683+
684+
it('should capture tags from span dispatch context', done => {
685+
config.setConfig({
686+
spanContextCallback: () => {
687+
let stack
688+
try {
689+
throw new Error('')
690+
} catch (error) {
691+
stack = error.stack || ''
692+
}
693+
stack = stack.split('\n').map(function (line) {
694+
return line.trim()
695+
})
696+
return { stack }
697+
}
698+
})
699+
const transactionService = new TransactionService(logger, config)
700+
701+
const sp1 = transactionService.startSpan('span1', 'span')
702+
703+
sp1.onEnd = () => {
704+
expect(sp1.context.tags.stack).toBeTruthy()
705+
done()
706+
}
707+
sp1.end()
708+
})
682709
})
683710

684711
it('should truncate active spans after transaction ends', () => {

packages/rum/src/index.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ declare module '@elastic/apm-rum' {
108108
payload?: string
109109
headers?: Record<string, string>
110110
}) => boolean,
111-
transactionContextCallback?: (...args: any[]) => any
111+
transactionContextCallback?: (...args: any[]) => any,
112+
spanContextCallback?: (...args: any[]) => any
112113
}
113114

114115
type Init = (options?: AgentConfigOptions) => ApmBase

0 commit comments

Comments
 (0)