diff --git a/lib/client/grpc-data-sender.js b/lib/client/grpc-data-sender.js index 64c59046..9a6eaa70 100644 --- a/lib/client/grpc-data-sender.js +++ b/lib/client/grpc-data-sender.js @@ -141,13 +141,10 @@ class GrpcDataSender { this.agentInfoDailyScheduler = new Scheduler(this.agentInfoRefreshInterval()) } - initializeProfilerClients(collectorIp, collectorTcpPort, config) { + initializeProfilerClients(collectorIp, collectorTcpPort) { const profilerBuilder = new OptionsBuilder() .addInterceptor(makeAgentInformationMetadataInterceptor(this.agentInfo)) - if (config && config.grpcServiceConfig && typeof config.grpcServiceConfig.getProfiler === 'function') { - profilerBuilder.setGrpcServiceConfig(config.grpcServiceConfig.getProfiler()) - } this.profilerClient = new services.ProfilerCommandServiceClient(collectorIp + ":" + collectorTcpPort, grpc.credentials.createInsecure(), profilerBuilder.build()) } diff --git a/lib/context/trace-context.js b/lib/context/trace-context.js index 913e2a07..710188cf 100644 --- a/lib/context/trace-context.js +++ b/lib/context/trace-context.js @@ -14,7 +14,6 @@ const log = require('../utils/logger') const sampler = require('../sampler/sampler') const DisableTrace = require('./disable-trace') const localStorage = require('../instrumentation/context/local-storage') -const activeRequestRepository = require('./trace/active-request-repository') const TraceSampler = require('./trace/trace-sampler') const SpanBuilder = require('./span-builder') const SpanChunkBuilder = require('./span-chunk-builder') @@ -24,6 +23,7 @@ const AsyncSpanChunkBuilder = require('./trace/async-span-chunk-builder') const ChildTraceBuilder = require('./trace/child-trace-builder') const DisableChildTrace = require('./trace/disable-child-trace') const disableAsyncId = require('./trace/disable-async-id') +const ActiveTraceRepository = require('../metric/active-trace-repository') class TraceContext { constructor(agentInfo, dataSender, config) { @@ -35,6 +35,7 @@ class TraceContext { this.enableSampling = config.sampling } this.traceSampler = new TraceSampler(agentInfo, config) + this.activeRequestRepository = new ActiveTraceRepository() } getAgentInfo() { @@ -82,6 +83,7 @@ class TraceContext { } try { trace.close() + this.activeRequestRepository.remove(trace.getTraceRoot()) // activeTrace.remove(trace) } catch (e) { log.error('Fail to complete trace object', e) @@ -116,7 +118,7 @@ class TraceContext { } newLocalTrace(traceRoot) { - activeRequestRepository.registry(traceRoot) + this.activeRequestRepository.register(traceRoot) return new DisableTrace(traceRoot) } @@ -135,6 +137,7 @@ class TraceContext { const spanBuilder = new SpanBuilder(traceRoot) const spanChunkBuilder = new SpanChunkBuilder(traceRoot) const repository = new SpanRepository(spanChunkBuilder, this.dataSender, this.agentInfo) + this.activeRequestRepository.register(traceRoot) return new Trace2(spanBuilder, repository) } diff --git a/lib/context/trace/active-request-repository.js b/lib/context/trace/active-request-repository.js deleted file mode 100644 index a46f295f..00000000 --- a/lib/context/trace/active-request-repository.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Pinpoint Node.js Agent - * Copyright 2020-present NAVER Corp. - * Apache License v2.0 - */ - -'use strict' -const SimpleCache = require('../../utils/simple-cache') -class ActiveRequestRepository { - constructor() { - this.cache = new SimpleCache() - } - - registry(traceRoot) { - this.cache.put(traceRoot.transactionId, traceRoot) - } - - remove(traceRoot) { - this.cache.delete(traceRoot.transactionId) - } -} - -module.exports = new ActiveRequestRepository() \ No newline at end of file diff --git a/lib/context/trace/child-trace-builder.js b/lib/context/trace/child-trace-builder.js index 95c607e2..70876108 100644 --- a/lib/context/trace/child-trace-builder.js +++ b/lib/context/trace/child-trace-builder.js @@ -6,7 +6,6 @@ 'use strict' -const SpanEventRecorder = require('./span-event-recorder2') const TraceRootSpanRecorder = require('./trace-root-span-recorder') const StackId = require('./stack-id') const CallStack = require('./call-stack') diff --git a/lib/metric/active-trace-repository.js b/lib/metric/active-trace-repository.js new file mode 100644 index 00000000..5f28d8ab --- /dev/null +++ b/lib/metric/active-trace-repository.js @@ -0,0 +1,32 @@ +/** + * Pinpoint Node.js Agent + * Copyright 2020-present NAVER Corp. + * Apache License v2.0 + */ + +'use strict' + +const SimpleCache = require('../utils/simple-cache') + +// DefaultActiveTraceRepository.java +class ActiveTraceRepository { + constructor() { + this.activeTraceCache = new SimpleCache() + } + + register(localTraceRoot) { + const id = localTraceRoot.getTransactionId() + if (typeof id !== 'string' || id.length < 1) { + return + } + + this.activeTraceCache.put(id, localTraceRoot) + } + + remove(localTraceRoot) { + const id = localTraceRoot.getTransactionId() + this.activeTraceCache.delete(id) + } +} + +module.exports = ActiveTraceRepository \ No newline at end of file diff --git a/test/stats/active-trace.test.js b/test/stats/active-trace.test.js index 2e02c69b..c3436105 100644 --- a/test/stats/active-trace.test.js +++ b/test/stats/active-trace.test.js @@ -11,6 +11,9 @@ const activeTrace = require('../../lib/metric/active-trace') const agent = require('../support/agent-singleton-mock') const express = require('express') const http = require('http') +const grpc = require('@grpc/grpc-js') +const services = require('../../lib/data/v1/Service_grpc_pb') +const spanMessages = require('../../lib/data/v1/Span_pb') const TEST_ENV = { host: 'localhost', @@ -37,9 +40,9 @@ test(`Should record active trace in multiple call`, function (t) { const server = app.listen(TEST_ENV.port, async function () { Promise.all([ - axios.get(getServerUrl(PATH), { httpAgent: new http.Agent({ keepAlive: false })}), - axios.get(getServerUrl(PATH), { httpAgent: new http.Agent({ keepAlive: false })}), - axios.get(getServerUrl(LASTONE_PATH), { httpAgent: new http.Agent({ keepAlive: false })}), + axios.get(getServerUrl(PATH), { httpAgent: new http.Agent({ keepAlive: false }) }), + axios.get(getServerUrl(PATH), { httpAgent: new http.Agent({ keepAlive: false }) }), + axios.get(getServerUrl(LASTONE_PATH), { httpAgent: new http.Agent({ keepAlive: false }) }), ]).then((result) => { t.equal(activeTrace.getAllTraces().length, 0) t.equal('' + agent.mockAgentStartTime, agent.agentInfo.startTimestamp, "startTimestamp equals") @@ -54,4 +57,43 @@ test(`Should record active trace in multiple call`, function (t) { t.equal(agent.mockAgentId, fixture.config.agentId, "Agent ID equals") t.equal(agent.agentInfo, agent.pinpointClient.agentInfo, "AgentInfo equals") +}) + +test(`Active trace should be recorded with HTTP call`, function (t) { + const collectorServer = new grpc.Server() + collectorServer.addService(services.MetadataService, { + requestApiMetaData: (call, callback) => { + const result = new spanMessages.PResult() + callback(null, result) + } + }) + collectorServer.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (err, port) => { + agent.bindHttpWithCallSite(port) + + const app = new express() + app.get('/active-trace', async (req, res) => { + agent.callbackTraceClose((trace) => { + const actualCached = agent.getTraceContext().activeRequestRepository.activeTraceCache.get(trace.getTraceRoot().getTransactionId()) + t.equal(actualCached, trace.getTraceRoot(), 'active trace traceRoot is cached') + }) + setTimeout(() => { + res.send('ok get') + }, 1000) + }) + + const server = app.listen(TEST_ENV.port, async () => { + const result = await axios.get(getServerUrl('/active-trace'), { httpAgent: new http.Agent({ keepAlive: false }) }) + t.equal(result.status, 200, 'status code is 200') + server.close(() => { + const cacheSize = agent.getTraceContext().activeRequestRepository.activeTraceCache.cache.size + t.equal(cacheSize, 0, 'active trace cache is empty') + t.end() + }) + }) + }) + t.teardown(() => { + collectorServer.tryShutdown(() => { + + }) + }) }) \ No newline at end of file diff --git a/test/support/agent-singleton-mock.js b/test/support/agent-singleton-mock.js index 6be93d5c..559ce8b3 100644 --- a/test/support/agent-singleton-mock.js +++ b/test/support/agent-singleton-mock.js @@ -111,6 +111,7 @@ class MockAgent extends Agent { if (sampler.getSamplingCountGenerator()) { sampler.getSamplingCountGenerator().reset() } + this.traceContext.activeRequestRepository.activeTraceCache.cache.clear() transactionIdGenerator.reset() httpShared.clearPathMatcher()