Operational monitoring for ActiveMQ

I have been seeing lots of questions regarding monitoring for ActiveMQ. Below are available options for Monitoring ActiveMQ and problem with them.

  • JBoss operational network
    • Pros: Redhat support and email alerts on particular condition or threshold breach
    • Cons: Not freeware and works only with Redhat AMQ version
  • RHQ
    • An upstream project for JBoss Operational network
    • Pros: Free and supports email alerting
    • Cons: very poorly documented and AMQ plugings are not avaialble. You will have to write AMQ plugin for RHQ
  • HAWTIO
    • Pros: Free and easy monitoring tool
    • Cons: No email alert support

So to tackle above problem I have written small script which will allow you to set alerts for various conditions and parameters value for AMQ.

The script takes advantage of jolokia agent which is by default bundled with activemq.  Jolokia agent allows us to get MBeans and Values using HTTP request.

AMQMonitor.py:

The script  is available here on github .

Pros:

  • Email alerts supported
  • No need to contineously monitoring like jconsole or jvisualvm
  • Super simple python script
  • Very flexible alert configuration

Cons:

  • Not tested for other version of ActiveMQ except 5.13.2
  • Needs to be scheduled to periodically run using cron or other way

AMQMonitor.py

Run this file in periodic intervals for operational monitoring

# -*- coding: utf-8 -*-
import base64,json
import urllib2
import smtplib
from email.mime.text import MIMEText
from AMQMOnitorConf import global_conf
import logging
import socket

logging.basicConfig(filename='AMQMonitor.log', level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s')

#Sends Email 
def send_mail(resourceDetailsJson,alert):
 alertBodyTemplate="Hi Team,\nThe AMQ instance on %s requires attention.\nBelow resource has raised alert:\nResource Name:%s\nThreshold Value:%s\nCurrent Value:%s\nThanks & Regards\nAMQ Monitor script";
 currentVal=resourceDetailsJson["value"][alert["param"]]

if(alert["condition"]=="percent"):
 percentAgainstVal=resourceDetailsJson["value"][alert["percentageAgainstParam"]]
 percentVal=(float(currentVal)/percentAgainstVal)*100
 currentVal=str(percentVal)+ "%";

alertBody=alertBodyTemplate%(socket.gethostname(),alert["param"],alert["thresholdVal"],currentVal)
 print(alertBody)
 msg=MIMEText(alertBody)
 msg['from']=socket.gethostname()+"@yourdomain.com"
 msg['subject']= "AMQ Alert:"+socket.gethostname()
 msg["to"]=alert["emailList"]
 s=smtplib.SMTP("localhost")

s.sendmail(socket.gethostname()+"@yourdomain.com",alert["emailList"].split(",") , msg.as_string())
 logging.info("Alert Email sent")
 s.quit();
 return;

#Condition checks current value and checks if value is within specified threshold as per conditions
def condition_check(resourceDetailsJson,alert):
 logging.info("Checking alert condition "+str(alert))
 paramVal=resourceDetailsJson["value"][alert["param"]]
 if alert["condition"]=="gt":
 if(paramVal>alert["thresholdVal"]):
 return True;
 elif alert["condition"]=="lt":
 if(paramVal<alert["thresholdVal"]):
 return True;
 elif alert["condition"]=="eq":
 if(paramVal==alert["thresholdVal"]):
 return True;
 elif alert["condition"]=="percent":
 percentAgainstVal=resourceDetailsJson["value"][alert["percentageAgainstParam"]]
 percentVal=(float(paramVal)/percentAgainstVal)*100
 logging.info("Param Val: %s Percent against val: %s Percentage:%s"%(paramVal,percentAgainstVal,percentVal))
 if(percentVal>float(alert["thresholdVal"])):
 return True;
 else:
 logging.error("Please speicify correct condition for alert "+ str(alert));
 return False;

#Calls the JolokiaURL and adds BasicAuth header to every reqest and dumps data as JSON
def read_request(requestURL):
 base64string = base64.b64encode('%s:%s' % (global_conf["jolokiaUserName"], global_conf["jolokiaPassword"]))
 opener=urllib2.build_opener()
 opener.addheaders=[("Authorization", "Basic %s" % base64string)]
 try:
 readRequest=opener.open(requestURL)
 if(readRequest.getcode()!=200):
 logging.warning("Request Did not complete normaly for"+ requestURL);
 readData=readRequest.read()
 jsonData=json.loads(readData);
 return jsonData;
 except urllib2.HTTPError as e:
 if e.code== 404:
 logging.error("Check for correct URL")
 return None
 if e.code==401 or e.code==403:
 logging.error("Check jolokiaUsername and jolokiaPassword ")
 return None
 except urllib2.URLError as u:
 logging.error("There was error connecting to broker");
 logging.error("Please check if broker is up")
 return None

#Script execution starts here
jsondata=read_request(global_conf["jolokiaBase"])
memoryJson=read_request(global_conf["jolokiaBase"]+"/read/java.lang:type=Memory/HeapMemoryUsage")
if(memoryJson==None):
 detailsJson={"value":{"Broker Connectivity":"DOWN","currentVal":"DOWN"}}
 brokerDownAlert={"param":"Broker Connectivity","condition":"available","thresholdVal":"UP","emailList":"abhinav.suryawanshi@tcs.com"}
 send_mail(detailsJson,brokerDownAlert)
 exit();
for alert in global_conf["jvmAlerts"]:
 if(condition_check(memoryJson,alert)):
 send_mail(memoryJson,alert)
for queueName,alertsArray in global_conf["queueAlert"].iteritems():
 logging.info("Fetching details for Queue:"+queueName)
 queueURL=global_conf["jolokiaBase"]+"/read/org.apache.activemq:type=Broker,brokerName="+global_conf["brokerName"]+",destinationType=Queue,destinationName="+queueName
 queueDetailsJson=read_request(queueURL)
 if queueDetailsJson["status"]!=200:
 logging.error("Queue does not exist")
 else:
 for alert in alertsArray:
 if(condition_check(queueDetailsJson,alert)):
 send_mail(queueDetailsJson,alert)

 

AMQMOnitorConf.py

The script contains all alerts definition. You can add alerts by simply putting new alert in array queueAlerts or jvmAlerts.

To know detailed parameter list on which you can put alerts please refer this gist


global_conf={
 "jolokiaBase":"http://localhost:8161/api/jolokia",
 "jolokiaUserName":"admin",
 "jolokiaPassword":"admin",
 "brokerName":"localhost",
 "brokerDownAlertEmail":"suryawanshi.abhinav89@gmail.com",
 "jvmAlerts":[
 {"param":"used","thresholdVal":"0.2","condition":"percent","emailList":"abhinav.suryawanshi@tcs.com","percentageAgainstParam":"max"}
 ],
 "queueAlert":{
 "cbr.queue":[
 {"param":"ConsumerCount","thresholdVal":200,"condition":"lt","emailList":"abhinav.suryawanshi@tcs.com"},
 {"param":"QueueSize","thresholdVal":1,"condition":"eq","emailList":"abhinav.suryawanshi@tcs.com"}
 ],
 "queue2":[]
 }
}
Advertisements

Configuring Fuse- Basics

Adding Users

Fuse_Installation_directory/etc/users.properties

Users are added as new user on new line as java properties file syntax

username=password,role

Role Based Authentication deserves its own separate post and is available from 6.2 on-wards only

E.g:

MyAdminUser=MyAdminPassword,admin
MyAdminUser2=MyAdminPassowrd2,admin

Editing name of Container

Read More »

Apache Karaf

Apache karaf is OSGi based runtime.
It is where our bundles (OSGi components) run. Fuse uses apache karaf as its OSGi container to make run bundles which collaborate to provide business functionality. So in order to understand fuse we have to understand karaf.

Apache karaf is very small and lightweight OSGi container which runs OSGi bundles ( components which make up our application).

It is built on Felix and  equinox which are OSGi framework.

image
Apache karaf

Read More »

What is ESB ?

ESB in its simplest form is a software architecture model which allows multiple application to communicate.

Nothing great about it?

What if those application were developed in different ages using different technologies? Like some in C, C++, Java etc. and nightmare is not over yet what if everyone needs their input data in their own format and produces output in their own format?What if every application resides on different hosts?

Read More »