88
99const path = require ( 'path' )
1010const fs = require ( 'fs' )
11- const defaultConfig = require ( './pinpoint-config-default' )
1211const log = require ( './utils/log/logger' )
1312const ServiceConfigBuilder = require ( './client/retry/service-config-builder' )
1413const { randomBytes } = require ( 'node:crypto' )
1514const levels = require ( 'loglevel' ) . levels
15+ const defaultConfig = require ( './pinpoint-config-default' )
16+
1617
1718const valueOfString = ( envName ) => {
1819 return ( ) => {
@@ -136,96 +137,6 @@ const ARRAY_CONFIG = [
136137 'traceExclusionUrlPatterns'
137138]
138139
139- const configurationValueValidations = {
140- validateTraceExclusionUrlCacheSize : ( ) => {
141- if ( typeof agentConfig . traceExclusionUrlCacheSize !== 'undefined' && typeof agentConfig . traceExclusionUrlPatterns === 'undefined' ) {
142- delete agentConfig . traceExclusionUrlCacheSize
143- log . warn ( `You have to set the PINPOINT_TRACE_EXCLUSION_URL_PATTERN, PINPOINT_TRACE_EXCLUSION_URL_CACHE_SIZE or trace-exclusion-url{ pattern: 'pattern', 'cache-size': 100} for using excludsion url cache.` )
144- }
145-
146- if ( Array . isArray ( agentConfig . traceExclusionUrlPatterns ) && Number . isInteger ( agentConfig . traceExclusionUrlCacheSize ) ) {
147- if ( agentConfig . traceExclusionUrlCacheSize < 100 ) {
148- agentConfig . traceExclusionUrlCacheSize = 100
149- }
150- }
151- } ,
152- validateIds : ( ) => {
153- [ { id : agentConfig . agentId , name : 'Agent ID' , maxLength : 24 , required : true }
154- , { id : agentConfig . applicationName , name : 'Application Name' , maxLength : 24 , required : true }
155- // Java PinpointConstants.AGENT_NAME_MAX_LEN = 255
156- , { id : agentConfig . agentName , name : 'Agent Name' , maxLength : 255 , required : false }
157- ] . filter ( id => id . id )
158- . filter ( id => {
159- if ( isNaN ( id . maxLength ) ) {
160- return false
161- }
162-
163- if ( id . required && typeof id . id !== 'string' ) {
164- agentConfig . enable = false
165- log . warn ( `You have to set ${ id . name } ` )
166- return false
167- }
168-
169- if ( id . required === false && typeof id . id !== 'string' ) {
170- return false
171- }
172-
173- const maxLength = id . maxLength
174- const idRegex = / ^ [ a - z A - Z 0 - 9 \\ . _ \\ - ] + $ /
175-
176- if ( id . id . length < 1 ) {
177- agentConfig . enable = false
178- log . warn ( `You have to set ${ id . name } ` )
179- return false
180- }
181-
182- if ( id . id . length > maxLength ) {
183- agentConfig . enable = false
184- log . warn ( `You have to set ${ id . name } to less ${ maxLength } characters.` )
185- return false
186- }
187-
188- if ( ! idRegex . test ( id . id ) ) {
189- agentConfig . enable = false
190- log . warn ( `invalidate ${ id . name } name with /[a-zA-Z0-9\\._\\-]+/ RegExp` )
191- return false
192- }
193- } )
194- }
195- }
196-
197- const init = ( initOptions = { } ) => {
198- agentConfig = Object . assign ( { } ,
199- readConfigJson ( defaultConfig ) ,
200- readConfigJson ( readRootConfigFile ( ) ) ,
201- readFromEnv ( ) ,
202- readConfigJson ( initOptions ) )
203-
204- Object . entries ( REQUIRE_CONFIG ) . forEach ( ( [ propertyName , description ] ) => {
205- if ( propertyName === 'agentId' && ! agentConfig [ propertyName ] ) {
206- return agentConfig . agentId = randomBytes ( 8 ) . toString ( 'hex' )
207- }
208- if ( agentConfig . enable && ! agentConfig [ propertyName ] ) {
209- agentConfig . enable = false
210- log . warn ( `You must set ${ description } .The Pinpoint Node JS Agent has been shutdown.` )
211- }
212- } )
213-
214- if ( ! ENV_MAP . container ( ) && isContainerEnvironment ( ) ) {
215- agentConfig . container = true
216- }
217-
218- for ( const [ key , validation ] of Object . entries ( configurationValueValidations ) ) {
219- validation ( )
220- }
221-
222- if ( typeof initOptions [ 'grpc.service_config' ] === 'object' ) {
223- agentConfig . grpcServiceConfig = new ServiceConfigBuilder ( ) . setJSON ( initOptions [ 'grpc.service_config' ] ) . build ( )
224- } else {
225- agentConfig . grpcServiceConfig = ServiceConfigBuilder . nullObject . build ( )
226- }
227- }
228-
229140const readFromEnv = ( ) => {
230141 return Object . entries ( ENV_MAP ) . reduce ( ( acc , [ key , valueOf ] ) => {
231142 const value = valueOf ( )
@@ -283,27 +194,6 @@ const getValue = (key, configFile) => {
283194 }
284195}
285196
286- const getConfig = ( initOptions ) => {
287- if ( ! agentConfig ) {
288- init ( initOptions )
289- }
290- return agentConfig
291- }
292-
293- const initializeConfig = ( initOptions ) => {
294- clear ( )
295- init ( initOptions )
296- loadedConfigCallbacks . forEach ( callback => {
297- try {
298- callback . callback ( agentConfig [ callback . propertyName ] )
299- } catch ( e ) {
300- log . error ( 'Error in loadedConfig callback' , e )
301- }
302- } )
303- }
304-
305- const clear = ( ) => agentConfig && ( agentConfig = null )
306-
307197//https://github.com/sindresorhus/is-docker
308198const isContainerEnvironment = ( ) => {
309199 return hasDockerEnv ( ) || hasDockerCGroup ( ) || ( process . env [ 'KUBERNETES_SERVICE_HOST' ] && process . env [ 'KUBERNETES_SERVICE_HOST' ] . length > 0 )
@@ -326,24 +216,153 @@ function hasDockerCGroup() {
326216 }
327217}
328218
329- let agentConfig
219+ class Config {
220+ constructor ( config ) {
221+ Object . assign ( this , config )
222+ Object . freeze ( this )
223+ }
224+ }
225+
226+ class ConfigBuilder {
227+ constructor ( agentStartupUserDefinedJson = { } ) {
228+ this . agentStartupUserDefinedJson = agentStartupUserDefinedJson
229+ }
330230
331- const loadedConfigCallbacks = [ ]
332- function registerLoadedConfig ( propertyName , callback ) {
333- if ( typeof propertyName !== 'string' || typeof callback !== 'function' ) {
334- return
231+ setDefaultJson ( json ) {
232+ this . defaultJson = json
233+ return this
335234 }
336235
337- loadedConfigCallbacks . push ( { propertyName, callback } )
236+ setUserDefinedJson ( json ) {
237+ this . userDefinedJson = json
238+ return this
239+ }
240+
241+ build ( ) {
242+ if ( ! this . defaultJson ) {
243+ this . defaultJson = defaultConfig
244+ }
245+
246+ if ( ! this . userDefinedJson ) {
247+ this . userDefinedJson = readRootConfigFile ( )
248+ }
249+
250+ const config = Object . assign ( { } ,
251+ readConfigJson ( this . defaultJson ) ,
252+ readConfigJson ( this . userDefinedJson ) ,
253+ readFromEnv ( ) ,
254+ readConfigJson ( this . agentStartupUserDefinedJson ) )
255+
256+ Object . entries ( REQUIRE_CONFIG ) . forEach ( ( [ propertyName , description ] ) => {
257+ if ( propertyName === 'agentId' && ! config [ propertyName ] ) {
258+ return config . agentId = randomBytes ( 8 ) . toString ( 'hex' )
259+ }
260+ if ( config . enable && ! config [ propertyName ] ) {
261+ config . enable = false
262+ log . warn ( `You must set ${ description } .The Pinpoint Node JS Agent has been shutdown.` )
263+ }
264+ } )
265+
266+ if ( ! ENV_MAP . container ( ) && isContainerEnvironment ( ) ) {
267+ config . container = true
268+ }
269+
270+ for ( const [ key , validation ] of Object . entries ( valueValidations ) ) {
271+ validation ( config )
272+ }
273+
274+ if ( typeof this . agentStartupUserDefinedJson ?. grpc ?. service_config === 'object' ) {
275+ config . grpcServiceConfig = new ServiceConfigBuilder ( ) . setJSON ( this . agentStartupUserDefinedJson . grpc . service_config ) . build ( )
276+ } else {
277+ config . grpcServiceConfig = ServiceConfigBuilder . nullObject . build ( )
278+ }
279+ return new Config ( config )
280+ }
338281}
339282
283+ const valueValidations = {
284+ validateTraceExclusionUrlCacheSize : ( config ) => {
285+ if ( typeof config . traceExclusionUrlCacheSize !== 'undefined' && typeof config . traceExclusionUrlPatterns === 'undefined' ) {
286+ delete config . traceExclusionUrlCacheSize
287+ log . warn ( `You have to set the PINPOINT_TRACE_EXCLUSION_URL_PATTERN, PINPOINT_TRACE_EXCLUSION_URL_CACHE_SIZE or trace-exclusion-url{ pattern: 'pattern', 'cache-size': 100} for using excludsion url cache.` )
288+ }
289+
290+ if ( Array . isArray ( config . traceExclusionUrlPatterns ) && Number . isInteger ( config . traceExclusionUrlCacheSize ) ) {
291+ if ( config . traceExclusionUrlCacheSize < 100 ) {
292+ config . traceExclusionUrlCacheSize = 100
293+ }
294+ }
295+ } ,
296+ validateIds : ( config ) => {
297+ [ { id : config . agentId , name : 'Agent ID' , maxLength : 24 , required : true }
298+ , { id : config . applicationName , name : 'Application Name' , maxLength : 24 , required : true }
299+ // Java PinpointConstants.AGENT_NAME_MAX_LEN = 255
300+ , { id : config . agentName , name : 'Agent Name' , maxLength : 255 , required : false }
301+ ] . filter ( id => id . id )
302+ . filter ( id => {
303+ if ( isNaN ( id . maxLength ) ) {
304+ return false
305+ }
306+
307+ if ( id . required && typeof id . id !== 'string' ) {
308+ config . enable = false
309+ log . warn ( `You have to set ${ id . name } ` )
310+ return false
311+ }
312+
313+ if ( id . required === false && typeof id . id !== 'string' ) {
314+ return false
315+ }
316+
317+ const maxLength = id . maxLength
318+ const idRegex = / ^ [ a - z A - Z 0 - 9 \\ . _ \\ - ] + $ /
319+
320+ if ( id . id . length < 1 ) {
321+ config . enable = false
322+ log . warn ( `You have to set ${ id . name } ` )
323+ return false
324+ }
325+
326+ if ( id . id . length > maxLength ) {
327+ config . enable = false
328+ log . warn ( `You have to set ${ id . name } to less ${ maxLength } characters.` )
329+ return false
330+ }
331+
332+ if ( ! idRegex . test ( id . id ) ) {
333+ config . enable = false
334+ log . warn ( `invalidate ${ id . name } name with /[a-zA-Z0-9\\._\\-]+/ RegExp` )
335+ return false
336+ }
337+ } )
338+ }
339+ }
340+
341+ let configInstance
342+ const getConfig = ( json ) => {
343+ if ( ! configInstance ) {
344+ configInstance = new ConfigBuilder ( json ) . build ( )
345+ }
346+ return configInstance
347+ }
348+
349+ const setConfig = ( config ) => {
350+ if ( ! ( config instanceof Config ) ) {
351+ throw new TypeError ( 'config must be an instance of Config' )
352+ }
353+
354+ configInstance = config
355+ }
356+
357+ const clear = ( ) => configInstance && ( configInstance = null )
358+
340359module . exports = {
341- getConfig,
342- clear,
343360 readConfigJson,
344361 readRootConfigFile,
345362 getMainModulePath,
346363 isContainerEnvironment,
347- initializeConfig,
348- registerLoadedConfig,
349- }
364+ ConfigBuilder,
365+ getConfig,
366+ setConfig,
367+ clear
368+ }
0 commit comments