Skip to content

Commit 98d1b3d

Browse files
committed
[#404] Configuration Reconstructing
1 parent 0a3fc0d commit 98d1b3d

File tree

4 files changed

+129
-45
lines changed

4 files changed

+129
-45
lines changed

lib/config-builder.js

Lines changed: 72 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
const fs = require('fs')
1010
const path = require('path')
1111
const { randomBytes } = require('node:crypto')
12+
const { levels } = require('loglevel')
1213

1314
class Config {
1415
constructor(config) {
@@ -52,13 +53,12 @@ class ConfigBuilder {
5253
this.userDefinedJson = this.userDefinedJsonFromFile()
5354
}
5455

55-
const config = Object.assign({},
56+
const config = mergeConfig(
5657
this.defaultJson,
5758
this.userDefinedJson,
5859
makeEnvironmentConfig(),
5960
this.agentStartupUserDefinedJson
6061
)
61-
6262
for (const handler of this.handlers) {
6363
const changes = handler.handle(config)
6464
applyConfigChanges(config, changes)
@@ -140,22 +140,37 @@ class ApplicationNameValidator {
140140
}
141141

142142
function makeEnvironmentConfig() {
143-
return {
143+
const envConfig = {
144144
agentId: valueOfString('PINPOINT_AGENT_ID'),
145145
agentName: valueOfString('PINPOINT_AGENT_NAME'),
146146
applicationName: valueOfString('PINPOINT_APPLICATION_NAME'),
147147
applicationServiceType: valueOfNumber('PINPOINT_SERVICE_TYPE'),
148-
collector: makeCollectorEnvironmentConfig(),
149-
sampling: makeSamplingEnvironmentConfig(),
148+
collector: {
149+
ip: valueOfString('PINPOINT_COLLECTOR_IP'),
150+
spanPort: valueOfNumber('PINPOINT_COLLECTOR_SPAN_PORT'),
151+
statPort: valueOfNumber('PINPOINT_COLLECTOR_STAT_PORT'),
152+
tcpPort: valueOfNumber('PINPOINT_COLLECTOR_TCP_PORT'),
153+
},
154+
sampling: {
155+
"enable": valueOfBoolean('PINPOINT_SAMPLING'),
156+
rate: valueOfNumber('PINPOINT_SAMPLING_RATE')
157+
},
150158
features: {
151159
container: valueOfBoolean('PINPOINT_CONTAINER'),
152160
logLevels: makeLogLevelsEnvironmentConfig(),
153-
traceExclusionUrl: makeTraceExclusionUrlEnvironmentConfig(),
161+
traceExclusionUrl: {
162+
patterns: valueOfString('PINPOINT_TRACE_EXCLUSION_URL_PATTERNS'),
163+
cacheSize: valueOfNumber('PINPOINT_TRACE_EXCLUSION_URL_CACHE_SIZE')
164+
},
154165
sqlStats: valueOfBoolean('PINPOINT_PROFILER_SQL_STAT')
155166
},
156-
plugins: makePluginsEnvironmentConfig(),
167+
plugins: {
168+
httpErrorStatusCodes: valueOfString('PINPOINT_HTTP_STATUS_CODE_ERRORS')
169+
},
157170
enable: valueOfBoolean('PINPOINT_ENABLE')
158171
}
172+
173+
return pruneUndefined(envConfig)
159174
}
160175

161176
function valueOfString(envName) {
@@ -173,25 +188,6 @@ function valueOfBoolean(envName) {
173188
return typeof value === 'string' ? value.toLowerCase() === 'true' : undefined
174189
}
175190

176-
function makeCollectorEnvironmentConfig() {
177-
return {
178-
ip: valueOfString('PINPOINT_COLLECTOR_IP'),
179-
spanPort: valueOfNumber('PINPOINT_COLLECTOR_SPAN_PORT'),
180-
statPort: valueOfNumber('PINPOINT_COLLECTOR_STAT_PORT'),
181-
tcpPort: valueOfNumber('PINPOINT_COLLECTOR_TCP_PORT'),
182-
}
183-
}
184-
185-
function makeSamplingEnvironmentConfig() {
186-
const samplingEnable = valueOfBoolean('PINPOINT_SAMPLING')
187-
if (!samplingEnable) {
188-
return
189-
}
190-
191-
return {
192-
rate: valueOfNumber('PINPOINT_SAMPLING_RATE')
193-
}
194-
}
195191

196192
function makeLogLevelsEnvironmentConfig() {
197193
const value = process.env['PINPOINT_LOGGER_LEVELS']
@@ -223,17 +219,60 @@ function makeLogLevelsEnvironmentConfig() {
223219
return Object.keys(loggerLevels).length > 0 ? loggerLevels : undefined
224220
}
225221

226-
function makeTraceExclusionUrlEnvironmentConfig() {
227-
return {
228-
patterns: valueOfString('PINPOINT_TRACE_EXCLUSION_URL_PATTERNS'),
229-
cacheSize: valueOfNumber('PINPOINT_TRACE_EXCLUSION_URL_CACHE_SIZE')
222+
223+
function mergeConfig(...sources) {
224+
const result = {}
225+
for (const source of sources) {
226+
mergeObject(result, source)
227+
}
228+
return result
229+
}
230+
231+
function mergeObject(target, source) {
232+
if (!isPlainObject(source)) {
233+
return target
234+
}
235+
236+
for (const [key, value] of Object.entries(source)) {
237+
if (value === undefined) {
238+
continue
239+
}
240+
241+
if (isPlainObject(value)) {
242+
if (!isPlainObject(target[key])) {
243+
target[key] = {}
244+
}
245+
mergeObject(target[key], value)
246+
} else {
247+
target[key] = value
248+
}
230249
}
250+
return target
231251
}
232252

233-
function makePluginsEnvironmentConfig() {
234-
return {
235-
httpErrorStatusCodes: valueOfString('PINPOINT_HTTP_STATUS_CODE_ERRORS')
253+
function pruneUndefined(value) {
254+
if (Array.isArray(value)) {
255+
return value
256+
}
257+
258+
if (!isPlainObject(value)) {
259+
return value
260+
}
261+
262+
const pruned = {}
263+
for (const [key, val] of Object.entries(value)) {
264+
if (val === undefined) {
265+
continue
266+
}
267+
268+
const normalizedVal = pruneUndefined(val)
269+
if (isPlainObject(normalizedVal) && Object.keys(normalizedVal).length === 0) {
270+
continue
271+
}
272+
273+
pruned[key] = normalizedVal
236274
}
275+
return pruned
237276
}
238277

239278
module.exports = {

lib/pinpoint-config-default2.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"deadlineMinutes": 10
99
},
1010
"sampling": {
11+
"enable": true,
1112
"rate": 10
1213
},
1314
"plugins": {

test/config.test.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ const { ConfigBuilder } = require('../lib/config-builder')
1313
test('Agent ID required field', function (t) {
1414
t.plan(1)
1515

16-
clear()
1716
delete process.env.PINPOINT_AGENT_ID
1817
delete process.env.PINPOINT_APPLICATION_NAME
1918

@@ -26,31 +25,32 @@ test('Should be configured with environment variable', function (t) {
2625

2726
const agentId = 'id-from-env'
2827
process.env.PINPOINT_AGENT_ID = agentId
29-
clear()
30-
const conf = getConfig()
3128

29+
const conf = new ConfigBuilder().build()
3230
t.equal(agentId, conf.agentId)
31+
32+
delete process.env.PINPOINT_AGENT_ID
3333
})
3434

3535
test('Should be configured with argument', function (t) {
3636
t.plan(1)
3737

3838
process.env.PINPOINT_AGENT_ID = 'id-from-env'
39-
clear()
40-
const conf = getConfig({
41-
'agent-id': 'id-from-argument'
42-
}, false)
4339

44-
t.equal('id-from-argument', conf.agentId)
40+
const conf = new ConfigBuilder({ 'agentId': 'id-from-argument' }).build()
41+
t.equal(conf.agentId, 'id-from-argument')
42+
43+
delete process.env.PINPOINT_AGENT_ID
4544
})
4645

4746
test('Should be read from config file', function (t) {
4847
t.plan(1)
4948

50-
const testConfig = require('./pinpoint-config-test')
51-
const result = readConfigJson(testConfig)
52-
log.debug(result)
53-
t.ok(result)
49+
delete process.env.PINPOINT_COLLECTOR_IP
50+
51+
const testConfig = require('./pinpoint-config-test2.json')
52+
const conf = new ConfigBuilder().setDefaultJson(testConfig).build()
53+
t.deepEqual(conf, testConfig)
5454
})
5555

5656
test('deadline config', (t) => {

test/pinpoint-config-test2.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"agentId": "node.test.app",
3+
"applicationName": "test.application.name",
4+
"applicationType": 1400,
5+
"collector": {
6+
"ip": "localhost",
7+
"spanPort": 9993,
8+
"statPort": 9992,
9+
"tcpPort": 9991,
10+
"deadlineMinutes": 10
11+
},
12+
"sampling": {
13+
"enable": true,
14+
"rate": 10
15+
},
16+
"plugins": {
17+
"http": {
18+
"errorStatusCodes": "5xx,401,403"
19+
},
20+
"express": true,
21+
"koa": true,
22+
"mongodb": true,
23+
"redis": true,
24+
"ioredis": true,
25+
"mysql": true,
26+
"postgresql": true
27+
},
28+
"features": {
29+
"activeThreadCount": true,
30+
"dataSending": true,
31+
"statsMonitoring": true,
32+
"traceLocationAndFilenameOfCallSite": false,
33+
"container": false,
34+
"sqlStats": false,
35+
"logLevels": {
36+
"default-logger": "WARN",
37+
"grpcLogger": "SILENT"
38+
},
39+
"traceExclusionUrl": {
40+
"patterns": "",
41+
"cacheSize": 100
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)