pms_md 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +93 -0
  2. package/node-monitor/ARCHITECTURE.md +341 -0
  3. package/node-monitor/CHANGELOG.md +105 -0
  4. package/node-monitor/CONTRIBUTING.md +96 -0
  5. package/node-monitor/DESIGN_IMPROVEMENTS.md +286 -0
  6. package/node-monitor/FILTER_BUTTONS_FIX.md +303 -0
  7. package/node-monitor/GETTING_STARTED.md +416 -0
  8. package/node-monitor/INSTALLATION.md +470 -0
  9. package/node-monitor/LICENSE +22 -0
  10. package/node-monitor/PUBLISHING_GUIDE.md +331 -0
  11. package/node-monitor/QUICK_REFERENCE.md +252 -0
  12. package/node-monitor/README.md +458 -0
  13. package/node-monitor/READY_TO_PUBLISH.md +272 -0
  14. package/node-monitor/SETUP_GUIDE.md +479 -0
  15. package/node-monitor/examples/EMAIL_SETUP_GUIDE.md +282 -0
  16. package/node-monitor/examples/ERROR_LOGGING_GUIDE.md +405 -0
  17. package/node-monitor/examples/GET_APP_PASSWORD.md +145 -0
  18. package/node-monitor/examples/LOG_FILES_REFERENCE.md +336 -0
  19. package/node-monitor/examples/QUICK_START_EMAIL.md +126 -0
  20. package/node-monitor/examples/express-app.js +499 -0
  21. package/node-monitor/examples/package-lock.json +1295 -0
  22. package/node-monitor/examples/package.json +18 -0
  23. package/node-monitor/examples/public/css/style.css +718 -0
  24. package/node-monitor/examples/public/js/dashboard.js +207 -0
  25. package/node-monitor/examples/public/js/health.js +114 -0
  26. package/node-monitor/examples/public/js/main.js +89 -0
  27. package/node-monitor/examples/public/js/metrics.js +225 -0
  28. package/node-monitor/examples/public/js/theme.js +138 -0
  29. package/node-monitor/examples/views/dashboard.ejs +20 -0
  30. package/node-monitor/examples/views/error-logs.ejs +1129 -0
  31. package/node-monitor/examples/views/health.ejs +21 -0
  32. package/node-monitor/examples/views/home.ejs +341 -0
  33. package/node-monitor/examples/views/layout.ejs +50 -0
  34. package/node-monitor/examples/views/metrics.ejs +16 -0
  35. package/node-monitor/examples/views/partials/footer.ejs +16 -0
  36. package/node-monitor/examples/views/partials/header.ejs +35 -0
  37. package/node-monitor/examples/views/partials/nav.ejs +23 -0
  38. package/node-monitor/examples/views/status.ejs +390 -0
  39. package/node-monitor/package-lock.json +4300 -0
  40. package/node-monitor/package.json +76 -0
  41. package/node-monitor/pre-publish-check.js +200 -0
  42. package/node-monitor/src/config/monitoringConfig.js +255 -0
  43. package/node-monitor/src/index.js +300 -0
  44. package/node-monitor/src/logger/errorLogger.js +297 -0
  45. package/node-monitor/src/monitors/apiErrorMonitor.js +156 -0
  46. package/node-monitor/src/monitors/dbConnectionMonitor.js +389 -0
  47. package/node-monitor/src/monitors/serverHealthMonitor.js +320 -0
  48. package/node-monitor/src/monitors/systemResourceMonitor.js +357 -0
  49. package/node-monitor/src/notifiers/emailNotifier.js +248 -0
  50. package/node-monitor/src/notifiers/notificationManager.js +96 -0
  51. package/node-monitor/src/notifiers/slackNotifier.js +209 -0
  52. package/node-monitor/src/views/dashboard.html +530 -0
  53. package/node-monitor/src/views/health.html +399 -0
  54. package/node-monitor/src/views/metrics.html +406 -0
  55. package/package.json +22 -0
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@projectmd/node-monitor",
3
+ "version": "1.0.0",
4
+ "description": "Comprehensive monitoring solution for Node.js applications with error tracking, health checks, and multi-channel notifications",
5
+ "main": "src/index.js",
6
+ "scripts": {
7
+ "test": "jest",
8
+ "start": "node examples/express-app.js",
9
+ "prepublishOnly": "echo 'Running pre-publish checks...'",
10
+ "version": "echo 'Version updated'"
11
+ },
12
+ "keywords": [
13
+ "monitoring",
14
+ "health-check",
15
+ "error-tracking",
16
+ "notifications",
17
+ "alerts",
18
+ "nodejs",
19
+ "express",
20
+ "logging",
21
+ "winston",
22
+ "error-handler",
23
+ "health-monitoring",
24
+ "system-monitoring",
25
+ "email-notifications",
26
+ "slack-notifications"
27
+ ],
28
+ "author": "ProjectMD",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/projectmd/node-monitor.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/projectmd/node-monitor/issues"
36
+ },
37
+ "homepage": "https://github.com/projectmd/node-monitor#readme",
38
+ "dependencies": {
39
+ "winston": "^3.11.0",
40
+ "winston-daily-rotate-file": "^4.7.1",
41
+ "nodemailer": "^6.9.7",
42
+ "@slack/webhook": "^7.0.2",
43
+ "axios": "^1.6.2",
44
+ "node-cron": "^3.0.3"
45
+ },
46
+ "peerDependencies": {
47
+ "express": "^4.18.0 || ^5.0.0",
48
+ "mongoose": "^7.0.0 || ^8.0.0",
49
+ "pg": "^8.11.0",
50
+ "mysql2": "^3.6.0",
51
+ "ioredis": "^5.3.0"
52
+ },
53
+ "peerDependenciesMeta": {
54
+ "express": {
55
+ "optional": true
56
+ },
57
+ "mongoose": {
58
+ "optional": true
59
+ },
60
+ "pg": {
61
+ "optional": true
62
+ },
63
+ "mysql2": {
64
+ "optional": true
65
+ },
66
+ "ioredis": {
67
+ "optional": true
68
+ }
69
+ },
70
+ "devDependencies": {
71
+ "jest": "^29.7.0"
72
+ },
73
+ "engines": {
74
+ "node": ">=14.0.0"
75
+ }
76
+ }
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Pre-publish validation script
5
+ * Run this before publishing to npm to ensure everything is ready
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ console.log('🔍 Running pre-publish checks...\n');
12
+
13
+ let hasErrors = false;
14
+ let hasWarnings = false;
15
+
16
+ // Check 1: package.json exists and is valid
17
+ console.log('📦 Checking package.json...');
18
+ try {
19
+ const pkg = require('./package.json');
20
+
21
+ if (!pkg.name) {
22
+ console.error(' ❌ package.json missing "name" field');
23
+ hasErrors = true;
24
+ } else {
25
+ console.log(` ✅ Package name: ${pkg.name}`);
26
+ }
27
+
28
+ if (!pkg.version) {
29
+ console.error(' ❌ package.json missing "version" field');
30
+ hasErrors = true;
31
+ } else {
32
+ console.log(` ✅ Version: ${pkg.version}`);
33
+ }
34
+
35
+ if (!pkg.description) {
36
+ console.warn(' ⚠️ package.json missing "description" field');
37
+ hasWarnings = true;
38
+ } else {
39
+ console.log(` ✅ Description: ${pkg.description.substring(0, 50)}...`);
40
+ }
41
+
42
+ if (!pkg.main) {
43
+ console.error(' ❌ package.json missing "main" field');
44
+ hasErrors = true;
45
+ } else {
46
+ console.log(` ✅ Main entry point: ${pkg.main}`);
47
+ }
48
+
49
+ if (!pkg.repository) {
50
+ console.warn(' ⚠️ package.json missing "repository" field');
51
+ hasWarnings = true;
52
+ } else {
53
+ console.log(` ✅ Repository: ${pkg.repository.url}`);
54
+ }
55
+
56
+ if (!pkg.license) {
57
+ console.warn(' ⚠️ package.json missing "license" field');
58
+ hasWarnings = true;
59
+ } else {
60
+ console.log(` ✅ License: ${pkg.license}`);
61
+ }
62
+
63
+ if (!pkg.keywords || pkg.keywords.length === 0) {
64
+ console.warn(' ⚠️ package.json has no keywords (helps with discoverability)');
65
+ hasWarnings = true;
66
+ } else {
67
+ console.log(` ✅ Keywords: ${pkg.keywords.length} keywords defined`);
68
+ }
69
+
70
+ } catch (error) {
71
+ console.error(' ❌ Error reading package.json:', error.message);
72
+ hasErrors = true;
73
+ }
74
+
75
+ console.log('');
76
+
77
+ // Check 2: Main entry point exists
78
+ console.log('📄 Checking main entry point...');
79
+ const mainFile = path.join(__dirname, 'src/index.js');
80
+ if (fs.existsSync(mainFile)) {
81
+ console.log(' ✅ src/index.js exists');
82
+ } else {
83
+ console.error(' ❌ src/index.js not found');
84
+ hasErrors = true;
85
+ }
86
+
87
+ console.log('');
88
+
89
+ // Check 3: README exists
90
+ console.log('📖 Checking README...');
91
+ const readmeFile = path.join(__dirname, 'README.md');
92
+ if (fs.existsSync(readmeFile)) {
93
+ const readmeContent = fs.readFileSync(readmeFile, 'utf8');
94
+ console.log(' ✅ README.md exists');
95
+
96
+ if (readmeContent.length < 100) {
97
+ console.warn(' ⚠️ README.md seems very short');
98
+ hasWarnings = true;
99
+ } else {
100
+ console.log(` ✅ README.md has ${readmeContent.length} characters`);
101
+ }
102
+ } else {
103
+ console.error(' ❌ README.md not found');
104
+ hasErrors = true;
105
+ }
106
+
107
+ console.log('');
108
+
109
+ // Check 4: LICENSE exists
110
+ console.log('⚖️ Checking LICENSE...');
111
+ const licenseFile = path.join(__dirname, 'LICENSE');
112
+ if (fs.existsSync(licenseFile)) {
113
+ console.log(' ✅ LICENSE file exists');
114
+ } else {
115
+ console.error(' ❌ LICENSE file not found');
116
+ hasErrors = true;
117
+ }
118
+
119
+ console.log('');
120
+
121
+ // Check 5: .npmignore exists
122
+ console.log('🚫 Checking .npmignore...');
123
+ const npmignoreFile = path.join(__dirname, '.npmignore');
124
+ if (fs.existsSync(npmignoreFile)) {
125
+ console.log(' ✅ .npmignore exists');
126
+ } else {
127
+ console.warn(' ⚠️ .npmignore not found (will use .gitignore)');
128
+ hasWarnings = true;
129
+ }
130
+
131
+ console.log('');
132
+
133
+ // Check 6: No .env files in root
134
+ console.log('🔐 Checking for sensitive files...');
135
+ const envFile = path.join(__dirname, '.env');
136
+ if (fs.existsSync(envFile)) {
137
+ console.warn(' ⚠️ .env file found (make sure it\'s in .npmignore)');
138
+ hasWarnings = true;
139
+ } else {
140
+ console.log(' ✅ No .env file in root');
141
+ }
142
+
143
+ console.log('');
144
+
145
+ // Check 7: Source files exist
146
+ console.log('📁 Checking source files...');
147
+ const srcDir = path.join(__dirname, 'src');
148
+ if (fs.existsSync(srcDir)) {
149
+ const srcFiles = fs.readdirSync(srcDir, { recursive: true });
150
+ const jsFiles = srcFiles.filter(f => f.endsWith('.js'));
151
+ console.log(` ✅ src/ directory exists with ${jsFiles.length} JavaScript files`);
152
+ } else {
153
+ console.error(' ❌ src/ directory not found');
154
+ hasErrors = true;
155
+ }
156
+
157
+ console.log('');
158
+
159
+ // Check 8: node_modules size warning
160
+ console.log('📦 Checking dependencies...');
161
+ const nodeModulesDir = path.join(__dirname, 'node_modules');
162
+ if (fs.existsSync(nodeModulesDir)) {
163
+ console.log(' ✅ Dependencies installed');
164
+ console.log(' ℹ️ Note: node_modules/ will be excluded from npm package');
165
+ } else {
166
+ console.warn(' ⚠️ node_modules/ not found - run "npm install" first');
167
+ hasWarnings = true;
168
+ }
169
+
170
+ console.log('');
171
+
172
+ // Summary
173
+ console.log('═══════════════════════════════════════════════════════');
174
+ if (hasErrors) {
175
+ console.log('❌ FAILED - Please fix the errors above before publishing');
176
+ process.exit(1);
177
+ } else if (hasWarnings) {
178
+ console.log('⚠️ PASSED WITH WARNINGS - Review warnings above');
179
+ console.log('');
180
+ console.log('✅ You can proceed with publishing, but consider fixing warnings');
181
+ console.log('');
182
+ console.log('Next steps:');
183
+ console.log(' 1. npm login');
184
+ console.log(' 2. npm publish --dry-run --access public');
185
+ console.log(' 3. npm publish --access public');
186
+ process.exit(0);
187
+ } else {
188
+ console.log('✅ ALL CHECKS PASSED!');
189
+ console.log('');
190
+ console.log('Your package is ready to publish! 🚀');
191
+ console.log('');
192
+ console.log('Next steps:');
193
+ console.log(' 1. npm login');
194
+ console.log(' 2. npm publish --dry-run --access public (test run)');
195
+ console.log(' 3. npm publish --access public (actual publish)');
196
+ console.log('');
197
+ console.log('See PUBLISHING_GUIDE.md for detailed instructions.');
198
+ process.exit(0);
199
+ }
200
+
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Monitoring Configuration Manager
3
+ * Handles configuration with environment variable support and validation
4
+ */
5
+
6
+ class MonitoringConfig {
7
+ constructor(userConfig = {}) {
8
+ this.config = this.mergeWithDefaults(userConfig);
9
+ this.validateConfig();
10
+ }
11
+
12
+ /**
13
+ * Default configuration values
14
+ */
15
+ getDefaults() {
16
+ return {
17
+ // Monitoring intervals (in milliseconds)
18
+ intervals: {
19
+ health: parseInt(process.env.MONITOR_HEALTH_INTERVAL) || 60000, // 1 minute
20
+ system: parseInt(process.env.MONITOR_SYSTEM_INTERVAL) || 300000, // 5 minutes
21
+ database: parseInt(process.env.MONITOR_DATABASE_INTERVAL) || 120000 // 2 minutes
22
+ },
23
+
24
+ // Alert thresholds
25
+ thresholds: {
26
+ cpu: parseInt(process.env.MONITOR_CPU_THRESHOLD) || 80, // percentage
27
+ memory: parseInt(process.env.MONITOR_MEMORY_THRESHOLD) || 90, // percentage
28
+ errorRate: parseInt(process.env.MONITOR_ERROR_RATE_THRESHOLD) || 50, // errors per minute
29
+ responseTime: parseInt(process.env.MONITOR_RESPONSE_TIME_THRESHOLD) || 5000, // milliseconds
30
+ consecutiveFailures: parseInt(process.env.MONITOR_CONSECUTIVE_FAILURES) || 3
31
+ },
32
+
33
+ // Notification settings
34
+ notifications: {
35
+ enabled: process.env.MONITOR_NOTIFICATIONS_ENABLED !== 'false',
36
+ cooldown: parseInt(process.env.MONITOR_NOTIFICATION_COOLDOWN) || 300000, // 5 minutes
37
+
38
+ email: {
39
+ enabled: process.env.MONITOR_EMAIL_ENABLED === 'true',
40
+ host: process.env.MONITOR_EMAIL_HOST || 'smtp.gmail.com',
41
+ port: parseInt(process.env.MONITOR_EMAIL_PORT) || 587,
42
+ secure: process.env.MONITOR_EMAIL_SECURE === 'true',
43
+ auth: {
44
+ user: process.env.MONITOR_EMAIL_USER || '',
45
+ pass: process.env.MONITOR_EMAIL_PASS || ''
46
+ },
47
+ from: process.env.MONITOR_EMAIL_FROM || '',
48
+ recipients: process.env.MONITOR_EMAIL_RECIPIENTS
49
+ ? process.env.MONITOR_EMAIL_RECIPIENTS.split(',')
50
+ : []
51
+ },
52
+
53
+ slack: {
54
+ enabled: process.env.MONITOR_SLACK_ENABLED === 'true',
55
+ webhook: process.env.MONITOR_SLACK_WEBHOOK || '',
56
+ channel: process.env.MONITOR_SLACK_CHANNEL || '#monitoring',
57
+ username: process.env.MONITOR_SLACK_USERNAME || 'Node Monitor'
58
+ },
59
+
60
+ sms: {
61
+ enabled: process.env.MONITOR_SMS_ENABLED === 'true',
62
+ provider: process.env.MONITOR_SMS_PROVIDER || 'twilio',
63
+ accountSid: process.env.MONITOR_SMS_ACCOUNT_SID || '',
64
+ authToken: process.env.MONITOR_SMS_AUTH_TOKEN || '',
65
+ from: process.env.MONITOR_SMS_FROM || '',
66
+ recipients: process.env.MONITOR_SMS_RECIPIENTS
67
+ ? process.env.MONITOR_SMS_RECIPIENTS.split(',')
68
+ : []
69
+ }
70
+ },
71
+
72
+ // Logging configuration
73
+ logging: {
74
+ enabled: process.env.MONITOR_LOGGING_ENABLED !== 'false',
75
+ level: process.env.MONITOR_LOG_LEVEL || 'info',
76
+ directory: process.env.MONITOR_LOG_DIRECTORY || './logs',
77
+ maxFiles: process.env.MONITOR_LOG_MAX_FILES || '14d',
78
+ maxSize: process.env.MONITOR_LOG_MAX_SIZE || '20m',
79
+ format: process.env.MONITOR_LOG_FORMAT || 'json', // 'json' or 'simple'
80
+ console: process.env.MONITOR_LOG_CONSOLE !== 'false'
81
+ },
82
+
83
+ // Health check configuration
84
+ healthCheck: {
85
+ enabled: process.env.MONITOR_HEALTH_CHECK_ENABLED !== 'false',
86
+ endpoint: process.env.MONITOR_HEALTH_ENDPOINT || '/health',
87
+ timeout: parseInt(process.env.MONITOR_HEALTH_TIMEOUT) || 5000
88
+ },
89
+
90
+ // Database monitoring
91
+ database: {
92
+ enabled: process.env.MONITOR_DATABASE_ENABLED !== 'false',
93
+ types: [], // Will be populated based on connections provided
94
+ queryTimeout: parseInt(process.env.MONITOR_DB_QUERY_TIMEOUT) || 5000
95
+ },
96
+
97
+ // System monitoring
98
+ system: {
99
+ enabled: process.env.MONITOR_SYSTEM_ENABLED !== 'false',
100
+ trackCpu: process.env.MONITOR_TRACK_CPU !== 'false',
101
+ trackMemory: process.env.MONITOR_TRACK_MEMORY !== 'false',
102
+ trackEventLoop: process.env.MONITOR_TRACK_EVENT_LOOP === 'true'
103
+ },
104
+
105
+ // Error tracking
106
+ errorTracking: {
107
+ enabled: process.env.MONITOR_ERROR_TRACKING_ENABLED !== 'false',
108
+ captureStackTrace: process.env.MONITOR_CAPTURE_STACK_TRACE !== 'false',
109
+ sanitizeSensitiveData: process.env.MONITOR_SANITIZE_DATA !== 'false',
110
+ sensitiveFields: ['password', 'token', 'apiKey', 'secret', 'authorization']
111
+ },
112
+
113
+ // Application metadata
114
+ app: {
115
+ name: process.env.MONITOR_APP_NAME || process.env.npm_package_name || 'nodejs-app',
116
+ environment: process.env.NODE_ENV || 'development',
117
+ version: process.env.MONITOR_APP_VERSION || process.env.npm_package_version || '1.0.0',
118
+ hostname: process.env.HOSTNAME || require('os').hostname()
119
+ }
120
+ };
121
+ }
122
+
123
+ /**
124
+ * Deep merge user config with defaults
125
+ */
126
+ mergeWithDefaults(userConfig) {
127
+ const defaults = this.getDefaults();
128
+ return this.deepMerge(defaults, userConfig);
129
+ }
130
+
131
+ /**
132
+ * Deep merge utility
133
+ */
134
+ deepMerge(target, source) {
135
+ const output = { ...target };
136
+
137
+ if (this.isObject(target) && this.isObject(source)) {
138
+ Object.keys(source).forEach(key => {
139
+ if (this.isObject(source[key])) {
140
+ if (!(key in target)) {
141
+ output[key] = source[key];
142
+ } else {
143
+ output[key] = this.deepMerge(target[key], source[key]);
144
+ }
145
+ } else {
146
+ output[key] = source[key];
147
+ }
148
+ });
149
+ }
150
+
151
+ return output;
152
+ }
153
+
154
+ /**
155
+ * Check if value is an object
156
+ */
157
+ isObject(item) {
158
+ return item && typeof item === 'object' && !Array.isArray(item);
159
+ }
160
+
161
+ /**
162
+ * Validate configuration
163
+ */
164
+ validateConfig() {
165
+ const errors = [];
166
+
167
+ // Validate intervals
168
+ if (this.config.intervals.health < 1000) {
169
+ errors.push('Health check interval must be at least 1000ms');
170
+ }
171
+
172
+ // Validate thresholds
173
+ if (this.config.thresholds.cpu < 0 || this.config.thresholds.cpu > 100) {
174
+ errors.push('CPU threshold must be between 0 and 100');
175
+ }
176
+ if (this.config.thresholds.memory < 0 || this.config.thresholds.memory > 100) {
177
+ errors.push('Memory threshold must be between 0 and 100');
178
+ }
179
+
180
+ // Validate email config if enabled
181
+ if (this.config.notifications.email.enabled) {
182
+ if (!this.config.notifications.email.auth.user || !this.config.notifications.email.auth.pass) {
183
+ errors.push('Email notifications enabled but credentials not provided');
184
+ }
185
+ if (this.config.notifications.email.recipients.length === 0) {
186
+ errors.push('Email notifications enabled but no recipients specified');
187
+ }
188
+ }
189
+
190
+ // Validate Slack config if enabled
191
+ if (this.config.notifications.slack.enabled) {
192
+ if (!this.config.notifications.slack.webhook) {
193
+ errors.push('Slack notifications enabled but webhook URL not provided');
194
+ }
195
+ }
196
+
197
+ // Validate SMS config if enabled
198
+ if (this.config.notifications.sms.enabled) {
199
+ if (!this.config.notifications.sms.accountSid || !this.config.notifications.sms.authToken) {
200
+ errors.push('SMS notifications enabled but credentials not provided');
201
+ }
202
+ if (this.config.notifications.sms.recipients.length === 0) {
203
+ errors.push('SMS notifications enabled but no recipients specified');
204
+ }
205
+ }
206
+
207
+ if (errors.length > 0) {
208
+ throw new Error(`Configuration validation failed:\n${errors.join('\n')}`);
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Get configuration value by path
214
+ */
215
+ get(path) {
216
+ return path.split('.').reduce((obj, key) => obj?.[key], this.config);
217
+ }
218
+
219
+ /**
220
+ * Set configuration value by path
221
+ */
222
+ set(path, value) {
223
+ const keys = path.split('.');
224
+ const lastKey = keys.pop();
225
+ const target = keys.reduce((obj, key) => obj[key], this.config);
226
+ target[lastKey] = value;
227
+ }
228
+
229
+ /**
230
+ * Get all configuration
231
+ */
232
+ getAll() {
233
+ return { ...this.config };
234
+ }
235
+
236
+ /**
237
+ * Get sanitized config (without sensitive data) for logging
238
+ */
239
+ getSanitized() {
240
+ const sanitized = JSON.parse(JSON.stringify(this.config));
241
+
242
+ // Remove sensitive fields
243
+ if (sanitized.notifications?.email?.auth) {
244
+ sanitized.notifications.email.auth.pass = '***';
245
+ }
246
+ if (sanitized.notifications?.sms) {
247
+ sanitized.notifications.sms.authToken = '***';
248
+ }
249
+
250
+ return sanitized;
251
+ }
252
+ }
253
+
254
+ module.exports = MonitoringConfig;
255
+