4.4. Extended Example: HTTP Metrics
- Issue a GET or HEAD request to the base URL for the given server.
- Collect both the HTTP return code and the response time as a resource trait.
Figure 4.2. Basic Agent Plug-in Scenario
![Basic Agent Plug-in Scenario](https://access.redhat.com/webassets/avalon/d/Red_Hat_JBoss_Operations_Network-3.3-Writing_Custom_Plug-ins-en-US/images/8df627ca533e1e422962b475f4d5aff4/6732.png)
rhq-plugin.xml
file as the plug-in descriptor, which is required for JBoss ON to recognize the plug-in configuration. The plug-in is built as a maven project, so it has a pom.xml
file, although that is not a requirement, since any properly configured JAR file can be deployed as an agent plug-in.
Figure 4.3. Directory Layout of an Agent Plug-in Project
![Directory Layout of an Agent Plug-in Project](https://access.redhat.com/webassets/avalon/d/Red_Hat_JBoss_Operations_Network-3.3-Writing_Custom_Plug-ins-en-US/images/d55300442aa41e9098c430c6f3f3bf05/6733.png)
4.4.1. Looking at the Plug-in Descriptor (rhq-plugin.xml)
Example 4.3. Basic Plug-in Information
<?xml version="1.0" encoding="UTF-8" ?> <plugin name="HttpTest" displayName="HttpTest plugin" package="org.rhq.plugins.httptest" version="2.0" description="Monitoring of http servers" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:xmlns:rhq-plugin" xmlns:c="urn:xmlns:rhq-configuration">
package
attribute identifies the Java package for Java class names that are referenced in the plug-in configuration in the descriptor.
Example 4.4. Server Definition
<server name="HttpCheck" description="Httpserver pinging" discovery="HttpDiscoveryComponent" class="HttpComponent">
.java
files and classes. The supportsManualAdd
option sells JBoss ON that the HTTP services can be added manually through the UI, which is important for administration.
Example 4.5. Service Definition
<service name="HttpServiceCheck" discovery="HttpServiceDiscoveryComponent" class="HttpServiceComponent" description="One remote Http Server" supportsManualAdd="true"
Example 4.6. Simple Configuration Properties
<plugin-configuration> <c:simple-property name="url" type="string" required="true" /> </plugin-configuration>
Example 4.7. Complex Configuration Properties
<plugin-configuration> <c:list-property name="Servers"> <c:map-property name="OneServer"> <c:simple-property name="host"/> <c:simple-property name="port"> <c:integer-constraint minimum="0" maximum="65535"/> </c:simple-property> <c:simple-property name="protocol"> <c:property-options> <c:option value="http" default="true"/> <c:option value="https"/> </c:property-options> </c:simple-property> </c:map-property> </c:list-property> </plugin-configuration>
Example 4.8. Defined Metrics
<metric property="responseTime" displayName="Response Time" measurementType="dynamic" units="milliseconds" displayType="summary"/> <metric property="status" displayName="Status Code" data type="trait" displayType="summary"/> </service> </server> </plugin>
Attribute | Description |
---|---|
property | Gives the unique name of this metric. The name can also be obtained in the code using the getName() call. |
description | Gives a human readable description of the metric. |
displayName | Gives the name that gets displayed in the JBoss ON UI. |
data type | Sets the type of metric, such as numeric or trait. |
units | The measurement units to use for numerical data type. |
displayType | If the value is set to summary, the metric is displayed in the indicator charts and collected by default. |
defaultOn | Sets whether the metric collected by default. |
measurementType |
Sets what characteristics the numerical values have. The options are trends up, trends down, or dynamic. For both trends metrics, the system automatically creates additional per minute metrics.
Values that form part of a larger data structure, such as an array of values, need to be deconstructed into individual values before they can be monitored.
|
4.4.2. Looking at the Discovery Components (HttpDiscoveryComponent.java and HttpServiceDiscoveryComponent.java)
HttpDiscoveryComponent.java
, discovers the HTTP metrics server. The discovery component is called by the InventoryManager in the agent to discover resources. This can be done by a process table scan, querying the MBeanServer, or other means. Whatever the method, the most important thing is that the discovery component returns the same unique key each time for the same resource. The DiscoveryComponent needs to implement org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent
and you need to implement discoverResources()
.
Example 4.9. HttpDiscoveryComponent.java
public class HttpDiscoveryComponent implements ResourceDiscoveryComponent { public Set discoverResources(ResourceDiscoveryContext context) throws InvalidPluginConfigurationException, Exception { Set<DiscoveredResourceDetails> result = new HashSet<DiscoveredResourceDetails>(); String key = "http://localhost:7080/"; // Jon server String name = key; String description = "Http server at " + key; Configuration configuration = null; ResourceType resourceType = context.getResourceType(); DiscoveredResourceDetails detail = new DiscoveredResourceDetails(resourceType, key, name, null, description, configuration, null ); result.add(detail); return result; }
HttpServiceDiscoveryComponent.java
) relies on information passed through the GUI to configure its resources, rather than a discovery scan. The initial definition in the Java file is similar to the one for the server discovery, but this definition has an additional List<Configuration> childConfigs
which processes the information that is passed through the UI. This pulls the information for the required url information supplied by the user.
Example 4.10. Service Discovery
public class HttpServiceDiscoveryComponent implements ResourceDiscoveryComponent<HttpServiceComponent>; { public Set<DiscoveredResourceDetails> discoverResources (ResourceDiscoveryContext<HttpServiceComponent> context) throws InvalidPluginConfigurationException, Exception { Set<DiscoveredResourceDetails> result = new HashSet<DiscoveredResourceDetails>(); ResourceType resourceType = context.getResourceType(); List<Configuration> childConfigs = context.getPluginConfigurations(); for (Configuration childConfig : childConfigs) { String key = childConfig.getSimpleValue("url", null); if (key == null) throw new InvalidPluginConfigurationException( "No URL provided");
Example 4.11. Listing HTTP URL Resources
String name = key; String description = "Http server at " + key; DiscoveredResourceDetails detail = new DiscoveredResourceDetails( resourceType, key, name, null, description, childConfig, null ); result.add(detail); } return result; }
4.4.3. Looking at the Plug-in Components (HttpComponent.java and HttpServiceComponent.java)
HttpComponent.java
), the plug-in is pretty simple. The component only implements placeholder methods from the ResourceComponent interface to set the server availability. Setting the availability to UP automatically allows the resource component to start.
Example 4.12. Server Availability After Discovery
public AvailabilityType getAvailability() { return AvailabilityType.UP; }
HttpServiceComponent.java
) is more complex because it must carry out the operations defined in the plug-in descriptor.
MeasurementFacet
.
MeasurementFacet
implements the following method:
getValues(MeasurementReport report, Set metrics)
MeasurementReport
passed in is where the monitoring results are added. The metrics
value is a list of metrics for which data should be gathered. All of this information can be defined in the <metrics> element or in the UI configuration.
public class HttpComponent implements ResourceComponent, MeasurementFacet { URL url; // remote server url long time; // response time from last collection String status; // Status code from last collection
getValues()
method from the MeasurementFacet
must be implemented, but that's not the first step to take. A resource cannot be discovered if the resource is down, so the first step is to set a start value to start the service from ResourceContext
and give it an availability of UP.
Example 4.13. Service Resource Availability
public void start(ResourceContext context) throws InvalidPluginConfigurationException, Exception { url = new URL(context.getResourceKey()); // Provide an initial status, so // getAvailability() returns up status = "200"; }
getValues()
can be implemented. This actually collects the monitoring data from the given URLs.
Example 4.14. Implementing getValues()
public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception { getData(); // Loop over the incoming requests and // fill in the requested data for (MeasurementScheduleRequest request : metrics) { if (request.getName().equals("responseTime")) { report.addData(new MeasurementDataNumeric( request, new Double(time))); } else if (request.getName().equals("status")) { report.addData(new MeasurementDataTrait (request, status)); } } }
getData()
method in the MeasurementFacet
loops the incoming request to see which metric is wanted and then to supply the collected value. Depending on the type of data, the data may be to be wrapped into the correct MeasurementData*
class.
Example 4.15. Implementing getData()
private void getData() { HttpURLConnection con = null; int code = 0; try { con = (HttpURLConnection) url.openConnection(); con.setConnectTimeout(1000); long now = System.currentTimeMillis(); con.connect(); code = con.getResponseCode(); long t2 = System.currentTimeMillis(); time = t2 - now; } catch (Exception e) { e.printStackTrace(); } if (con != null) con.disconnect(); status = String.valueOf(code); }