pms_md 1.0.0 → 1.0.2
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.
- package/MYSQL2_SEQUELIZE_SUPPORT.md +334 -0
- package/index.js +14 -0
- package/node-monitor/GETTING_STARTED.md +35 -0
- package/node-monitor/README.md +21 -3
- package/node-monitor/examples/MYSQL_SEQUELIZE_GUIDE.md +321 -0
- package/node-monitor/examples/sequelize-mysql-example.js +147 -0
- package/node-monitor/package.json +6 -2
- package/node-monitor/src/monitors/dbConnectionMonitor.js +99 -17
- package/package.json +62 -5
- package/pms_md-1.0.1.tgz +0 -0
- package/pms_md-1.0.2.tgz +0 -0
- package/test-sequelize-monitor.js +102 -0
- package/node-monitor/DESIGN_IMPROVEMENTS.md +0 -286
- package/node-monitor/FILTER_BUTTONS_FIX.md +0 -303
- package/node-monitor/PUBLISHING_GUIDE.md +0 -331
- package/node-monitor/READY_TO_PUBLISH.md +0 -272
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# MySQL2 & Sequelize Monitoring Guide
|
|
2
|
+
|
|
3
|
+
This guide shows you how to use the Node Monitor package with MySQL2 and Sequelize.
|
|
4
|
+
|
|
5
|
+
## 📦 Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install the monitoring package
|
|
9
|
+
npm install pms_md
|
|
10
|
+
|
|
11
|
+
# Install MySQL2 (required)
|
|
12
|
+
npm install mysql2
|
|
13
|
+
|
|
14
|
+
# Install Sequelize (optional, if using ORM)
|
|
15
|
+
npm install sequelize
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 🔧 MySQL2 Setup
|
|
21
|
+
|
|
22
|
+
### Option 1: MySQL2 Promise Pool (Recommended)
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
const mysql = require('mysql2/promise');
|
|
26
|
+
const NodeMonitor = require('pms_md');
|
|
27
|
+
|
|
28
|
+
// Create MySQL2 connection pool
|
|
29
|
+
const pool = mysql.createPool({
|
|
30
|
+
host: 'localhost',
|
|
31
|
+
user: 'root',
|
|
32
|
+
password: 'your-password',
|
|
33
|
+
database: 'your-database',
|
|
34
|
+
waitForConnections: true,
|
|
35
|
+
connectionLimit: 10,
|
|
36
|
+
queueLimit: 0
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Initialize monitor
|
|
40
|
+
const monitor = new NodeMonitor({
|
|
41
|
+
app: {
|
|
42
|
+
name: 'My App',
|
|
43
|
+
version: '1.0.0'
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Register MySQL2 pool for monitoring
|
|
48
|
+
monitor.registerDatabase('mysql', 'mysql2', pool);
|
|
49
|
+
|
|
50
|
+
// Start monitoring
|
|
51
|
+
monitor.start();
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Option 2: MySQL2 Callback-based Connection
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
const mysql = require('mysql2');
|
|
58
|
+
|
|
59
|
+
const connection = mysql.createConnection({
|
|
60
|
+
host: 'localhost',
|
|
61
|
+
user: 'root',
|
|
62
|
+
password: 'your-password',
|
|
63
|
+
database: 'your-database'
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
connection.connect();
|
|
67
|
+
|
|
68
|
+
// Register for monitoring
|
|
69
|
+
monitor.registerDatabase('mysql', 'mysql2', connection);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 🎯 Sequelize Setup
|
|
75
|
+
|
|
76
|
+
### Basic Sequelize Configuration
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
const { Sequelize } = require('sequelize');
|
|
80
|
+
const NodeMonitor = require('pms_md');
|
|
81
|
+
|
|
82
|
+
// Create Sequelize instance
|
|
83
|
+
const sequelize = new Sequelize('database', 'username', 'password', {
|
|
84
|
+
host: 'localhost',
|
|
85
|
+
dialect: 'mysql', // or 'postgres', 'sqlite', 'mssql'
|
|
86
|
+
logging: false,
|
|
87
|
+
pool: {
|
|
88
|
+
max: 5,
|
|
89
|
+
min: 0,
|
|
90
|
+
acquire: 30000,
|
|
91
|
+
idle: 10000
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Initialize monitor
|
|
96
|
+
const monitor = new NodeMonitor({
|
|
97
|
+
app: {
|
|
98
|
+
name: 'Sequelize App',
|
|
99
|
+
version: '1.0.0'
|
|
100
|
+
},
|
|
101
|
+
notifications: {
|
|
102
|
+
email: {
|
|
103
|
+
enabled: true,
|
|
104
|
+
host: 'smtp.gmail.com',
|
|
105
|
+
port: 587,
|
|
106
|
+
auth: {
|
|
107
|
+
user: 'your-email@gmail.com',
|
|
108
|
+
pass: 'your-app-password'
|
|
109
|
+
},
|
|
110
|
+
recipients: ['admin@example.com']
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Test connection and register
|
|
116
|
+
async function setupDatabase() {
|
|
117
|
+
try {
|
|
118
|
+
await sequelize.authenticate();
|
|
119
|
+
console.log('Database connected successfully');
|
|
120
|
+
|
|
121
|
+
// Register Sequelize instance for monitoring
|
|
122
|
+
monitor.registerDatabase('mydb', 'sequelize', sequelize);
|
|
123
|
+
|
|
124
|
+
// Start monitoring
|
|
125
|
+
monitor.start();
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Unable to connect to database:', error);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
setupDatabase();
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🚀 Complete Express + Sequelize Example
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
const express = require('express');
|
|
140
|
+
const { Sequelize } = require('sequelize');
|
|
141
|
+
const NodeMonitor = require('pms_md');
|
|
142
|
+
|
|
143
|
+
// Initialize Sequelize
|
|
144
|
+
const sequelize = new Sequelize('myapp', 'root', 'password', {
|
|
145
|
+
host: 'localhost',
|
|
146
|
+
dialect: 'mysql'
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Initialize Monitor
|
|
150
|
+
const monitor = new NodeMonitor({
|
|
151
|
+
app: { name: 'My App', version: '1.0.0' }
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const app = express();
|
|
155
|
+
app.use(express.json());
|
|
156
|
+
|
|
157
|
+
// Add monitoring middleware
|
|
158
|
+
app.use(monitor.requestLogger());
|
|
159
|
+
|
|
160
|
+
// Health check
|
|
161
|
+
app.get('/health', monitor.healthCheckEndpoint());
|
|
162
|
+
|
|
163
|
+
// Your routes
|
|
164
|
+
app.get('/users', monitor.asyncHandler(async (req, res) => {
|
|
165
|
+
const [users] = await sequelize.query('SELECT * FROM users');
|
|
166
|
+
res.json(users);
|
|
167
|
+
}));
|
|
168
|
+
|
|
169
|
+
// Error handling
|
|
170
|
+
app.use(monitor.notFoundHandler());
|
|
171
|
+
app.use(monitor.errorMiddleware());
|
|
172
|
+
|
|
173
|
+
// Start server
|
|
174
|
+
async function start() {
|
|
175
|
+
await sequelize.authenticate();
|
|
176
|
+
monitor.registerDatabase('mysql', 'sequelize', sequelize);
|
|
177
|
+
|
|
178
|
+
const server = app.listen(3000, () => {
|
|
179
|
+
console.log('Server running on port 3000');
|
|
180
|
+
monitor.start();
|
|
181
|
+
monitor.setupGracefulShutdown(server);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
start();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 📊 Monitoring Features
|
|
191
|
+
|
|
192
|
+
### Get Database Statistics
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
// Get MySQL connection stats
|
|
196
|
+
const stats = await monitor.getDatabaseStats('mysql');
|
|
197
|
+
console.log(stats);
|
|
198
|
+
// Output: { type: 'mysql', threadsConnected: 5 }
|
|
199
|
+
|
|
200
|
+
// Get Sequelize stats
|
|
201
|
+
const seqStats = await monitor.getDatabaseStats('mydb');
|
|
202
|
+
console.log(seqStats);
|
|
203
|
+
// Output: {
|
|
204
|
+
// type: 'sequelize',
|
|
205
|
+
// dialect: 'mysql',
|
|
206
|
+
// database: 'myapp',
|
|
207
|
+
// host: 'localhost',
|
|
208
|
+
// pool: { size: 5, available: 3, using: 2, waiting: 0 }
|
|
209
|
+
// }
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Custom Health Checks
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
// Add custom database health check
|
|
216
|
+
monitor.registerHealthCheck('database', async () => {
|
|
217
|
+
try {
|
|
218
|
+
await sequelize.authenticate();
|
|
219
|
+
return true;
|
|
220
|
+
} catch {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Check health status
|
|
226
|
+
app.get('/health', monitor.healthCheckEndpoint());
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Monitor Connection Status
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
// Get all database connection statuses
|
|
233
|
+
const status = monitor.getStatus();
|
|
234
|
+
console.log(status.databases);
|
|
235
|
+
// Output: {
|
|
236
|
+
// mysql: { type: 'sequelize', connected: true, consecutiveFailures: 0 }
|
|
237
|
+
// }
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 🔔 Automatic Notifications
|
|
243
|
+
|
|
244
|
+
The monitor will automatically send notifications when:
|
|
245
|
+
|
|
246
|
+
- ✅ Database connection is lost
|
|
247
|
+
- ✅ Database connection is restored
|
|
248
|
+
- ✅ Connection check fails multiple times
|
|
249
|
+
- ✅ Query timeout occurs
|
|
250
|
+
|
|
251
|
+
Configure email notifications:
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
const monitor = new NodeMonitor({
|
|
255
|
+
notifications: {
|
|
256
|
+
email: {
|
|
257
|
+
enabled: true,
|
|
258
|
+
host: 'smtp.gmail.com',
|
|
259
|
+
port: 587,
|
|
260
|
+
auth: {
|
|
261
|
+
user: 'your-email@gmail.com',
|
|
262
|
+
pass: 'your-app-password'
|
|
263
|
+
},
|
|
264
|
+
recipients: ['admin@example.com']
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 🛠️ Troubleshooting
|
|
273
|
+
|
|
274
|
+
### Connection Issues
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
// Test Sequelize connection
|
|
278
|
+
try {
|
|
279
|
+
await sequelize.authenticate();
|
|
280
|
+
console.log('✅ Connection successful');
|
|
281
|
+
} catch (error) {
|
|
282
|
+
console.error('❌ Connection failed:', error);
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Check Monitor Logs
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
# View application logs
|
|
290
|
+
cat logs/application-*.log
|
|
291
|
+
|
|
292
|
+
# View error logs
|
|
293
|
+
cat logs/error-*.log
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## 📚 Additional Resources
|
|
299
|
+
|
|
300
|
+
- [Sequelize Documentation](https://sequelize.org/)
|
|
301
|
+
- [MySQL2 Documentation](https://github.com/sidorares/node-mysql2)
|
|
302
|
+
- [Node Monitor README](../README.md)
|
|
303
|
+
- [Getting Started Guide](../GETTING_STARTED.md)
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## 💡 Best Practices
|
|
308
|
+
|
|
309
|
+
1. **Use Connection Pooling**: Always use connection pools in production
|
|
310
|
+
2. **Set Timeouts**: Configure appropriate query timeouts
|
|
311
|
+
3. **Monitor Regularly**: Check database health at regular intervals
|
|
312
|
+
4. **Handle Errors**: Always wrap database queries in try-catch blocks
|
|
313
|
+
5. **Graceful Shutdown**: Close database connections on app shutdown
|
|
314
|
+
|
|
315
|
+
```javascript
|
|
316
|
+
monitor.setupGracefulShutdown(server, async () => {
|
|
317
|
+
await sequelize.close();
|
|
318
|
+
console.log('Database connection closed');
|
|
319
|
+
});
|
|
320
|
+
```
|
|
321
|
+
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Using Node Monitor with Sequelize and MySQL2
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to integrate the monitoring package
|
|
5
|
+
* with Sequelize ORM and MySQL2 database.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const express = require('express');
|
|
9
|
+
const { Sequelize } = require('sequelize');
|
|
10
|
+
const NodeMonitor = require('../src/index');
|
|
11
|
+
|
|
12
|
+
// Initialize Sequelize with MySQL2
|
|
13
|
+
const sequelize = new Sequelize('asset_tracking', 'root', 'password', {
|
|
14
|
+
host: 'localhost',
|
|
15
|
+
dialect: 'mysql',
|
|
16
|
+
logging: false, // Disable SQL logging
|
|
17
|
+
pool: {
|
|
18
|
+
max: 5,
|
|
19
|
+
min: 0,
|
|
20
|
+
acquire: 30000,
|
|
21
|
+
idle: 10000
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Initialize Node Monitor
|
|
26
|
+
const monitor = new NodeMonitor({
|
|
27
|
+
app: {
|
|
28
|
+
name: 'Sequelize MySQL App',
|
|
29
|
+
version: '1.0.0',
|
|
30
|
+
environment: process.env.NODE_ENV || 'development'
|
|
31
|
+
},
|
|
32
|
+
notifications: {
|
|
33
|
+
email: {
|
|
34
|
+
enabled: true,
|
|
35
|
+
host: 'smtp.gmail.com',
|
|
36
|
+
port: 587,
|
|
37
|
+
auth: {
|
|
38
|
+
user: process.env.EMAIL_USER || 'your-email@gmail.com',
|
|
39
|
+
pass: process.env.EMAIL_PASS || 'your-app-password'
|
|
40
|
+
},
|
|
41
|
+
from: process.env.EMAIL_USER || 'your-email@gmail.com',
|
|
42
|
+
recipients: [process.env.EMAIL_RECIPIENTS || 'admin@example.com']
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
database: {
|
|
46
|
+
enabled: true,
|
|
47
|
+
queryTimeout: 5000
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Create Express app
|
|
52
|
+
const app = express();
|
|
53
|
+
app.use(express.json());
|
|
54
|
+
|
|
55
|
+
// Add monitoring middleware
|
|
56
|
+
app.use(monitor.requestLogger());
|
|
57
|
+
|
|
58
|
+
// Health check endpoint
|
|
59
|
+
app.get('/health', monitor.healthCheckEndpoint());
|
|
60
|
+
|
|
61
|
+
// Dashboard endpoint
|
|
62
|
+
app.get('/dashboard', monitor.dashboardEndpoint());
|
|
63
|
+
|
|
64
|
+
// Example routes
|
|
65
|
+
app.get('/', (req, res) => {
|
|
66
|
+
res.json({
|
|
67
|
+
message: 'Sequelize MySQL Monitoring Example',
|
|
68
|
+
status: 'running'
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Example database query endpoint
|
|
73
|
+
app.get('/db-test', monitor.asyncHandler(async (req, res) => {
|
|
74
|
+
// Test database connection
|
|
75
|
+
await sequelize.authenticate();
|
|
76
|
+
|
|
77
|
+
// Execute a simple query
|
|
78
|
+
const [results] = await sequelize.query('SELECT 1 + 1 AS result');
|
|
79
|
+
|
|
80
|
+
res.json({
|
|
81
|
+
message: 'Database connection successful',
|
|
82
|
+
result: results
|
|
83
|
+
});
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
// Get database stats
|
|
87
|
+
app.get('/db-stats', monitor.asyncHandler(async (req, res) => {
|
|
88
|
+
const stats = await monitor.getDatabaseStats('mysql');
|
|
89
|
+
res.json(stats);
|
|
90
|
+
}));
|
|
91
|
+
|
|
92
|
+
// Error handling middleware (must be last)
|
|
93
|
+
app.use(monitor.notFoundHandler());
|
|
94
|
+
app.use(monitor.errorMiddleware());
|
|
95
|
+
|
|
96
|
+
// Start server
|
|
97
|
+
async function startServer() {
|
|
98
|
+
try {
|
|
99
|
+
// Test database connection
|
|
100
|
+
console.log('Testing database connection...');
|
|
101
|
+
await sequelize.authenticate();
|
|
102
|
+
console.log('✅ Database connection established successfully.');
|
|
103
|
+
|
|
104
|
+
// Register database for monitoring
|
|
105
|
+
monitor.registerDatabase('mysql', 'sequelize', sequelize);
|
|
106
|
+
console.log('✅ Database registered for monitoring.');
|
|
107
|
+
|
|
108
|
+
// Register custom health check for database
|
|
109
|
+
monitor.registerHealthCheck('database', async () => {
|
|
110
|
+
try {
|
|
111
|
+
await sequelize.authenticate();
|
|
112
|
+
return true;
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Start the server
|
|
119
|
+
const PORT = process.env.PORT || 3000;
|
|
120
|
+
const server = app.listen(PORT, () => {
|
|
121
|
+
console.log(`\n🚀 Server running on http://localhost:${PORT}`);
|
|
122
|
+
console.log(`📊 Health check: http://localhost:${PORT}/health`);
|
|
123
|
+
console.log(`📈 Dashboard: http://localhost:${PORT}/dashboard`);
|
|
124
|
+
console.log(`🔍 DB Test: http://localhost:${PORT}/db-test`);
|
|
125
|
+
console.log(`📊 DB Stats: http://localhost:${PORT}/db-stats\n`);
|
|
126
|
+
|
|
127
|
+
// Start monitoring
|
|
128
|
+
monitor.start();
|
|
129
|
+
console.log('✅ Monitoring started\n');
|
|
130
|
+
|
|
131
|
+
// Setup graceful shutdown
|
|
132
|
+
monitor.setupGracefulShutdown(server, async () => {
|
|
133
|
+
console.log('Closing database connection...');
|
|
134
|
+
await sequelize.close();
|
|
135
|
+
console.log('Database connection closed.');
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error('❌ Unable to start server:', error);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Start the application
|
|
146
|
+
startServer();
|
|
147
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@projectmd/node-monitor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Comprehensive monitoring solution for Node.js applications with error tracking, health checks, and multi-channel notifications",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
"express": "^4.18.0 || ^5.0.0",
|
|
48
48
|
"mongoose": "^7.0.0 || ^8.0.0",
|
|
49
49
|
"pg": "^8.11.0",
|
|
50
|
-
"mysql2": "^3.
|
|
50
|
+
"mysql2": "^2.0.0 || ^3.0.0",
|
|
51
|
+
"sequelize": "^6.0.0",
|
|
51
52
|
"ioredis": "^5.3.0"
|
|
52
53
|
},
|
|
53
54
|
"peerDependenciesMeta": {
|
|
@@ -63,6 +64,9 @@
|
|
|
63
64
|
"mysql2": {
|
|
64
65
|
"optional": true
|
|
65
66
|
},
|
|
67
|
+
"sequelize": {
|
|
68
|
+
"optional": true
|
|
69
|
+
},
|
|
66
70
|
"ioredis": {
|
|
67
71
|
"optional": true
|
|
68
72
|
}
|
|
@@ -104,18 +104,22 @@ class DbConnectionMonitor {
|
|
|
104
104
|
case 'mongodb':
|
|
105
105
|
case 'mongoose':
|
|
106
106
|
return this.checkMongoConnection(connection);
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
case 'postgresql':
|
|
109
109
|
case 'postgres':
|
|
110
110
|
case 'pg':
|
|
111
111
|
return this.checkPostgresConnection(connection, testQuery);
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
case 'mysql':
|
|
114
|
+
case 'mysql2':
|
|
114
115
|
return this.checkMySqlConnection(connection, testQuery);
|
|
115
|
-
|
|
116
|
+
|
|
117
|
+
case 'sequelize':
|
|
118
|
+
return this.checkSequelizeConnection(connection);
|
|
119
|
+
|
|
116
120
|
case 'redis':
|
|
117
121
|
return this.checkRedisConnection(connection);
|
|
118
|
-
|
|
122
|
+
|
|
119
123
|
default:
|
|
120
124
|
throw new Error(`Unsupported database type: ${type}`);
|
|
121
125
|
}
|
|
@@ -160,16 +164,48 @@ class DbConnectionMonitor {
|
|
|
160
164
|
}
|
|
161
165
|
|
|
162
166
|
/**
|
|
163
|
-
* Check MySQL connection
|
|
167
|
+
* Check MySQL/MySQL2 connection
|
|
164
168
|
*/
|
|
165
169
|
async checkMySqlConnection(connection, testQuery = 'SELECT 1') {
|
|
166
170
|
try {
|
|
167
|
-
|
|
168
|
-
|
|
171
|
+
// Support for mysql2 pool or connection
|
|
172
|
+
if (connection.query) {
|
|
173
|
+
const result = await Promise.race([
|
|
174
|
+
connection.query(testQuery),
|
|
175
|
+
this.timeout(this.config.database.queryTimeout)
|
|
176
|
+
]);
|
|
177
|
+
// mysql2 returns [rows, fields]
|
|
178
|
+
return Array.isArray(result) ? !!result[0] : !!result;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Support for mysql2 promise pool
|
|
182
|
+
if (connection.execute) {
|
|
183
|
+
const [rows] = await Promise.race([
|
|
184
|
+
connection.execute(testQuery),
|
|
185
|
+
this.timeout(this.config.database.queryTimeout)
|
|
186
|
+
]);
|
|
187
|
+
return !!rows;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return false;
|
|
191
|
+
} catch (error) {
|
|
192
|
+
this.logger.logWarning('mysql_check_failed', `MySQL connection check failed: ${error.message}`);
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Check Sequelize connection
|
|
199
|
+
*/
|
|
200
|
+
async checkSequelizeConnection(connection) {
|
|
201
|
+
try {
|
|
202
|
+
await Promise.race([
|
|
203
|
+
connection.authenticate(),
|
|
169
204
|
this.timeout(this.config.database.queryTimeout)
|
|
170
205
|
]);
|
|
171
|
-
return
|
|
172
|
-
} catch {
|
|
206
|
+
return true;
|
|
207
|
+
} catch (error) {
|
|
208
|
+
this.logger.logWarning('sequelize_check_failed', `Sequelize connection check failed: ${error.message}`);
|
|
173
209
|
return false;
|
|
174
210
|
}
|
|
175
211
|
}
|
|
@@ -275,18 +311,22 @@ class DbConnectionMonitor {
|
|
|
275
311
|
case 'mongodb':
|
|
276
312
|
case 'mongoose':
|
|
277
313
|
return this.getMongoStats(connection);
|
|
278
|
-
|
|
314
|
+
|
|
279
315
|
case 'postgresql':
|
|
280
316
|
case 'postgres':
|
|
281
317
|
case 'pg':
|
|
282
318
|
return this.getPostgresStats(connection);
|
|
283
|
-
|
|
319
|
+
|
|
284
320
|
case 'mysql':
|
|
321
|
+
case 'mysql2':
|
|
285
322
|
return this.getMySqlStats(connection);
|
|
286
|
-
|
|
323
|
+
|
|
324
|
+
case 'sequelize':
|
|
325
|
+
return this.getSequelizeStats(connection);
|
|
326
|
+
|
|
287
327
|
case 'redis':
|
|
288
328
|
return this.getRedisStats(connection);
|
|
289
|
-
|
|
329
|
+
|
|
290
330
|
default:
|
|
291
331
|
return { type, status: 'unknown' };
|
|
292
332
|
}
|
|
@@ -333,21 +373,63 @@ class DbConnectionMonitor {
|
|
|
333
373
|
}
|
|
334
374
|
|
|
335
375
|
/**
|
|
336
|
-
* Get MySQL statistics
|
|
376
|
+
* Get MySQL/MySQL2 statistics
|
|
337
377
|
*/
|
|
338
378
|
async getMySqlStats(connection) {
|
|
339
379
|
try {
|
|
340
|
-
|
|
341
|
-
|
|
380
|
+
let rows;
|
|
381
|
+
|
|
382
|
+
// Try mysql2 format first
|
|
383
|
+
if (connection.query) {
|
|
384
|
+
const result = await connection.query('SHOW STATUS LIKE "Threads_connected"');
|
|
385
|
+
rows = Array.isArray(result) ? result[0] : result;
|
|
386
|
+
} else if (connection.execute) {
|
|
387
|
+
[rows] = await connection.execute('SHOW STATUS LIKE "Threads_connected"');
|
|
388
|
+
}
|
|
389
|
+
|
|
342
390
|
return {
|
|
343
391
|
type: 'mysql',
|
|
344
|
-
threadsConnected: rows[0]?.Value || 0
|
|
392
|
+
threadsConnected: rows?.[0]?.Value || 0
|
|
345
393
|
};
|
|
346
394
|
} catch (error) {
|
|
347
395
|
return { type: 'mysql', error: error.message };
|
|
348
396
|
}
|
|
349
397
|
}
|
|
350
398
|
|
|
399
|
+
/**
|
|
400
|
+
* Get Sequelize statistics
|
|
401
|
+
*/
|
|
402
|
+
async getSequelizeStats(connection) {
|
|
403
|
+
try {
|
|
404
|
+
// Get database dialect
|
|
405
|
+
const dialect = connection.getDialect();
|
|
406
|
+
|
|
407
|
+
// Get pool information if available
|
|
408
|
+
const poolInfo = connection.connectionManager?.pool
|
|
409
|
+
? {
|
|
410
|
+
size: connection.connectionManager.pool.size || 0,
|
|
411
|
+
available: connection.connectionManager.pool.available || 0,
|
|
412
|
+
using: connection.connectionManager.pool.using || 0,
|
|
413
|
+
waiting: connection.connectionManager.pool.waiting || 0
|
|
414
|
+
}
|
|
415
|
+
: null;
|
|
416
|
+
|
|
417
|
+
// Get basic connection info
|
|
418
|
+
const dbName = connection.config?.database || 'unknown';
|
|
419
|
+
const host = connection.config?.host || 'unknown';
|
|
420
|
+
|
|
421
|
+
return {
|
|
422
|
+
type: 'sequelize',
|
|
423
|
+
dialect,
|
|
424
|
+
database: dbName,
|
|
425
|
+
host,
|
|
426
|
+
pool: poolInfo
|
|
427
|
+
};
|
|
428
|
+
} catch (error) {
|
|
429
|
+
return { type: 'sequelize', error: error.message };
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
351
433
|
/**
|
|
352
434
|
* Get Redis statistics
|
|
353
435
|
*/
|