Skip to content

Commit 51d3213

Browse files
author
didil
committed
init
0 parents  commit 51d3213

File tree

7 files changed

+295
-0
lines changed

7 files changed

+295
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
.idea/
3+
test-data/

README.md

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# pm2-postgres
2+
PostgreSQL module for Keymetrics
3+
4+
![pm2-postgres screenshot](https://raw.githubusercontent.com/pm2-hive/pm2-postgres/master/pm2-postgres.jpg)
5+
6+
## Description
7+
8+
PM2 module to monitor key PostgreSQL server metrics:
9+
10+
*
11+
*
12+
*
13+
*
14+
15+
## Requirements
16+
17+
This module requires a PostgreSQL install (tested against v9.4).
18+
19+
## Install
20+
21+
```bash
22+
$ npm install pm2 -g
23+
24+
$ pm2 install pm2-postgres
25+
```
26+
27+
## Config
28+
29+
The default connection details are :
30+
"hostname": "localhost"
31+
"port": 5432
32+
"username": "guest"
33+
"password": "guest"
34+
"database": "postgres"
35+
36+
To modify the config values you can use the commands:
37+
```bash
38+
$ pm2 set pm2-postgres:hostname localhost
39+
$ pm2 set pm2-postgres:port 5432
40+
$ pm2 set pm2-postgres:username guest
41+
$ pm2 set pm2-postgres:password guest
42+
$ pm2 set pm2-postgres:database postgres
43+
```
44+
45+
## Uninstall
46+
47+
```bash
48+
$ pm2 uninstall pm2-postgres
49+
```
50+
51+
# License
52+
53+
MIT

app.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
var pmx = require('pmx');
2+
var pgClientFactory = require('./lib/clientFactory.js');
3+
var pgStats = require('./lib/stats.js');
4+
var pgActions = require('./lib/actions.js');
5+
6+
pmx.initModule({
7+
8+
pid: pmx.resolvePidPaths(['/var/run/postgresql/9.4-main.pid', '/var/run/postgresql/9.3-main.pid']),
9+
10+
// Options related to the display style on Keymetrics
11+
widget: {
12+
13+
// Logo displayed
14+
logo: 'http://www.inquidia.com/sites/default/files/postgresql_logo%5B1%5D.png',
15+
16+
// Module colors
17+
// 0 = main element
18+
// 1 = secondary
19+
// 2 = main border
20+
// 3 = secondary border
21+
theme: ['#141A1F', '#222222', '#FC6400', '#807C7C'],
22+
23+
// Section to show / hide
24+
el: {
25+
probes: true,
26+
actions: true
27+
},
28+
29+
// Main block to show / hide
30+
block: {
31+
actions: true,
32+
issues: true,
33+
meta: true,
34+
35+
// Custom metrics to put in BIG
36+
main_probes: ['Tables', 'Indexes']
37+
}
38+
39+
}
40+
41+
}, function (err, conf) {
42+
var pgClient = pgClientFactory.build(conf);
43+
44+
// Init metrics refresh loop
45+
pgStats.init(pgClient);
46+
47+
// Init actions
48+
pgActions.init(pgClient);
49+
});

lib/actions.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var pmx = require('pmx');
2+
3+
function initActions(pgClient) {
4+
5+
6+
}
7+
8+
function init(pgClient) {
9+
initActions(pgClient);
10+
}
11+
12+
module.exports.init = init;

lib/clientFactory.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
var pg = require('pg');
2+
var pmx = require('pmx');
3+
4+
function build(conf) {
5+
var pgClient = {};
6+
7+
var connectionString = "postgres://" + conf.username + ":" + conf.password + "@" + conf.hostname + ":" + conf.port + "/" + conf.database;
8+
9+
pgClient.query = function (queryString, cb) {
10+
pg.connect(connectionString, function (err, client, done) {
11+
if (err) {
12+
// A connection error occurred, remove the client from the connection pool.
13+
if (client) {
14+
done(client);
15+
}
16+
return pmx.notify("Couldn't connect to postgres: " + err);
17+
}
18+
19+
client.query(queryString, function (err, result) {
20+
if (err) {
21+
// return client to the connection pool
22+
done();
23+
return cb(err);
24+
}
25+
26+
// return client to the connection pool
27+
done();
28+
return cb(null, result);
29+
});
30+
});
31+
};
32+
33+
return pgClient;
34+
}
35+
36+
module.exports.build = build;

lib/stats.js

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
var pmx = require('pmx');
2+
3+
var metrics = {};
4+
var REFRESH_RATE = 10000; // ms
5+
var probe = pmx.probe();
6+
7+
// Init metrics with default values
8+
function initMetrics() {
9+
metrics.tableCount = probe.metric({
10+
name: 'Tables',
11+
value: 'N/A'
12+
});
13+
metrics.indexCount = probe.metric({
14+
name: 'Indexes',
15+
value: 'N/A'
16+
});
17+
metrics.transactionsCommitted = probe.metric({
18+
name: 'Transactions Committed',
19+
value: 'N/A'
20+
});
21+
metrics.transactionsRollback = probe.metric({
22+
name: 'Transactions Rollback',
23+
value: 'N/A'
24+
});
25+
metrics.tuplesFetched = probe.metric({
26+
name: 'Tuples Fetched',
27+
value: 'N/A'
28+
});
29+
metrics.tuplesInserted = probe.metric({
30+
name: 'Tuples Inserted',
31+
value: 'N/A'
32+
});
33+
metrics.tuplesUpdated = probe.metric({
34+
name: 'Tuples Updated',
35+
value: 'N/A'
36+
});
37+
metrics.tuplesDeleted = probe.metric({
38+
name: 'Tuples Deleted',
39+
value: 'N/A'
40+
});
41+
}
42+
43+
// Refresh metrics
44+
function refreshMetrics(pgClient) {
45+
refreshTableCount(pgClient);
46+
refreshIndexCount(pgClient);
47+
refreshTransactionMetrics(pgClient);
48+
}
49+
50+
function refreshTableCount(pgClient) {
51+
var queryString = "SELECT count(1) as relations FROM pg_class WHERE relkind IN ('r', 't');";
52+
pgClient.query(queryString, function (err, results) {
53+
if (err) {
54+
return pmx.notify("Table Query Error: " + err);
55+
}
56+
57+
// # of Tables
58+
metrics.tableCount.set(results.rows[0].relations);
59+
});
60+
}
61+
62+
function refreshIndexCount(pgClient) {
63+
var queryString = "SELECT count(1) as indexes FROM pg_class WHERE relkind = 'i';";
64+
pgClient.query(queryString, function (err, results) {
65+
if (err) {
66+
return pmx.notify("Index Query Error: " + err);
67+
}
68+
69+
// # of Indexes
70+
metrics.indexCount.set(results.rows[0].indexes);
71+
});
72+
}
73+
74+
function refreshTransactionMetrics(pgClient) {
75+
var queryString = "SELECT sum(xact_commit) AS transactions_committed,"
76+
+ " sum(xact_rollback) AS transactions_rollback, sum(blks_read) AS blocks_read,"
77+
+ " sum(blks_hit) AS blocks_hit, sum(tup_returned) AS tuples_returned,"
78+
+ " sum(tup_fetched) AS tuples_fetched, sum(tup_inserted) AS tuples_inserted,"
79+
+ " sum(tup_updated) AS tuples_updated, sum(tup_deleted) AS tuples_deleted"
80+
+ " FROM pg_stat_database;";
81+
pgClient.query(queryString, function (err, results) {
82+
if (err) {
83+
return pmx.notify("Transaction Query Error: " + err);
84+
}
85+
86+
// Transactions Committed
87+
metrics.transactionsCommitted.set(results.rows[0].transactions_committed);
88+
89+
// Transactions Rollback
90+
metrics.transactionsRollback.set(results.rows[0].transactions_rollback);
91+
92+
// Tuples Fetched
93+
metrics.tuplesFetched.set(results.rows[0].tuples_fetched);
94+
95+
// Tuples Inserted
96+
metrics.tuplesInserted.set(results.rows[0].tuples_inserted);
97+
98+
// Tuples Updated
99+
metrics.tuplesUpdated.set(results.rows[0].tuples_updated);
100+
101+
// Tuples Deleted
102+
metrics.tuplesDeleted.set(results.rows[0].tuples_deleted);
103+
});
104+
}
105+
106+
function init(pgClient) {
107+
initMetrics();
108+
setInterval(refreshMetrics.bind(this, pgClient), REFRESH_RATE);
109+
}
110+
111+
module.exports.init = init;

package.json

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "pm2-postgres",
3+
"version": "0.0.1",
4+
"description": "PM2 PostgreSQL Module",
5+
"main": "app.js",
6+
"dependencies": {
7+
"pg": "^4.4.2",
8+
"pmx": ">=0.5.5"
9+
},
10+
"repository": {
11+
"type": "git",
12+
"url": "https://github.com/pm2-hive/pm2-postgres.git"
13+
},
14+
"config": {
15+
"hostname": "localhost",
16+
"port": 5432,
17+
"username": "guest",
18+
"password": "guest",
19+
"database": "postgres"
20+
},
21+
"apps": [
22+
{
23+
"merge_logs": true,
24+
"max_memory_restart": "200M",
25+
"script": "app.js"
26+
}
27+
],
28+
"author": "Keymetrics Inc.",
29+
"license": "MIT",
30+
"devDependencies": {}
31+
}

0 commit comments

Comments
 (0)