Skip to content

Commit

Permalink
[pinpoint-apm#226] Implemetations TraceRoot
Browse files Browse the repository at this point in the history
* URL have to create baseURL that To parse the URL into its parts
* TraceContext no needs Singleton. It is only a member variable of the agent singleton
* Fix a test failure
* Fix github actions
  • Loading branch information
feelform committed Oct 16, 2024
1 parent c3ab121 commit 04759ad
Show file tree
Hide file tree
Showing 31 changed files with 1,089 additions and 427 deletions.
31 changes: 23 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ name: CI
# Controls when the action will run.
on: [push, pull_request]

permissions:
contents: read
pull-requests: write

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
Expand Down Expand Up @@ -35,12 +39,23 @@ jobs:
# path: '**/checkstyle-result.xml'
- name: Coverage
run: npm run coverage
# Required for generating html artifact, can be skipped if not generating html artifact
# - name: Report coverage
# uses: hrishikesh-kadam/setup-lcov@v1
# - name: Upload coverage report
# uses: kefasjw/lcov-pull-request-report@v1
# with:
# # Lcov file location. For example, coverage/lcov.info
# lcov-file: coverage/lcov.info

# # Github token required for getting list of changed files and posting comments
# github-token: ${{ secrets.GITHUB_TOKEN }}
# ... Generate LCOV files or download it from a different job
- name: Setup LCOV
uses: hrishikesh-kadam/setup-lcov@v1
- name: Report coverage
uses: zgosalvez/github-actions-report-lcov@v3
with:
coverage-files: coverage/lcov.info
github-token: ${{ secrets.ACTIONS_TOKEN }}
update-comment: true
# - name: Setup LCOV
# uses: hrishikesh-kadam/setup-lcov@v1
# - name: Report coverage
# uses: zgosalvez/github-actions-report-lcov@v4
# with:
# coverage-files: coverage/lcov.info
# github-token: ${{ secrets.ACTIONS_TOKEN }}
# update-comment: true
4 changes: 2 additions & 2 deletions lib/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
'use strict'

const ModuleHook = require('./instrumentation/module-hook')
const traceContext = require('./context/trace-context')
const TraceContext = require('./context/trace-context')
const log = require('./utils/logger')
const stringMetaService = require('./context/string-meta-service')
const apiMetaService = require('./context/api-meta-service')
Expand Down Expand Up @@ -40,7 +40,7 @@ class Agent {
this.initializeDataSender()
this.initializePinpointClient()

this.traceContext = traceContext.init(this.agentInfo, this.dataSender, this.config)
this.traceContext = new TraceContext(this.agentInfo, this.dataSender, this.config)

stringMetaService.init(this.dataSender)
apiMetaService.init(this.dataSender)
Expand Down
7 changes: 4 additions & 3 deletions lib/client/grpc-data-sender.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,16 @@ class GrpcDataSender {
if (this.statClient) {
this.statClient.close()
}

if (this.profilerClient) {
this.profilerClient.close()
}
if (this.commandStream) {
this.commandStream.end()
}
if (this.activeThreadCountStream) {
this.activeThreadCountStream.end()
}
if (this.profilerClient) {
this.profilerClient.close()
}
}

initializeClients(collectorIp, collectorTcpPort, config) {
Expand Down
8 changes: 7 additions & 1 deletion lib/client/grpc-readable-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class GrpcReadableStream {
const writableStream = this.makeCall()
writableStream.on('error', (error) => {
if (error) {
log.error('writable steam error', error)
log.error('writable steam error in GrpcReadableStream', error)
}
})

Expand All @@ -61,6 +61,12 @@ class GrpcReadableStream {

end() {
this.readableStream.end()
this.writableStream.on('finish', () => {
log.debug('writable stream "finish" event')
})
this.writableStream.on('close', () => {
log.debug('writable stream "close" event')
})
}
}

Expand Down
3 changes: 2 additions & 1 deletion lib/context/disable-trace.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ const DisableSpanRecorder = require('./disable-span-recorder')

// https://github.com/naver/pinpoint/blob/master/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/DisableTrace.java
class DisableTrace {
constructor() {
constructor(traceRoot) {
this.traceRoot = traceRoot
this.spanRecorder = new DisableSpanRecorder()
}

Expand Down
43 changes: 43 additions & 0 deletions lib/context/remote-trace-root-builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Pinpoint Node.js Agent
* Copyright 2020-present NAVER Corp.
* Apache License v2.0
*/

'use strict'

const TraceRootBuilder = require("./trace-root-builder")
const TraceIdBuilder = require("./trace/trace-id-builder")

class RemoteTraceRoot {
constructor(traceId, traceRoot) {
this.traceId = traceId
this.traceRoot = traceRoot
}

getTraceStartTime() {
return this.traceRoot.getTraceStartTime()
}
}

class RemoteTraceRootBuilder {
constructor(agentInfo) {
this.agentInfo = agentInfo
}

setTraceId(traceId) {
this.traceId = traceId
return this
}

build(transactionId) {
if (this.traceId) {
return new RemoteTraceRoot(this.traceId, new TraceRootBuilder(this.agentInfo.agentId).build(transactionId))
}

const traceId = new TraceIdBuilder(this.agentInfo, transactionId).build()
return new RemoteTraceRoot(traceId, new TraceRootBuilder(this.agentInfo.agentId).build(transactionId))
}
}

module.exports = RemoteTraceRootBuilder
26 changes: 26 additions & 0 deletions lib/context/span-builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Pinpoint Node.js Agent
* Copyright 2020-present NAVER Corp.
* Apache License v2.0
*/

'use strict'

class Span {
constructor(traceRoot) {
this.traceRoot = traceRoot
this.startTime = traceRoot.getTraceStartTime()
}
}

class SpanBuilder {
constructor(traceRoot) {
this.traceRoot = traceRoot
}

build() {
return new Span(this.traceRoot)
}
}

module.exports = SpanBuilder
25 changes: 25 additions & 0 deletions lib/context/span-chunk-builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Pinpoint Node.js Agent
* Copyright 2020-present NAVER Corp.
* Apache License v2.0
*/

'use strict'
class SpanChunk {
constructor(traceRoot, spanEventList) {
this.traceRoot = traceRoot
this.spanEventList = spanEventList
}
}

class SpanChunkBuilder {
constructor(traceRoot) {
this.traceRoot = traceRoot
}

build(spanEventList) {
return new SpanChunk(this.traceRoot, spanEventList)
}
}

module.exports = SpanChunkBuilder
8 changes: 4 additions & 4 deletions lib/context/span-chunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ class SpanChunk {
this.localAsyncId = asyncId
}

static getFactoryMethod(agentInfo, traceId) {
return (spanEventList) => new SpanChunk(agentInfo, traceId, null, spanEventList)
static getFactoryMethod(traceId, agentInfo) {
return (spanEventList) => new SpanChunk(traceId, agentInfo, null, spanEventList)
}

static getAsyncFactoryMethod(agentInfo, traceId, asyncId) {
return (spanEventList) => new SpanChunk(agentInfo, traceId, asyncId, spanEventList)
static getAsyncFactoryMethod(traceId, agentInfo, asyncId) {
return (spanEventList) => new SpanChunk(traceId, agentInfo, asyncId, spanEventList)
}

get spanMessage() {
Expand Down
32 changes: 32 additions & 0 deletions lib/context/trace-builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Pinpoint Node.js Agent
* Copyright 2020-present NAVER Corp.
* Apache License v2.0
*/

'use strict'

class Trace {
constructor(span, repository, spanRecorder, spanEventRecorder) {
this.span = span
this.repository = repository
this.spanRecorder = spanRecorder
this.spanEventRecorder = spanEventRecorder
}

}

class TraceBuilder {
constructor(span, repository, spanRecorder, spanEventRecorder) {
this.span = span
this.repository = repository
this.spanRecorder = spanRecorder
this.spanEventRecorder = spanEventRecorder
}

build() {
return new Trace(this.span, this.repository, this.spanRecorder, this.spanEventRecorder)
}
}

module.exports = TraceBuilder
79 changes: 48 additions & 31 deletions lib/context/trace-context.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,28 @@ const log = require('../utils/logger')
const sampler = require('../sampler/sampler')
const DisableTrace = require('./disable-trace')
const localStorage = require('../instrumentation/context/local-storage')
const TraceRootBuilder = require('./trace-root-builder')
const RemoteTraceRootBuilder = require('./remote-trace-root-builder')
const activeRequestRepository = require('./trace/active-request-repository')
const TraceSampler = require('./trace/trace-sampler')
const SpanBuilder = require('./span-builder')
const SpanChunkBuilder = require('./span-chunk-builder')
const SpanRepository = require('./trace/span-repository')
const SpanRecorder = require('./span-recorder')
const SpanEventRecorderBuilder = require('./trace/span-event-recorder-builder')
const TraceBuilder = require('./trace-builder')

class TraceContext {
constructor() {
this.agentInfo = null
this.dataSender = null
}

/**
* trace context singleton instance
* @param {string} options
* @param {string} dataSender
* @param {string} config
* @returns {TraceContext}
* @constructor
*/
static init(options, dataSender, config) {
if (!options.agentId || !options.applicationName) {
throw new Error('Fail to initialize pinpoint context')
}

const instance = new TraceContext()
instance.agentInfo = {
agentId: options.agentId,
applicationName: options.applicationName,
agentStartTime: options.agentStartTime,
serviceType: options.serviceType,
}
instance.dataSender = dataSender
constructor(agentInfo, dataSender, config) {
this.agentInfo = agentInfo
this.dataSender = dataSender
this.config = config
if (config) {
instance.isSampling = sampler.getIsSampling(config.sampling, config.sampleRate)
instance.enableSampling = config.sampling
this.isSampling = sampler.getIsSampling(config.sampling, config.sampleRate)
this.enableSampling = config.sampling
}

return instance
this.traceSampler = new TraceSampler(config)
this.localTraceRootBuilder = new TraceRootBuilder(agentInfo.agentId)
}

continueTraceObject(requestData) {
Expand Down Expand Up @@ -120,6 +108,35 @@ class TraceContext {
return this.newTraceObject(this.isSampling())
}
}

// disableSampling() method in DefaultBaseTraceFactory.java
disableSampling() {
const state = this.traceSampler.getContinueDisabledState()
return this.newLocalTrace(state.nextId())
}

newLocalTrace(nextDisabledId) {
const traceRoot = this.localTraceRootBuilder.build(nextDisabledId)
activeRequestRepository.registry(traceRoot)
return new DisableTrace(traceRoot)
}

// newTraceObject method in DefaultBaseTraceFactory.java
newTraceObject2(urlPath) {
const state = this.traceSampler.newState(urlPath)
if (!state.isSampled()) {
return this.newLocalTrace(state.nextId())
}

const traceRoot = new RemoteTraceRootBuilder(this.agentInfo).build(state.nextId())
const span = new SpanBuilder(traceRoot).build()
const spanChunkBuilder = new SpanChunkBuilder(traceRoot)
const repository = new SpanRepository(spanChunkBuilder, this.dataSender)

const spanRecorder = new SpanRecorder(span)
const spanEventRecorder = new SpanEventRecorderBuilder(traceRoot).build()
return new TraceBuilder(span, repository, spanRecorder, spanEventRecorder).build()
}
}

module.exports = TraceContext
module.exports = TraceContext
31 changes: 31 additions & 0 deletions lib/context/trace-root-builder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Pinpoint Node.js Agent
* Copyright 2020-present NAVER Corp.
* Apache License v2.0
*/

'use strict'

class TraceRoot {
constructor(agentId, traceStartTime, transactionId) {
this.agentId = agentId
this.traceStartTime = traceStartTime
this.transactionId = transactionId
}

getTraceStartTime() {
return this.traceStartTime
}
}

class TraceRootBuilder {
constructor(agentId) {
this.agentId = agentId
}

build(transactionId) {
return new TraceRoot(this.agentId, Date.now(), transactionId)
}
}

module.exports = TraceRootBuilder
Loading

0 comments on commit 04759ad

Please sign in to comment.