Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@

const { AgentBuilder } = require('./lib/agent-builder')
const AgentInfo = require('./lib/data/dto/agent-info')
const { getConfig } = require('./lib/config')
const { ConfigBuilder, setConfig } = require('./lib/config')
const { LogBuilder } = require('./lib/utils/log/log-builder')
const logger = require('./lib/utils/log/logger')

const config = getConfig()
const config = new ConfigBuilder().build()
setConfig(config)
logger.setRootLogger(LogBuilder.createDefaultLogBuilder().setConfig(config).build())

const agentInfo = AgentInfo.make(config)
Expand Down
6 changes: 3 additions & 3 deletions lib/agent-builder.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Apache License v2.0
*/

import { PinpointConfig } from './config';
import { Config } from './config';
import AgentInfo = require('./data/dto/agent-info');

interface TraceObject {
Expand All @@ -25,7 +25,7 @@ interface DataSender {

interface Agent {
agentInfo: AgentInfo;
config: PinpointConfig;
config: Config;
dataSender: DataSender;
traceContext: TraceContext;
services: Array<() => void>;
Expand All @@ -42,7 +42,7 @@ interface Agent {
declare class AgentBuilder {
constructor(agentInfo: AgentInfo);

setConfig(config: PinpointConfig): AgentBuilder;
setConfig(config: Config): AgentBuilder;
setDataSender(dataSender: DataSender): AgentBuilder;
addService(service: () => void): AgentBuilder;
disableStatsScheduler(): AgentBuilder;
Expand Down
17 changes: 10 additions & 7 deletions lib/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface LoggerLevels {
[loggerName: string]: string;
}

export interface PinpointConfig {
export interface Config {
enable: boolean;
agentId: string;
agentName?: string;
Expand Down Expand Up @@ -40,11 +40,14 @@ export interface PinpointConfig {
[key: string]: any;
}

export declare function getConfig(initOptions?: { [key: string]: any }): PinpointConfig;
export declare class ConfigBuilder {
constructor(agentStartupUserDefinedJson?: { [key: string]: any });
setDefaultJson(json: { [key: string]: any }): ConfigBuilder;
setUserDefinedJson(json: { [key: string]: any }): ConfigBuilder;
build(): Config;
}

export declare function getConfig(initOptions?: { [key: string]: any }): Config;
export declare function setConfig(config: Config): void;
export declare function clear(): void;
export declare function readConfigJson(formattedConfig: any): Partial<PinpointConfig>;
export declare function readRootConfigFile(): { [key: string]: any };
export declare function getMainModulePath(requireFunction: NodeRequire): string | undefined;
export declare function isContainerEnvironment(): boolean;
export declare function initializeConfig(initOptions?: { [key: string]: any }): void;
export declare function registerLoadedConfig(propertyName: string, callback: (value: any) => void): void;
265 changes: 142 additions & 123 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@

const path = require('path')
const fs = require('fs')
const defaultConfig = require('./pinpoint-config-default')
const log = require('./utils/log/logger')
const ServiceConfigBuilder = require('./client/retry/service-config-builder')
const { randomBytes } = require('node:crypto')
const levels = require('loglevel').levels
const defaultConfig = require('./pinpoint-config-default')


const valueOfString = (envName) => {
return () => {
Expand Down Expand Up @@ -136,96 +137,6 @@ const ARRAY_CONFIG = [
'traceExclusionUrlPatterns'
]

const configurationValueValidations = {
validateTraceExclusionUrlCacheSize: () => {
if (typeof agentConfig.traceExclusionUrlCacheSize !== 'undefined' && typeof agentConfig.traceExclusionUrlPatterns === 'undefined') {
delete agentConfig.traceExclusionUrlCacheSize
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.`)
}

if (Array.isArray(agentConfig.traceExclusionUrlPatterns) && Number.isInteger(agentConfig.traceExclusionUrlCacheSize)) {
if (agentConfig.traceExclusionUrlCacheSize < 100) {
agentConfig.traceExclusionUrlCacheSize = 100
}
}
},
validateIds: () => {
[{ id: agentConfig.agentId, name: 'Agent ID', maxLength: 24, required: true }
, { id: agentConfig.applicationName, name: 'Application Name', maxLength: 24, required: true }
// Java PinpointConstants.AGENT_NAME_MAX_LEN = 255
, { id: agentConfig.agentName, name: 'Agent Name', maxLength: 255, required: false }
].filter(id => id.id)
.filter(id => {
if (isNaN(id.maxLength)) {
return false
}

if (id.required && typeof id.id !== 'string') {
agentConfig.enable = false
log.warn(`You have to set ${id.name}`)
return false
}

if (id.required === false && typeof id.id !== 'string') {
return false
}

const maxLength = id.maxLength
const idRegex = /^[a-zA-Z0-9\\._\\-]+$/

if (id.id.length < 1) {
agentConfig.enable = false
log.warn(`You have to set ${id.name}`)
return false
}

if (id.id.length > maxLength) {
agentConfig.enable = false
log.warn(`You have to set ${id.name} to less ${maxLength} characters.`)
return false
}

if (!idRegex.test(id.id)) {
agentConfig.enable = false
log.warn(`invalidate ${id.name} name with /[a-zA-Z0-9\\._\\-]+/ RegExp`)
return false
}
})
}
}

const init = (initOptions = {}) => {
agentConfig = Object.assign({},
readConfigJson(defaultConfig),
readConfigJson(readRootConfigFile()),
readFromEnv(),
readConfigJson(initOptions))

Object.entries(REQUIRE_CONFIG).forEach(([propertyName, description]) => {
if (propertyName === 'agentId' && !agentConfig[propertyName]) {
return agentConfig.agentId = randomBytes(8).toString('hex')
}
if (agentConfig.enable && !agentConfig[propertyName]) {
agentConfig.enable = false
log.warn(`You must set ${description}.The Pinpoint Node JS Agent has been shutdown.`)
}
})

if (!ENV_MAP.container() && isContainerEnvironment()) {
agentConfig.container = true
}

for (const [key, validation] of Object.entries(configurationValueValidations)) {
validation()
}

if (typeof initOptions['grpc.service_config'] === 'object') {
agentConfig.grpcServiceConfig = new ServiceConfigBuilder().setJSON(initOptions['grpc.service_config']).build()
} else {
agentConfig.grpcServiceConfig = ServiceConfigBuilder.nullObject.build()
}
}

const readFromEnv = () => {
return Object.entries(ENV_MAP).reduce((acc, [key, valueOf]) => {
const value = valueOf()
Expand Down Expand Up @@ -283,27 +194,6 @@ const getValue = (key, configFile) => {
}
}

const getConfig = (initOptions) => {
if (!agentConfig) {
init(initOptions)
}
return agentConfig
}

const initializeConfig = (initOptions) => {
clear()
init(initOptions)
loadedConfigCallbacks.forEach(callback => {
try {
callback.callback(agentConfig[callback.propertyName])
} catch (e) {
log.error('Error in loadedConfig callback', e)
}
})
}

const clear = () => agentConfig && (agentConfig = null)

//https://github.com/sindresorhus/is-docker
const isContainerEnvironment = () => {
return hasDockerEnv() || hasDockerCGroup() || (process.env['KUBERNETES_SERVICE_HOST'] && process.env['KUBERNETES_SERVICE_HOST'].length > 0)
Expand All @@ -326,24 +216,153 @@ function hasDockerCGroup() {
}
}

let agentConfig
class Config {
constructor(config) {
Object.assign(this, config)
Object.freeze(this)
}
}

class ConfigBuilder {
constructor(agentStartupUserDefinedJson = {}) {
this.agentStartupUserDefinedJson = agentStartupUserDefinedJson
}

const loadedConfigCallbacks = []
function registerLoadedConfig(propertyName, callback) {
if (typeof propertyName !== 'string' || typeof callback !== 'function') {
return
setDefaultJson(json) {
this.defaultJson = json
return this
}

loadedConfigCallbacks.push({ propertyName, callback })
setUserDefinedJson(json) {
this.userDefinedJson = json
return this
}

build() {
if (!this.defaultJson) {
this.defaultJson = defaultConfig
}

if (!this.userDefinedJson) {
this.userDefinedJson = readRootConfigFile()
}

const config = Object.assign({},
readConfigJson(this.defaultJson),
readConfigJson(this.userDefinedJson),
readFromEnv(),
readConfigJson(this.agentStartupUserDefinedJson))

Object.entries(REQUIRE_CONFIG).forEach(([propertyName, description]) => {
if (propertyName === 'agentId' && !config[propertyName]) {
return config.agentId = randomBytes(8).toString('hex')
}
if (config.enable && !config[propertyName]) {
config.enable = false
log.warn(`You must set ${description}.The Pinpoint Node JS Agent has been shutdown.`)
}
})

if (!ENV_MAP.container() && isContainerEnvironment()) {
config.container = true
}

for (const [key, validation] of Object.entries(valueValidations)) {
validation(config)
}

if (typeof this.agentStartupUserDefinedJson?.grpc?.service_config === 'object') {
config.grpcServiceConfig = new ServiceConfigBuilder().setJSON(this.agentStartupUserDefinedJson.grpc.service_config).build()
} else {
config.grpcServiceConfig = ServiceConfigBuilder.nullObject.build()
}
return new Config(config)
}
}

const valueValidations = {
validateTraceExclusionUrlCacheSize: (config) => {
if (typeof config.traceExclusionUrlCacheSize !== 'undefined' && typeof config.traceExclusionUrlPatterns === 'undefined') {
delete config.traceExclusionUrlCacheSize
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.`)
}

if (Array.isArray(config.traceExclusionUrlPatterns) && Number.isInteger(config.traceExclusionUrlCacheSize)) {
if (config.traceExclusionUrlCacheSize < 100) {
config.traceExclusionUrlCacheSize = 100
}
}
},
validateIds: (config) => {
[{ id: config.agentId, name: 'Agent ID', maxLength: 24, required: true }
, { id: config.applicationName, name: 'Application Name', maxLength: 24, required: true }
// Java PinpointConstants.AGENT_NAME_MAX_LEN = 255
, { id: config.agentName, name: 'Agent Name', maxLength: 255, required: false }
].filter(id => id.id)
.filter(id => {
if (isNaN(id.maxLength)) {
return false
}

if (id.required && typeof id.id !== 'string') {
config.enable = false
log.warn(`You have to set ${id.name}`)
return false
}

if (id.required === false && typeof id.id !== 'string') {
return false
}

const maxLength = id.maxLength
const idRegex = /^[a-zA-Z0-9\\._\\-]+$/

if (id.id.length < 1) {
config.enable = false
log.warn(`You have to set ${id.name}`)
return false
}

if (id.id.length > maxLength) {
config.enable = false
log.warn(`You have to set ${id.name} to less ${maxLength} characters.`)
return false
}

if (!idRegex.test(id.id)) {
config.enable = false
log.warn(`invalidate ${id.name} name with /[a-zA-Z0-9\\._\\-]+/ RegExp`)
return false
}
})
}
}

let configInstance
const getConfig = (json) => {
if (!configInstance) {
configInstance = new ConfigBuilder(json).build()
}
return configInstance
}

const setConfig = (config) => {
if (!(config instanceof Config)) {
throw new TypeError('config must be an instance of Config')
}

configInstance = config
}

const clear = () => configInstance && (configInstance = null)

module.exports = {
getConfig,
clear,
readConfigJson,
readRootConfigFile,
getMainModulePath,
isContainerEnvironment,
initializeConfig,
registerLoadedConfig,
}
ConfigBuilder,
getConfig,
setConfig,
clear
}
2 changes: 1 addition & 1 deletion lib/context/method-descriptor-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class MethodDescriptorBuilder {
if (this.apiDescriptor) {
return this.apiDescriptor
}

const cacheIds = [this.formattedStringOfCall()]

if (typeof this.fileName === 'string') {
Expand Down
Loading