From f594c365f4dc1c3ce88c67a45941418bf4dd3b84 Mon Sep 17 00:00:00 2001 From: Yongseok Date: Tue, 24 Dec 2024 16:04:52 +0900 Subject: [PATCH] [#251] Fix SQL-ID not found sqlId:1 bug * GrpcDataSender fixtures close resources * Functional Test port number --- lib/agent.js | 26 ++++--- lib/client/data-sender-factory.js | 3 +- lib/client/pinpoint-client.js | 1 - lib/context/span-event-recorder.js | 4 +- lib/context/trace/span-event-recorder2.js | 4 +- .../sql/sql-metadata-service.js | 16 ++-- test/client/data-sender.test.js | 5 +- test/client/grpc-data-sender.test.js | 10 +-- test/client/mock-grpc-data-sender.js | 35 ++++++--- test/fixtures/mock-data-sender.js | 65 ---------------- .../context/nested-async-trace.test.js | 49 +++++++----- .../request-header-utils.test.js | 4 +- test/support/agent-singleton-mock.js | 76 +++++++++++++++---- test/support/data-sender-mock.js | 29 ++++--- test/utils/log/logger.test.js | 8 +- 15 files changed, 176 insertions(+), 159 deletions(-) delete mode 100644 test/fixtures/mock-data-sender.js diff --git a/lib/agent.js b/lib/agent.js index ea2606d7..50bcea7d 100644 --- a/lib/agent.js +++ b/lib/agent.js @@ -11,6 +11,7 @@ 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') +const sqlMetadataService = require('./instrumentation/sql/sql-metadata-service') const Scheduler = require('./utils/scheduler') const AgentStatsMonitor = require('./metric/agent-stats-monitor') const { initializeConfig, getConfig } = require('./config') @@ -37,14 +38,13 @@ class Agent { const agentStartTime = Date.now() this.agentInfo = this.createAgentInfo(this.config, agentStartTime) - this.initializeDataSender() - this.initializePinpointClient() + const dataSender = this.makeDataSender() + this.dataSender = dataSender + this.initializeDataSender(dataSender) + this.initializePinpointClient(dataSender) this.traceContext = new TraceContext(this.agentInfo, this.dataSender, this.config) - stringMetaService.init(this.dataSender) - apiMetaService.init(this.dataSender) - this.startSchedule(agentId, agentStartTime) this.initializeSupportModules() @@ -53,17 +53,23 @@ class Agent { log.warn('[Pinpoint Agent][' + agentId + '] Init Completed') } - initializeDataSender() { - this.dataSender = dataSenderFactory.create(this.config, this.agentInfo) - this.dataSender.send(this.agentInfo) + makeDataSender() { + return dataSenderFactory.create(this.config, this.agentInfo) + } + + initializeDataSender(dataSender) { + dataSender.send(this.agentInfo) + stringMetaService.init(dataSender) + apiMetaService.init(dataSender) + sqlMetadataService.setDataSender(dataSender) } initializeSupportModules() { this.moduleHook = new ModuleHook(this) } - initializePinpointClient() { - this.pinpointClient = new PinpointClient(this.config, this.agentInfo, this.dataSender) + initializePinpointClient(dataSender) { + this.pinpointClient = new PinpointClient(this.config, this.agentInfo, dataSender) } createTraceObject(requestData) { diff --git a/lib/client/data-sender-factory.js b/lib/client/data-sender-factory.js index d27a5e11..29df5b21 100644 --- a/lib/client/data-sender-factory.js +++ b/lib/client/data-sender-factory.js @@ -10,7 +10,7 @@ const GrpcDataSender = require('./grpc-data-sender') const DataSender = require('./data-sender') const create = (config, agentInfo) => { - const dataSender = new DataSender(config, new GrpcDataSender( + return new DataSender(config, new GrpcDataSender( config.collectorIp, config.collectorTcpPort, config.collectorStatPort, @@ -18,7 +18,6 @@ const create = (config, agentInfo) => { agentInfo, config )) - return dataSender } module.exports = { diff --git a/lib/client/pinpoint-client.js b/lib/client/pinpoint-client.js index 0d9e27a6..8a59c9b8 100644 --- a/lib/client/pinpoint-client.js +++ b/lib/client/pinpoint-client.js @@ -7,7 +7,6 @@ 'use strict' const CommandType = require('../constant/commaned-type').CommandType -const log = require('../utils/logger') class PinpointClient { constructor(config, agentInfo, dataSender) { diff --git a/lib/context/span-event-recorder.js b/lib/context/span-event-recorder.js index 7b3dd00b..f9881621 100644 --- a/lib/context/span-event-recorder.js +++ b/lib/context/span-event-recorder.js @@ -11,7 +11,7 @@ const StringMetaService = require('./string-meta-service') const AsyncId = require('./async-id') const AnnotationKeyUtils = require('./annotation-key-utils') const log = require('../utils/logger') -const sqlMetaDataService = require('../instrumentation/sql/sql-metadata-service') +const sqlMetadataService = require('../instrumentation/sql/sql-metadata-service') const Annotations = require('../instrumentation/context/annotation/annotations') // https://github.com/pinpoint-apm/pinpoint/blob/master/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/context/SpanEventRecorder.java @@ -157,7 +157,7 @@ class SpanEventRecorder { return } - const parsingResult = sqlMetaDataService.cacheSql(sql) + const parsingResult = sqlMetadataService.cacheSql(sql) this.recordSqlParsingResult(parsingResult, bindString) return parsingResult } diff --git a/lib/context/trace/span-event-recorder2.js b/lib/context/trace/span-event-recorder2.js index a4653512..a918d2db 100644 --- a/lib/context/trace/span-event-recorder2.js +++ b/lib/context/trace/span-event-recorder2.js @@ -11,7 +11,7 @@ const Annotations = require('../../instrumentation/context/annotation/annotation const SpanEventBuilder = require('./span-event-builder') const log = require('../../utils/logger') const AnnotationKeyUtils = require('../annotation-key-utils') -const sqlMetaDataService = require('../../instrumentation/sql/sql-metadata-service') +const sqlMetadataService = require('../../instrumentation/sql/sql-metadata-service') const stringMetaService = require('../string-meta-service') const AsyncId = require('../async-id') @@ -127,7 +127,7 @@ class SpanEventRecorder { return } - const parsingResult = sqlMetaDataService.cacheSql(sql) + const parsingResult = sqlMetadataService.cacheSql(sql) this.recordSqlParsingResult(parsingResult, bindString) return parsingResult } diff --git a/lib/instrumentation/sql/sql-metadata-service.js b/lib/instrumentation/sql/sql-metadata-service.js index 707158b0..eadc67f8 100644 --- a/lib/instrumentation/sql/sql-metadata-service.js +++ b/lib/instrumentation/sql/sql-metadata-service.js @@ -8,17 +8,13 @@ const SimpleCache = require('../../utils/simple-cache') const SqlParser = require('./sql-parser') const ParsingResult = require('./parsing-result') -class SqlMetaDataService { +class SqlMetadataService { constructor() { this.cache = new SimpleCache(1024) } - set dataSender(dataSender) { - this._dataSender = dataSender - } - - get dataSender() { - return this._dataSender + setDataSender(dataSender) { + this.dataSender = dataSender } cacheSql(sql) { @@ -38,10 +34,8 @@ class SqlMetaDataService { } send(sqlMetaData) { - if (this.dataSender && typeof this.dataSender.send === 'function') { - this.dataSender.send(sqlMetaData) - } + this.dataSender?.send?.(sqlMetaData) } } -module.exports = new SqlMetaDataService() \ No newline at end of file +module.exports = new SqlMetadataService() \ No newline at end of file diff --git a/test/client/data-sender.test.js b/test/client/data-sender.test.js index 192dc54f..d0840bb1 100644 --- a/test/client/data-sender.test.js +++ b/test/client/data-sender.test.js @@ -6,7 +6,7 @@ const test = require('tape') -require('../support/agent-singleton-mock') +const agent = require('../support/agent-singleton-mock') const { fixture } = require('../test-helper') const dataSenderMock = require('../support/data-sender-mock') const dataSender = dataSenderMock() @@ -18,6 +18,7 @@ const defaultPredefinedMethodDescriptorRegistry = require('../../lib/constant/de test('Should send agent info', function (t) { t.plan(1) + agent.bindHttp() dataSender.send(agentInfo) @@ -26,6 +27,7 @@ test('Should send agent info', function (t) { test('Should send api meta info', function (t) { t.plan(1) + agent.bindHttp() const methodDescriptor = defaultPredefinedMethodDescriptorRegistry.nodeServerMethodDescriptor const apiMetaInfo = ApiMetaInfo.create(methodDescriptor) @@ -36,6 +38,7 @@ test('Should send api meta info', function (t) { test('Should send string meta info', function (t) { t.plan(1) + agent.bindHttp() const stringMetaInfo = StringMetaInfo.create('1', 'test string') dataSender.send(stringMetaInfo) diff --git a/test/client/grpc-data-sender.test.js b/test/client/grpc-data-sender.test.js index 00725697..33d29b5f 100644 --- a/test/client/grpc-data-sender.test.js +++ b/test/client/grpc-data-sender.test.js @@ -20,10 +20,10 @@ const AsyncSpanChunkBuilder = require('../../lib/context/trace/async-span-chunk- const SpanRepository = require('../../lib/context/trace/span-repository') const ChildTraceBuilder = require('../../lib/context/trace/child-trace-builder') const serviceType = require('../../lib/context/service-type') -const makeMockDataSender = require('../fixtures/mock-data-sender') const SpanChunkBuilder = require('../../lib/context/span-chunk-builder') const Trace = require('../../lib/context/trace/trace2') const defaultPredefinedMethodDescriptorRegistry = require('../../lib/constant/default-predefined-method-descriptor-registry') +const dataSenderMock = require('../support/data-sender-mock') let sendSpanMethodOnDataCallback function sendSpan(call) { @@ -70,7 +70,7 @@ test('Should send span', function (t) { server.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => { const grpcDataSender = beforeSpecificOne(port, DataSource) const traceRoot = new RemoteTraceRootBuilder(agent.agentInfo, '5').build() - dataSender = makeMockDataSender(agent.config, grpcDataSender) + dataSender = dataSenderMock(agent.config, grpcDataSender) const spanBuilder = new SpanBuilder(traceRoot) spanBuilder.setServiceType(1400) spanBuilder.setEndPoint('localhost:3000') @@ -167,7 +167,7 @@ test('sendSpanChunk redis.SET.end', function (t) { const grpcDataSender = beforeSpecificOne(port, DataSource) const traceRoot = new RemoteTraceRootBuilder(agent.agentInfo, '5').build() const asyncId = AsyncId.make() - dataSender = makeMockDataSender(agent.config, grpcDataSender) + dataSender = dataSenderMock(agent.config, grpcDataSender) const spanChunkBuilder = new AsyncSpanChunkBuilder(traceRoot, asyncId) const repository = new SpanRepository(spanChunkBuilder, dataSender, agent.agentInfo) const childTraceBuilder = new ChildTraceBuilder(traceRoot, repository, asyncId) @@ -245,7 +245,7 @@ test('sendSpanChunk redis.GET.end', (t) => { const grpcDataSender = beforeSpecificOne(port, DataSource) const traceRoot = new RemoteTraceRootBuilder(agent.agentInfo, '5').build() const asyncId = AsyncId.make() - dataSender = makeMockDataSender(agent.config, grpcDataSender) + dataSender = dataSenderMock(agent.config, grpcDataSender) const spanChunkBuilder = new AsyncSpanChunkBuilder(traceRoot, asyncId) const repository = new SpanRepository(spanChunkBuilder, dataSender, agent.agentInfo) const childTraceBuilder = new ChildTraceBuilder(traceRoot, repository, asyncId) @@ -315,7 +315,7 @@ test('sendSpan', (t) => { server.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), (error, port) => { const grpcDataSender = beforeSpecificOne(port, DataSource) const traceRoot = new RemoteTraceRootBuilder(agent.agentInfo, '5').build() - dataSender = makeMockDataSender(agent.config, grpcDataSender) + dataSender = dataSenderMock(agent.config, grpcDataSender) const spanBuilder = new SpanBuilder(traceRoot) const spanChunkBuilder = new SpanChunkBuilder(traceRoot) const repository = new SpanRepository(spanChunkBuilder, dataSender, agent.agentInfo) diff --git a/test/client/mock-grpc-data-sender.js b/test/client/mock-grpc-data-sender.js index 7ad8b86d..bbfe1fce 100644 --- a/test/client/mock-grpc-data-sender.js +++ b/test/client/mock-grpc-data-sender.js @@ -7,12 +7,27 @@ 'use strict' const GrpcDataSender = require('../../lib/client/grpc-data-sender') +class MockGrpcStream { + constructor(stream) { + this.grpcStream = stream + } + + write(data) { + this.grpcStream.write(data) + } + + end() { + } +} + class MockGrpcDataSender extends GrpcDataSender { initializeClients() { let self = this this.agentClient = { requestAgentInfo: function (pAgentInfo) { self.actualAgentInfo = pAgentInfo + }, + close: function () { } } @@ -28,12 +43,14 @@ class MockGrpcDataSender extends GrpcDataSender { }, requestSqlUidMetaData: function (pSqlUidMetaData) { self.actualSqlUidMetaData = pSqlUidMetaData + }, + close: function () { } } this.actualSpans = [] } - get actualSpan () { + get actualSpan() { return this.actualSpans[this.actualSpans.length - 1] } @@ -42,19 +59,19 @@ class MockGrpcDataSender extends GrpcDataSender { initializeSpanStream() { let self = this - this.spanStream = { + this.spanStream = new MockGrpcStream({ write: function (span) { self.actualSpans.push(span) }, end: function () { } - } + }) } initializeProfilerClients() { let self = this - this.commandStream = { + this.commandStream = new MockGrpcStream({ write: function (pmessage) { self.actualPCmdMessage = pmessage }, @@ -64,12 +81,12 @@ class MockGrpcDataSender extends GrpcDataSender { on: function () { } - } + }) } initializeStatStream() { let self = this - this.statStream = { + this.statStream = new MockGrpcStream({ write: function (pmessage) { self.actualPStatMessage = pmessage }, @@ -79,12 +96,12 @@ class MockGrpcDataSender extends GrpcDataSender { on: function () { } - } + }) } initializePingStream() { let self = this - this.pingStream = { + this.pingStream = new MockGrpcStream({ write: function (pmessage) { self.actualPingMessage = pmessage }, @@ -94,7 +111,7 @@ class MockGrpcDataSender extends GrpcDataSender { on: function () { } - } + }) } initializeAgentInfoScheduler() { diff --git a/test/fixtures/mock-data-sender.js b/test/fixtures/mock-data-sender.js deleted file mode 100644 index 89688894..00000000 --- a/test/fixtures/mock-data-sender.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Pinpoint Node.js Agent - * Copyright 2020-present NAVER Corp. - * Apache License v2.0 - */ - -'use strict' - -const DataSender = require('../../lib/client/data-sender') -const AgentInfo = require('../../lib/data/dto/agent-info') -const ApiMetaInfo = require('../../lib/data/dto/api-meta-info') -const StringMetaInfo = require('../../lib/data/dto/string-meta-info') -const Span = require('../../lib/context/span') -const SpanChunk = require('../../lib/context/span-chunk') -const SqlMetaData = require('../../lib/client/sql-meta-data') - -class MockDataSender extends DataSender { - constructor(config, dataSender) { - super(config, dataSender) - this.mockAPIMetaInfos = [] - this.mockSpanChunks = [] - this.mockSpans = [] - } - - send(data) { - if (data instanceof AgentInfo) { - this.mockAgentInfo = data - super.send(data) - } else if (data instanceof ApiMetaInfo) { - this.mockAPIMetaInfos.push(data) - super.send(data) - } else if (data instanceof StringMetaInfo) { - this.mockMetaInfo = data - super.send(data) - } else if (data instanceof Span) { - this.mockSpan = data - this.mockSpans.push(data) - super.send(data) - } else if (data instanceof SpanChunk) { - this.mockSpanChunks.push(data) - super.send(data) - } else if (data instanceof SqlMetaData) { - this.mockSqlMetaData = data - super.send(data) - } else if (data?.isAsyncSpanChunk?.()) { - this.mockSpanChunks.push(data) - super.send(data) - } else if (data?.isSpan?.()) { - this.mockSpan = data - this.mockSpans.push(data) - super.send(data) - } - } - - findSpanChunk(asyncId) { - return this.mockSpanChunks.find(spanChunk => spanChunk.localAsyncId.asyncId === (asyncId.asyncId || asyncId)) - } - findSpanEvent(apiId) { - return this.mockSpan.spanEventList.find(event => event.apiId === apiId) - } -} - -const makeMockDataSender = (config, dataSender) => new MockDataSender(config, dataSender) - -module.exports = makeMockDataSender \ No newline at end of file diff --git a/test/instrumentation/context/nested-async-trace.test.js b/test/instrumentation/context/nested-async-trace.test.js index 97b73d72..e5929cf4 100644 --- a/test/instrumentation/context/nested-async-trace.test.js +++ b/test/instrumentation/context/nested-async-trace.test.js @@ -26,6 +26,7 @@ const services = require('../../../lib/data/v1/Service_grpc_pb') const spanMessages = require('../../../lib/data/v1/Span_pb') const log = require('../../../lib/utils/logger') const { Empty } = require('google-protobuf/google/protobuf/empty_pb') +const sqlMetadataService = require('../../../lib/instrumentation/sql/sql-metadata-service') let callbackPresultReturnUnaryService const pResultReturnUnaryService = (call, callback) => { @@ -56,9 +57,7 @@ const spanMessageStreamService = (call) => { spanMessageEndEventCallback?.() } }) - - call.on('end', () => { - }) + call.on('end', () => {}) } function sendAgentStat(call, callback) { @@ -95,6 +94,7 @@ test(`nested mysql async query with express`, async (t) => { collectorServer.addService(services.MetadataService, { requestApiMetaData: pResultReturnUnaryService, requestSqlUidMetaData: pResultReturnUnaryService, + requestSqlMetaData: pResultReturnUnaryService }) process.env['PINPOINT_PROFILER_SQL_STAT'] = 'true' @@ -298,6 +298,7 @@ test(`nested mysql2 async query with express`, async (t) => { collectorServer.addService(services.MetadataService, { requestApiMetaData: pResultReturnUnaryService, requestSqlUidMetaData: pResultReturnUnaryService, + requestSqlMetaData: pResultReturnUnaryService }) collectorServer.bindAsync('localhost:0', grpc.ServerCredentials.createInsecure(), async (err, port) => { @@ -363,7 +364,7 @@ test(`nested mysql2 async query with express`, async (t) => { t.true(trace.spanBuilder.remoteAddress === '127.0.0.1' || trace.spanBuilder.remoteAddress === '::1', `remoteAddress is ${trace.spanBuilder.remoteAddress}`) let actualBuilder = new MethodDescriptorBuilder(expected('get', 'app.get')) .setClassName(expected('app', 'Function')) - .setLineNumber(319) + .setLineNumber(320) .setFileName('nested-async-trace.test.js') let actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder) let actualSpanEvent = trace.spanBuilder.spanEventList.find(spanEvent => spanEvent.sequence === 0) @@ -376,7 +377,7 @@ test(`nested mysql2 async query with express`, async (t) => { t.equal(actualSpanEvent.serviceType, expressServiceType.getCode(), 'serviceType is express') actualBuilder = new MethodDescriptorBuilder('createConnection') - .setLineNumber(320) + .setLineNumber(321) .setFileName('nested-async-trace.test.js') actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder) actualSpanEvent = trace.spanBuilder.spanEventList.find(spanEvent => spanEvent.sequence === 1) @@ -389,7 +390,7 @@ test(`nested mysql2 async query with express`, async (t) => { actualBuilder = new MethodDescriptorBuilder('query') .setClassName('Connection') - .setLineNumber(330) + .setLineNumber(331) .setFileName('nested-async-trace.test.js') actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder) actualSpanEvent = trace.spanBuilder.spanEventList.find(spanEvent => spanEvent.sequence === 2) @@ -411,7 +412,7 @@ test(`nested mysql2 async query with express`, async (t) => { actualBuilder = new MethodDescriptorBuilder('query') .setClassName('Connection') - .setLineNumber(336) + .setLineNumber(337) .setFileName('nested-async-trace.test.js') actualMethodDescriptor = apiMetaService.cacheApiWithBuilder(actualBuilder) actualSpanEvent = actualSpanChunk.spanEventList[1] @@ -459,6 +460,7 @@ test(`nested mysql2 async query with express`, async (t) => { connection.end() t.equal(agent.getSendedApiMetaInfos().length, 0, 'agent.getSendedApiMetaInfos() is empty') + t.equal(agent.getSqlMetadata().length, 0, 'agent.getSqlMetadata() is empty') t.end() trace.repository.dataSender.close() } @@ -466,17 +468,28 @@ test(`nested mysql2 async query with express`, async (t) => { }) callbackPresultReturnUnaryService = async (error, result, call) => { - const apiDescriptor = [...apiMetaService.cache.cache.entries()] - .map(([, value]) => value) - .find(apiDescriptor => apiDescriptor.apiId === call.request.getApiid()) - t.equal(call.request.getApiid(), apiDescriptor.apiId, `apiId is ${call.request.getApiid()}`) - t.equal(call.request.getApiinfo(), apiDescriptor.getApiDescriptor(), `apiInfo is ${call.request.getApiinfo()}`) - t.equal(call.request.getLine(), apiDescriptor.lineNumber, `line is ${call.request.getLine()}`) - t.equal(call.request.getLocation(), apiDescriptor.getLocation(), `location is ${call.request.getLocation()}`) - t.equal(call.request.getType(), apiDescriptor.getType(), `type is ${call.request.getType()}`) - const sendedApiMetaInfos = agent.getSendedApiMetaInfos() - const index = sendedApiMetaInfos.findIndex(item => item === apiDescriptor) - sendedApiMetaInfos.splice(index, 1) + if (typeof call.request.getApiid === 'function') { + const apiDescriptor = [...apiMetaService.cache.cache.entries()] + .map(([, value]) => value) + .find(apiDescriptor => apiDescriptor.apiId === call.request.getApiid()) + t.equal(call.request.getApiid(), apiDescriptor.apiId, `apiId is ${call.request.getApiid()}`) + t.equal(call.request.getApiinfo(), apiDescriptor.getApiDescriptor(), `apiInfo is ${call.request.getApiinfo()}`) + t.equal(call.request.getLine(), apiDescriptor.lineNumber, `line is ${call.request.getLine()}`) + t.equal(call.request.getLocation(), apiDescriptor.getLocation(), `location is ${call.request.getLocation()}`) + t.equal(call.request.getType(), apiDescriptor.getType(), `type is ${call.request.getType()}`) + const sendedApiMetaInfos = agent.getSendedApiMetaInfos() + const index = sendedApiMetaInfos.findIndex(item => item === apiDescriptor) + sendedApiMetaInfos.splice(index, 1) + } else { + const parsingResult = [...sqlMetadataService.cache.cache.entries()] + .map(([, value]) => value) + .find(parsingResult => parsingResult.sqlMetaDataValue().sqlId === call.request.getSqlid()) + t.equal(call.request.getSqlid(), parsingResult.sqlMetaDataValue().sqlId, `sqlId is ${call.request.getSqlid()}`) + t.equal(call.request.getSql(), parsingResult.sqlMetaDataValue().sql, `sql is ${call.request.getSql()}`) + const sendedSqlMetadata = agent.getSqlMetadata() + const index = sendedSqlMetadata.findIndex(item => item === parsingResult) + sendedSqlMetadata.splice(index, 1) + } } dataStreamCount = 0 diff --git a/test/instrumentation/request-header-utils.test.js b/test/instrumentation/request-header-utils.test.js index 920c9cab..9a1a0a77 100644 --- a/test/instrumentation/request-header-utils.test.js +++ b/test/instrumentation/request-header-utils.test.js @@ -10,7 +10,6 @@ const http = require('http') const https = require('https') const { fixture } = require('../test-helper') const agent = require('../support/agent-singleton-mock') -agent.bindHttp() const localStorage = require('../../lib/instrumentation/context/local-storage') const express = require('express') const HttpOutgoingRequestHeader = require('../../lib/instrumentation/http/http-outgoing-request-header') @@ -27,6 +26,7 @@ const endPoint = 'localhost:5005' const rpcName = '/tests/123' test('Should read pinpoint header', async function (t) { + agent.bindHttp() const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }) res.end('hello') @@ -47,6 +47,7 @@ test('Should read pinpoint header', async function (t) { }) test('Should write pinpoint header', async function (t) { + agent.bindHttp() const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }) res.end('hello') @@ -79,6 +80,7 @@ test('Should write pinpoint header', async function (t) { }) test('nested request HTTP', async function (t) { + agent.bindHttp() const app = new express() let actualAssertsOn5006 diff --git a/test/support/agent-singleton-mock.js b/test/support/agent-singleton-mock.js index c0988ae9..06d517cd 100644 --- a/test/support/agent-singleton-mock.js +++ b/test/support/agent-singleton-mock.js @@ -15,7 +15,7 @@ const shimmer = require('@pinpoint-apm/shimmer') const httpShared = require('../../lib/instrumentation/http-shared') const activeTrace = require('../../lib/metric/active-trace') const localStorage = require('../../lib/instrumentation/context/local-storage') -const sqlMetaDataService = require('../../lib/instrumentation/sql/sql-metadata-service') +const sqlMetadataService = require('../../lib/instrumentation/sql/sql-metadata-service') const SimpleCache = require('../../lib/utils/simple-cache') const sampler = require('../../lib/sampler/sampler') const TraceSampler = require('../../lib/context/trace/trace-sampler') @@ -47,6 +47,15 @@ const resetSendedApiMetaInfos = () => { const getSendedApiMetaInfos = () => { return sendedApiMetaInfos } + +let sqlMetadata = [] +const resetSqlMetaData = () => { + sqlMetadata = [] +} +const getSqlMetadata = () => { + return sqlMetadata +} + const getTraceByAsyncId = (asyncId) => { return getTraces().find(trace => { const spanChunkSpanEvents = agent.dataSender.mockSpanChunks.flatMap(spanChunk => spanChunk.spanEventList) @@ -57,6 +66,14 @@ const getTraceByAsyncId = (asyncId) => { } class MockAgent extends Agent { + constructor(initOptions) { + initOptions.collector['span-port'] = -1 + initOptions.collector['stat-port'] = -1 + initOptions.collector['tcp-port'] = -1 + initOptions = portProperties(initOptions) + super(initOptions) + } + startSchedule(agentId, agentStartTime) { this.mockAgentId = agentId this.mockAgentStartTime = agentStartTime @@ -71,8 +88,7 @@ class MockAgent extends Agent { this.cleanHttp() this.dataSender.clear() - json = this.portProperties(json) - + json = portProperties(json) if (!json) { json = require('../pinpoint-config-test') } else { @@ -82,7 +98,7 @@ class MockAgent extends Agent { const config = require('../../lib/config').getConfig(json) this.config = config - sqlMetaDataService.cache = new SimpleCache(1024) + sqlMetadataService.cache = new SimpleCache(1024) this.traceContext.isSampling = sampler.getIsSampling(config.sampling, config.sampleRate) if (sampler.getSamplingCountGenerator()) { sampler.getSamplingCountGenerator().reset() @@ -107,12 +123,14 @@ class MockAgent extends Agent { this.traceContext.traceSampler = new TraceSampler(this.agentInfo, config) this.traceContext.config = config - const dataSender = dataSenderMock(this.config, this.agentInfo) + const dataSender = this.makeDataSender() this.traceContext.dataSender = dataSender + this.dataSender.close() this.dataSender = dataSender - + // this.initializeDataSender(dataSender) stringMetaService.init(dataSender) apiMetaService.init(dataSender) + sqlMetadataService.setDataSender(dataSender) resetSpanOrSpanChunks() @@ -151,6 +169,15 @@ class MockAgent extends Agent { return returned } }) + + resetSqlMetaData() + shimmer.wrap(sqlMetadataService, 'send', function (origin) { + return function () { + const returned = origin.apply(this, arguments) + getSqlMetadata().push(arguments[0]) + return returned + } + }) } cleanHttp() { @@ -170,20 +197,11 @@ class MockAgent extends Agent { } bindHttpWithCallSite(conf) { - conf = this.portProperties(conf) + conf = portProperties(conf) conf = Object.assign({}, { 'trace-location-and-filename-of-call-site': true }, conf) this.bindHttp(conf) } - portProperties(conf) { - if (typeof conf !== 'number') { - return conf - } - const testConf = require('../pinpoint-config-test') - const collectorConf = Object.assign(testConf.collector, { 'span-port': conf, 'stat-port': conf, 'tcp-port': conf }) - return Object.assign({}, { collector: collectorConf }) - } - completeTraceObject(trace) { super.completeTraceObject(trace) } @@ -208,6 +226,10 @@ class MockAgent extends Agent { return getSendedApiMetaInfos() } + getSqlMetadata() { + return getSqlMetadata() + } + setNewTraceCallback(callback) { this.newTraceCallback = callback } @@ -219,7 +241,29 @@ class MockAgent extends Agent { getTraceByAsyncId(asyncId) { return getTraceByAsyncId(asyncId) } + + makeDataSender() { + return dataSenderMock(this.config, this.agentInfo) + } } +function portProperties(conf) { + if (!conf) { + return conf + } + + if (typeof conf !== 'number') { + if (conf.collector) { + return conf + } + const collectorConf = Object.assign({ 'ip': '127.0.0.1', 'span-port': -1, 'stat-port': -1, 'tcp-port': -1 }) + return Object.assign(conf, { collector: collectorConf }) + } + const portNumber = conf + const collectorConf = Object.assign(require('../pinpoint-config-test').collector, { 'span-port': portNumber, 'stat-port': portNumber, 'tcp-port': portNumber }) + return Object.assign({ collector: collectorConf }) +} + + const agent = new MockAgent(require('../pinpoint-config-test')) module.exports = agent \ No newline at end of file diff --git a/test/support/data-sender-mock.js b/test/support/data-sender-mock.js index 7ec0b1c7..7c18a4ba 100644 --- a/test/support/data-sender-mock.js +++ b/test/support/data-sender-mock.js @@ -15,6 +15,7 @@ const DataSender = require('../../lib/client/data-sender') const MockGrpcDataSender = require('../client/mock-grpc-data-sender') const SqlMetaData = require('../../lib/client/sql-meta-data') const GrpcDataSender = require('../../lib/client/grpc-data-sender') +const SqlUidMetaData = require('../../lib/client/sql-uid-meta-data') class MockDataSender extends DataSender { constructor(config, dataSender) { @@ -22,6 +23,8 @@ class MockDataSender extends DataSender { this.mockAPIMetaInfos = [] this.mockSpanChunks = [] this.mockSpans = [] + this.mockSqlMetadata = [] + this.mockSqlUidMetadata = [] } send(data) { @@ -31,31 +34,26 @@ class MockDataSender extends DataSender { if (data instanceof AgentInfo) { this.mockAgentInfo = data - super.send(data) } else if (data instanceof ApiMetaInfo) { this.mockAPIMetaInfos.push(data) - super.send(data) } else if (data instanceof StringMetaInfo) { this.mockMetaInfo = data - super.send(data) } else if (data instanceof Span) { this.mockSpan = data this.mockSpans.push(data) - super.send(data) } else if (data instanceof SpanChunk) { this.mockSpanChunks.push(data) - super.send(data) } else if (data instanceof SqlMetaData) { - this.mockSqlMetaData = data - super.send(data) + this.mockSqlMetadata.push(data) } else if (data?.isAsyncSpanChunk?.()) { this.mockSpanChunks.push(data) - super.send(data) } else if (data?.isSpan?.()) { this.mockSpan = data this.mockSpans.push(data) - super.send(data) + } else if (data instanceof SqlUidMetaData) { + this.mockSqlUidMetadata.push(data) } + super.send(data) } findSpanChunk(asyncId) { @@ -69,6 +67,8 @@ class MockDataSender extends DataSender { this.mockAPIMetaInfos = [] this.mockSpanChunks = [] this.mockSpans = [] + this.mockSqlMetadata = [] + this.mockSqlUidMetadata = [] } close() { @@ -77,11 +77,16 @@ class MockDataSender extends DataSender { } } -const dataSender = (conf, agentInfo) => { - if (typeof conf?.collectorSpanPort === 'number') { +const dataSender = (conf, agentInfoOrGrpcDataSender) => { + if (typeof agentInfoOrGrpcDataSender?.sendAgentInfo === 'function') { return new MockDataSender({ enabledDataSending: true, - }, new GrpcDataSender(conf.collectorIp, conf.collectorSpanPort, conf.collectorStatPort, conf.collectorTcpPort, agentInfo, conf)) + }, agentInfoOrGrpcDataSender) + } + if (conf?.collectorSpanPort > 0) { + return new MockDataSender({ + enabledDataSending: true, + }, new GrpcDataSender(conf.collectorIp, conf.collectorSpanPort, conf.collectorStatPort, conf.collectorTcpPort, agentInfoOrGrpcDataSender, conf)) } return new MockDataSender({ enabledDataSending: true, diff --git a/test/utils/log/logger.test.js b/test/utils/log/logger.test.js index fdfca3a8..bdddecfa 100644 --- a/test/utils/log/logger.test.js +++ b/test/utils/log/logger.test.js @@ -60,16 +60,16 @@ test('Logger.Builder', (t) => { test('Logger by a log level', (t) => { let actual = Logger.makeBuilder('debug', {}).build() - t.equal(actual.type.name, 'DEBUG') + t.equal(actual.type.name, 'DEBUG', `debug name match`) actual = Logger.makeBuilder('info', {}).build() - t.equal(actual.type.name, 'INFO') + t.equal(actual.type.name, 'INFO', `info name match`) actual = Logger.makeBuilder('warn', {}).build() - t.equal(actual.type.name, 'WARN') + t.equal(actual.type.name, 'WARN', `warn name match`) actual = Logger.makeBuilder('error', {}).build() - t.equal(actual.type.name, 'ERROR') + t.equal(actual.type.name, 'ERROR', `error name match`) t.end() }) \ No newline at end of file