Skip to content

Commit 63736d7

Browse files
committed
[#231] Support ChildTrace
1 parent 6484775 commit 63736d7

25 files changed

+631
-106
lines changed

lib/context/async-id.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class AsyncId {
1515

1616
// DefaultAsyncIdGenerator.java: nextAsyncId()
1717
static make() {
18-
return new AsyncId(AsyncId.asyncIdGenerator.next, 0)
18+
return new AsyncId(AsyncId.asyncIdGenerator.getAndIncrement(), 0)
1919
}
2020

2121
constructor(asyncId, sequence) {

lib/context/remote-trace-root-builder.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,39 @@ class RemoteTraceRoot {
2222
isSampled() {
2323
return true
2424
}
25+
26+
getTraceId() {
27+
return this.traceId
28+
}
2529
}
2630

2731
class RemoteTraceRootBuilder {
28-
constructor(agentInfo) {
32+
constructor(agentInfo, transactionId) {
2933
this.agentInfo = agentInfo
34+
this.transactionId = transactionId
35+
}
36+
37+
make(transactionId) {
38+
return new RemoteTraceRootBuilder(this.agentInfo, transactionId)
3039
}
3140

3241
setTraceId(traceId) {
3342
this.traceId = traceId
3443
return this
3544
}
3645

37-
build(transactionId) {
38-
if (this.traceId) {
39-
return new RemoteTraceRoot(this.traceId, new TraceRootBuilder(this.agentInfo.agentId).build(transactionId))
46+
build() {
47+
const agentId = this.agentInfo.getAgentId()
48+
if (this.isNewTraceRoot()) {
49+
const traceId = new TraceIdBuilder(this.agentInfo, this.transactionId).build()
50+
return new RemoteTraceRoot(traceId, new TraceRootBuilder(agentId, this.transactionId).build())
4051
}
4152

42-
const traceId = new TraceIdBuilder(this.agentInfo, transactionId).build()
43-
return new RemoteTraceRoot(traceId, new TraceRootBuilder(this.agentInfo.agentId).build(transactionId))
53+
return new RemoteTraceRoot(this.traceId, new TraceRootBuilder(agentId, this.transactionId).build())
54+
}
55+
56+
isNewTraceRoot() {
57+
return !this.traceId
4458
}
4559
}
4660

lib/context/span-builder.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ class Span {
1010
constructor(traceRoot) {
1111
this.traceRoot = traceRoot
1212
}
13+
14+
isSpan() {
15+
return true
16+
}
1317
}
1418

1519
class SpanBuilder {
@@ -64,6 +68,10 @@ class SpanBuilder {
6468
return this
6569
}
6670

71+
getTraceRoot() {
72+
return this.traceRoot
73+
}
74+
6775
build() {
6876
const span = new Span(this.traceRoot)
6977
this.startTime = this.startTime || Date.now()

lib/context/span-id.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,29 @@
88

99
// SpanId.java in Java agent
1010
class SpanId {
11-
static nullSpanId = -1
12-
13-
constructor () {
11+
constructor() {
1412
this.MAX_NUM = Number.MAX_SAFE_INTEGER
1513
}
1614

17-
get next () {
15+
nullSpanId() {
16+
return '-1'
17+
}
18+
19+
get next() {
1820
return Math.floor(Math.random() * this.MAX_NUM)
1921
}
2022

2123
newSpanId() {
2224
return this.next.toString()
2325
}
26+
27+
nextSpanId(spanId, parentSpanId) {
28+
let newId = this.newSpanId()
29+
while (newId === spanId || newId === parentSpanId) {
30+
newId = this.newSpanId()
31+
}
32+
return newId
33+
}
2434
}
2535

2636
module.exports = new SpanId()

lib/context/trace-context.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ const SpanBuilder = require('./span-builder')
2020
const SpanChunkBuilder = require('./span-chunk-builder')
2121
const SpanRepository = require('./trace/span-repository')
2222
const Trace2 = require('./trace/trace2')
23+
const AsyncSpanChunkBuilder = require('./trace/async-span-chunk-builder')
24+
const ChildTraceBuilder = require('./trace/child-trace-builder')
2325

2426
class TraceContext {
2527
constructor(agentInfo, dataSender, config) {
@@ -33,6 +35,10 @@ class TraceContext {
3335
this.traceSampler = new TraceSampler(agentInfo, config)
3436
}
3537

38+
getAgentInfo() {
39+
return this.agentInfo
40+
}
41+
3642
continueTraceObject(requestData) {
3743
const traceId = new TraceId(
3844
requestData.transactionId,
@@ -125,14 +131,16 @@ class TraceContext {
125131
const spanBuilder = new SpanBuilder(traceRoot)
126132
const spanChunkBuilder = new SpanChunkBuilder(traceRoot)
127133
const repository = new SpanRepository(spanChunkBuilder, this.dataSender)
128-
return new Trace2(spanBuilder, repository, this.agentInfo.getServiceType())
134+
return new Trace2(spanBuilder, repository)
129135
}
130136

131137
// DefaultAsyncContext.java: newAsyncContextTrace
132138
// DefaultBaseTraceFactory.java: continueAsyncContextTraceObject
133-
continueAsyncContextTraceObject(traceRoot, asyncId) {
134-
const localAsyncId = asyncId.nextLocalAsyncId2()
135-
139+
// AsyncContextSpanEventEndPointApiAwareInterceptor.java : before
140+
continueAsyncContextTraceObject(traceRoot, localAsyncId) {
141+
const spanChunkBuilder = new AsyncSpanChunkBuilder(traceRoot, localAsyncId)
142+
const repository = new SpanRepository(spanChunkBuilder, this.dataSender)
143+
return new ChildTraceBuilder(traceRoot, repository, localAsyncId)
136144
}
137145
}
138146

lib/context/trace-root-builder.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@ class TraceRoot {
2323
}
2424

2525
class TraceRootBuilder {
26-
constructor(agentId) {
26+
constructor(agentId, localTransactionId) {
2727
this.agentId = agentId
28+
this.localTransactionId = localTransactionId
29+
this.traceStartTime = Date.now()
2830
}
2931

30-
build(transactionId) {
31-
return new TraceRoot(this.agentId, Date.now(), transactionId)
32+
make(localTransactionId) {
33+
return new TraceRootBuilder(this.agentId, localTransactionId)
34+
}
35+
36+
// DefaultTraceRootFactory.java: newDisableTraceRoot
37+
build() {
38+
return new TraceRoot(this.agentId, this.traceStartTime, this.localTransactionId)
3239
}
3340
}
3441

lib/context/trace/async-span-chunk-builder.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ class AsyncSpanChunk extends SpanChunk {
1919
return this.localAsyncId
2020
}
2121

22+
isAsyncSpanChunk() {
23+
return true
24+
}
25+
2226
toString() {
2327
return `AsyncSpanChunk(traceRoot=${this.traceRoot}, spanEventList=${this.spanEventList}, localAsyncId=${this.localAsyncId})`
2428
}
@@ -32,7 +36,7 @@ class AsyncSpanChunkBuilder {
3236
}
3337

3438
build(spanEventList) {
35-
return new AsyncSpanChunk(this.traceRoot, this.asyncId, spanEventList)
39+
return new AsyncSpanChunk(this.traceRoot, spanEventList, this.asyncId)
3640
}
3741

3842
toString() {

lib/context/trace/call-stack.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Pinpoint Node.js Agent
3+
* Copyright 2020-present NAVER Corp.
4+
* Apache License v2.0
5+
*/
6+
7+
'use strict'
8+
9+
const SpanEventBuilder = require('./span-event-builder')
10+
const SpanEventRecorder = require('./span-event-recorder2')
11+
12+
/**
13+
* DefaultCallStack.java in Java agent
14+
*/
15+
class CallStack {
16+
constructor() {
17+
this.stack = []
18+
this.sequence = 0
19+
this.depth = 0
20+
}
21+
22+
makeSpanEventRecorder(stackId) {
23+
const recorder = new SpanEventRecorder(SpanEventBuilder.make(stackId))
24+
this.push(recorder.getSpanEventBuilder())
25+
return recorder
26+
}
27+
28+
push(spanEventBuilder) {
29+
if (spanEventBuilder.needsSequence()) {
30+
spanEventBuilder.setSequence(this.sequence++)
31+
}
32+
33+
if (spanEventBuilder.needsDepth()) {
34+
spanEventBuilder.setDepth(this.stack.length + 1)
35+
}
36+
37+
this.stack.push(spanEventBuilder)
38+
}
39+
40+
// pop in java agent
41+
pop() {
42+
if (this.stack.length < 1) {
43+
return SpanEventBuilder.nullObject()
44+
}
45+
return this.stack.pop()
46+
}
47+
}
48+
49+
module.exports = CallStack

lib/context/trace/child-trace-builder.js

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66

77
'use strict'
88

9-
const SpanEventRecorder = require('./span-event-recorder')
9+
const SpanEventRecorder = require('./span-event-recorder2')
1010
const Trace = require('./trace2')
11+
const TraceRootSpanRecorder = require('./trace-root-span-recorder')
12+
const StackId = require('./stack-id')
13+
const CallStack = require('./call-stack')
1114

1215
class ChildTrace extends Trace {
1316
constructor(spanBuilder, repository, localAsyncId) {
@@ -17,14 +20,48 @@ class ChildTrace extends Trace {
1720
}
1821

1922
class ChildTraceBuilder {
20-
constructor(traceRoot, localAsyncId) {
23+
constructor(traceRoot, repository, localAsyncId) {
2124
this.traceRoot = traceRoot
25+
this.repository = repository
26+
this.spanRecorder = new TraceRootSpanRecorder(traceRoot)
2227
this.localAsyncId = localAsyncId
2328

24-
this.callStack = []
29+
this.callStack = new CallStack()
2530
this.closed = false
2631

27-
this.spanEventRecorder = SpanEventRecorder.nullObject()
32+
this.traceBlockBegin(StackId.asyncBeginStackId)
33+
}
34+
35+
traceBlockBegin(stackId = StackId.default) {
36+
if (this.closed) {
37+
return SpanEventRecorder.nullObject()
38+
}
39+
40+
return this.callStack.makeSpanEventRecorder(stackId)
41+
}
42+
43+
traceBlockEnd() {
44+
if (this.closed) {
45+
return
46+
}
47+
48+
const spanEventBuilder = this.callStack.pop()
49+
spanEventBuilder.markAfterTime()
50+
this.repository.storeSpanEvent(spanEventBuilder)
51+
}
52+
53+
getTraceRoot() {
54+
return this.traceRoot
55+
}
56+
57+
getTraceId() {
58+
return this.traceRoot.getTraceId()
59+
}
60+
61+
close() {
62+
this.traceBlockEnd(StackId.asyncBeginStackId)
63+
this.closed = true
64+
this.repository.flush()
2865
}
2966
}
3067

0 commit comments

Comments
 (0)