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

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

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>Table 4.5. metric Attributes
| 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 collectiongetValues() 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);
}
Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.