├── .gitignore ├── README.md ├── app.js ├── lib └── rabbitmq_stats.js ├── package.json └── pm2-rabbitmq.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea/ 3 | test-data/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pm2-rabbitmq 2 | RabbitMQ module for Keymetrics 3 | 4 | ![pm2-rabbitmq screenshot](https://raw.githubusercontent.com/pm2-hive/pm2-rabbitmq/master/pm2-rabbitmq.jpg) 5 | 6 | ## Description 7 | 8 | PM2 module to monitor key RabbitMQ server metrics: 9 | 10 | * # of Connections / Queues / Channels / Consumers / Exchanges 11 | * # of Total messages / Ready messages / Unacknowledged messages 12 | * Publish Rate / Deliver Rate 13 | 14 | ## Requirements 15 | 16 | This module requires a RabbitMQ install (tested against v3.5.4). 17 | You also need to enable the [RabbitMQ management plugin](https://www.rabbitmq.com/management.html) 18 | 19 | ## Install 20 | 21 | ```bash 22 | $ npm install pm2 -g 23 | 24 | $ pm2 install pm2-rabbitmq 25 | ``` 26 | 27 | ## Config 28 | 29 | The default connection details are : 30 | "username": "guest" 31 | "password": "guest" 32 | "hostname": "localhost:15672" 33 | "protocol": "http" 34 | 35 | guest/guest is a user created by default when installing RabbitMQ but you can change this to any other admin user 36 | 37 | To modify the config values you can use the commands: 38 | ```bash 39 | $ pm2 set pm2-rabbitmq:username myuser 40 | $ pm2 set pm2-rabbitmq:password mypass 41 | $ pm2 set pm2-rabbitmq:hostname a.b.c.d:port 42 | $ pm2 set pm2-rabbitmq:protocol https 43 | ``` 44 | 45 | ## Uninstall 46 | 47 | ```bash 48 | $ pm2 uninstall pm2-rabbitmq 49 | ``` 50 | 51 | # License 52 | 53 | MIT 54 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var pmx = require('pmx'); 2 | var rabbitmqStats = require('./lib/rabbitmq_stats.js'); 3 | 4 | pmx.initModule({ 5 | 6 | pid: pmx.resolvePidPaths(['/var/run/rabbitmq/pid']), 7 | 8 | // Options related to the display style on Keymetrics 9 | widget: { 10 | 11 | // Logo displayed 12 | logo: 'https://cloud.google.com/solutions/rabbitmq/images/rabbitmq_logo.png', 13 | 14 | // Module colors 15 | // 0 = main element 16 | // 1 = secondary 17 | // 2 = main border 18 | // 3 = secondary border 19 | theme: ['#141A1F', '#222222', '#FC6400', '#807C7C'], 20 | 21 | // Section to show / hide 22 | el: { 23 | probes: true, 24 | actions: true 25 | }, 26 | 27 | // Main block to show / hide 28 | block: { 29 | actions: false, 30 | issues: true, 31 | meta: true, 32 | 33 | // Custom metrics to put in BIG 34 | main_probes: ['Queues', 'Connections', 'Consumers', 'Total Messages', 'Publish Rate/sec', 'Deliver Rate/sec'] 35 | } 36 | 37 | } 38 | 39 | }, function (err, conf) { 40 | 41 | // Init metrics refresh loop 42 | rabbitmqStats.init(conf); 43 | }); 44 | -------------------------------------------------------------------------------- /lib/rabbitmq_stats.js: -------------------------------------------------------------------------------- 1 | var pmx = require('pmx'); 2 | var dotty = require("dotty"); 3 | var AMQPStats = require('amqp-stats'); 4 | var metrics = {}; 5 | var REFRESH_RATE = 5000; // ms 6 | var probe = pmx.probe(); 7 | 8 | // Init metrics with default values 9 | function initMetrics() { 10 | metrics.rabbitmqVersion = probe.metric({ 11 | name: 'RabbitMQ Version', 12 | value: 'N/A' 13 | }); 14 | metrics.queues = probe.metric({ 15 | name: 'Queues', 16 | value: 'N/A' 17 | }); 18 | metrics.connections = probe.metric({ 19 | name: 'Connections', 20 | value: 'N/A' 21 | }); 22 | metrics.consumers = probe.metric({ 23 | name: 'Consumers', 24 | value: 'N/A' 25 | }); 26 | metrics.channels = probe.metric({ 27 | name: 'Channels', 28 | value: 'N/A' 29 | }); 30 | metrics.exchanges = probe.metric({ 31 | name: 'Exchanges', 32 | value: 'N/A' 33 | }); 34 | metrics.totalMessages = probe.metric({ 35 | name: 'Total Messages', 36 | value: 'N/A' 37 | }); 38 | metrics.publishRate = probe.metric({ 39 | name: 'Publish Rate/sec', 40 | value: 'N/A' 41 | }); 42 | metrics.deliverRate = probe.metric({ 43 | name: 'Deliver Rate/sec', 44 | value: 'N/A' 45 | }); 46 | metrics.messagesReady = probe.metric({ 47 | name: 'Ready Messages', 48 | value: 'N/A' 49 | }); 50 | metrics.messagesUnacknowledged = probe.metric({ 51 | name: 'Unacknowledged Messages', 52 | value: 'N/A' 53 | }); 54 | } 55 | 56 | // Init amqp stats agent 57 | function initAgent(conf) { 58 | return new AMQPStats({ 59 | username: conf.username, 60 | password: conf.password, 61 | hostname: conf.hostname, 62 | protocol: conf.protocol 63 | }); 64 | } 65 | 66 | // Refresh metrics 67 | function refreshMetrics(statsAgent) { 68 | statsAgent.overview(function (err, res, data) { 69 | if(err){ 70 | var errMatch = err.message.match(/Status code: (\d+)/); 71 | if(errMatch){ 72 | return pmx.notify("Couldn't connect to Rabbit MQ - " + err.message); 73 | } 74 | else if (err.code === 'ECONNREFUSED'){ 75 | return pmx.notify("Couldn't access RabbitMQ management plugin - make sure RabbitMQ management plugin is installed and accessible at: "+ statsAgent.protocol + "://" + statsAgent.hostname); 76 | } 77 | else{ 78 | return pmx.notify(err); 79 | } 80 | } 81 | 82 | // RabbitMQ version 83 | metrics.rabbitmqVersion.set(data.rabbitmq_version); 84 | 85 | // # of Queues 86 | var queues = dotty.get(data, 'object_totals.queues'); 87 | if (queues === undefined) { 88 | queues = 'N/A'; 89 | } 90 | metrics.queues.set(queues); 91 | 92 | // # of Connections 93 | var connections = dotty.get(data, 'object_totals.connections'); 94 | if (connections === undefined) { 95 | connections = 'N/A'; 96 | } 97 | metrics.connections.set(connections); 98 | 99 | // # of Consumers 100 | var consumers = dotty.get(data, 'object_totals.consumers'); 101 | if (consumers === undefined) { 102 | consumers = 'N/A'; 103 | } 104 | metrics.consumers.set(consumers); 105 | 106 | // # of Channels 107 | var channels = dotty.get(data, 'object_totals.channels'); 108 | if (channels === undefined) { 109 | channels = 'N/A'; 110 | } 111 | metrics.channels.set(channels); 112 | 113 | // # of Exchanges 114 | var exchanges = dotty.get(data, 'object_totals.exchanges'); 115 | if (exchanges === undefined) { 116 | exchanges = 'N/A'; 117 | } 118 | metrics.exchanges.set(exchanges); 119 | 120 | // # of Total Messages 121 | var totalMessages = dotty.get(data, 'queue_totals.messages'); 122 | if (totalMessages === undefined) { 123 | totalMessages = 'N/A'; 124 | } 125 | metrics.totalMessages.set(totalMessages); 126 | 127 | // Publish Rate 128 | var publishRate = dotty.get(data, 'message_stats.publish_details.rate'); 129 | if (publishRate === undefined) { 130 | publishRate = 'N/A'; 131 | } 132 | metrics.publishRate.set(publishRate); 133 | 134 | // Deliver Rate 135 | var deliverRate = dotty.get(data, 'message_stats.deliver_get_details.rate'); 136 | if (deliverRate === undefined) { 137 | deliverRate = 'N/A'; 138 | } 139 | metrics.deliverRate.set(deliverRate); 140 | 141 | // # of Ready Messages 142 | var messagesReady = dotty.get(data, 'queue_totals.messages_ready'); 143 | if (messagesReady === undefined) { 144 | messagesReady = 'N/A'; 145 | } 146 | metrics.messagesReady.set(messagesReady); 147 | 148 | // # of Unacknowledged Messages 149 | var messagesUnacknowledged = dotty.get(data, 'queue_totals.messages_unacknowledged'); 150 | if (messagesUnacknowledged === undefined) { 151 | messagesUnacknowledged = 'N/A'; 152 | } 153 | metrics.messagesUnacknowledged.set(messagesUnacknowledged); 154 | 155 | }); 156 | } 157 | 158 | function init(conf) { 159 | var statsAgent; 160 | 161 | initMetrics(); 162 | statsAgent = initAgent(conf); 163 | setInterval(refreshMetrics.bind(this, statsAgent), REFRESH_RATE); 164 | } 165 | 166 | module.exports.init = init; 167 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pm2-rabbitmq", 3 | "version": "0.0.3", 4 | "description": "PM2 RabbitMQ Module", 5 | "main": "app.js", 6 | "dependencies": { 7 | "pmx" : ">=0.5.5", 8 | "amqp-stats": "0.0.14", 9 | "dotty": "0.0.2" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/pm2-hive/pm2-rabbitmq.git" 14 | }, 15 | "config" : { 16 | "username": "guest", 17 | "password": "guest", 18 | "hostname": "localhost:15672", 19 | "protocol": "http" 20 | }, 21 | "apps" : [{ 22 | "merge_logs" : true, 23 | "max_memory_restart" : "200M", 24 | "script" : "app.js" 25 | }], 26 | "author": "Keymetrics Inc.", 27 | "license": "MIT" 28 | } 29 | -------------------------------------------------------------------------------- /pm2-rabbitmq.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pm2-hive/pm2-rabbitmq/58971b3336df2f16008d9d4a101a0efeb062b63a/pm2-rabbitmq.jpg --------------------------------------------------------------------------------