JPPF, java, parallel computing, distributed computing, grid computing, parallel, distributed, cluster, grid, cloud, open source, android, .net
JPPF, java, parallel computing, distributed computing, grid computing, parallel, distributed, cluster, grid, cloud, open source, android, .net
JPPF

The open source
grid computing
solution

 Home   About   Features   Download   Documentation   On Github   Forums 

Monitoring data providers

From JPPF 6.3 Documentation

(Difference between revisions)
Jump to: navigation, search
(Value converters)
 

Latest revision as of 08:00, 14 February 2019

Contents

Main Page > Customizing JPPF > Monitoring data providers


A monitoring data provider is a service which provides diagnostics, health or information data about the (JVM) process of a JPPF node or driver, or about the machine it runs on. This data is provided to the health monitoring MBean, and transported in each health snapshot that it supplies on-demand.

The providers are also used by the JPPF desktop and web admin consoles, where they are rendered as columns in the JVM health view. The desktop console also makes the numeric values available as selectable fields for the charts.

[edit] 1 Defining a provider

A monitoring data provider is defined as a subclass of the abstract class MonitoringDataProvider, which specifies three abstract methods to override:

public abstract class MonitoringDataProvider {
  // Perform the initialization of this provider
  public abstract void init();

  // Perform the definition of the properties supplied by this provider
  public abstract void defineProperties();

  // Get the values for the defined properties
  public abstract TypedProperties getValues();

  ...
}

The init() method is invoked exactly once for each provider in a JPPF node or driver (producer side). It is intended for one-time initializations such as loading native libraries or reading resources files, etc. If no such initialization is needed in a provider, then the method's implementation should be left empty.

The method defineProperties() is called exactly once on both producer side, where the data comes from (drivers and nodes), and consumer side, where the data is rendered (web and desktop administration consoles). Each defined property has a name, a type, and optionally a validity range for the numeric properties. Individual properties are defined using the setXXXProperty() methods of MonitoringDataProvider, where XXX represents the type of the property's value.

The getValues() method is intented to be called repeatedly on the producer side only. It performs the association between the names of the properties defined in defineProperies() and their actual value. This method returns the association as a TypedProperties object.

Important: a concrete implementation of MonitoringDataProvider must provide a no-args constructor, either implicit or explicit

As an example, let's define a MonitoringDataProvider that supplies the system time as a formatted string. We could implement it as follows:

public class SystemTimeProvider extends MonitoringDataProvider {
  // example: 2018-05-21 17:40:37
  private final SimpleDateFormat dtFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");

  @Override public void init() { } // nothing to initialize

  @Override
  public void defineProperties() {
    // define the "systemTime" property as a string with an empty default value
    setStringProperty("systemTime", "");
  }

  @Override
  public TypedProperties getValues() {
    // set the current value of the "systemTime" property
    return new TypedProperties().setString("systemTime", dtFormat.format(new Date()));
  }
}

[edit] 2 Value converters

A monitoring data provider can associate a converter for each property it defines, in order to produce a displayable string based on the raw value of the property. This displayable string will then be used by the administration consoles UIs, instead of those generated by default converters.

A value converter is an implementation of the MonitoringValueConverter interface, declared as follows:

public interface MonitoringValueConverter
  // Convert or format the specified value expressed as a string
  String convert(String value);
}

The association of a value converter with a monitored property is performed with the setConverter(String, MonitoredValueConverter) method of MonitoringDataProvider. The following example redefines our SystemTimeProvider implementation, such that the value of the property becomes the result of System.currentTimeMillis() (a long value), with an associated converter that transforms it into a readable date:

public class SystemTimeProvider extends MonitoringDataProvider {
  ...

  @Override
  public void defineProperties() {
    setLongProperty("systemTime", System.currentTimeMillis());
    // convert to a formatted date
    setConverter("systemTime", value -> dtFormat.format(new Date(Long.valueOf(value))));
  }

  @Override
  public TypedProperties getValues() {
    return new TypedProperties().setLong("systemTime", System.currentTimeMillis()));
  }
}

MonitoringValueConverter also defines a number of specialized sub-interfaces and an implementation to conveniently convert typed data (int, long, float, double): IntConverter, LongConverter, FloatConverter, DoubleConverter and DoubleConverterWithFractionDigits. Accordingly, the defineProperties() method of our SystemTimeProvider can be further simplified:

public class SystemTimeProvider extends MonitoringDataProvider {
  ...

  @Override
  public void defineProperties() {
    setLongProperty("systemTime", System.currentTimeMillis());
    // convert to a formatted date
    setConverter("systemTime", (LongConverter) value -> dtFormat.format(new Date(value)));
  }
}

[edit] 3 Plugging a monitoring data provider

Monitoring data providers are discovered via the Service Provider Interface (SPI) mechanism. To plug a provider into JPPF, proceed as follows:

- In your source directory, or in a separate resources directory, create the service file:

META-INF/services/org.jppf.management.diagnostics.provider.MonitoringDataProvider

- Open this file in a text editor and add a line with the fully qualifed name of your provider implementation. For instance, for the SystemTimeProvider example in the previous section, we would add a line with the following content:

test.SystemTimeProvider

Note: you can add as many provider implementations as you wish.

- Create a jar file which contains this service file, along with your provider implementation and its support classes

- To make the provider available to the drivers and nodes, just add the jar file to each driver's classpath. The nodes will automatically lookup and download the provider implementations from the driver, using their distributed classloader.

- To make the provider available to a desktop administration console, just add the jar file to the console's classpath. The provider's properties will be shown as additional columns in the "JVM health" view of the console. The numeric properties will also be added to the list of available fields in the charts configuration dialog.

- To make the provider available to a web administration console, you will need to repackage the war file so as to add the provider jar to its WEB-INF/lib folder

[edit] 4 Localization support

If you have integrated a monitoring data provider in one of the administration consoles, you may have noticed that the corresponding column name in the "JVM health" view is exactly the name of the property, which may be more or less readable. The column header tooltip will also display the property name. If you need something more readable, based on the user's locale, follow these steps:

- in your provider implementation, override the getLocalizationBase() method of the MonitoringDataProvider class, to specify the base name of the localization files. For the SystemTimeProvider example, we could do as follows:

@Override
protected String getLocalizationBase() {
  return "test.SystemTimeProvider";
}

The returned string is used as the prefix for one or more properties files, based on the locale. For example the default translation would be found in the test.SystemTimeProvider.properties file, whereas the translation for the en_GB locale would be found in test.SystemTimeProvider_en_GB.properties.

- write a default translation file, where you can specify the column name and associated tooltip as follows:

property_name = some short translation
property_name.doc = a longer localized tooltip text \n possibly on multiple lines

The file name must be the string returned by getLocalizationBase(), with the .properties extension, for example: test.SystemTimeProvider.properties, with the following content:

# column name in JVM health view
systemTime = System time
# column header tooltip (.doc suffix)
systemTime.doc = The current system time in "YYYY-MM-dd HH:mm:ss" format

The screenshot below shows how htis is rendered in the desktop console:

CustomMonitoringData.png

- finally, do the same for all locales or languages for which you need a translation.

[edit] 5 Accessing the supplied values

The values supplied by the MonitoringDataProvider can be accessed via HealthSnapshot objects, which are obtained from the DiagnosticsMBean management bean. For more information on the DiagnosticsMBean and how to use it, please read the documentation on JVM health monitoring.

From a HealthSnapshot, individual values can be obtained vith one of the getXXX(String) methods, where XXX represents the desired type of the value. For example:

try (JMXDriverConnectionWrapper driverJmx =
       new JMXDriverConnectionWrapper("my.driver.host", 11111)) {
  // wait up to 5s for the JMX connection to the driver
  driverJmx.connectAndWait(5000L); 
  // obtain a proxy to the DiagnosticsMBean
  DiagnosticsMBean diag = driverJmx.getDiagnosticsProxy();
  // request a snapshot
  HealthSnapshot snapshot = diag.healthSnapshot();
  // print the value of "systemTime"
  System.out.println("the driver system time is " + snapshot.getString("systemTime"));
} catch (Exception e) { e.printStackTrace(); }

You may also obtain all the values as a TypedProperties object with the snapshot's getProperties() method:

DiagnosticsMBean diag = ...;
HealthSnapshot snapshot = diag.healthSnapshot();
// get all properties and print the value of "systemTime"
TypedProperties properties = snapshot.getProperties;
System.out.println("the driver system time is " + properties.getString("systemTime"));

Lastly, you can also use the DiagnosticsMBean's healthSnapshotAsString() method, which provides a string with all properties and their values, in a format compatible with properties files. This allows you to view the snapshot from external tools such as JConsole or VisualVM, as illustrated in this screenshot:

MonitoringDataFromVisualVM.png


Main Page > Customizing JPPF > Monitoring data providers



JPPF Copyright © 2005-2020 JPPF.org Powered by MediaWiki