Tuesday, April 5, 2011

Check process output with Monit workaround

We are monitoring our client's daemons with Monit. This works just fine, but sometimes we would like to run a process and have monit do something depending on its result which is not supported...

So you could just go and run the command from a cron script and do all actions from the cron script. But if you restart a service maybe you run into problems/conflicts with monit, and if you want alerts you have to configure them some other way, so it ends up bing a bit messy.

Another option would be write status to syslog and check for matching lines in monit but this would cause alerts/actions to be performed every time the matching line is logged.

So we're using the following workaround:
  • Run command periodically with cron and save output to a status-file

  • Monitor the status-file checking for a regular expressing


Monit's file content checking is thought for logs - so it tries to read from where it left off last time unless the file shrinks or the inode changes. To make monit reread the file everytime it changes we're using the following wrapper script "monitwrapper.sh":


#!/bin/sh

FILE=$1
shift

#make sure file exists
touch $FILE

#run command and gather output (exit status and stdout)
NEWSTDOUT=`$@`
STATUS=$?
NEWV=$STATUS:$NEWSTDOUT

#get output of last run
OLDV=`cat $FILE`

#if status has changed:
#change inode of the file to make monit reread
if [ "$NEWV" != "$OLDV" ]; then
echo $NEWV > $FILE.tmp
mv $FILE.tmp $FILE
fi


This leaves us with the return status and the stdout written to the status file only if the content is different.

We can run this from cron:

*/5 * * * * root monitwrapper.sh /var/run/teststatus testcmd


And monitor with monit:

check file status with path /var/run/teststatus
if not match "^0" then alert

Saturday, March 5, 2011

Automatic generic typesafe DAO implementation using Guice and Hibernate

Hi,

When you want to use DAO's for your application you will very likely going to use an interface like this:


public interface DAO<T, K extends Serializable> {

T findById(K id);

List<t> list();

void persist(T instance);

void delete(T instance);
}


Using Hibernate for O/R Mapping and Guice as DI framework you can use a sort of template for getting typesafe implementations of DAO's automatically generated for you, and you can ask for them to be injected like this:


public class NeedsDao {

@Inject
public NeedsDao(Dao<MyEntity, Integer> entityDao) {
List<MyEntity> miEntities = entityDao.list();
Entity EntityById = entityDao.findById(3);
}
}


Of course you need to know which type of key you need to use to get your entity, in this case we suppose the key is a plain Integer.

The class that implements the logic for this would be:


public class GenericDAO<T,K> implements DAO<T,K> {

private final Class<T> typeClass;
private final Provider<Session> sessionProvider;

@Inject
public GenericDAO(Provider<Session> sessionProvider, TypeLiteral<T> t) {
this.sessionProvider = sessionProvider;
this.typeClass=(Class<T>)t.getRawType();
}

public List<T> list() {
Session session = sessionProvider.get();
return (List<T>)session.createCriteria(typeClass).list();
}

@SuppressWarnings("unchecked")
@Override
public T findById(K id) {
Session session = sessionProvider.get();
return (T)session.get(typeClass, id);
}

@Override
public void persist(T instance) {
Session session = sessionProvider.get();
session.persist(instance);
}

@Override
public void delete(T instance) {
Session session = sessionProvider.get();
session.delete(instance);
}

}


With this parameterized class we implement all the DAO's we need. We circumvent type erasuring using Guice TypeLiteral injection feature, which allows us for inspecting at runtime which parameter the class has been parameterized with.

Now we only have left to make the wiring in Guice. The easiest way to do this is inspecting Hibernate configuration and generate a binding for each persistent class we have configured. We can write this module:


public class HibernateAutoModule extends AbstractModule {

public HibernateAutoModule(Configuration configuration) {
this.configuration = configuration;

}

@Override
protected void configure() {
configuration.buildMappings();
Iterator<PersistentClass> classMappings = configuration
.getClassMappings();
while (classMappings.hasNext()) {
PersistentClass persistentClass = (PersistentClass) classMappings
.next();
bind(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(
DAO.class, persistentClass.getMappedClass(),
persistentClass.getKey().getType()
.getReturnedClass()))).to(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(
GenericDAO.class,
persistentClass.getMappedClass(), persistentClass
.getKey().getType().getReturnedClass()))
);
}
}
}


You only need to correctly provide a fresh Configuration object from hibernate and install this module. Note that GenericDAO also depends on you providing a Session object from Hibernate.

Should you want to provide a different implementation for any of the interfaces you can use the Modules.override mechanism from Guice. Just generate a new binding for the interface you want to change the implementation.

I figure that the code won't work for you as is, but I think you can get the idea so you can adapt it for your needs.

Hope this helps!