As many of you know, I have been doing a ton of development. Some for my work at Cisco and some for fun. I like using PM2 to manage my node processes, logging, restarts, etc. As my integrations and bots have started getting more use I became fascinated/addicted with watching the logs for errors.
This was all great until last week, I realized it was really distracting me from my real job! I decided it was time to take these my hobby bots/apps to the next level.
I set out to find a solution that would alert me if a PM2 process reset/stopped, PM2 died, my server went offline as well as capture stack traces if/when a node process threw an exception. Keymetrics.io Has an awesome option for this. If you are running node apps in production and are making money with them, this would be an excellent option. Since my apps are mostly running for free, I kept looking. I already have Zabbix set up to monitor the infrastructure for Douglas Automotive and was excited when I found a module was already written for Zabbix to monitor PM2!
This was fairly painless to configure. I will post some details below. Zabbix has me covered for the process monitoring, server load, resets, etc. But I still needed a solution for stack traces.
There are lots of options out there for capturing and analyzing logs in the cloud. Many of them come with a hefty monthly price tag. After trying a couple options. I decided to use sentry.io, setting up an account and integrating into node was very simple.
Here is an example of a stack trace from some tests I was doing.
With these two solutions in place, I hope to maintain my sanity and continue to write more code that other people find useful! I am always looking for better ways to do things. If you have a logging/monitoring solution that is better, let me know!
Zabbix Config Detail:
You can find the Zabbix PM2 module here. I am running Zabbix on an EC2 Amazon Linux AMI. The example startup files were written for Debian where Amazon Linux is more like CentOS/RHEL. After lots of trial and error I was able to make the following script work.
Zabbix-pm2 AMI startup
#!/bin/sh
# Install this file as /etc/init.d/pm2-zabbix
### BEGIN INIT INFO
# Provides: pm2-zabbix
# Required-Start: $network $remote_fs $syslog
# Required-Stop: $network $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: Start PM2 monitor for Zabbix
### END INIT INFO
. /etc/rc.d/init.d/functions
NAME="pm2-zabbix"
DAEMON=/usr/local/bin/pm2-zabbix
PIDFILE=/var/run/pm2-zabbix/pm2-zabbix.pid
PATH=/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Actual start/stop logic
[ -x "$DAEMON" ] || exit 0
start() {
echo -n "Starting PM2 Zabbix: "
daemon --user "ec2-user" --pidfile $PIDFILE $DAEMON "--monitor 2>&1 &"
RETVAL=$?
sleep 5
PID=`ps aux|grep -vE 'grep|runuser|bash'|grep -w "$DAEMON"|awk '{print $2}'`
if [ -z "$PID" ]; then
printf "[ \e[31mFAIL\033[0m ]\n"
else
echo $PID > $PIDFILE
printf "[ \e[32mOK\033[0m ]\n"
fi
}
stop() {
echo -n "Shutting down PM2 Zabbix: "
echo
killproc -p $PIDFILE pm2-zabbix
echo
rm -f /var/lock/subsys/pm2-zabbix
return 0
}
case $1 in
start)
start
;;
stop)
stop
;;
restart|force-reload)
$0 stop && sleep 2 && $0 start
;;
try-restart)
if $0 status >/dev/null; then
$0 restart
else
exit 0
fi
;;
reload)
exit 3
;;
status)
status -p "$PIDFILE" "$DAEMON" "$NAME" && exit 0 || exit $?
;;
*)
echo "Usage: $0 {start|stop|restart|try-restart|force-reload|status}"
exit 2
;;
esac