@vtex/diagnostics-nodejs
Version:
Diagnostics library for Node.js applications
141 lines • 5.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileProvider = exports.FileSource = void 0;
exports.newFileSource = newFileSource;
exports.newFileProvider = newFileProvider;
const fs_1 = require("fs");
const fs_2 = require("fs");
const events_1 = require("events");
class FileSource extends events_1.EventEmitter {
constructor(config) {
super();
this.watcher = null;
this.lastContent = '';
this.filePath = config.path;
this.refreshIntervalMs = config.refreshIntervalMs || 60000;
}
async load() {
try {
const content = await fs_1.promises.readFile(this.filePath, 'utf8');
this.lastContent = content;
let config;
try {
config = JSON.parse(content);
}
catch (parseError) {
const errMsg = parseError instanceof Error ? parseError.message : String(parseError);
throw new Error(`Invalid JSON in config file: ${errMsg}`);
}
for (const [accountId, rate] of Object.entries(config)) {
if (typeof rate !== 'number' || rate < 0 || rate > 1) {
throw new Error(`Invalid sampling rate for account ${accountId}: ${rate}. Must be between 0 and 1.`);
}
}
return config;
}
catch (error) {
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
console.warn(`Config file ${this.filePath} not found, using empty configuration`);
return {};
}
throw error;
}
}
watch() {
if (this.watcher) {
return;
}
try {
this.watcher = (0, fs_2.watch)(this.filePath, async (eventType) => {
if (eventType === 'change') {
try {
await new Promise(resolve => setTimeout(resolve, 100)); // gambs
const content = await fs_1.promises.readFile(this.filePath, 'utf8');
if (content !== this.lastContent) {
this.lastContent = content;
const config = JSON.parse(content);
this.emit('update', config);
}
}
catch (error) {
const errMsg = error instanceof Error ? error.message : String(error);
console.error(`Error watching config file: ${errMsg}`);
}
}
});
const checkFileInterval = setInterval(async () => {
try {
const content = await fs_1.promises.readFile(this.filePath, 'utf8');
if (content !== this.lastContent) {
this.lastContent = content;
const config = JSON.parse(content);
this.emit('update', config);
}
}
catch (error) {
const errMsg = error instanceof Error ? error.message : String(error);
console.debug(`Error checking file: ${errMsg}`);
}
}, this.refreshIntervalMs);
this.once('stopWatch', () => {
clearInterval(checkFileInterval);
});
}
catch (error) {
const errMsg = error instanceof Error ? error.message : String(error);
console.error(`Error setting up file watcher: ${errMsg}`);
}
}
stopWatch() {
if (this.watcher) {
this.watcher.close();
this.watcher = null;
this.emit('stopWatch');
}
}
}
exports.FileSource = FileSource;
function newFileSource(config) {
return new FileSource(config);
}
class FileProvider {
constructor(sourceConfig, defaultRate = 0.1) {
this.accounts = {};
this.defaultRate = defaultRate;
this.source = newFileSource(sourceConfig);
this.refresh().catch(err => {
console.error('Failed to load initial configuration:', err);
});
this.setupWatcher();
}
setupWatcher() {
this.source.on('update', (newConfig) => {
this.accounts = newConfig;
console.debug('Account sampling rates updated from file');
});
this.source.watch();
}
async refresh() {
try {
this.accounts = await this.source.load();
}
catch (error) {
console.error('Failed to reload configuration:', error);
}
}
getSamplingRate(accountId) {
const rate = this.accounts[accountId];
return [rate !== undefined ? rate : this.defaultRate, rate !== undefined];
}
getDefaultRate() {
return this.defaultRate;
}
shutdown() {
this.source.stopWatch();
}
}
exports.FileProvider = FileProvider;
function newFileProvider(sourceConfig, defaultRate = 0.1) {
return new FileProvider(sourceConfig, defaultRate);
}
//# sourceMappingURL=file-source.js.map