Internally, Cougar uses Tornjak, please see this guide
for details of how to configure that framework, paying particular attention to the active monitoring setup
if you plan to use the resulting status to drive a load balancer. To expose the status of your application to the Cougar
data services container, you are required to expose an instance of the MonitorRegistry
interface from your Service
.
This should have been exemplified in the archetype you used as a basis for your service (look at your cougar-application-spring.xml
), you just need to tailor it to your needs.
Your service’s status information will then be available to you if you use the Cougar Health Service module (included by default in the archetype).
<dependency>
<groupId>com.betfair.cougar</groupId>
<artifactId>cougar-health-service-app</artifactId>
<version>${cougar.version}</version>
<scope>runtime</scope>
</dependency>
Port is usually 8080 unless over-ridden by jetty.http.port
.
What | Where | Notes |
---|---|---|
Health check summary (RESCRIPT) | http://localhost:8080/healthcheck/v2/summary | Use this for webping style checks |
Health check detail (RESCRIPT) | http://localhost:8080/healthcheck/v2/detailed | - |
Health check WSDL | http://localhost:8080/wsdl/CougarHealthService.wsdl | - |
Health check SOAP Endpoint | http://localhost:8080/HealthService/v3 | - |
The cougar data services container has a secondary HTTP port, independent of the deployed transport that allows remote monitoring of the cougar application.
It has 4 distinct interfaces, available on different urls, although this number may increase or decrease depending on the modules installed.
The port is usually 9999 unless over-ridden by jmx.html.port
.
The protocol for the services on port 9999 is usually HTTP when the application is run up in dev mode (e.g. via `exec:java`), and HTTPS everywhere else. In this document HTTP is used, simply replace with HTTPS where necessary. |
The port is protected by HTTP basic auth. The username is always jmxadmin
. The default password (usually used in dev) is password
.
The username and password are governed by the jmx.html.username
and jmx.html.password
properties.
By default, Cougar runs this monitoring interface with SSL enabled. This is strongly recommended for production. Unfortunately,
it’s not possible for us to distribute certificates, so you need to specify 3 properties to setup SSL properly:
jmx.html.keystore.filepath
, jmx.html.keystore.password
and jmx.html.keystore.certpassword
. If you want to
disable SSL for use in a development environment, then use jmx.html.tls.enabled
, setting it to false
.
The simplest interface is to browse all exported JMX beans in the system as web pages. Using this interface, the operator both interrogate and interact with beans (i.e. operations can be called to change the state of the application, should they be exposed). This interface may be reached at: https://localhost:9999/ (or http://localhost:9999/ if you have SSL disabled)
This interface is used to interrogate the state of the JVM threads. The page reports deadlocks and blocked threads, as well as giving an overview of all threads in the system and their current state. It is reached at https://localhost:9999/administration/threaddump.jsp (or http://localhost:9999/administration/threaddump.jsp if you have SSL disabled)
This is an API (if we’re going to be really generous) that allows beans and attributes to be returned in an easy-to-parse format,
either individually or in batches. It is accessed at https://localhost:9999/administration/batchquery.jsp
(or http://localhost:9999/administration/batchquery.jsp
if you have SSL disabled) and takes the following attributes:
All responses to the batchquery.jsp are returned in the following format (assuming the separator character is a tilde):
(Time)(BeanName)(Attribute)(Attribute) | (BeanName)(Attribute)(Attribute) |
where
All these examples should work on the Baseline Service. Other deployed services may need some tweaking.
All the attributes of a bean are listed by not specifying an attribute (“an”) parameter.
https://localhost:9002/administration/batchquery.jsp?on=java.lang%3Atype=Runtime
The skeleton of the return value is shown below. It has been formatted for ease of reading.
java.lang:type=Runtime
~Name~2344@HOSTNAME
~ClassPath~...
~VmName~Java HotSpot(TM) Server VM
~VmVendor~Sun Microsystems Inc.
~VmVersion~14.0-b16
~BootClassPathSupported~true
...
https://localhost:9999/administration/batchquery.jsp?on=java.lang%3Atype=Runtime&t&an=VmVersion
The formatted return value is shown below.
Time~2009-10-29 14:51:28.932~
java.lang:type=Runtime
~VmVersion~14.0-b16
https://localhost:9999/administration/batchquery.jsp?on=SYSTEM&an=java.runtime.name
The skeleton formatted return value is shown below.
System Properties
~java.runtime.name~Java(TM) SE Runtime Environment
https://localhost:9999/administration/batchquery.jsp?on=CoUGAR.service.Baseline.v1.0:type=operation,name=**&an=Calls
The formatted return value is shown below.
CoUGAR.service.Baseline.v1.0:type=operation,name=testException
~Calls~67
|
CoUGAR.service.Baseline.v1.0:type=operation,name=testStringableLists
~Calls~0
|
CoUGAR.service.Baseline.v1.0:type=operation,name=testLargePost
~Calls~275
...
As above, but don’t specify an attribute (“an”) parameter.
https://localhost:9999/administration/batchquery.jsp?on=CoUGAR.service.Baseline.v1.0:type=operation,name=**
The operation must accept no parameters.
https://localhost:9999/administration/batchquery.jsp?on=CoUGAR:name=Logging&op=getNumErrors
the Formatted return value is in the form (BeanName)(OperationName)(Result)
CoUGAR:name=Logging~getNumErrors~0~
You can add your own MBeans by using the javax.management
API, either in Java code, or in Spring. Here’s an example in Spring using annotations.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean id="myBean" class="com.betfair.services.example.EchoBean"/>
<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" />
<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="server">
<bean class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true"/>
</bean>
</property>
<property name="assembler">
<bean class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource" />
</bean>
</property>
<property name="namingStrategy">
<bean class="org.springframework.jmx.export.naming.KeyNamingStrategy"/>
</property>
<property name="autodetect" value="false" />
<property name="registrationBehaviorName" value="REGISTRATION_FAIL_ON_EXISTING"/>
<property name="beans">
<map>
<entry key="Foo.Bar:wizz=bang" value-ref="myBean"/>
</map>
</property>
</bean>
</beans>
Here’s an example of what myBean
could look like, using annotations.
import org.springframework.jmx.export.annotation.*;
@ManagedResource(description="My Managed Bean")
public class EchoBean {
private String prefix;
@ManagedAttribute(description="Get the prefix")
public String getPrefix() {
return prefix;
}
@ManagedAttribute(description="Set the prefix")
public void setPrefix(String prefix) {
this.prefix = prefix;
}
@ManagedOperation(description="Echoes the argument, prepending the prefix")
@ManagedOperationParameters({
@ManagedOperationParameter(name = "argument", description = "The argument")
})
public String echo(String arg) {
return prefix <u> ": " </u> arg;
}
public void dontExposeMe() {
//
}
}
There are many possible ways of adding MBeans in Spring or in plain old Java, this is just one of them exposed as an example. The key thing is to use the platform MBean server.
It’s unwise to set autodetect
to true, as this can expose some classes in other modules (Cougar core or otherwise)
that weren’t supposed to be.
com.betfair.cougar.core.api.jmx
com.betfair.cougar.core.impl.jmx