99const fs = require ( 'fs' )
1010const path = require ( 'path' )
1111const { randomBytes } = require ( 'node:crypto' )
12+ const { levels } = require ( 'loglevel' )
1213
1314class 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
142142function 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
161176function 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
196192function 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
239278module . exports = {
0 commit comments